diff options
33 files changed, 493 insertions, 458 deletions
diff --git a/buildscripts/resmokeconfig/suites/aggregation_facet_unwind_passthrough.yml b/buildscripts/resmokeconfig/suites/aggregation_facet_unwind_passthrough.yml index 02b5e483b17..40d248aa22d 100644 --- a/buildscripts/resmokeconfig/suites/aggregation_facet_unwind_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/aggregation_facet_unwind_passthrough.yml @@ -5,8 +5,6 @@ selector: - jstests/aggregation/bugs/*.js - jstests/aggregation/expressions/*.js - jstests/aggregation/sources/*/*.js - exclude_with_any_tags: - - do_not_wrap_aggregations_in_facets executor: js_test: diff --git a/buildscripts/resmokeconfig/suites/core.yml b/buildscripts/resmokeconfig/suites/core.yml index ea3f789e0e8..04a6f97cb7d 100644 --- a/buildscripts/resmokeconfig/suites/core.yml +++ b/buildscripts/resmokeconfig/suites/core.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js executor: js_test: diff --git a/buildscripts/resmokeconfig/suites/core_auth.yml b/buildscripts/resmokeconfig/suites/core_auth.yml index 56c40ce81ce..78cbad244e5 100644 --- a/buildscripts/resmokeconfig/suites/core_auth.yml +++ b/buildscripts/resmokeconfig/suites/core_auth.yml @@ -6,10 +6,10 @@ config_variables: selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: # Skip any tests that run with auth explicitly. - - jstests/core/*[aA]uth*.js + - jstests/core/**/*[aA]uth*.js executor: js_test: diff --git a/buildscripts/resmokeconfig/suites/core_compression.yml b/buildscripts/resmokeconfig/suites/core_compression.yml index 3c7ffefc984..d09716735da 100644 --- a/buildscripts/resmokeconfig/suites/core_compression.yml +++ b/buildscripts/resmokeconfig/suites/core_compression.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js executor: js_test: diff --git a/buildscripts/resmokeconfig/suites/core_ese.yml b/buildscripts/resmokeconfig/suites/core_ese.yml index b12f3c5be79..74ab7c9b195 100644 --- a/buildscripts/resmokeconfig/suites/core_ese.yml +++ b/buildscripts/resmokeconfig/suites/core_ese.yml @@ -5,7 +5,7 @@ config_variables: selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js executor: js_test: diff --git a/buildscripts/resmokeconfig/suites/core_minimum_batch_size.yml b/buildscripts/resmokeconfig/suites/core_minimum_batch_size.yml index 43f5c34b78d..085c32c8c29 100644 --- a/buildscripts/resmokeconfig/suites/core_minimum_batch_size.yml +++ b/buildscripts/resmokeconfig/suites/core_minimum_batch_size.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: # The following tests fail when specifying a minimal batchSize: - jstests/core/find9.js # Reduction of objsLeftInBatch. diff --git a/buildscripts/resmokeconfig/suites/core_op_query.yml b/buildscripts/resmokeconfig/suites/core_op_query.yml index de695c650b6..5ec056a57ff 100644 --- a/buildscripts/resmokeconfig/suites/core_op_query.yml +++ b/buildscripts/resmokeconfig/suites/core_op_query.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js executor: js_test: diff --git a/buildscripts/resmokeconfig/suites/core_small_oplog.yml b/buildscripts/resmokeconfig/suites/core_small_oplog.yml index 95cc6b24638..4af7ba65c02 100644 --- a/buildscripts/resmokeconfig/suites/core_small_oplog.yml +++ b/buildscripts/resmokeconfig/suites/core_small_oplog.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: # These tests are not expected to pass with master-slave: - jstests/core/dbadmin.js diff --git a/buildscripts/resmokeconfig/suites/core_small_oplog_rs.yml b/buildscripts/resmokeconfig/suites/core_small_oplog_rs.yml index c3c4bf06769..c89d0bd1020 100644 --- a/buildscripts/resmokeconfig/suites/core_small_oplog_rs.yml +++ b/buildscripts/resmokeconfig/suites/core_small_oplog_rs.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: # These tests are not expected to pass with replica-sets: - jstests/core/dbadmin.js diff --git a/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync.yml b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync.yml index 31dde7b0a84..c348c8f720e 100644 --- a/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync.yml +++ b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: # These tests are not expected to pass with replica-sets: - jstests/core/dbadmin.js diff --git a/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync_static.yml b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync_static.yml index f6440433bce..c15b23046a9 100644 --- a/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync_static.yml +++ b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync_static.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: # These tests are not expected to pass with replica-sets: - jstests/core/dbadmin.js diff --git a/buildscripts/resmokeconfig/suites/core_small_oplog_rs_resync.yml b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_resync.yml index f5ae15d9cc7..ca81bd3033d 100644 --- a/buildscripts/resmokeconfig/suites/core_small_oplog_rs_resync.yml +++ b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_resync.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: # These tests are not expected to pass with replica-sets: - jstests/core/dbadmin.js diff --git a/buildscripts/resmokeconfig/suites/core_small_oplog_rs_resync_static.yml b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_resync_static.yml index ca6c529b0ca..27fdbc8bed8 100644 --- a/buildscripts/resmokeconfig/suites/core_small_oplog_rs_resync_static.yml +++ b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_resync_static.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: # These tests are not expected to pass with replica-sets: - jstests/core/dbadmin.js diff --git a/buildscripts/resmokeconfig/suites/dur_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/dur_jscore_passthrough.yml index 24feea7e14b..347d23de967 100644 --- a/buildscripts/resmokeconfig/suites/dur_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/dur_jscore_passthrough.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: - jstests/core/repair*.js # Fails on recovery. - jstests/core/shellkillop.js # Takes forever and doesn't test anything new. diff --git a/buildscripts/resmokeconfig/suites/read_concern_majority_passthrough.yml b/buildscripts/resmokeconfig/suites/read_concern_majority_passthrough.yml index d5795e0c84d..1efc20ea6e0 100644 --- a/buildscripts/resmokeconfig/suites/read_concern_majority_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/read_concern_majority_passthrough.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: # Tests that won't work with an injected 'majority' readConcern # and/or an injected 'majority' writeConcern. Where a function is diff --git a/buildscripts/resmokeconfig/suites/sharded_collections_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/sharded_collections_jscore_passthrough.yml index 1d78d60e858..a67084a55eb 100644 --- a/buildscripts/resmokeconfig/suites/sharded_collections_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/sharded_collections_jscore_passthrough.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: # The following tests fail because a certain command or functionality is not supported by # mongos. This command or functionality is placed in a comment next to the failing test. @@ -64,6 +64,7 @@ selector: - jstests/core/dbcase2.js - jstests/core/no_db_created.js - jstests/core/ns_length.js + - jstests/core/views/*.js # Views tests aren't expected to work when collections are implicitly sharded. executor: js_test: diff --git a/buildscripts/resmokeconfig/suites/sharding_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/sharding_jscore_passthrough.yml index f2121d49d72..3b966ac4a71 100644 --- a/buildscripts/resmokeconfig/suites/sharding_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/sharding_jscore_passthrough.yml @@ -1,7 +1,7 @@ selector: js_test: roots: - - jstests/core/*.js + - jstests/core/**/*.js exclude_files: # The following tests fail because a certain command or functionality is not supported on # mongos. This command or functionality is placed in a comment next to the failing test. @@ -44,6 +44,9 @@ selector: # TODO: SERVER-18292 remove once OP_COMMAND is implemented in mongos. - jstests/core/invalid_db_name.js - jstests/core/validate_cmd_ns.js + - jstests/core/views/invalid_system_views.js # We expect listCollections to fail when there's an invalid view. + # TODO: SERVER-27269: mongos can't establish cursor if view has $collStats and views another view. + - jstests/core/views/views_coll_stats.js executor: js_test: diff --git a/etc/evergreen.yml b/etc/evergreen.yml index 676e8375fd7..ce49cc26192 100644 --- a/etc/evergreen.yml +++ b/etc/evergreen.yml @@ -445,6 +445,9 @@ functions: fi set -o errexit + # Combine the exclusion tags from both the variant and the task. + extra_args="$extra_args --excludeWithAnyTags=${task_excluded_tags},${variant_excluded_flags}" + path_value="$PATH" if [ ${variant_path_suffix} ]; then path_value="$path_value:${variant_path_suffix}" @@ -1496,6 +1499,7 @@ tasks: vars: resmoke_args: --suites=aggregation_facet_unwind_passthrough --storageEngine=wiredTiger run_multiple_jobs: true + task_excluded_tags: do_not_wrap_aggregations_in_facets - <<: *task_template name: aggregation_read_concern_majority_passthrough_WT @@ -1862,6 +1866,7 @@ tasks: vars: resmoke_args: --suites=core --shellReadMode=legacy --shellWriteMode=compatibility --storageEngine=mmapv1 run_multiple_jobs: true + task_excluded_tags: requires_find_command - <<: *task_template name: jsCore_compatibility_WT @@ -1873,6 +1878,7 @@ tasks: vars: resmoke_args: --suites=core --shellReadMode=legacy --shellWriteMode=compatibility --storageEngine=wiredTiger run_multiple_jobs: true + task_excluded_tags: requires_find_command - <<: *task_template name: jsCore_compression @@ -2087,8 +2093,9 @@ tasks: - func: "run tests" vars: task_path_suffix: /data/multiversion - resmoke_args: --suites=multiversion --storageEngine=mmapv1 --excludeWithAnyTags=requires_wiredtiger + resmoke_args: --suites=multiversion --storageEngine=mmapv1 run_multiple_jobs: true + task_excluded_tags: requires_wiredtiger - <<: *task_template name: multiversion_WT @@ -2098,8 +2105,9 @@ tasks: - func: "run tests" vars: task_path_suffix: /data/multiversion - resmoke_args: --suites=multiversion --storageEngine=wiredTiger --excludeWithAnyTags=requires_mmapv1 + resmoke_args: --suites=multiversion --storageEngine=wiredTiger run_multiple_jobs: true + task_excluded_tags: requires_mmapv1 - <<: *task_template name: multiversion_multistorage_engine @@ -2256,6 +2264,7 @@ tasks: vars: resmoke_args: --suites=sharding_jscore_passthrough --storageEngine=wiredTiger --shellReadMode=legacy --shellWriteMode=compatibility run_multiple_jobs: true + task_excluded_tags: requires_find_command - <<: *task_template name: parallel @@ -3515,7 +3524,8 @@ buildvariants: push_arch: x86_64 compile_flags: -j$(grep -c ^processor /proc/cpuinfo) CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy num_jobs_available: $(grep -c ^processor /proc/cpuinfo) - test_flags: --nojournal --excludeWithAnyTags=requires_journaling + test_flags: --nojournal + variant_excluded_flags: requires_journaling use_scons_cache: true build_mongoreplay: true tasks: @@ -4023,7 +4033,7 @@ buildvariants: push_arch: arm64-enterprise-ubuntu1604 compile_flags: --ssl MONGO_DISTMOD=ubuntu1604 -j$(grep -c ^processor /proc/cpuinfo) CCFLAGS="-march=armv8-a+crc -mtune=generic" --release CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy num_jobs_available: $(grep -c ^processor /proc/cpuinfo) - test_flags: --excludeWithAnyTags=requires_mmapv1 + variant_excluded_flags: requires_mmapv1 has_packages: true packager_script: packager-enterprise.py packager_arch: arm64 @@ -4099,7 +4109,7 @@ buildvariants: push_arch: arm64-ubuntu1604 compile_flags: --ssl MONGO_DISTMOD=ubuntu1604 -j$(grep -c ^processor /proc/cpuinfo) --release CCFLAGS="-march=armv8-a+crc -mtune=generic" CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy num_jobs_available: $(grep -c ^processor /proc/cpuinfo) - test_flags: --excludeWithAnyTags=requires_mmapv1 + variant_excluded_flags: requires_mmapv1 has_packages: true packager_script: packager.py packager_arch: arm64 @@ -4177,7 +4187,7 @@ buildvariants: push_arch: ppc64le-enterprise-ubuntu1604 compile_flags: --ssl MONGO_DISTMOD=ubuntu1604 -j$(echo "$(grep -c processor /proc/cpuinfo)/2" | bc) --release CCFLAGS="-mcpu=power8 -mtune=power8 -mcmodel=medium" CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy num_jobs_available: 2 - test_flags: --excludeWithAnyTags=requires_mmapv1 + variant_excluded_flags: requires_mmapv1 has_packages: true packager_script: packager-enterprise.py packager_arch: ppc64le @@ -4256,7 +4266,7 @@ buildvariants: push_arch: s390x-enterprise-ubuntu1604 compile_flags: --ssl MONGO_DISTMOD=ubuntu1604 --release -j$(grep -c ^processor /proc/cpuinfo) CCFLAGS="-march=z196 -mtune=zEC12" CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy num_jobs_available: 2 - test_flags: --excludeWithAnyTags=requires_mmapv1 + variant_excluded_flags: requires_mmapv1 has_packages: true packager_script: packager-enterprise.py packager_arch: s390x @@ -4997,7 +5007,8 @@ buildvariants: content_type: application/zip compile_flags: --release --ssl MONGO_DISTMOD=windows-64 CPPPATH="c:/openssl/include c:/sasl/include c:/snmp/include c:/curl/include" LIBPATH="c:/openssl/lib c:/sasl/lib c:/snmp/lib c:/curl/lib" -j$(( $(grep -c ^processor /proc/cpuinfo) / 2 )) --dynamic-windows --win-version-min=ws08r2 VARIANT_DIR=win32 num_jobs_available: $(grep -c ^processor /proc/cpuinfo) - test_flags: --storageEngine=inMemory --excludeWithAnyTags=requires_persistence,requires_journaling + test_flags: --storageEngine=inMemory + variant_excluded_flags: requires_persistence,requires_journaling ext: zip use_scons_cache: true tasks: @@ -6237,7 +6248,7 @@ buildvariants: # We need to compensate for SMT8 setting the cpu count very high and lower the amount of parallelism down compile_flags: --ssl MONGO_DISTMOD=rhel71 --release -j$(echo "$(grep -c processor /proc/cpuinfo)/2" | bc) CCFLAGS="-mcpu=power8 -mtune=power8 -mcmodel=medium" CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy num_jobs_available: $(echo "$(grep -c processor /proc/cpuinfo)/4" | bc) - test_flags: --excludeWithAnyTags=requires_mmapv1 + variant_excluded_flags: requires_mmapv1 has_packages: true packager_script: packager-enterprise.py packager_arch: ppc64le @@ -6374,7 +6385,7 @@ buildvariants: tooltags: -gccgoflags "$(pkg-config --libs --cflags libssl libsasl2)" -tags 'sasl ssl' compile_flags: --ssl MONGO_DISTMOD=rhel72 --release -j3 CCFLAGS="-march=z196 -mtune=zEC12" CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy num_jobs_available: 2 - test_flags: --excludeWithAnyTags=requires_mmapv1 + variant_excluded_flags: requires_mmapv1 has_packages: true packager_script: packager-enterprise.py packager_arch: s390x @@ -6780,7 +6791,7 @@ buildvariants: push_arch: s390x-enterprise-suse12 compile_flags: --ssl MONGO_DISTMOD=suse12 --release -j$(( $(grep -c ^processor /proc/cpuinfo) / 2 )) CCFLAGS="-march=z196 -mtune=zEC12" CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy num_jobs_available: $(grep -c ^processor /proc/cpuinfo) - test_flags: --excludeWithAnyTags=requires_mmapv1 + variant_excluded_flags: requires_mmapv1 has_packages: true packager_script: packager-enterprise.py packager_arch: s390x @@ -7051,7 +7062,7 @@ buildvariants: push_arch: s390x-enterprise-suse11 compile_flags: --ssl MONGO_DISTMOD=suse11 --release -j$(grep -c ^processor /proc/cpuinfo) CCFLAGS="-march=z196 -mtune=zEC12" CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy --use-s390x-crc32=off num_jobs_available: $(grep -c ^processor /proc/cpuinfo) - test_flags: --excludeWithAnyTags=requires_mmapv1 + variant_excluded_flags: requires_mmapv1 has_packages: true packager_script: packager-enterprise.py packager_arch: s390x @@ -7723,9 +7734,10 @@ buildvariants: gorootvars: GOROOT=/opt/go PATH="/opt/go/bin:$PATH" tooltags: "-tags 'ssl sasl'" rlp_environment: MONGOD_UNITTEST_RLP_LANGUAGE_TEST_BTROOT=/opt/basis - test_flags: --storageEngine=inMemory --excludeWithAnyTags=requires_persistence,requires_journaling + test_flags: --storageEngine=inMemory compile_flags: --ssl MONGO_DISTMOD=rhel62 -j$(grep -c ^processor /proc/cpuinfo) CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy CPPPATH="/opt/basis/rlp/rlp/include /opt/basis/rlp/utilities/include" --use-basis-tech-rosette-linguistics-platform=on num_jobs_available: $(grep -c ^processor /proc/cpuinfo) + variant_excluded_flags: requires_persistence,requires_journaling use_scons_cache: true build_mongoreplay: true tasks: @@ -7806,9 +7818,10 @@ buildvariants: - rhel62-small batchtime: 1440 # 1 day expansions: - test_flags: --storageEngine=ephemeralForTest --excludeWithAnyTags=requires_persistence,requires_fsync,SERVER-21420,SERVER-21658,requires_journaling + test_flags: --storageEngine=ephemeralForTest compile_flags: -j$(grep -c ^processor /proc/cpuinfo) --dbg=off --opt=on CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy num_jobs_available: $(grep -c ^processor /proc/cpuinfo) + variant_excluded_flags: requires_persistence,requires_fsync,SERVER-21420,SERVER-21658,requires_journaling use_scons_cache: true build_mongoreplay: true tasks: @@ -7892,7 +7905,8 @@ buildvariants: # We need to compensate for SMT8 setting the cpu count very high and lower the amount of parallelism down compile_flags: --dbg=on --opt=on --ssl MONGO_DISTMOD=rhel71 -j$(echo "$(grep -c processor /proc/cpuinfo)/2" | bc) CCFLAGS="-mcpu=power8 -mtune=power8 -mcmodel=medium" CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy num_jobs_available: $(echo "$(grep -c processor /proc/cpuinfo)/4" | bc) - test_flags: --storageEngine=inMemory --excludeWithAnyTags=requires_persistence,requires_mmapv1,requires_journaling + test_flags: --storageEngine=inMemory + variant_excluded_flags: requires_persistence,requires_mmapv1,requires_journaling build_mongoreplay: true tasks: - name: compile @@ -7970,7 +7984,8 @@ buildvariants: tooltags: -gccgoflags "$(pkg-config --libs --cflags libssl libsasl2)" -tags 'sasl ssl' compile_flags: --dbg=on --opt=on --ssl --link-model=static MONGO_DISTMOD=rhel72 -j3 CCFLAGS="-march=z196 -mtune=zEC12" CC=/opt/mongodbtoolchain/v2/bin/gcc CXX=/opt/mongodbtoolchain/v2/bin/g++ OBJCOPY=/opt/mongodbtoolchain/v2/bin/objcopy num_jobs_available: 2 - test_flags: --storageEngine=inMemory --excludeWithAnyTags=requires_persistence,requires_mmapv1,requires_journaling + test_flags: --storageEngine=inMemory + variant_excluded_flags: requires_persistence,requires_mmapv1,requires_journaling build_mongoreplay: true tasks: - name: compile diff --git a/jstests/views/invalid_system_views.js b/jstests/core/views/invalid_system_views.js index d02c9c3e61e..14b8b49a2b7 100644 --- a/jstests/views/invalid_system_views.js +++ b/jstests/core/views/invalid_system_views.js @@ -105,12 +105,12 @@ } let badViews = [ - {_id: "badview", pipeline: "bad"}, - {_id: "badview", pipeline: {}}, - {_id: "badview", pipeline: 7}, - {_id: "badview", pipeline: [1]}, - {_id: "badview", pipeline: [{}]}, - {_id: "badview", pipeline: [[]]}, + {_id: "badViewStringPipeline", pipeline: "bad"}, + {_id: "badViewEmptyObjectPipeline", pipeline: {}}, + {_id: "badViewNumericalPipeline", pipeline: 7}, + {_id: "badViewArrayWithIntegerPipeline", pipeline: [1]}, + {_id: "badViewArrayWithEmptyObjectPipeline", pipeline: [{}]}, + {_id: "badViewArrayWithEmptyArrayPipeline", pipeline: [[]]}, {_id: 7, pipeline: []}, ]; badViews.forEach(runTest); diff --git a/jstests/views/views_aggregation.js b/jstests/core/views/views_aggregation.js index 5a9c010be43..8da8df5c27f 100644 --- a/jstests/views/views_aggregation.js +++ b/jstests/core/views/views_aggregation.js @@ -1,4 +1,7 @@ -// Tests aggregation on views for proper pipeline concatenation and semantics. +/** + * Tests aggregation on views for proper pipeline concatenation and semantics. + * @tags: [requires_find_command] + */ (function() { "use strict"; @@ -72,6 +75,58 @@ // Test that the $out stage errors when given a view namespace. assertErrorCode(coll, [{$out: "emptyPipelineView"}], 18631); + // Test that an aggregate on a view propagates the 'bypassDocumentValidation' option. + const validatedCollName = "collectionWithValidator"; + viewsDB[validatedCollName].drop(); + assert.commandWorked( + viewsDB.createCollection(validatedCollName, {validator: {illegalField: {$exists: false}}})); + + viewsDB.invalidDocs.drop(); + viewsDB.invalidDocsView.drop(); + assert.writeOK(viewsDB.invalidDocs.insert({illegalField: "present"})); + assert.commandWorked(viewsDB.createView("invalidDocsView", "invalidDocs", [])); + + assert.commandWorked( + viewsDB.runCommand({ + aggregate: "invalidDocsView", + pipeline: [{$out: validatedCollName}], + bypassDocumentValidation: true + }), + "Expected $out insertions to succeed since 'bypassDocumentValidation' was specified"); + + // Test that an aggregate on a view propagates the 'allowDiskUse' option. + const extSortLimit = 100 * 1024 * 1024; + const largeStrSize = 10 * 1024 * 1024; + const largeStr = new Array(largeStrSize).join('x'); + viewsDB.largeColl.drop(); + for (let i = 0; i <= extSortLimit / largeStrSize; ++i) { + assert.writeOK(viewsDB.largeColl.insert({x: i, largeStr: largeStr})); + } + assertErrorCode(viewsDB.largeColl, + [{$sort: {x: -1}}], + 16819, + "Expected in-memory sort to fail due to excessive memory usage"); + viewsDB.largeView.drop(); + assert.commandWorked(viewsDB.createView("largeView", "largeColl", [])); + assertErrorCode(viewsDB.largeView, + [{$sort: {x: -1}}], + 16819, + "Expected in-memory sort to fail due to excessive memory usage"); + + assert.commandWorked( + viewsDB.runCommand( + {aggregate: "largeView", pipeline: [{$sort: {x: -1}}], allowDiskUse: true}), + "Expected aggregate to succeed since 'allowDiskUse' was specified"); + + // The remaining tests involve $lookup and $graphLookup. We cannot lookup into sharded + // collections, so skip these tests if running in a sharded configuration. + let isMasterResponse = assert.commandWorked(viewsDB.runCommand("isMaster")); + const isMongos = (isMasterResponse.msg === "isdbgrid"); + if (isMongos) { + jsTest.log("Tests are being run on a mongos; skipping all $lookup and $graphLookup tests."); + return; + } + // Test that the $lookup stage resolves the view namespace referenced in the 'from' field. assertAggResultEq( coll.getName(), @@ -161,46 +216,4 @@ [{$facet: {nested: graphLookupPipeline}}], [{nested: [{_id: "New York", matchedId1: "New York", matchedId2: "New York"}]}]); - // Test that an aggregate on a view propagates the 'bypassDocumentValidation' option. - const validatedCollName = "collectionWithValidator"; - viewsDB[validatedCollName].drop(); - assert.commandWorked( - viewsDB.createCollection(validatedCollName, {validator: {illegalField: {$exists: false}}})); - - viewsDB.invalidDocs.drop(); - viewsDB.invalidDocsView.drop(); - assert.writeOK(viewsDB.invalidDocs.insert({illegalField: "present"})); - assert.commandWorked(viewsDB.createView("invalidDocsView", "invalidDocs", [])); - - assert.commandWorked( - viewsDB.runCommand({ - aggregate: "invalidDocsView", - pipeline: [{$out: validatedCollName}], - bypassDocumentValidation: true - }), - "Expected $out insertions to succeed since 'bypassDocumentValidation' was specified"); - - // Test that an aggregate on a view propagates the 'allowDiskUse' option. - const extSortLimit = 100 * 1024 * 1024; - const largeStrSize = 10 * 1024 * 1024; - const largeStr = new Array(largeStrSize).join('x'); - viewsDB.largeColl.drop(); - for (let i = 0; i <= extSortLimit / largeStrSize; ++i) { - assert.writeOK(viewsDB.largeColl.insert({x: i, largeStr: largeStr})); - } - assertErrorCode(viewsDB.largeColl, - [{$sort: {x: -1}}], - 16819, - "Expected in-memory sort to fail due to excessive memory usage"); - viewsDB.largeView.drop(); - assert.commandWorked(viewsDB.createView("largeView", "largeColl", [])); - assertErrorCode(viewsDB.largeView, - [{$sort: {x: -1}}], - 16819, - "Expected in-memory sort to fail due to excessive memory usage"); - - assert.commandWorked( - viewsDB.runCommand( - {aggregate: "largeView", pipeline: [{$sort: {x: -1}}], allowDiskUse: true}), - "Expected aggregate to succeed since 'allowDiskUse' was specified"); }()); diff --git a/jstests/views/views_all_commands.js b/jstests/core/views/views_all_commands.js index 8511a263ea7..e4c44e4a223 100644 --- a/jstests/views/views_all_commands.js +++ b/jstests/core/views/views_all_commands.js @@ -334,9 +334,6 @@ "mapreduce.shardedfinish": {skip: isAnInternalCommand}, mergeChunks: { command: {mergeChunks: "test.view", bounds: [{x: 0}, {x: 10}]}, - setup: function(conn) { - assert.commandWorked(conn.adminCommand({enableSharding: "test"})); - }, skipStandalone: true, isAdminCommand: true, expectFailure: true, @@ -344,9 +341,6 @@ }, moveChunk: { command: {moveChunk: "test.view"}, - setup: function(conn) { - assert.commandWorked(conn.adminCommand({enableSharding: "test"})); - }, skipStandalone: true, isAdminCommand: true, expectFailure: true, @@ -372,12 +366,14 @@ isAdminCommand: true, command: {renameCollection: "test.view", to: "test.otherview"}, expectFailure: true, + skipSharded: true, }, { isAdminCommand: true, command: {renameCollection: "test.collection", to: "test.view"}, expectFailure: true, expectedErrorCode: ErrorCodes.NamespaceExists, + skipSharded: true, } ], repairCursor: {command: {repairCursor: "view"}, expectFailure: true}, @@ -438,9 +434,6 @@ sleep: {skip: isUnrelated}, split: { command: {split: "test.view", find: {_id: 1}}, - setup: function(conn) { - assert.commandWorked(conn.adminCommand({enableSharding: "test"})); - }, skipStandalone: true, expectFailure: true, expectedErrorCode: ErrorCodes.NamespaceNotSharded, @@ -511,89 +504,79 @@ assert.commandFailed(res, msg); }; - function runTests(db) { - // Are we on a mongos? - var isMaster = db.runCommand("ismaster"); - assert.commandWorked(isMaster); - var isMongos = (isMaster.msg === "isdbgrid"); + // Are we on a mongos? + var isMaster = db.runCommand("ismaster"); + assert.commandWorked(isMaster); + var isMongos = (isMaster.msg === "isdbgrid"); - // Obtain a list of all commands. - let res = db.runCommand({listCommands: 1}); - assert.commandWorked(res); + // Obtain a list of all commands. + let res = db.runCommand({listCommands: 1}); + assert.commandWorked(res); - let commands = Object.keys(res.commands); - for (let command of commands) { - let test = viewsCommandTests[command]; - assert(test !== undefined, - "Coverage failure: must explicitly define a views test for " + command); + let commands = Object.keys(res.commands); + for (let command of commands) { + let test = viewsCommandTests[command]; + assert(test !== undefined, + "Coverage failure: must explicitly define a views test for " + command); - if (!(test instanceof Array)) - test = [test]; - let subtest_nr = 0; - for (let subtest of test) { - // Tests can be explicitly skipped. Print the name of the skipped test, as well as - // the reason why. - if (subtest.skip !== undefined) { - print("Skipping " + command + ": " + subtest.skip); - continue; - } + if (!(test instanceof Array)) + test = [test]; + let subtest_nr = 0; + for (let subtest of test) { + // Tests can be explicitly skipped. Print the name of the skipped test, as well as + // the reason why. + if (subtest.skip !== undefined) { + print("Skipping " + command + ": " + subtest.skip); + continue; + } - let dbHandle = db.getSiblingDB("test"); - let commandHandle = dbHandle; + let dbHandle = db.getSiblingDB("test"); + let commandHandle = dbHandle; - // Skip tests depending on sharding configuration. - if (subtest.skipSharded && isMongos) { - print("Skipping " + command + ": not applicable to mongoS"); - continue; - } + // Skip tests depending on sharding configuration. + if (subtest.skipSharded && isMongos) { + print("Skipping " + command + ": not applicable to mongoS"); + continue; + } - if (subtest.skipStandalone && !isMongos) { - print("Skipping " + command + ": not applicable to mongoD"); - continue; - } + if (subtest.skipStandalone && !isMongos) { + print("Skipping " + command + ": not applicable to mongoD"); + continue; + } - // Perform test setup, and call any additional setup callbacks provided by the test. - // All tests assume that there exists a view named 'view' that is backed by - // 'collection'. - assert.commandWorked(dbHandle.dropDatabase()); - assert.commandWorked(dbHandle.runCommand({create: "view", viewOn: "collection"})); - assert.writeOK(dbHandle.collection.insert({x: 1})); - if (subtest.setup !== undefined) - subtest.setup(dbHandle); + // Perform test setup, and call any additional setup callbacks provided by the test. + // All tests assume that there exists a view named 'view' that is backed by + // 'collection'. + assert.commandWorked(dbHandle.dropDatabase()); + assert.commandWorked(dbHandle.runCommand({create: "view", viewOn: "collection"})); + assert.writeOK(dbHandle.collection.insert({x: 1})); + if (subtest.setup !== undefined) + subtest.setup(dbHandle); - // Execute the command. Print the command name for the first subtest, as otherwise - // it may be hard to figure out what command caused a failure. - if (!subtest_nr++) - print("Testing " + command); + // Execute the command. Print the command name for the first subtest, as otherwise + // it may be hard to figure out what command caused a failure. + if (!subtest_nr++) + print("Testing " + command); - if (subtest.isAdminCommand) - commandHandle = db.getSiblingDB("admin"); + if (subtest.isAdminCommand) + commandHandle = db.getSiblingDB("admin"); - if (subtest.expectFailure) { - let expectedErrorCode = subtest.expectedErrorCode; - if (expectedErrorCode === undefined) - expectedErrorCode = ErrorCodes.CommandNotSupportedOnView; + if (subtest.expectFailure) { + let expectedErrorCode = subtest.expectedErrorCode; + if (expectedErrorCode === undefined) + expectedErrorCode = ErrorCodes.CommandNotSupportedOnView; - assertCommandOrWriteFailed(commandHandle.runCommand(subtest.command), - expectedErrorCode, - tojson(subtest.command)); - } else if (subtest.command instanceof Function) - subtest.command(commandHandle); - else - assert.commandWorked(commandHandle.runCommand(subtest.command), - tojson(subtest.command)); + assertCommandOrWriteFailed(commandHandle.runCommand(subtest.command), + expectedErrorCode, + tojson(subtest.command)); + } else if (subtest.command instanceof Function) + subtest.command(commandHandle); + else + assert.commandWorked(commandHandle.runCommand(subtest.command), + tojson(subtest.command)); - if (subtest.teardown !== undefined) - subtest.teardown(dbHandle); - } + if (subtest.teardown !== undefined) + subtest.teardown(dbHandle); } } - - // Run tests against mongoD. - runTests(db.getSiblingDB("test")); - - // Run tests against mongoS. - var st = new ShardingTest({shards: 2}); - runTests(st.s.getDB("test")); - st.stop(); }()); diff --git a/jstests/views/views_basic.js b/jstests/core/views/views_basic.js index d6032b105df..d6032b105df 100644 --- a/jstests/views/views_basic.js +++ b/jstests/core/views/views_basic.js diff --git a/jstests/views/views_change.js b/jstests/core/views/views_change.js index be39afe3fc1..002284095c5 100644 --- a/jstests/views/views_change.js +++ b/jstests/core/views/views_change.js @@ -1,5 +1,7 @@ -// Tests the behavior of views when the backing view or collection is changed. - +/** + * Tests the behavior of views when the backing view or collection is changed. + * @tags: [requires_find_command] + */ (function() { "use strict"; @@ -25,18 +27,46 @@ let assertFindResultEq = function(collName, expected) { let res = viewDB.runCommand({find: collName, filter: {}, projection: {_id: 0, a: 1, b: 1}}); assert.commandWorked(res); - let cursor = new DBCommandCursor(db.getMongo(), res); - assert(arrayEq(cursor.toArray(), expected)); + let arr = new DBCommandCursor(db.getMongo(), res).toArray(); + let errmsg = tojson({expected: expected, got: arr}); + assert(arrayEq(arr, expected), errmsg); }; let doc = {a: 1, b: 1}; resetCollectionAndViews(); + // A view is updated when its viewOn is modified. When auth is enabled, we expect collMod to + // fail when specifying "viewOn" but not "pipeline". + assert.writeOK(collection.insert(doc)); + assertFindResultEq("view", [doc]); + let res = viewDB.runCommand({collMod: "view", viewOn: "nonexistent"}); + if (jsTest.options().auth) { + assert.commandFailedWithCode(res, ErrorCodes.InvalidOptions); + } else { + assert.commandWorked(res); + assertFindResultEq("view", []); + } + + resetCollectionAndViews(); + + // A view is updated when its pipeline is modified. When auth is enabled, we expect collMod to + // fail when specifying "pipeline" but not "viewOn". + assert.writeOK(collection.insert(doc)); + assert.writeOK(collection.insert({a: 7})); + assertFindResultEq("view", [doc]); + res = viewDB.runCommand({collMod: "view", pipeline: [{$match: {a: {$gt: 4}}}]}); + if (jsTest.options().auth) { + assert.commandFailedWithCode(res, ErrorCodes.InvalidOptions); + } else { + assert.commandWorked(res); + assertFindResultEq("view", [{a: 7}]); + } + + resetCollectionAndViews(); + // A view is updated when the backing collection is updated. assert.writeOK(collection.insert(doc)); - printjson(viewDB.collection.find().toArray()); - printjson(viewDB.view.find().toArray()); assertFindResultEq("view", [doc]); assert.writeOK(collection.update({a: 1}, {$set: {a: 2}})); assertFindResultEq("view", []); @@ -46,8 +76,8 @@ // A view is updated when a backing view is updated. assert.writeOK(collection.insert(doc)); assertFindResultEq("viewOnView", [doc]); - assert.commandWorked( - viewDB.runCommand({collMod: "view", pipeline: [{$match: {nonexistent: 1}}]})); + assert.commandWorked(viewDB.runCommand( + {collMod: "view", viewOn: "collection", pipeline: [{$match: {nonexistent: 1}}]})); assertFindResultEq("viewOnView", []); resetCollectionAndViews(); diff --git a/jstests/views/views_coll_stats.js b/jstests/core/views/views_coll_stats.js index 384fa17c015..384fa17c015 100644 --- a/jstests/views/views_coll_stats.js +++ b/jstests/core/views/views_coll_stats.js diff --git a/jstests/core/views/views_collation.js b/jstests/core/views/views_collation.js new file mode 100644 index 00000000000..9e4ed7feb30 --- /dev/null +++ b/jstests/core/views/views_collation.js @@ -0,0 +1,256 @@ +/** + * Tests the behavior of operations when interacting with a view's default collation. + */ +(function() { + "use strict"; + + let viewsDB = db.getSiblingDB("views_collation"); + assert.commandWorked(viewsDB.dropDatabase()); + assert.commandWorked(viewsDB.runCommand({create: "simpleCollection"})); + assert.commandWorked(viewsDB.runCommand({create: "ukCollection", collation: {locale: "uk"}})); + assert.commandWorked(viewsDB.runCommand({create: "filCollection", collation: {locale: "fil"}})); + + // Creating a view without specifying a collation defaults to the simple collation. + assert.commandWorked(viewsDB.runCommand({create: "simpleView", viewOn: "ukCollection"})); + let listCollectionsOutput = viewsDB.runCommand({listCollections: 1, filter: {type: "view"}}); + assert.commandWorked(listCollectionsOutput); + assert(!listCollectionsOutput.cursor.firstBatch[0].options.hasOwnProperty("collation")); + + // Operations that do not specify a collation succeed. + assert.commandWorked(viewsDB.runCommand({aggregate: "simpleView", pipeline: []})); + assert.commandWorked(viewsDB.runCommand({find: "simpleView"})); + assert.commandWorked(viewsDB.runCommand({count: "simpleView"})); + assert.commandWorked(viewsDB.runCommand({distinct: "simpleView", key: "x"})); + + // Operations that explicitly ask for the "simple" locale succeed against a view with the + // simple collation. + assert.commandWorked( + viewsDB.runCommand({aggregate: "simpleView", pipeline: [], collation: {locale: "simple"}})); + assert.commandWorked(viewsDB.runCommand({find: "simpleView", collation: {locale: "simple"}})); + assert.commandWorked(viewsDB.runCommand({count: "simpleView", collation: {locale: "simple"}})); + assert.commandWorked( + viewsDB.runCommand({distinct: "simpleView", key: "x", collation: {locale: "simple"}})); + + // Attempting to override a view's simple collation fails. + assert.commandFailedWithCode( + viewsDB.runCommand({aggregate: "simpleView", pipeline: [], collation: {locale: "en"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand({find: "simpleView", collation: {locale: "fr"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand({count: "simpleView", collation: {locale: "fil"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand({distinct: "simpleView", key: "x", collation: {locale: "es"}}), + ErrorCodes.OptionNotSupportedOnView); + + // Create a view with an explicit, non-simple collation. + assert.commandWorked( + viewsDB.createView("filView", "ukCollection", [], {collation: {locale: "fil"}})); + listCollectionsOutput = viewsDB.runCommand({listCollections: 1, filter: {name: "filView"}}); + assert.commandWorked(listCollectionsOutput); + assert.eq(listCollectionsOutput.cursor.firstBatch[0].options.collation.locale, "fil"); + + // Operations that do not specify a collation succeed. + assert.commandWorked(viewsDB.runCommand({aggregate: "filView", pipeline: []})); + assert.commandWorked(viewsDB.runCommand({find: "filView"})); + assert.commandWorked(viewsDB.runCommand({count: "filView"})); + assert.commandWorked(viewsDB.runCommand({distinct: "filView", key: "x"})); + + // Operations with a matching collation succeed. + assert.commandWorked( + viewsDB.runCommand({aggregate: "filView", pipeline: [], collation: {locale: "fil"}})); + assert.commandWorked(viewsDB.runCommand({find: "filView", collation: {locale: "fil"}})); + assert.commandWorked(viewsDB.runCommand({count: "filView", collation: {locale: "fil"}})); + assert.commandWorked( + viewsDB.runCommand({distinct: "filView", key: "x", collation: {locale: "fil"}})); + + // Attempting to override the non-simple default collation of a view fails. + assert.commandFailedWithCode( + viewsDB.runCommand({aggregate: "filView", pipeline: [], collation: {locale: "en"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand({aggregate: "filView", pipeline: [], collation: {locale: "simple"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode(viewsDB.runCommand({find: "filView", collation: {locale: "fr"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand({find: "filView", collation: {locale: "simple"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode(viewsDB.runCommand({count: "filView", collation: {locale: "zh"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand({count: "filView", collation: {locale: "simple"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand({distinct: "filView", key: "x", collation: {locale: "es"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand({distinct: "filView", key: "x", collation: {locale: "simple"}}), + ErrorCodes.OptionNotSupportedOnView); + + const lookupSimpleView = { + $lookup: {from: "simpleView", localField: "x", foreignField: "x", as: "result"} + }; + const graphLookupSimpleView = { + $graphLookup: { + from: "simpleView", + startWith: "$_id", + connectFromField: "_id", + connectToField: "matchedId", + as: "matched" + } + }; + + // You can lookup into a view with the simple collation if the collection also has the same + // default collation. + assert.commandWorked( + viewsDB.runCommand({aggregate: "simpleCollection", pipeline: [lookupSimpleView]})); + assert.commandWorked( + viewsDB.runCommand({aggregate: "simpleCollection", pipeline: [graphLookupSimpleView]})); + + // You can lookup into a view with the simple collation if the operation has a matching + // collation. + assert.commandWorked(viewsDB.runCommand( + {aggregate: "ukCollection", pipeline: [lookupSimpleView], collation: {locale: "simple"}})); + assert.commandWorked(viewsDB.runCommand({ + aggregate: "ukCollection", + pipeline: [graphLookupSimpleView], + collation: {locale: "simple"} + })); + + // You can't lookup into a view with the simple collation if the operation has a conflicting + // collation. + assert.commandFailedWithCode(viewsDB.runCommand({ + aggregate: "simpleCollection", + pipeline: [lookupSimpleView], + collation: {locale: "en"} + }), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode(viewsDB.runCommand({ + aggregate: "simpleCollection", + pipeline: [graphLookupSimpleView], + collation: {locale: "zh"} + }), + ErrorCodes.OptionNotSupportedOnView); + + const lookupFilView = { + $lookup: {from: "filView", localField: "x", foreignField: "x", as: "result"} + }; + const graphLookupFilView = { + $graphLookup: { + from: "filView", + startWith: "$_id", + connectFromField: "_id", + connectToField: "matchedId", + as: "matched" + } + }; + + // You can lookup into a view with no operation collation specified if the collection's + // collation matches the collation of the view. + assert.commandWorked( + viewsDB.runCommand({aggregate: "filCollection", pipeline: [lookupFilView]})); + assert.commandWorked( + viewsDB.runCommand({aggregate: "filCollection", pipeline: [graphLookupFilView]})); + + // You can lookup into a view with a non-simple collation if the operation's collation + // matches. + assert.commandWorked(viewsDB.runCommand( + {aggregate: "ukCollection", pipeline: [lookupFilView], collation: {locale: "fil"}})); + assert.commandWorked(viewsDB.runCommand( + {aggregate: "ukCollection", pipeline: [graphLookupFilView], collation: {locale: "fil"}})); + + // You can't lookup into a view when aggregating a collection whose default collation does + // not match the view's default collation. + assert.commandFailedWithCode( + viewsDB.runCommand({aggregate: "simpleCollection", pipeline: [lookupFilView]}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand({aggregate: "simpleCollection", pipeline: [graphLookupFilView]}), + ErrorCodes.OptionNotSupportedOnView); + + // You can't lookup into a view when aggregating a collection and the operation's collation + // does not match the view's default collation. + assert.commandFailedWithCode( + viewsDB.runCommand( + {aggregate: "filCollection", pipeline: [lookupFilView], collation: {locale: "zh"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode(viewsDB.runCommand({ + aggregate: "filCollection", + pipeline: [graphLookupFilView], + collation: {locale: "zh"} + }), + ErrorCodes.OptionNotSupportedOnView); + + // You may perform an aggregation involving multiple views if they all have the same default + // collation. + assert.commandWorked(viewsDB.runCommand( + {create: "simpleView2", viewOn: "simpleCollection", collation: {locale: "simple"}})); + assert.commandWorked( + viewsDB.runCommand({aggregate: "simpleView2", pipeline: [lookupSimpleView]})); + assert.commandWorked( + viewsDB.runCommand({aggregate: "simpleView2", pipeline: [graphLookupSimpleView]})); + + // You may perform an aggregation involving multiple views and collections if all the views + // have the same default collation. + const graphLookupUkCollection = { + $graphLookup: { + from: "ukCollection", + startWith: "$_id", + connectFromField: "_id", + connectToField: "matchedId", + as: "matched" + } + }; + assert.commandWorked(viewsDB.runCommand( + {aggregate: "simpleView2", pipeline: [lookupSimpleView, graphLookupUkCollection]})); + + // You cannot perform an aggregation involving multiple views if the views don't all have + // the same default collation. + assert.commandFailedWithCode( + viewsDB.runCommand({aggregate: "filView", pipeline: [lookupSimpleView]}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand({aggregate: "simpleView", pipeline: [lookupFilView]}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand( + {aggregate: "simpleCollection", pipeline: [lookupFilView, graphLookupSimpleView]}), + ErrorCodes.OptionNotSupportedOnView); + + // You cannot create a view that depends on another view with a different default collation. + assert.commandFailedWithCode( + viewsDB.runCommand({create: "zhView", viewOn: "filView", collation: {locale: "zh"}}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode(viewsDB.runCommand({ + create: "zhView", + viewOn: "simpleCollection", + pipeline: [lookupFilView], + collation: {locale: "zh"} + }), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode(viewsDB.runCommand({ + create: "zhView", + viewOn: "simpleCollection", + pipeline: [graphLookupSimpleView], + collation: {locale: "zh"} + }), + ErrorCodes.OptionNotSupportedOnView); + + // You cannot modify a view to depend on another view with a different default collation. + assert.commandWorked(viewsDB.runCommand( + {create: "esView", viewOn: "simpleCollection", collation: {locale: "es"}})); + assert.commandFailedWithCode( + viewsDB.runCommand({collMod: "esView", viewOn: "filView", pipeline: []}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand( + {collMod: "esView", viewOn: "simpleCollection", pipeline: [lookupSimpleView]}), + ErrorCodes.OptionNotSupportedOnView); + assert.commandFailedWithCode( + viewsDB.runCommand( + {collMod: "esView", viewOn: "simpleCollection", pipeline: [graphLookupFilView]}), + ErrorCodes.OptionNotSupportedOnView); +}()); diff --git a/jstests/views/views_count.js b/jstests/core/views/views_count.js index e7503e1d74d..e7503e1d74d 100644 --- a/jstests/views/views_count.js +++ b/jstests/core/views/views_count.js diff --git a/jstests/views/views_creation.js b/jstests/core/views/views_creation.js index 2f8bcf52142..2f8bcf52142 100644 --- a/jstests/views/views_creation.js +++ b/jstests/core/views/views_creation.js diff --git a/jstests/views/views_distinct.js b/jstests/core/views/views_distinct.js index 9e99b2552e7..9e99b2552e7 100644 --- a/jstests/views/views_distinct.js +++ b/jstests/core/views/views_distinct.js diff --git a/jstests/views/views_drop.js b/jstests/core/views/views_drop.js index 5163e607444..bc2a654415e 100644 --- a/jstests/views/views_drop.js +++ b/jstests/core/views/views_drop.js @@ -1,3 +1,8 @@ +/** + * Tests the behavior of views when its backing collection is dropped, as well as the behavior of + * system.views when views are dropped. + * @tags: [requires_find_command] + */ (function() { "use strict"; diff --git a/jstests/views/views_find.js b/jstests/core/views/views_find.js index 204c5064bf6..7d48af1e293 100644 --- a/jstests/views/views_find.js +++ b/jstests/core/views/views_find.js @@ -1,4 +1,7 @@ -// Tests the find command on views. +/** + * Tests the find command on views. + * @tags: [requires_find_command] + */ (function() { "use strict"; diff --git a/jstests/views/views_stats.js b/jstests/core/views/views_stats.js index 550d1e81f82..75feb857c9a 100644 --- a/jstests/views/views_stats.js +++ b/jstests/core/views/views_stats.js @@ -26,6 +26,13 @@ assert.writeError(view.update({}, {})); lastHistogram = assertHistogramDiffEq(view, lastHistogram, 0, 1, 0); + let isMasterResponse = assert.commandWorked(viewsDB.runCommand("isMaster")); + const isMongos = (isMasterResponse.msg === "isdbgrid"); + if (isMongos) { + jsTest.log("Tests are being run on a mongos; skipping top tests."); + return; + } + // Check the top counters. let lastTop = getTop(view); view.aggregate([{$match: {}}]); diff --git a/jstests/views/views_validation.js b/jstests/core/views/views_validation.js index 15702a70521..84c7f1d3510 100644 --- a/jstests/views/views_validation.js +++ b/jstests/core/views/views_validation.js @@ -109,17 +109,18 @@ // Check that collMod also checks for cycles. makeView("a", "b"); makeView("b", "c"); - assert.commandFailedWithCode(viewsDb.runCommand({collMod: "b", viewOn: "a"}), + assert.commandFailedWithCode(viewsDb.runCommand({collMod: "b", viewOn: "a", pipeline: []}), ErrorCodes.GraphContainsCycle, "collmod changed view to create a cycle"); // Check that collMod disallows the specification of invalid pipelines. - assert.commandFailedWithCode(viewsDb.runCommand({collMod: "b", pipeline: {}}), - ErrorCodes.InvalidOptions, - "collMod modified view to have invalid pipeline"); - assert.commandFailedWithCode(viewsDb.runCommand({collMod: "b", pipeline: {0: {$limit: 7}}}), + assert.commandFailedWithCode(viewsDb.runCommand({collMod: "b", viewOn: "c", pipeline: {}}), ErrorCodes.InvalidOptions, "collMod modified view to have invalid pipeline"); + assert.commandFailedWithCode( + viewsDb.runCommand({collMod: "b", viewOn: "c", pipeline: {0: {$limit: 7}}}), + ErrorCodes.InvalidOptions, + "collMod modified view to have invalid pipeline"); clear(); // Check that invalid pipelines are disallowed. diff --git a/jstests/views/views_collation.js b/jstests/views/views_collation.js deleted file mode 100644 index 04abf106292..00000000000 --- a/jstests/views/views_collation.js +++ /dev/null @@ -1,280 +0,0 @@ -/** - * Tests the behavior of operations when interacting with a view's default collation. - */ -(function() { - "use strict"; - - function runTest(conn) { - let viewsDB = conn.getDB("views_collation"); - assert.commandWorked(viewsDB.dropDatabase()); - assert.commandWorked(viewsDB.runCommand({create: "simpleCollection"})); - assert.commandWorked( - viewsDB.runCommand({create: "ukCollection", collation: {locale: "uk"}})); - assert.commandWorked( - viewsDB.runCommand({create: "filCollection", collation: {locale: "fil"}})); - - // Creating a view without specifying a collation defaults to the simple collation. - assert.commandWorked(viewsDB.runCommand({create: "simpleView", viewOn: "ukCollection"})); - let listCollectionsOutput = - viewsDB.runCommand({listCollections: 1, filter: {type: "view"}}); - assert.commandWorked(listCollectionsOutput); - assert(!listCollectionsOutput.cursor.firstBatch[0].options.hasOwnProperty("collation")); - - // Operations that do not specify a collation succeed. - assert.commandWorked(viewsDB.runCommand({aggregate: "simpleView", pipeline: []})); - assert.commandWorked(viewsDB.runCommand({find: "simpleView"})); - assert.commandWorked(viewsDB.runCommand({count: "simpleView"})); - assert.commandWorked(viewsDB.runCommand({distinct: "simpleView", key: "x"})); - - // Operations that explicitly ask for the "simple" locale succeed against a view with the - // simple collation. - assert.commandWorked(viewsDB.runCommand( - {aggregate: "simpleView", pipeline: [], collation: {locale: "simple"}})); - assert.commandWorked( - viewsDB.runCommand({find: "simpleView", collation: {locale: "simple"}})); - assert.commandWorked( - viewsDB.runCommand({count: "simpleView", collation: {locale: "simple"}})); - assert.commandWorked( - viewsDB.runCommand({distinct: "simpleView", key: "x", collation: {locale: "simple"}})); - - // Attempting to override a view's simple collation fails. - assert.commandFailedWithCode( - viewsDB.runCommand({aggregate: "simpleView", pipeline: [], collation: {locale: "en"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({find: "simpleView", collation: {locale: "fr"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({count: "simpleView", collation: {locale: "fil"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({distinct: "simpleView", key: "x", collation: {locale: "es"}}), - ErrorCodes.OptionNotSupportedOnView); - - // Create a view with an explicit, non-simple collation. - assert.commandWorked( - viewsDB.createView("filView", "ukCollection", [], {collation: {locale: "fil"}})); - listCollectionsOutput = viewsDB.runCommand({listCollections: 1, filter: {name: "filView"}}); - assert.commandWorked(listCollectionsOutput); - assert.eq(listCollectionsOutput.cursor.firstBatch[0].options.collation.locale, "fil"); - - // Operations that do not specify a collation succeed. - assert.commandWorked(viewsDB.runCommand({aggregate: "filView", pipeline: []})); - assert.commandWorked(viewsDB.runCommand({find: "filView"})); - assert.commandWorked(viewsDB.runCommand({count: "filView"})); - assert.commandWorked(viewsDB.runCommand({distinct: "filView", key: "x"})); - - // Operations with a matching collation succeed. - assert.commandWorked( - viewsDB.runCommand({aggregate: "filView", pipeline: [], collation: {locale: "fil"}})); - assert.commandWorked(viewsDB.runCommand({find: "filView", collation: {locale: "fil"}})); - assert.commandWorked(viewsDB.runCommand({count: "filView", collation: {locale: "fil"}})); - assert.commandWorked( - viewsDB.runCommand({distinct: "filView", key: "x", collation: {locale: "fil"}})); - - // Attempting to override the non-simple default collation of a view fails. - assert.commandFailedWithCode( - viewsDB.runCommand({aggregate: "filView", pipeline: [], collation: {locale: "en"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({aggregate: "filView", pipeline: [], collation: {locale: "simple"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({find: "filView", collation: {locale: "fr"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({find: "filView", collation: {locale: "simple"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({count: "filView", collation: {locale: "zh"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({count: "filView", collation: {locale: "simple"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({distinct: "filView", key: "x", collation: {locale: "es"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({distinct: "filView", key: "x", collation: {locale: "simple"}}), - ErrorCodes.OptionNotSupportedOnView); - - const lookupSimpleView = { - $lookup: {from: "simpleView", localField: "x", foreignField: "x", as: "result"} - }; - const graphLookupSimpleView = { - $graphLookup: { - from: "simpleView", - startWith: "$_id", - connectFromField: "_id", - connectToField: "matchedId", - as: "matched" - } - }; - - // You can lookup into a view with the simple collation if the collection also has the same - // default collation. - assert.commandWorked( - viewsDB.runCommand({aggregate: "simpleCollection", pipeline: [lookupSimpleView]})); - assert.commandWorked( - viewsDB.runCommand({aggregate: "simpleCollection", pipeline: [graphLookupSimpleView]})); - - // You can lookup into a view with the simple collation if the operation has a matching - // collation. - assert.commandWorked(viewsDB.runCommand({ - aggregate: "ukCollection", - pipeline: [lookupSimpleView], - collation: {locale: "simple"} - })); - assert.commandWorked(viewsDB.runCommand({ - aggregate: "ukCollection", - pipeline: [graphLookupSimpleView], - collation: {locale: "simple"} - })); - - // You can't lookup into a view with the simple collation if the operation has a conflicting - // collation. - assert.commandFailedWithCode(viewsDB.runCommand({ - aggregate: "simpleCollection", - pipeline: [lookupSimpleView], - collation: {locale: "en"} - }), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode(viewsDB.runCommand({ - aggregate: "simpleCollection", - pipeline: [graphLookupSimpleView], - collation: {locale: "zh"} - }), - ErrorCodes.OptionNotSupportedOnView); - - const lookupFilView = { - $lookup: {from: "filView", localField: "x", foreignField: "x", as: "result"} - }; - const graphLookupFilView = { - $graphLookup: { - from: "filView", - startWith: "$_id", - connectFromField: "_id", - connectToField: "matchedId", - as: "matched" - } - }; - - // You can lookup into a view with no operation collation specified if the collection's - // collation matches the collation of the view. - assert.commandWorked( - viewsDB.runCommand({aggregate: "filCollection", pipeline: [lookupFilView]})); - assert.commandWorked( - viewsDB.runCommand({aggregate: "filCollection", pipeline: [graphLookupFilView]})); - - // You can lookup into a view with a non-simple collation if the operation's collation - // matches. - assert.commandWorked(viewsDB.runCommand( - {aggregate: "ukCollection", pipeline: [lookupFilView], collation: {locale: "fil"}})); - assert.commandWorked(viewsDB.runCommand({ - aggregate: "ukCollection", - pipeline: [graphLookupFilView], - collation: {locale: "fil"} - })); - - // You can't lookup into a view when aggregating a collection whose default collation does - // not match the view's default collation. - assert.commandFailedWithCode( - viewsDB.runCommand({aggregate: "simpleCollection", pipeline: [lookupFilView]}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({aggregate: "simpleCollection", pipeline: [graphLookupFilView]}), - ErrorCodes.OptionNotSupportedOnView); - - // You can't lookup into a view when aggregating a collection and the operation's collation - // does not match the view's default collation. - assert.commandFailedWithCode( - viewsDB.runCommand( - {aggregate: "filCollection", pipeline: [lookupFilView], collation: {locale: "zh"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode(viewsDB.runCommand({ - aggregate: "filCollection", - pipeline: [graphLookupFilView], - collation: {locale: "zh"} - }), - ErrorCodes.OptionNotSupportedOnView); - - // You may perform an aggregation involving multiple views if they all have the same default - // collation. - assert.commandWorked(viewsDB.runCommand( - {create: "simpleView2", viewOn: "simpleCollection", collation: {locale: "simple"}})); - assert.commandWorked( - viewsDB.runCommand({aggregate: "simpleView2", pipeline: [lookupSimpleView]})); - assert.commandWorked( - viewsDB.runCommand({aggregate: "simpleView2", pipeline: [graphLookupSimpleView]})); - - // You may perform an aggregation involving multiple views and collections if all the views - // have the same default collation. - const graphLookupUkCollection = { - $graphLookup: { - from: "ukCollection", - startWith: "$_id", - connectFromField: "_id", - connectToField: "matchedId", - as: "matched" - } - }; - assert.commandWorked(viewsDB.runCommand( - {aggregate: "simpleView2", pipeline: [lookupSimpleView, graphLookupUkCollection]})); - - // You cannot perform an aggregation involving multiple views if the views don't all have - // the same default collation. - assert.commandFailedWithCode( - viewsDB.runCommand({aggregate: "filView", pipeline: [lookupSimpleView]}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand({aggregate: "simpleView", pipeline: [lookupFilView]}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand( - {aggregate: "simpleCollection", pipeline: [lookupFilView, graphLookupSimpleView]}), - ErrorCodes.OptionNotSupportedOnView); - - // You cannot create a view that depends on another view with a different default collation. - assert.commandFailedWithCode( - viewsDB.runCommand({create: "zhView", viewOn: "filView", collation: {locale: "zh"}}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode(viewsDB.runCommand({ - create: "zhView", - viewOn: "simpleCollection", - pipeline: [lookupFilView], - collation: {locale: "zh"} - }), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode(viewsDB.runCommand({ - create: "zhView", - viewOn: "simpleCollection", - pipeline: [graphLookupSimpleView], - collation: {locale: "zh"} - }), - ErrorCodes.OptionNotSupportedOnView); - - // You cannot modify a view to depend on another view with a different default collation. - assert.commandWorked(viewsDB.runCommand( - {create: "esView", viewOn: "simpleCollection", collation: {locale: "es"}})); - assert.commandFailedWithCode(viewsDB.runCommand({collMod: "esView", viewOn: "filView"}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand( - {collMod: "esView", viewOn: "simpleCollection", pipeline: [lookupSimpleView]}), - ErrorCodes.OptionNotSupportedOnView); - assert.commandFailedWithCode( - viewsDB.runCommand( - {collMod: "esView", viewOn: "simpleCollection", pipeline: [graphLookupFilView]}), - ErrorCodes.OptionNotSupportedOnView); - } - - // Run the test on a standalone. - let mongod = MongoRunner.runMongod({}); - runTest(mongod); - MongoRunner.stopMongod(mongod); - - // Run the test on a sharded cluster. - let cluster = new ShardingTest({shards: 1, mongos: 1}); - runTest(cluster); - cluster.stop(); -}()); |