diff options
author | Ian Boros <ian.boros@mongodb.com> | 2019-11-15 22:41:41 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-11-15 22:41:41 +0000 |
commit | f031fff64ea75f70e01cadc973290072605c9f25 (patch) | |
tree | 2a505b8ddbedd8e9d4081746fed233e24bc78be5 | |
parent | 057cbc36a1fde617f8b5047a1c1a146b33214b92 (diff) | |
download | mongo-f031fff64ea75f70e01cadc973290072605c9f25.tar.gz |
SERVER-44269 Replace core/max_time_ms.js with modernized version in noPassthrough
23 files changed, 524 insertions, 492 deletions
diff --git a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_100ms_refresh_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_100ms_refresh_jscore_passthrough.yml index 72da949cc48..451de036802 100644 --- a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_100ms_refresh_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_100ms_refresh_jscore_passthrough.yml @@ -30,7 +30,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/mr_replaceIntoDB.js # MapReduceResult, SERVER-20495. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. diff --git a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_10sec_refresh_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_10sec_refresh_jscore_passthrough.yml index a806ec5ac57..4f86e857d2b 100644 --- a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_10sec_refresh_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_10sec_refresh_jscore_passthrough.yml @@ -30,7 +30,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/mr_replaceIntoDB.js # MapReduceResult, SERVER-20495. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. diff --git a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_1sec_refresh_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_1sec_refresh_jscore_passthrough.yml index efb7ae3d0a1..a75746c8596 100644 --- a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_1sec_refresh_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_1sec_refresh_jscore_passthrough.yml @@ -30,7 +30,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/mr_replaceIntoDB.js # MapReduceResult, SERVER-20495. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. diff --git a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_default_refresh_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_default_refresh_jscore_passthrough.yml index 95177f30486..2abb080d45b 100644 --- a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_default_refresh_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_default_refresh_jscore_passthrough.yml @@ -30,7 +30,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/mr_replaceIntoDB.js # MapReduceResult, SERVER-20495. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. diff --git a/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml index e056e160377..b038017cd18 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml @@ -31,7 +31,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/mr_replaceIntoDB.js # MapReduceResult, SERVER-20495. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. @@ -285,7 +284,6 @@ selector: - jstests/core/kill_cursors.js - jstests/core/list_collections1.js - jstests/core/list_indexes.js - - jstests/core/max_time_ms.js - jstests/core/oro.js # Expects certain number of operations in the system.profile collection. diff --git a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml index 0e7b56025cb..1cac4029e20 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml @@ -31,7 +31,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/mr_replaceIntoDB.js # MapReduceResult, SERVER-20495. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. @@ -312,7 +311,6 @@ selector: - jstests/core/kill_cursors.js - jstests/core/list_collections1.js - jstests/core/list_indexes.js - - jstests/core/max_time_ms.js - jstests/core/oro.js # Expects certain number of operations in the system.profile collection. diff --git a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml index 3cfa0050da3..1d91d755423 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml @@ -31,7 +31,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/mr_replaceIntoDB.js # MapReduceResult, SERVER-20495. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. @@ -297,7 +296,6 @@ selector: - jstests/core/kill_cursors.js - jstests/core/list_collections1.js - jstests/core/list_indexes.js - - jstests/core/max_time_ms.js - jstests/core/oro.js # Expects certain number of operations in the system.profile collection. diff --git a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml index e8d10941693..241af05766d 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml @@ -31,7 +31,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/mr_replaceIntoDB.js # MapReduceResult, SERVER-20495. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. @@ -306,7 +305,6 @@ selector: - jstests/core/kill_cursors.js - jstests/core/list_collections1.js - jstests/core/list_indexes.js - - jstests/core/max_time_ms.js - jstests/core/oro.js # Expects certain number of operations in the system.profile collection. diff --git a/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml b/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml index aa97b5220b7..c9d1bc39459 100644 --- a/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml +++ b/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml @@ -31,7 +31,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/mr_replaceIntoDB.js # MapReduceResult, SERVER-20495. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. @@ -329,7 +328,6 @@ selector: - jstests/core/kill_cursors.js - jstests/core/list_collections1.js - jstests/core/list_indexes.js - - jstests/core/max_time_ms.js - jstests/core/oro.js # Expects certain number of operations in the system.profile collection. diff --git a/buildscripts/resmokeconfig/suites/read_concern_linearizable_passthrough.yml b/buildscripts/resmokeconfig/suites/read_concern_linearizable_passthrough.yml index 50b431c3456..e26d5f1401b 100644 --- a/buildscripts/resmokeconfig/suites/read_concern_linearizable_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/read_concern_linearizable_passthrough.yml @@ -22,7 +22,6 @@ selector: - jstests/core/awaitdata_getmore_cmd.js # This test uses a very short timeout for a read that becomes unreliable with read concern # linearizable. - - jstests/core/max_time_ms.js exclude_with_any_tags: ## # The next three tags correspond to the special errors thrown by the diff --git a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml index 34c19724e0a..817eceb11d1 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml @@ -227,7 +227,6 @@ selector: - jstests/core/kill_cursors.js - jstests/core/list_collections1.js - jstests/core/list_indexes.js - - jstests/core/max_time_ms.js - jstests/core/oro.js # Expects certain number of operations in the system.profile collection. diff --git a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml index 0ddded3faa0..c09fa51e041 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml @@ -224,7 +224,6 @@ selector: - jstests/core/kill_cursors.js - jstests/core/list_collections1.js - jstests/core/list_indexes.js - - jstests/core/max_time_ms.js - jstests/core/oro.js # Expects certain number of operations in the system.profile collection. diff --git a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_stepdown_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_stepdown_jscore_passthrough.yml index 0b248d0728c..7336d0cd656 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_stepdown_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_stepdown_jscore_passthrough.yml @@ -224,7 +224,6 @@ selector: - jstests/core/kill_cursors.js - jstests/core/list_collections1.js - jstests/core/list_indexes.js - - jstests/core/max_time_ms.js - jstests/core/oro.js # Expects certain number of operations in the system.profile collection. diff --git a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_terminate_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_terminate_primary_jscore_passthrough.yml index 49742d96afe..e2c550c1f52 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_terminate_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_terminate_primary_jscore_passthrough.yml @@ -221,7 +221,6 @@ selector: - jstests/core/kill_cursors.js - jstests/core/list_collections1.js - jstests/core/list_indexes.js - - jstests/core/max_time_ms.js - jstests/core/oro.js # Expects certain number of operations in the system.profile collection. diff --git a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml index 2350e6b5408..f39dbe7bbf5 100644 --- a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml @@ -23,7 +23,6 @@ selector: # These test run commands using legacy queries, which are not supported on sessions. - jstests/core/exhaust.js - - jstests/core/max_time_ms.js - jstests/core/validate_cmd_ns.js # TODO SERVER-31249: getLastError should not be affected by no-op retries. diff --git a/buildscripts/resmokeconfig/suites/session_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/session_jscore_passthrough.yml index 4c709b1d53b..2859b08b13f 100644 --- a/buildscripts/resmokeconfig/suites/session_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/session_jscore_passthrough.yml @@ -9,7 +9,6 @@ selector: # These test run commands using legacy queries, which are not supported on sessions. - jstests/core/exhaust.js - - jstests/core/max_time_ms.js - jstests/core/validate_cmd_ns.js # Unacknowledged writes prohibited in an explicit session. diff --git a/buildscripts/resmokeconfig/suites/sharded_collections_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/sharded_collections_jscore_passthrough.yml index 9a3028493b0..ee82af67b33 100644 --- a/buildscripts/resmokeconfig/suites/sharded_collections_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/sharded_collections_jscore_passthrough.yml @@ -31,7 +31,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/mr_replaceIntoDB.js # MapReduceResult, SERVER-20495. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. diff --git a/buildscripts/resmokeconfig/suites/sharded_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/sharded_multi_stmt_txn_jscore_passthrough.yml index 228dcdec60d..e225c598f99 100644 --- a/buildscripts/resmokeconfig/suites/sharded_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/sharded_multi_stmt_txn_jscore_passthrough.yml @@ -28,7 +28,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. - jstests/core/queryoptimizera.js # "local" database. @@ -258,7 +257,6 @@ selector: - jstests/core/kill_cursors.js - jstests/core/list_collections1.js - jstests/core/list_indexes.js - - jstests/core/max_time_ms.js - jstests/core/oro.js # Expects certain number of operations in the system.profile collection. diff --git a/buildscripts/resmokeconfig/suites/sharding_jscore_op_query_passthrough.yml b/buildscripts/resmokeconfig/suites/sharding_jscore_op_query_passthrough.yml index 40b2193ec12..b117bf1640f 100644 --- a/buildscripts/resmokeconfig/suites/sharding_jscore_op_query_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/sharding_jscore_op_query_passthrough.yml @@ -31,7 +31,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. - jstests/core/queryoptimizera.js # "local" database. diff --git a/buildscripts/resmokeconfig/suites/sharding_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/sharding_jscore_passthrough.yml index 54393249267..7a10e7b5d49 100644 --- a/buildscripts/resmokeconfig/suites/sharding_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/sharding_jscore_passthrough.yml @@ -31,7 +31,6 @@ selector: - jstests/core/geo_update_btree2.js # notablescan. - jstests/core/index_id_options.js # "local" database. - jstests/core/index9.js # "local" database. - - jstests/core/max_time_ms.js # sleep, SERVER-2212. - jstests/core/notablescan.js # notablescan. - jstests/core/profile*.js # profiling. - jstests/core/queryoptimizera.js # "local" database. diff --git a/jstests/core/max_time_ms.js b/jstests/core/max_time_ms.js deleted file mode 100644 index b8bb94b4e6f..00000000000 --- a/jstests/core/max_time_ms.js +++ /dev/null @@ -1,465 +0,0 @@ -// Tests query/command option $maxTimeMS. -// -// @tags: [ -// # This test attempts to perform read operations after having enabled the maxTimeAlwaysTimeOut -// # failpoint. The former operations may be routed to a secondary in the replica set, whereas the -// # latter must be routed to the primary. -// assumes_read_preference_unchanged, -// requires_fastcount, -// requires_getmore, -// # Uses $where operator -// requires_scripting, -// uses_testing_only_commands, -// ] - -var t = db.max_time_ms; -var cursor; -var res; -var error; - -// -// Simple positive test for query: a ~100 second query with a 100ms time limit should be aborted. -// - -t.drop(); -assert.commandWorked(t.insert(Array.from({length: 1000}, _ => ({})))); - -cursor = t.find({ - $where: function() { - sleep(100); - return true; - } -}); -cursor.maxTimeMS(100); -error = assert.throws(function() { - cursor.itcount(); -}, [], "expected query to abort due to time limit"); -// TODO SERVER-32565: The error should always be MaxTimeMSExpired, but there are rare cases where -// interrupting javascript execution on the server with a stepdown or timeout results in an error -// code of InternalError or Interrupted instead, so we also accept those here. -assert.contains(error.code, - [ErrorCodes.MaxTimeMSExpired, ErrorCodes.Interrupted, ErrorCodes.InternalError], - "Failed with error: " + tojson(error)); - -// -// Simple negative test for query: a ~300ms query with a 10s time limit should not hit the time -// limit. -// - -t.drop(); -assert.commandWorked(t.insert([{}, {}, {}])); -cursor = t.find({ - $where: function() { - sleep(100); - return true; - } -}); -cursor.maxTimeMS(10 * 1000); -assert.doesNotThrow(function() { - cursor.itcount(); -}, [], "expected query to not hit the time limit"); - -// -// Simple positive test for getmore: -// - Issue a find() that returns 2 batches: a fast batch, then a slow batch. -// - The find() has a 4-second time limit; the first batch should run "instantly", but the second -// batch takes ~15 seconds, so the getmore should be aborted. -// - -t.drop(); -assert.commandWorked(t.insert([{_id: 0}, {_id: 1}, {_id: 2}])); // fast batch -assert.commandWorked( - t.insert([{_id: 3, slow: true}, {_id: 4, slow: true}, {_id: 5, slow: true}])); // slow batch -cursor = t.find({ - $where: function() { - if (this.slow) { - sleep(5 * 1000); - } - return true; - } - }).sort({_id: 1}); -cursor.batchSize(3); -cursor.maxTimeMS(4 * 1000); -assert.doesNotThrow(function() { - cursor.next(); - cursor.next(); - cursor.next(); -}, [], "expected batch 1 (query) to not hit the time limit"); -error = assert.throws(function() { - cursor.next(); - cursor.next(); - cursor.next(); -}, [], "expected batch 2 (getmore) to abort due to time limit"); -// TODO SERVER-32565: The error should always be MaxTimeMSExpired, but there are rare cases where -// interrupting javascript execution on the server with a stepdown or timeout results in an error -// code of InternalError or Interrupted instead, so we also accept those here. -assert.contains(error.code, - [ErrorCodes.MaxTimeMSExpired, ErrorCodes.Interrupted, ErrorCodes.InternalError], - "Failed with error: " + tojson(error)); - -// -// Simple negative test for getmore: -// - Issue a find() that returns 2 batches: a fast batch, then a slow batch. -// - The find() has a 10-second time limit; the first batch should run "instantly", and the second -// batch takes only ~2 seconds, so both the query and getmore should not hit the time limit. -// - -t.drop(); -assert.commandWorked(t.insert([{_id: 0}, {_id: 1}, {_id: 2}])); // fast batch -assert.commandWorked(t.insert([{_id: 3}, {_id: 4}, {_id: 5, slow: true}])); // slow batch -cursor = t.find({ - $where: function() { - if (this.slow) { - sleep(2 * 1000); - } - return true; - } - }).sort({_id: 1}); -cursor.batchSize(3); -cursor.maxTimeMS(10 * 1000); -assert.doesNotThrow(function() { - cursor.next(); - cursor.next(); - cursor.next(); -}, [], "expected batch 1 (query) to not hit the time limit"); -assert.doesNotThrow(function() { - cursor.next(); - cursor.next(); - cursor.next(); -}, [], "expected batch 2 (getmore) to not hit the time limit"); - -// -// Many-batch positive test for getmore: -// - Issue a many-batch find() with a 6-second time limit where the results take 10 seconds to -// generate; one of the later getmore ops should be aborted. -// - -t.drop(); -for (var i = 0; i < 5; i++) { - assert.commandWorked( - t.insert([{_id: 3 * i}, {_id: (3 * i) + 1}, {_id: (3 * i) + 2, slow: true}])); -} -cursor = t.find({ - $where: function() { - if (this.slow) { - sleep(2 * 1000); - } - return true; - } - }).sort({_id: 1}); -cursor.batchSize(3); -cursor.maxTimeMS(6 * 1000); -error = assert.throws(function() { - cursor.itcount(); -}, [], "expected find() to abort due to time limit"); -// TODO SERVER-32565: The error should always be MaxTimeMSExpired, but there are rare cases where -// interrupting javascript execution on the server with a stepdown or timeout results in an error -// code of InternalError or Interrupted instead, so we also accept those here. -assert.contains(error.code, - [ErrorCodes.MaxTimeMSExpired, ErrorCodes.Interrupted, ErrorCodes.InternalError], - "Failed with error: " + tojson(error)); - -// -// Many-batch negative test for getmore: -// - Issue a many-batch find() with a 20-second time limit where the results take 10 seconds to -// generate; the find() should not hit the time limit. -// - -t.drop(); -for (var i = 0; i < 5; i++) { - assert.commandWorked( - t.insert([{_id: 3 * i}, {_id: (3 * i) + 1}, {_id: (3 * i) + 2, slow: true}])); -} -cursor = t.find({ - $where: function() { - if (this.slow) { - sleep(2 * 1000); - } - return true; - } - }).sort({_id: 1}); -cursor.batchSize(3); -cursor.maxTimeMS(20 * 1000); -assert.doesNotThrow(function() { - // SERVER-40305: Add some additional logging here in case this fails to help us track down why - // it failed. - assert.commandWorked(db.adminCommand({setParameter: 1, traceExceptions: 1})); - cursor.itcount(); - assert.commandWorked(db.adminCommand({setParameter: 1, traceExceptions: 0})); -}, [], "expected find() to not hit the time limit"); - -// -// Simple positive test for commands: a ~300ms command with a 100ms time limit should be aborted. -// - -t.drop(); -res = t.getDB().adminCommand({sleep: 1, millis: 300, maxTimeMS: 100}); -assert(res.ok == 0 && res.code == ErrorCodes.MaxTimeMSExpired, - "expected sleep command to abort due to time limit, ok=" + res.ok + ", code=" + res.code); - -// -// Simple negative test for commands: a ~300ms command with a 10s time limit should not hit the -// time limit. -// - -t.drop(); -res = t.getDB().adminCommand({sleep: 1, millis: 300, maxTimeMS: 10 * 1000}); -assert(res.ok == 1, - "expected sleep command to not hit the time limit, ok=" + res.ok + ", code=" + res.code); - -// -// Tests for input validation. -// - -t.drop(); -assert.commandWorked(t.insert({})); - -// Verify lower boundary for acceptable input (0 is acceptable, 1 isn't). - -assert.doesNotThrow.automsg(function() { - t.find().maxTimeMS(0).itcount(); -}); -assert.doesNotThrow.automsg(function() { - t.find().maxTimeMS(NumberInt(0)).itcount(); -}); -assert.doesNotThrow.automsg(function() { - t.find().maxTimeMS(NumberLong(0)).itcount(); -}); -assert.eq(1, t.getDB().runCommand({ping: 1, maxTimeMS: 0}).ok); -assert.eq(1, t.getDB().runCommand({ping: 1, maxTimeMS: NumberInt(0)}).ok); -assert.eq(1, t.getDB().runCommand({ping: 1, maxTimeMS: NumberLong(0)}).ok); - -assert.throws.automsg(function() { - t.find().maxTimeMS(-1).itcount(); - }); -assert.throws.automsg(function() { - t.find().maxTimeMS(NumberInt(-1)).itcount(); - }); -assert.throws.automsg(function() { - t.find().maxTimeMS(NumberLong(-1)).itcount(); - }); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: -1}).ok); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: NumberInt(-1)}).ok); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: NumberLong(-1)}).ok); - -// Verify upper boundary for acceptable input (2^31-1 is acceptable, 2^31 isn't). - -var maxValue = Math.pow(2, 31) - 1; - -assert.doesNotThrow.automsg(function() { - t.find().maxTimeMS(maxValue).itcount(); -}); -assert.doesNotThrow.automsg(function() { - t.find().maxTimeMS(NumberInt(maxValue)).itcount(); -}); -assert.doesNotThrow.automsg(function() { - t.find().maxTimeMS(NumberLong(maxValue)).itcount(); -}); -assert.eq(1, t.getDB().runCommand({ping: 1, maxTimeMS: maxValue}).ok); -assert.eq(1, t.getDB().runCommand({ping: 1, maxTimeMS: NumberInt(maxValue)}).ok); -assert.eq(1, t.getDB().runCommand({ping: 1, maxTimeMS: NumberLong(maxValue)}).ok); - -assert.throws.automsg(function() { - t.find().maxTimeMS(maxValue + 1).itcount(); - }); -assert.throws.automsg(function() { - t.find().maxTimeMS(NumberInt(maxValue + 1)).itcount(); - }); -assert.throws.automsg(function() { - t.find().maxTimeMS(NumberLong(maxValue + 1)).itcount(); - }); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: maxValue + 1}).ok); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: NumberInt(maxValue + 1)}).ok); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: NumberLong(maxValue + 1)}).ok); - -// Verify invalid values are rejected. -assert.throws.automsg(function() { - t.find().maxTimeMS(0.1).itcount(); - }); -assert.throws.automsg(function() { - t.find().maxTimeMS(-0.1).itcount(); - }); -assert.throws.automsg(function() { - t.find().maxTimeMS().itcount(); - }); -assert.throws.automsg(function() { - t.find().maxTimeMS("").itcount(); - }); -assert.throws.automsg(function() { - t.find().maxTimeMS(true).itcount(); - }); -assert.throws.automsg(function() { - t.find().maxTimeMS({}).itcount(); - }); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: 0.1}).ok); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: -0.1}).ok); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: undefined}).ok); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: ""}).ok); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: true}).ok); -assert.eq(0, t.getDB().runCommand({ping: 1, maxTimeMS: {}}).ok); - -// Verify that the maxTimeMS command argument can be sent with $query-wrapped commands. -cursor = t.getDB().$cmd.find({ping: 1, maxTimeMS: 0}).limit(-1); -cursor._ensureSpecial(); -assert.eq(1, cursor.next().ok); - -// Verify that the server rejects invalid command argument $maxTimeMS. -cursor = t.getDB().$cmd.find({ping: 1, $maxTimeMS: 0}).limit(-1); -cursor._ensureSpecial(); -assert.eq(0, cursor.next().ok); - -// Verify that the $maxTimeMS query option can't be sent with $query-wrapped commands. -cursor = t.getDB().$cmd.find({ping: 1}).limit(-1).maxTimeMS(0); -cursor._ensureSpecial(); -assert.commandFailed(cursor.next()); - -// -// Tests for fail points maxTimeAlwaysTimeOut and maxTimeNeverTimeOut. -// - -// maxTimeAlwaysTimeOut positive test for command. -t.drop(); -try { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "alwaysOn"})); - res = t.getDB().runCommand({ping: 1, maxTimeMS: 10 * 1000}); - assert(res.ok == 0 && res.code == ErrorCodes.MaxTimeMSExpired, - "expected command to trigger maxTimeAlwaysTimeOut fail point, ok=" + res.ok + - ", code=" + res.code); -} finally { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "off"})); -} - -// maxTimeNeverTimeOut positive test for command. -t.drop(); -try { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeNeverTimeOut", mode: "alwaysOn"})); - res = t.getDB().adminCommand({sleep: 1, millis: 300, maxTimeMS: 100}); - assert(res.ok == 1, - "expected command to trigger maxTimeNeverTimeOut fail point, ok=" + res.ok + - ", code=" + res.code); -} finally { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeNeverTimeOut", mode: "off"})); -} - -// maxTimeAlwaysTimeOut positive test for query. -t.drop(); -try { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "alwaysOn"})); - assert.throws(function() { - t.find().maxTimeMS(10 * 1000).itcount(); - }, [], "expected query to trigger maxTimeAlwaysTimeOut fail point"); -} finally { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "off"})); -} - -// maxTimeNeverTimeOut positive test for query. -try { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeNeverTimeOut", mode: "alwaysOn"})); - t.drop(); - assert.commandWorked(t.insert([{}, {}, {}])); - cursor = t.find({ - $where: function() { - sleep(100); - return true; - } - }); - cursor.maxTimeMS(100); - assert.doesNotThrow(function() { - cursor.itcount(); - }, [], "expected query to trigger maxTimeNeverTimeOut fail point"); -} finally { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeNeverTimeOut", mode: "off"})); -} - -// maxTimeAlwaysTimeOut positive test for getmore. -t.drop(); -assert.commandWorked(t.insert([{}, {}, {}])); -cursor = t.find().maxTimeMS(10 * 1000).batchSize(2); -assert.doesNotThrow.automsg(function() { - cursor.next(); - cursor.next(); -}); -try { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "alwaysOn"})); - assert.throws(function() { - cursor.next(); - }, [], "expected getmore to trigger maxTimeAlwaysTimeOut fail point"); -} finally { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "off"})); -} - -// maxTimeNeverTimeOut positive test for getmore. -t.drop(); -assert.commandWorked(t.insert([{_id: 0}, {_id: 1}, {_id: 2}])); // fast batch -assert.commandWorked( - t.insert([{_id: 3, slow: true}, {_id: 4, slow: true}, {_id: 5, slow: true}])); // slow batch -cursor = t.find({ - $where: function() { - if (this.slow) { - sleep(2 * 1000); - } - return true; - } - }).sort({_id: 1}); -cursor.batchSize(3); -cursor.maxTimeMS(2 * 1000); -assert.doesNotThrow(function() { - cursor.next(); - cursor.next(); - cursor.next(); -}, [], "expected batch 1 (query) to not hit the time limit"); -try { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeNeverTimeOut", mode: "alwaysOn"})); - assert.doesNotThrow(function() { - cursor.next(); - cursor.next(); - cursor.next(); - }, [], "expected batch 2 (getmore) to trigger maxTimeNeverTimeOut fail point"); -} finally { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeNeverTimeOut", mode: "off"})); -} - -// -// Test that maxTimeMS is accepted by commands that have an option whitelist. -// - -// "aggregate" command. -res = t.runCommand("aggregate", {pipeline: [], cursor: {}, maxTimeMS: 60 * 1000}); -assert(res.ok == 1, - "expected aggregate with maxtime to succeed, ok=" + res.ok + ", code=" + res.code); - -// "collMod" command. -res = t.runCommand("collMod", {maxTimeMS: 60 * 1000}); -assert(res.ok == 1, - "expected collmod with maxtime to succeed, ok=" + res.ok + ", code=" + res.code); - -// "createIndexes" command. -assert.commandWorked( - t.runCommand("createIndexes", {indexes: [{key: {x: 1}, name: "x_1"}], maxTimeMS: 60 * 1000})); - -// -// test count shell helper SERVER-13334 -// -t.drop(); -try { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeNeverTimeOut", mode: "alwaysOn"})); - assert.doesNotThrow(function() { - t.find({}).maxTimeMS(1).count(); - }); -} finally { - assert.commandWorked( - t.getDB().adminCommand({configureFailPoint: "maxTimeNeverTimeOut", mode: "off"})); -}
\ No newline at end of file diff --git a/jstests/libs/parallelTester.js b/jstests/libs/parallelTester.js index d8238dca0b4..2a2a1576763 100644 --- a/jstests/libs/parallelTester.js +++ b/jstests/libs/parallelTester.js @@ -191,7 +191,6 @@ if (typeof _threadInject != "undefined") { "set_param1.js", // changes global state "geo_update_btree2.js", // SERVER-11132 test disables table scans "update_setOnInsert.js", // SERVER-9982 - "max_time_ms.js", // Sensitive to query execution time, by design "autocomplete.js", // Likewise. // This overwrites MinKey/MaxKey's singleton which breaks diff --git a/jstests/noPassthrough/max_time_ms.js b/jstests/noPassthrough/max_time_ms.js new file mode 100644 index 00000000000..851be0637d6 --- /dev/null +++ b/jstests/noPassthrough/max_time_ms.js @@ -0,0 +1,524 @@ +/* + * Tests query/command option $maxTimeMS. + + * Creates a sharded cluster. + * @tags: [requires_sharding] + */ +(function() { +"use strict"; + +load("jstests/libs/fixture_helpers.js"); // For runCommandOnEachPrimary(). + +function executeTest(db, isMongos) { + let cursor; + let error; + + const admin = db.getSiblingDB("admin"); + + function setFailPoint(fpCommand) { + if (isMongos) { + FixtureHelpers.runCommandOnEachPrimary({db: admin, cmdObj: fpCommand}); + } + + // Also set it on mongos (or if we're not connected to mongos, the primary). + assert.commandWorked(admin.runCommand(fpCommand)); + } + + // + // Simple positive test for query: a ~100 second query with a 100ms time limit should be + // aborted. + // + (function simplePositiveCase() { + const t = db.max_time_ms_simple_positive; + + assert.commandWorked(t.insert(Array.from({length: 1000}, _ => ({})))); + cursor = t.find({ + $where: function() { + sleep(100); + return true; + } + }); + cursor.maxTimeMS(100); + error = assert.throws(function() { + cursor.itcount(); + }, [], "expected query to abort due to time limit"); + // TODO SERVER-32565: The error should always be MaxTimeMSExpired, but there are rare cases + // where interrupting javascript execution on the server with a stepdown or timeout results + // in an error code of InternalError or Interrupted instead, so we also accept those here. + assert.commandFailedWithCode( + error, [ErrorCodes.MaxTimeMSExpired, ErrorCodes.Interrupted, ErrorCodes.InternalError]); + })(); + + // + // Simple negative test for query: a ~300ms query with a 10s time limit should not hit the time + // limit. + // + (function simpleNegative() { + const t = db.max_time_ms_simple_negative; + + assert.commandWorked(t.insert([{}, {}, {}])); + cursor = t.find({ + $where: function() { + sleep(100); + return true; + } + }); + cursor.maxTimeMS(10 * 1000); + assert.doesNotThrow(function() { + cursor.itcount(); + }, [], "expected query to not hit the time limit"); + })(); + + // + // Simple positive test for getmore: + // - Issue a find() that returns 2 batches: a fast batch, then a slow batch. + // - The find() has a 4-second time limit; the first batch should run "instantly", but the + // second + // batch takes ~15 seconds, so the getmore should be aborted. + // + (function simplePositiveGetMore() { + const t = db.max_time_ms_simple_positive_get_more; + + assert.commandWorked(t.insert([{_id: 0}, {_id: 1}, {_id: 2}])); // fast batch + assert.commandWorked(t.insert( + [{_id: 3, slow: true}, {_id: 4, slow: true}, {_id: 5, slow: true}])); // slow batch + cursor = t.find({ + $where: function() { + if (this.slow) { + sleep(5 * 1000); + } + return true; + } + }).sort({_id: 1}); + cursor.batchSize(3); + cursor.maxTimeMS(4 * 1000); + assert.doesNotThrow(function() { + cursor.next(); + cursor.next(); + cursor.next(); + }, [], "expected batch 1 (query) to not hit the time limit"); + error = assert.throws(function() { + cursor.next(); + cursor.next(); + cursor.next(); + }, [], "expected batch 2 (getmore) to abort due to time limit"); + // TODO SERVER-32565: The error should always be MaxTimeMSExpired, but there are rare cases + // where interrupting javascript execution on the server with a stepdown or timeout results + // in an error code of InternalError or Interrupted instead, so we also accept those here. + assert.commandFailedWithCode( + error, [ErrorCodes.MaxTimeMSExpired, ErrorCodes.Interrupted, ErrorCodes.InternalError]); + })(); + + // + // Simple negative test for getmore: + // - Issue a find() that returns 2 batches: a fast batch, then a slow batch. + // - The find() has a 10-second time limit; the first batch should run "instantly", and the + // second + // batch takes only ~2 seconds, so both the query and getmore should not hit the time limit. + // + (function simpleNegativeGetMore() { + const t = db.max_time_ms_simple_negative_get_more; + + assert.commandWorked(t.insert([{_id: 0}, {_id: 1}, {_id: 2}])); // fast batch + assert.commandWorked(t.insert([{_id: 3}, {_id: 4}, {_id: 5, slow: true}])); // slow batch + cursor = t.find({ + $where: function() { + if (this.slow) { + sleep(2 * 1000); + } + return true; + } + }).sort({_id: 1}); + cursor.batchSize(3); + cursor.maxTimeMS(10 * 1000); + assert.doesNotThrow(function() { + cursor.next(); + cursor.next(); + cursor.next(); + }, [], "expected batch 1 (query) to not hit the time limit"); + assert.doesNotThrow(function() { + cursor.next(); + cursor.next(); + cursor.next(); + }, [], "expected batch 2 (getmore) to not hit the time limit"); + })(); + + // + // Many-batch positive test for getmore: + // - Issue a many-batch find() with a 6-second time limit where the results take 10 seconds to + // generate; one of the later getmore ops should be aborted. + // + (function manyBatchPositiveGetMore() { + const t = db.max_time_ms_many_batch_positive_get_more; + + for (let i = 0; i < 5; i++) { + assert.commandWorked( + t.insert([{_id: 3 * i}, {_id: (3 * i) + 1}, {_id: (3 * i) + 2, slow: true}])); + } + cursor = t.find({ + $where: function() { + if (this.slow) { + sleep(2 * 1000); + } + return true; + } + }).sort({_id: 1}); + cursor.batchSize(3); + cursor.maxTimeMS(6 * 1000); + error = assert.throws(function() { + cursor.itcount(); + }, [], "expected find() to abort due to time limit"); + // TODO SERVER-32565: The error should always be MaxTimeMSExpired, but there are rare cases + // where interrupting javascript execution on the server with a stepdown or timeout results + // in an error code of InternalError or Interrupted instead, so we also accept those here. + assert.commandFailedWithCode( + error, [ErrorCodes.MaxTimeMSExpired, ErrorCodes.Interrupted, ErrorCodes.InternalError]); + })(); + + // + // Many-batch negative test for getmore: + // - Issue a many-batch find() with a 20-second time limit where the results take 10 seconds to + // generate; the find() should not hit the time limit. + // + (function manyBatchNegativeGetMore() { + const t = db.many_batch_negative_get_more; + for (var i = 0; i < 5; i++) { + assert.commandWorked( + t.insert([{_id: 3 * i}, {_id: (3 * i) + 1}, {_id: (3 * i) + 2, slow: true}])); + } + cursor = t.find({ + $where: function() { + if (this.slow) { + sleep(2 * 1000); + } + return true; + } + }).sort({_id: 1}); + cursor.batchSize(3); + cursor.maxTimeMS(20 * 1000); + assert.doesNotThrow(function() { + // SERVER-40305: Add some additional logging here in case this fails to help us track + // down why it failed. + assert.commandWorked(db.adminCommand({setParameter: 1, traceExceptions: 1})); + cursor.itcount(); + assert.commandWorked(db.adminCommand({setParameter: 1, traceExceptions: 0})); + }, [], "expected find() to not hit the time limit"); + })(); + + // + // Simple positive test for commands: a ~300ms command with a 100ms time limit should be + // aborted. + // + (function simplePositiveSleepCmd() { + if (isMongos) { + // Test-only sleep command is not supported on mongos. + return; + } + assert.commandFailedWithCode( + db.adminCommand({sleep: 1, millis: 300, maxTimeMS: 100, lock: "none"}), + ErrorCodes.MaxTimeMSExpired); + })(); + + // + // Simple negative test for commands: a ~300ms command with a 10s time limit should not hit the + // time limit. + // + (function simpleNegativeSleepCmd() { + if (isMongos) { + // Test-only sleep command is not supported on mongos. + return; + } + assert.commandWorked( + db.adminCommand({sleep: 1, millis: 300, maxTimeMS: 10 * 1000, lock: "none"})); + })(); + + // + // Tests for input validation. + // + (function checkValidation() { + const t = db.max_time_ms_validation; + assert.commandWorked(t.insert({})); + + // Verify lower boundary for acceptable input (0 is acceptable, 1 isn't). + assert.doesNotThrow.automsg(function() { + t.find().maxTimeMS(0).itcount(); + }); + assert.doesNotThrow.automsg(function() { + t.find().maxTimeMS(NumberInt(0)).itcount(); + }); + assert.doesNotThrow.automsg(function() { + t.find().maxTimeMS(NumberLong(0)).itcount(); + }); + assert.commandWorked(db.runCommand({ping: 1, maxTimeMS: 0})); + assert.commandWorked(db.runCommand({ping: 1, maxTimeMS: NumberInt(0)})); + assert.commandWorked(db.runCommand({ping: 1, maxTimeMS: NumberLong(0)})); + + assert.throws.automsg(function() { + t.find().maxTimeMS(-1).itcount(); + }); + assert.throws.automsg(function() { + t.find().maxTimeMS(NumberInt(-1)).itcount(); + }); + assert.throws.automsg(function() { + t.find().maxTimeMS(NumberLong(-1)).itcount(); + }); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: -1}), ErrorCodes.BadValue); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: NumberInt(-1)}), + ErrorCodes.BadValue); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: NumberLong(-1)}), + ErrorCodes.BadValue); + + // Verify upper boundary for acceptable input (2^31-1 is acceptable, 2^31 isn't). + + var maxValue = Math.pow(2, 31) - 1; + + assert.doesNotThrow.automsg(function() { + t.find().maxTimeMS(maxValue).itcount(); + }); + assert.doesNotThrow.automsg(function() { + t.find().maxTimeMS(NumberInt(maxValue)).itcount(); + }); + assert.doesNotThrow.automsg(function() { + t.find().maxTimeMS(NumberLong(maxValue)).itcount(); + }); + assert.commandWorked(db.runCommand({ping: 1, maxTimeMS: maxValue})); + assert.commandWorked(db.runCommand({ping: 1, maxTimeMS: NumberInt(maxValue)})); + assert.commandWorked(db.runCommand({ping: 1, maxTimeMS: NumberLong(maxValue)})); + + assert.throws.automsg(function() { + t.find().maxTimeMS(maxValue + 1).itcount(); + }); + assert.throws.automsg(function() { + t.find().maxTimeMS(NumberInt(maxValue + 1)).itcount(); + }); + assert.throws.automsg(function() { + t.find().maxTimeMS(NumberLong(maxValue + 1)).itcount(); + }); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: maxValue + 1}), + ErrorCodes.BadValue); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: NumberInt(maxValue + 1)}), + ErrorCodes.BadValue); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: NumberLong(maxValue + 1)}), + ErrorCodes.BadValue); + + // Verify invalid values are rejected. + assert.throws.automsg(function() { + t.find().maxTimeMS(0.1).itcount(); + }); + assert.throws.automsg(function() { + t.find().maxTimeMS(-0.1).itcount(); + }); + assert.throws.automsg(function() { + t.find().maxTimeMS().itcount(); + }); + assert.throws.automsg(function() { + t.find().maxTimeMS("").itcount(); + }); + assert.throws.automsg(function() { + t.find().maxTimeMS(true).itcount(); + }); + assert.throws.automsg(function() { + t.find().maxTimeMS({}).itcount(); + }); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: 0.1}), ErrorCodes.BadValue); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: -0.1}), + ErrorCodes.BadValue); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: undefined}), + ErrorCodes.BadValue); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: ""}), ErrorCodes.BadValue); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: true}), + ErrorCodes.BadValue); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: {}}), ErrorCodes.BadValue); + + // Verify that the maxTimeMS command argument can be sent with $query-wrapped commands. + cursor = t.getDB().$cmd.find({ping: 1, maxTimeMS: 0}).limit(-1); + cursor._ensureSpecial(); + assert.eq(1, cursor.next().ok); + + // Verify that the server rejects invalid command argument $maxTimeMS. + cursor = t.getDB().$cmd.find({ping: 1, $maxTimeMS: 0}).limit(-1); + cursor._ensureSpecial(); + assert.commandFailed(cursor.next()); + + // Verify that the $maxTimeMS query option can't be sent with $query-wrapped commands. + cursor = t.getDB().$cmd.find({ping: 1}).limit(-1).maxTimeMS(0); + cursor._ensureSpecial(); + assert.commandFailed(cursor.next()); + })(); + + // + // Tests for fail points maxTimeAlwaysTimeOut and maxTimeNeverTimeOut. + // + (function checkFailPointsWork() { + // maxTimeAlwaysTimeOut positive test for command. + const t = db.max_time_ms_always_time_out_fp; + try { + assert.commandWorked( + db.adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "alwaysOn"})); + assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: 10 * 1000}), + ErrorCodes.MaxTimeMSExpired); + } finally { + assert.commandWorked( + db.adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "off"})); + } + + // maxTimeNeverTimeOut positive test for command. Don't run on mongos because there's no + // sleep command. + if (!isMongos) { + try { + assert.commandWorked( + db.adminCommand({configureFailPoint: "maxTimeNeverTimeOut", mode: "alwaysOn"})); + assert.commandWorked( + db.adminCommand({sleep: 1, millis: 300, maxTimeMS: 100, lock: "none"})); + } finally { + assert.commandWorked( + db.adminCommand({configureFailPoint: "maxTimeNeverTimeOut", mode: "off"})); + } + } + + // maxTimeAlwaysTimeOut positive test for query. + try { + setFailPoint({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "alwaysOn"}); + + assert.throws(function() { + t.find().maxTimeMS(10 * 1000).itcount(); + }, [], "expected query to trigger maxTimeAlwaysTimeOut fail point"); + } finally { + setFailPoint({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "off"}); + } + + // maxTimeNeverTimeOut positive test for query. + try { + setFailPoint({configureFailPoint: "maxTimeNeverTimeOut", mode: "alwaysOn"}); + const coll = db.max_time_ms_never_time_out_positive_query; + assert.commandWorked(coll.insert([{}, {}, {}])); + cursor = coll.find({ + $where: function() { + sleep(100); + return true; + } + }); + cursor.maxTimeMS(100); + assert.doesNotThrow(function() { + cursor.itcount(); + }, [], "expected query to trigger maxTimeNeverTimeOut fail point"); + } finally { + setFailPoint({configureFailPoint: "maxTimeNeverTimeOut", mode: "off"}); + } + })(); + + // maxTimeAlwaysTimeOut positive test for getmore. + (function alwaysTimeOutPositiveTest() { + const coll = db.max_time_ms_always_time_out_positive_get_more; + assert.commandWorked(coll.insert([{}, {}, {}])); + cursor = coll.find().maxTimeMS(10 * 1000).batchSize(2); + assert.doesNotThrow.automsg(function() { + cursor.next(); + cursor.next(); + }); + try { + setFailPoint({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "alwaysOn"}); + assert.throws(function() { + cursor.next(); + }, [], "expected getmore to trigger maxTimeAlwaysTimeOut fail point"); + } finally { + setFailPoint({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "off"}); + } + })(); + + // maxTimeNeverTimeOut positive test for getmore. + (function neverTimeOutPositiveTest() { + const coll = db.max_time_ms_never_time_out_fp; + assert.commandWorked(coll.insert([{_id: 0}, {_id: 1}, {_id: 2}])); // fast batch + assert.commandWorked(coll.insert( + [{_id: 3, slow: true}, {_id: 4, slow: true}, {_id: 5, slow: true}])); // slow batch + cursor = coll.find({ + $where: function() { + if (this.slow) { + sleep(2 * 1000); + } + return true; + } + }) + .sort({_id: 1}); + cursor.batchSize(3); + cursor.maxTimeMS(2 * 1000); + assert.doesNotThrow(function() { + cursor.next(); + cursor.next(); + cursor.next(); + }, [], "expected batch 1 (query) to not hit the time limit"); + try { + setFailPoint({configureFailPoint: "maxTimeNeverTimeOut", mode: "alwaysOn"}); + + assert.doesNotThrow(function() { + cursor.next(); + cursor.next(); + cursor.next(); + }, [], "expected batch 2 (getmore) to trigger maxTimeNeverTimeOut fail point"); + } finally { + setFailPoint({configureFailPoint: "maxTimeNeverTimeOut", mode: "off"}); + } + })(); + + // + // Test that maxTimeMS is accepted by commands that have an option whitelist. + // + (function testCommandsWithOptionWhitelist() { + const t = db.max_time_ms_option_whitelist; + // The namespace must exist for collMod to work. + assert.commandWorked(t.insert({x: 1})); + + // "aggregate" command. + assert.commandWorked( + t.runCommand("aggregate", {pipeline: [], cursor: {}, maxTimeMS: 60 * 1000})); + + // "collMod" command. + assert.commandWorked(t.runCommand("collMod", {maxTimeMS: 60 * 1000})); + + // "createIndexes" command. + assert.commandWorked(t.runCommand( + "createIndexes", {indexes: [{key: {x: 1}, name: "x_1"}], maxTimeMS: 60 * 1000})); + })(); + + // + // Test count shell helper (see SERVER-13334). + // + (function testCountShellHelper() { + const t = db.max_time_ms_shell_helper; + try { + setFailPoint({configureFailPoint: "maxTimeNeverTimeOut", mode: "alwaysOn"}); + + assert.doesNotThrow(function() { + t.find({}).maxTimeMS(1).count(); + }); + } finally { + setFailPoint({configureFailPoint: "maxTimeNeverTimeOut", mode: "off"}); + } + })(); +} + +const enableTestCmd = { + setParameter: "enableTestCommands=1" +}; +(function runOnStandalone() { + const conn = MongoRunner.runMongod(enableTestCmd); + assert.neq(null, conn, "mongod was unable to start up"); + try { + executeTest(conn.getDB("test"), false); + } finally { + MongoRunner.stopMongod(conn); + } +})(); + +(function runSharded() { + const enableTestCmd = {setParameter: "enableTestCommands=1"}; + const st = new ShardingTest( + {shards: 2, other: {shardOptions: enableTestCmd, mongosOptions: enableTestCmd}}); + try { + executeTest(st.s.getDB("test"), true); + } finally { + st.stop(); + } +})(); +})(); |