From 6b0123594aeb6d4fa618568a28cab3344c5422f0 Mon Sep 17 00:00:00 2001 From: Prashant Mital <5883388+prashantmital@users.noreply.github.com> Date: Mon, 21 Dec 2020 19:22:29 -0800 Subject: [PATCH] PYTHON-2033 Unified Test Format (#519) --- test/__init__.py | 10 + test/test_unified_format.py | 73 ++ .../example-insertOne.json | 100 ++ .../collectionData-additionalProperties.json | 40 + ...ollectionData-collectionName-required.json | 38 + .../collectionData-collectionName-type.json | 39 + .../collectionData-databaseName-required.json | 38 + .../collectionData-databaseName-type.json | 39 + .../collectionData-documents-items.json | 41 + .../collectionData-documents-required.json | 38 + .../collectionData-documents-type.json | 39 + ...rDatabaseOptions-additionalProperties.json | 27 + ...ionOrDatabaseOptions-readConcern-type.json | 27 + ...OrDatabaseOptions-readPreference-type.json | 27 + ...onOrDatabaseOptions-writeConcern-type.json | 27 + .../invalid/createEntities-items.json | 13 + .../invalid/createEntities-minItems.json | 11 + .../invalid/createEntities-type.json | 11 + .../invalid/description-required.json | 9 + .../invalid/entity-additionalProperties.json | 15 + .../entity-bucket-additionalProperties.json | 31 + .../entity-bucket-bucketOptions-type.json | 31 + .../entity-bucket-database-required.json | 29 + .../invalid/entity-bucket-database-type.json | 30 + .../invalid/entity-bucket-id-required.json | 29 + .../invalid/entity-bucket-id-type.json | 30 + .../entity-client-additionalProperties.json | 18 + .../invalid/entity-client-id-required.json | 15 + .../invalid/entity-client-id-type.json | 17 + ...t-ignoreCommandMonitoringEvents-items.json | 20 + ...gnoreCommandMonitoringEvents-minItems.json | 18 + ...nt-ignoreCommandMonitoringEvents-type.json | 18 + .../entity-client-observeEvents-enum.json | 20 + .../entity-client-observeEvents-items.json | 20 + .../entity-client-observeEvents-minItems.json | 18 + .../entity-client-observeEvents-type.json | 18 + .../entity-client-uriOptions-type.json | 18 + ...ntity-client-useMultipleMongoses-type.json | 18 + ...ntity-collection-additionalProperties.json | 32 + ...ty-collection-collectionName-required.json | 30 + ...entity-collection-collectionName-type.json | 31 + ...ity-collection-collectionOptions-type.json | 32 + .../entity-collection-database-required.json | 30 + .../entity-collection-database-type.json | 31 + .../entity-collection-id-required.json | 30 + .../invalid/entity-collection-id-type.json | 31 + .../entity-database-additionalProperties.json | 25 + .../entity-database-client-required.json | 23 + .../invalid/entity-database-client-type.json | 24 + ...entity-database-databaseName-required.json | 23 + .../entity-database-databaseName-type.json | 24 + .../entity-database-databaseOptions-type.json | 25 + .../invalid/entity-database-id-required.json | 23 + .../invalid/entity-database-id-type.json | 24 + .../invalid/entity-maxProperties.json | 22 + .../invalid/entity-minProperties.json | 13 + .../entity-session-additionalProperties.json | 24 + .../entity-session-client-required.json | 22 + .../invalid/entity-session-client-type.json | 23 + .../invalid/entity-session-id-required.json | 22 + .../invalid/entity-session-id-type.json | 23 + .../entity-session-sessionOptions-type.json | 24 + .../entity-stream-additionalProperties.json | 19 + .../entity-stream-hexBytes-pattern.json | 18 + .../entity-stream-hexBytes-required.json | 17 + .../invalid/entity-stream-hexBytes-type.json | 18 + .../invalid/entity-stream-id-required.json | 17 + .../invalid/entity-stream-id-type.json | 18 + .../expectedError-additionalProperties.json | 25 + .../invalid/expectedError-errorCode-type.json | 25 + .../expectedError-errorCodeName-type.json | 25 + .../expectedError-errorContains-type.json | 25 + ...xpectedError-errorLabelsContain-items.json | 27 + ...ctedError-errorLabelsContain-minItems.json | 25 + ...expectedError-errorLabelsContain-type.json | 25 + .../expectedError-errorLabelsOmit-items.json | 27 + ...xpectedError-errorLabelsOmit-minItems.json | 25 + .../expectedError-errorLabelsOmit-type.json | 25 + .../expectedError-isClientError-type.json | 25 + .../invalid/expectedError-isError-const.json | 25 + .../invalid/expectedError-isError-type.json | 25 + .../invalid/expectedError-minProperties.json | 23 + .../expectedEvent-additionalProperties.json | 32 + ...t-commandFailedEvent-commandName-type.json | 34 + ...mandStartedEvent-additionalProperties.json | 34 + ...vent-commandStartedEvent-command-type.json | 34 + ...-commandStartedEvent-commandName-type.json | 34 + ...commandStartedEvent-databaseName-type.json | 34 + ...ommandSucceededEvent-commandName-type.json | 34 + ...vent-commandSucceededEvent-reply-type.json | 34 + .../invalid/expectedEvent-maxProperties.json | 33 + .../invalid/expectedEvent-minProperties.json | 30 + ...dEventsForClient-additionalProperties.json | 29 + ...pectedEventsForClient-client-required.json | 27 + .../expectedEventsForClient-client-type.json | 28 + .../expectedEventsForClient-events-items.json | 30 + ...pectedEventsForClient-events-required.json | 27 + .../expectedEventsForClient-events-type.json | 28 + .../invalid/initialData-items.json | 13 + .../invalid/initialData-minItems.json | 11 + .../invalid/initialData-type.json | 11 + .../operation-additionalProperties.json | 23 + .../invalid/operation-arguments-type.json | 23 + ...pectError-conflicts_with_expectResult.json | 26 + ...ror-conflicts_with_saveResultAsEntity.json | 26 + .../invalid/operation-expectError-type.json | 23 + .../invalid/operation-expectEvents-type.json | 23 + .../invalid/operation-name-required.json | 21 + .../invalid/operation-name-type.json | 22 + .../invalid/operation-object-required.json | 21 + .../invalid/operation-object-type.json | 22 + .../operation-saveResultAsEntity-type.json | 23 + ...runOnRequirement-additionalProperties.json | 16 + ...nRequirement-maxServerVersion-pattern.json | 15 + ...unOnRequirement-maxServerVersion-type.json | 15 + .../runOnRequirement-minProperties.json | 13 + ...nRequirement-minServerVersion-pattern.json | 15 + ...unOnRequirement-minServerVersion-type.json | 15 + .../runOnRequirement-topologies-enum.json | 17 + .../runOnRequirement-topologies-items.json | 17 + .../runOnRequirement-topologies-minItems.json | 15 + .../runOnRequirement-topologies-type.json | 15 + .../invalid/runOnRequirements-items.json | 13 + .../invalid/runOnRequirements-minItems.json | 11 + .../invalid/runOnRequirements-type.json | 11 + .../invalid/schemaVersion-pattern.json | 10 + .../invalid/schemaVersion-required.json | 9 + .../invalid/schemaVersion-type.json | 10 + .../invalid/test-additionalProperties.json | 11 + .../invalid/test-description-required.json | 9 + .../invalid/test-description-type.json | 10 + .../invalid/test-expectEvents-items.json | 13 + .../invalid/test-expectEvents-type.json | 11 + .../invalid/test-operations-items.json | 12 + .../invalid/test-operations-required.json | 9 + .../invalid/test-operations-type.json | 10 + .../invalid/test-outcome-items.json | 13 + .../invalid/test-outcome-minItems.json | 11 + .../invalid/test-outcome-type.json | 11 + .../invalid/test-runOnRequirements-items.json | 13 + .../test-runOnRequirements-minItems.json | 11 + .../invalid/test-runOnRequirements-type.json | 11 + .../invalid/test-skipReason-type.json | 11 + .../invalid/tests-items.json | 7 + .../invalid/tests-minItems.json | 5 + .../invalid/tests-required.json | 4 + .../invalid/tests-type.json | 5 + .../entity-bucket-database-undefined.json | 18 + .../entity-collection-database-undefined.json | 19 + .../entity-database-client-undefined.json | 19 + .../entity-session-client-undefined.json | 18 + .../returnDocument-enum-invalid.json | 66 ++ .../valid-fail/schemaVersion-unsupported.json | 10 + .../valid-pass/poc-change-streams.json | 414 +++++++ .../valid-pass/poc-command-monitoring.json | 222 ++++ .../valid-pass/poc-crud.json | 446 +++++++ .../valid-pass/poc-gridfs.json | 301 +++++ .../valid-pass/poc-retryable-reads.json | 433 +++++++ .../valid-pass/poc-retryable-writes.json | 483 ++++++++ .../valid-pass/poc-sessions.json | 466 ++++++++ .../poc-transactions-convenient-api.json | 505 ++++++++ .../poc-transactions-mongos-pin-auto.json | 409 +++++++ .../valid-pass/poc-transactions.json | 322 +++++ test/unified_format.py | 1032 +++++++++++++++++ test/utils.py | 131 ++- test/utils_spec_runner.py | 102 +- 166 files changed, 8646 insertions(+), 94 deletions(-) create mode 100644 test/test_unified_format.py create mode 100644 test/unified-test-format/example-insertOne.json create mode 100644 test/unified-test-format/invalid/collectionData-additionalProperties.json create mode 100644 test/unified-test-format/invalid/collectionData-collectionName-required.json create mode 100644 test/unified-test-format/invalid/collectionData-collectionName-type.json create mode 100644 test/unified-test-format/invalid/collectionData-databaseName-required.json create mode 100644 test/unified-test-format/invalid/collectionData-databaseName-type.json create mode 100644 test/unified-test-format/invalid/collectionData-documents-items.json create mode 100644 test/unified-test-format/invalid/collectionData-documents-required.json create mode 100644 test/unified-test-format/invalid/collectionData-documents-type.json create mode 100644 test/unified-test-format/invalid/collectionOrDatabaseOptions-additionalProperties.json create mode 100644 test/unified-test-format/invalid/collectionOrDatabaseOptions-readConcern-type.json create mode 100644 test/unified-test-format/invalid/collectionOrDatabaseOptions-readPreference-type.json create mode 100644 test/unified-test-format/invalid/collectionOrDatabaseOptions-writeConcern-type.json create mode 100644 test/unified-test-format/invalid/createEntities-items.json create mode 100644 test/unified-test-format/invalid/createEntities-minItems.json create mode 100644 test/unified-test-format/invalid/createEntities-type.json create mode 100644 test/unified-test-format/invalid/description-required.json create mode 100644 test/unified-test-format/invalid/entity-additionalProperties.json create mode 100644 test/unified-test-format/invalid/entity-bucket-additionalProperties.json create mode 100644 test/unified-test-format/invalid/entity-bucket-bucketOptions-type.json create mode 100644 test/unified-test-format/invalid/entity-bucket-database-required.json create mode 100644 test/unified-test-format/invalid/entity-bucket-database-type.json create mode 100644 test/unified-test-format/invalid/entity-bucket-id-required.json create mode 100644 test/unified-test-format/invalid/entity-bucket-id-type.json create mode 100644 test/unified-test-format/invalid/entity-client-additionalProperties.json create mode 100644 test/unified-test-format/invalid/entity-client-id-required.json create mode 100644 test/unified-test-format/invalid/entity-client-id-type.json create mode 100644 test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-items.json create mode 100644 test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-minItems.json create mode 100644 test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-type.json create mode 100644 test/unified-test-format/invalid/entity-client-observeEvents-enum.json create mode 100644 test/unified-test-format/invalid/entity-client-observeEvents-items.json create mode 100644 test/unified-test-format/invalid/entity-client-observeEvents-minItems.json create mode 100644 test/unified-test-format/invalid/entity-client-observeEvents-type.json create mode 100644 test/unified-test-format/invalid/entity-client-uriOptions-type.json create mode 100644 test/unified-test-format/invalid/entity-client-useMultipleMongoses-type.json create mode 100644 test/unified-test-format/invalid/entity-collection-additionalProperties.json create mode 100644 test/unified-test-format/invalid/entity-collection-collectionName-required.json create mode 100644 test/unified-test-format/invalid/entity-collection-collectionName-type.json create mode 100644 test/unified-test-format/invalid/entity-collection-collectionOptions-type.json create mode 100644 test/unified-test-format/invalid/entity-collection-database-required.json create mode 100644 test/unified-test-format/invalid/entity-collection-database-type.json create mode 100644 test/unified-test-format/invalid/entity-collection-id-required.json create mode 100644 test/unified-test-format/invalid/entity-collection-id-type.json create mode 100644 test/unified-test-format/invalid/entity-database-additionalProperties.json create mode 100644 test/unified-test-format/invalid/entity-database-client-required.json create mode 100644 test/unified-test-format/invalid/entity-database-client-type.json create mode 100644 test/unified-test-format/invalid/entity-database-databaseName-required.json create mode 100644 test/unified-test-format/invalid/entity-database-databaseName-type.json create mode 100644 test/unified-test-format/invalid/entity-database-databaseOptions-type.json create mode 100644 test/unified-test-format/invalid/entity-database-id-required.json create mode 100644 test/unified-test-format/invalid/entity-database-id-type.json create mode 100644 test/unified-test-format/invalid/entity-maxProperties.json create mode 100644 test/unified-test-format/invalid/entity-minProperties.json create mode 100644 test/unified-test-format/invalid/entity-session-additionalProperties.json create mode 100644 test/unified-test-format/invalid/entity-session-client-required.json create mode 100644 test/unified-test-format/invalid/entity-session-client-type.json create mode 100644 test/unified-test-format/invalid/entity-session-id-required.json create mode 100644 test/unified-test-format/invalid/entity-session-id-type.json create mode 100644 test/unified-test-format/invalid/entity-session-sessionOptions-type.json create mode 100644 test/unified-test-format/invalid/entity-stream-additionalProperties.json create mode 100644 test/unified-test-format/invalid/entity-stream-hexBytes-pattern.json create mode 100644 test/unified-test-format/invalid/entity-stream-hexBytes-required.json create mode 100644 test/unified-test-format/invalid/entity-stream-hexBytes-type.json create mode 100644 test/unified-test-format/invalid/entity-stream-id-required.json create mode 100644 test/unified-test-format/invalid/entity-stream-id-type.json create mode 100644 test/unified-test-format/invalid/expectedError-additionalProperties.json create mode 100644 test/unified-test-format/invalid/expectedError-errorCode-type.json create mode 100644 test/unified-test-format/invalid/expectedError-errorCodeName-type.json create mode 100644 test/unified-test-format/invalid/expectedError-errorContains-type.json create mode 100644 test/unified-test-format/invalid/expectedError-errorLabelsContain-items.json create mode 100644 test/unified-test-format/invalid/expectedError-errorLabelsContain-minItems.json create mode 100644 test/unified-test-format/invalid/expectedError-errorLabelsContain-type.json create mode 100644 test/unified-test-format/invalid/expectedError-errorLabelsOmit-items.json create mode 100644 test/unified-test-format/invalid/expectedError-errorLabelsOmit-minItems.json create mode 100644 test/unified-test-format/invalid/expectedError-errorLabelsOmit-type.json create mode 100644 test/unified-test-format/invalid/expectedError-isClientError-type.json create mode 100644 test/unified-test-format/invalid/expectedError-isError-const.json create mode 100644 test/unified-test-format/invalid/expectedError-isError-type.json create mode 100644 test/unified-test-format/invalid/expectedError-minProperties.json create mode 100644 test/unified-test-format/invalid/expectedEvent-additionalProperties.json create mode 100644 test/unified-test-format/invalid/expectedEvent-commandFailedEvent-commandName-type.json create mode 100644 test/unified-test-format/invalid/expectedEvent-commandStartedEvent-additionalProperties.json create mode 100644 test/unified-test-format/invalid/expectedEvent-commandStartedEvent-command-type.json create mode 100644 test/unified-test-format/invalid/expectedEvent-commandStartedEvent-commandName-type.json create mode 100644 test/unified-test-format/invalid/expectedEvent-commandStartedEvent-databaseName-type.json create mode 100644 test/unified-test-format/invalid/expectedEvent-commandSucceededEvent-commandName-type.json create mode 100644 test/unified-test-format/invalid/expectedEvent-commandSucceededEvent-reply-type.json create mode 100644 test/unified-test-format/invalid/expectedEvent-maxProperties.json create mode 100644 test/unified-test-format/invalid/expectedEvent-minProperties.json create mode 100644 test/unified-test-format/invalid/expectedEventsForClient-additionalProperties.json create mode 100644 test/unified-test-format/invalid/expectedEventsForClient-client-required.json create mode 100644 test/unified-test-format/invalid/expectedEventsForClient-client-type.json create mode 100644 test/unified-test-format/invalid/expectedEventsForClient-events-items.json create mode 100644 test/unified-test-format/invalid/expectedEventsForClient-events-required.json create mode 100644 test/unified-test-format/invalid/expectedEventsForClient-events-type.json create mode 100644 test/unified-test-format/invalid/initialData-items.json create mode 100644 test/unified-test-format/invalid/initialData-minItems.json create mode 100644 test/unified-test-format/invalid/initialData-type.json create mode 100644 test/unified-test-format/invalid/operation-additionalProperties.json create mode 100644 test/unified-test-format/invalid/operation-arguments-type.json create mode 100644 test/unified-test-format/invalid/operation-expectError-conflicts_with_expectResult.json create mode 100644 test/unified-test-format/invalid/operation-expectError-conflicts_with_saveResultAsEntity.json create mode 100644 test/unified-test-format/invalid/operation-expectError-type.json create mode 100644 test/unified-test-format/invalid/operation-expectEvents-type.json create mode 100644 test/unified-test-format/invalid/operation-name-required.json create mode 100644 test/unified-test-format/invalid/operation-name-type.json create mode 100644 test/unified-test-format/invalid/operation-object-required.json create mode 100644 test/unified-test-format/invalid/operation-object-type.json create mode 100644 test/unified-test-format/invalid/operation-saveResultAsEntity-type.json create mode 100644 test/unified-test-format/invalid/runOnRequirement-additionalProperties.json create mode 100644 test/unified-test-format/invalid/runOnRequirement-maxServerVersion-pattern.json create mode 100644 test/unified-test-format/invalid/runOnRequirement-maxServerVersion-type.json create mode 100644 test/unified-test-format/invalid/runOnRequirement-minProperties.json create mode 100644 test/unified-test-format/invalid/runOnRequirement-minServerVersion-pattern.json create mode 100644 test/unified-test-format/invalid/runOnRequirement-minServerVersion-type.json create mode 100644 test/unified-test-format/invalid/runOnRequirement-topologies-enum.json create mode 100644 test/unified-test-format/invalid/runOnRequirement-topologies-items.json create mode 100644 test/unified-test-format/invalid/runOnRequirement-topologies-minItems.json create mode 100644 test/unified-test-format/invalid/runOnRequirement-topologies-type.json create mode 100644 test/unified-test-format/invalid/runOnRequirements-items.json create mode 100644 test/unified-test-format/invalid/runOnRequirements-minItems.json create mode 100644 test/unified-test-format/invalid/runOnRequirements-type.json create mode 100644 test/unified-test-format/invalid/schemaVersion-pattern.json create mode 100644 test/unified-test-format/invalid/schemaVersion-required.json create mode 100644 test/unified-test-format/invalid/schemaVersion-type.json create mode 100644 test/unified-test-format/invalid/test-additionalProperties.json create mode 100644 test/unified-test-format/invalid/test-description-required.json create mode 100644 test/unified-test-format/invalid/test-description-type.json create mode 100644 test/unified-test-format/invalid/test-expectEvents-items.json create mode 100644 test/unified-test-format/invalid/test-expectEvents-type.json create mode 100644 test/unified-test-format/invalid/test-operations-items.json create mode 100644 test/unified-test-format/invalid/test-operations-required.json create mode 100644 test/unified-test-format/invalid/test-operations-type.json create mode 100644 test/unified-test-format/invalid/test-outcome-items.json create mode 100644 test/unified-test-format/invalid/test-outcome-minItems.json create mode 100644 test/unified-test-format/invalid/test-outcome-type.json create mode 100644 test/unified-test-format/invalid/test-runOnRequirements-items.json create mode 100644 test/unified-test-format/invalid/test-runOnRequirements-minItems.json create mode 100644 test/unified-test-format/invalid/test-runOnRequirements-type.json create mode 100644 test/unified-test-format/invalid/test-skipReason-type.json create mode 100644 test/unified-test-format/invalid/tests-items.json create mode 100644 test/unified-test-format/invalid/tests-minItems.json create mode 100644 test/unified-test-format/invalid/tests-required.json create mode 100644 test/unified-test-format/invalid/tests-type.json create mode 100644 test/unified-test-format/valid-fail/entity-bucket-database-undefined.json create mode 100644 test/unified-test-format/valid-fail/entity-collection-database-undefined.json create mode 100644 test/unified-test-format/valid-fail/entity-database-client-undefined.json create mode 100644 test/unified-test-format/valid-fail/entity-session-client-undefined.json create mode 100644 test/unified-test-format/valid-fail/returnDocument-enum-invalid.json create mode 100644 test/unified-test-format/valid-fail/schemaVersion-unsupported.json create mode 100644 test/unified-test-format/valid-pass/poc-change-streams.json create mode 100644 test/unified-test-format/valid-pass/poc-command-monitoring.json create mode 100644 test/unified-test-format/valid-pass/poc-crud.json create mode 100644 test/unified-test-format/valid-pass/poc-gridfs.json create mode 100644 test/unified-test-format/valid-pass/poc-retryable-reads.json create mode 100644 test/unified-test-format/valid-pass/poc-retryable-writes.json create mode 100644 test/unified-test-format/valid-pass/poc-sessions.json create mode 100644 test/unified-test-format/valid-pass/poc-transactions-convenient-api.json create mode 100644 test/unified-test-format/valid-pass/poc-transactions-mongos-pin-auto.json create mode 100644 test/unified-test-format/valid-pass/poc-transactions.json create mode 100644 test/unified_format.py diff --git a/test/__init__.py b/test/__init__.py index 88e48b7cd..d24601551 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -613,6 +613,16 @@ class ClientContext(object): return True if 'sharded' in topologies and self.is_mongos: return True + if 'sharded-replicaset' in topologies and self.is_mongos: + shards = list(client_context.client.config.shards.find()) + for shard in shards: + # For a 3-member RS-backed sharded cluster, shard['host'] + # will be 'replicaName/ip1:port1,ip2:port2,ip3:port3' + # Otherwise it will be 'ip1:port1' + host_spec = shard['host'] + if not len(host_spec.split('/')) > 1: + return False + return True return False def require_cluster_type(self, topologies=[]): diff --git a/test/test_unified_format.py b/test/test_unified_format.py new file mode 100644 index 000000000..a32918c4d --- /dev/null +++ b/test/test_unified_format.py @@ -0,0 +1,73 @@ +# Copyright 2020-present MongoDB, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import sys + +sys.path[0:0] = [""] + +from bson import ObjectId + +from test import unittest +from test.unified_format import generate_test_classes, MatchEvaluatorUtil + + +_TEST_PATH = os.path.join( + os.path.dirname(os.path.realpath(__file__)), 'unified-test-format') + + +globals().update(generate_test_classes( + os.path.join(_TEST_PATH, 'valid-pass'), + module=__name__, + class_name_prefix='UnifiedTestFormat', + expected_failures=[ + 'Client side error in command starting transaction', # PYTHON-1894 + ])) + + +globals().update(generate_test_classes( + os.path.join(_TEST_PATH, 'valid-fail'), + module=__name__, + class_name_prefix='UnifiedTestFormat', + bypass_test_generation_errors=True, + expected_failures=[ + '.*', # All tests expected to fail + ])) + + +class TestMatchEvaluatorUtil(unittest.TestCase): + def setUp(self): + self.match_evaluator = MatchEvaluatorUtil(self) + + def test_unsetOrMatches(self): + spec = {'$$unsetOrMatches': {'y': {'$$unsetOrMatches': 2}}} + for actual in [{}, {'y': 2}, None]: + self.match_evaluator.match_result(spec, actual) + + spec = {'x': {'$$unsetOrMatches': {'y': {'$$unsetOrMatches': 2}}}} + for actual in [{}, {'x': {}}, {'x': {'y': 2}}]: + self.match_evaluator.match_result(spec, actual) + + def test_type(self): + self.match_evaluator.match_result( + {'operationType': 'insert', + 'ns': {'db': 'change-stream-tests', 'coll': 'test'}, + 'fullDocument': {'_id': {'$$type': 'objectId'}, 'x': 1}}, + {'operationType': 'insert', + 'fullDocument': {'_id': ObjectId('5fc93511ac93941052098f0c'), 'x': 1}, + 'ns': {'db': 'change-stream-tests', 'coll': 'test'}}) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/unified-test-format/example-insertOne.json b/test/unified-test-format/example-insertOne.json new file mode 100644 index 000000000..be41f9eac --- /dev/null +++ b/test/unified-test-format/example-insertOne.json @@ -0,0 +1,100 @@ +{ + "description": "example-insertOne", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "2.6" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "test" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "test", + "documents": [ + { + "_id": 1 + } + ] + } + ], + "tests": [ + { + "description": "insertOne", + "operations": [ + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + } + }, + "expectResult": { + "insertedId": { + "$$unsetOrMatches": 2 + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "insert", + "databaseName": "test", + "command": { + "insert": "coll", + "documents": [ + { + "_id": 2 + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "test", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionData-additionalProperties.json b/test/unified-test-format/invalid/collectionData-additionalProperties.json new file mode 100644 index 000000000..2d8509310 --- /dev/null +++ b/test/unified-test-format/invalid/collectionData-additionalProperties.json @@ -0,0 +1,40 @@ +{ + "description": "collectionData-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "foo", + "foo": 0 + } + } + ], + "initialData": [ + { + "collectionName": "foo", + "databaseName": "foo", + "documents": [], + "foo": 0 + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionData-collectionName-required.json b/test/unified-test-format/invalid/collectionData-collectionName-required.json new file mode 100644 index 000000000..040dd86a1 --- /dev/null +++ b/test/unified-test-format/invalid/collectionData-collectionName-required.json @@ -0,0 +1,38 @@ +{ + "description": "collectionData-collectionName-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "foo", + "foo": 0 + } + } + ], + "initialData": [ + { + "databaseName": "foo", + "documents": [] + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionData-collectionName-type.json b/test/unified-test-format/invalid/collectionData-collectionName-type.json new file mode 100644 index 000000000..676d822e5 --- /dev/null +++ b/test/unified-test-format/invalid/collectionData-collectionName-type.json @@ -0,0 +1,39 @@ +{ + "description": "collectionData-collectionName-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "foo", + "foo": 0 + } + } + ], + "initialData": [ + { + "collectionName": 0, + "databaseName": "foo", + "documents": [] + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionData-databaseName-required.json b/test/unified-test-format/invalid/collectionData-databaseName-required.json new file mode 100644 index 000000000..7548f9d5b --- /dev/null +++ b/test/unified-test-format/invalid/collectionData-databaseName-required.json @@ -0,0 +1,38 @@ +{ + "description": "collectionData-databaseName-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "foo", + "foo": 0 + } + } + ], + "initialData": [ + { + "collectionName": "foo", + "documents": [] + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionData-databaseName-type.json b/test/unified-test-format/invalid/collectionData-databaseName-type.json new file mode 100644 index 000000000..ef719bbf6 --- /dev/null +++ b/test/unified-test-format/invalid/collectionData-databaseName-type.json @@ -0,0 +1,39 @@ +{ + "description": "collectionData-databaseName-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "foo", + "foo": 0 + } + } + ], + "initialData": [ + { + "collectionName": "foo", + "databaseName": 0, + "documents": [] + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionData-documents-items.json b/test/unified-test-format/invalid/collectionData-documents-items.json new file mode 100644 index 000000000..2916718d5 --- /dev/null +++ b/test/unified-test-format/invalid/collectionData-documents-items.json @@ -0,0 +1,41 @@ +{ + "description": "collectionData-documents-items", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "foo", + "foo": 0 + } + } + ], + "initialData": [ + { + "collectionName": "foo", + "databaseName": "foo", + "documents": [ + 0 + ] + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionData-documents-required.json b/test/unified-test-format/invalid/collectionData-documents-required.json new file mode 100644 index 000000000..7b8a7ead2 --- /dev/null +++ b/test/unified-test-format/invalid/collectionData-documents-required.json @@ -0,0 +1,38 @@ +{ + "description": "collectionData-documents-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "foo", + "foo": 0 + } + } + ], + "initialData": [ + { + "collectionName": "foo", + "databaseName": "foo" + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionData-documents-type.json b/test/unified-test-format/invalid/collectionData-documents-type.json new file mode 100644 index 000000000..953cabae6 --- /dev/null +++ b/test/unified-test-format/invalid/collectionData-documents-type.json @@ -0,0 +1,39 @@ +{ + "description": "collectionData-documents-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "foo", + "foo": 0 + } + } + ], + "initialData": [ + { + "collectionName": "foo", + "databaseName": "foo", + "documents": 0 + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionOrDatabaseOptions-additionalProperties.json b/test/unified-test-format/invalid/collectionOrDatabaseOptions-additionalProperties.json new file mode 100644 index 000000000..beef260ee --- /dev/null +++ b/test/unified-test-format/invalid/collectionOrDatabaseOptions-additionalProperties.json @@ -0,0 +1,27 @@ +{ + "description": "collectionOrDatabaseOptions-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo", + "databaseOptions": { + "foo": 0 + } + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionOrDatabaseOptions-readConcern-type.json b/test/unified-test-format/invalid/collectionOrDatabaseOptions-readConcern-type.json new file mode 100644 index 000000000..1b9f4bcbe --- /dev/null +++ b/test/unified-test-format/invalid/collectionOrDatabaseOptions-readConcern-type.json @@ -0,0 +1,27 @@ +{ + "description": "collectionOrDatabaseOptions-readConcern-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo", + "databaseOptions": { + "readConcern": 0 + } + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionOrDatabaseOptions-readPreference-type.json b/test/unified-test-format/invalid/collectionOrDatabaseOptions-readPreference-type.json new file mode 100644 index 000000000..988b594d1 --- /dev/null +++ b/test/unified-test-format/invalid/collectionOrDatabaseOptions-readPreference-type.json @@ -0,0 +1,27 @@ +{ + "description": "collectionOrDatabaseOptions-readPreference-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo", + "databaseOptions": { + "readPreference": 0 + } + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/collectionOrDatabaseOptions-writeConcern-type.json b/test/unified-test-format/invalid/collectionOrDatabaseOptions-writeConcern-type.json new file mode 100644 index 000000000..bd2157c5c --- /dev/null +++ b/test/unified-test-format/invalid/collectionOrDatabaseOptions-writeConcern-type.json @@ -0,0 +1,27 @@ +{ + "description": "collectionOrDatabaseOptions-writeConcern-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo", + "databaseOptions": { + "writeConcern": 0 + } + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/createEntities-items.json b/test/unified-test-format/invalid/createEntities-items.json new file mode 100644 index 000000000..8e9d6ff70 --- /dev/null +++ b/test/unified-test-format/invalid/createEntities-items.json @@ -0,0 +1,13 @@ +{ + "description": "createEntities-items", + "schemaVersion": "1.0", + "createEntities": [ + 0 + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/createEntities-minItems.json b/test/unified-test-format/invalid/createEntities-minItems.json new file mode 100644 index 000000000..3654923d2 --- /dev/null +++ b/test/unified-test-format/invalid/createEntities-minItems.json @@ -0,0 +1,11 @@ +{ + "description": "createEntities-minItems", + "schemaVersion": "1.0", + "createEntities": [], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/createEntities-type.json b/test/unified-test-format/invalid/createEntities-type.json new file mode 100644 index 000000000..ce3c382c9 --- /dev/null +++ b/test/unified-test-format/invalid/createEntities-type.json @@ -0,0 +1,11 @@ +{ + "description": "createEntities-type", + "schemaVersion": "1.0", + "createEntities": 0, + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/description-required.json b/test/unified-test-format/invalid/description-required.json new file mode 100644 index 000000000..e4e0d0efd --- /dev/null +++ b/test/unified-test-format/invalid/description-required.json @@ -0,0 +1,9 @@ +{ + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-additionalProperties.json b/test/unified-test-format/invalid/entity-additionalProperties.json new file mode 100644 index 000000000..38b889878 --- /dev/null +++ b/test/unified-test-format/invalid/entity-additionalProperties.json @@ -0,0 +1,15 @@ +{ + "description": "entity-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "foo": 0 + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-bucket-additionalProperties.json b/test/unified-test-format/invalid/entity-bucket-additionalProperties.json new file mode 100644 index 000000000..46f9b4038 --- /dev/null +++ b/test/unified-test-format/invalid/entity-bucket-additionalProperties.json @@ -0,0 +1,31 @@ +{ + "description": "entity-bucket-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0", + "foo": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-bucket-bucketOptions-type.json b/test/unified-test-format/invalid/entity-bucket-bucketOptions-type.json new file mode 100644 index 000000000..c3d7423e6 --- /dev/null +++ b/test/unified-test-format/invalid/entity-bucket-bucketOptions-type.json @@ -0,0 +1,31 @@ +{ + "description": "entity-bucket-bucketOptions-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0", + "bucketOptions": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-bucket-database-required.json b/test/unified-test-format/invalid/entity-bucket-database-required.json new file mode 100644 index 000000000..1fde5a96c --- /dev/null +++ b/test/unified-test-format/invalid/entity-bucket-database-required.json @@ -0,0 +1,29 @@ +{ + "description": "entity-bucket-database-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "bucket": { + "id": "bucket0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-bucket-database-type.json b/test/unified-test-format/invalid/entity-bucket-database-type.json new file mode 100644 index 000000000..798d273fb --- /dev/null +++ b/test/unified-test-format/invalid/entity-bucket-database-type.json @@ -0,0 +1,30 @@ +{ + "description": "entity-bucket-database-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "bucket": { + "id": "bucket0", + "database": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-bucket-id-required.json b/test/unified-test-format/invalid/entity-bucket-id-required.json new file mode 100644 index 000000000..c547d8ea3 --- /dev/null +++ b/test/unified-test-format/invalid/entity-bucket-id-required.json @@ -0,0 +1,29 @@ +{ + "description": "entity-bucket-id-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "bucket": { + "database": "database0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-bucket-id-type.json b/test/unified-test-format/invalid/entity-bucket-id-type.json new file mode 100644 index 000000000..f4e10ee63 --- /dev/null +++ b/test/unified-test-format/invalid/entity-bucket-id-type.json @@ -0,0 +1,30 @@ +{ + "description": "entity-bucket-id-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "bucket": { + "id": 0, + "database": "database0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-additionalProperties.json b/test/unified-test-format/invalid/entity-client-additionalProperties.json new file mode 100644 index 000000000..467e1d6ae --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-additionalProperties.json @@ -0,0 +1,18 @@ +{ + "description": "entity-client-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "foo": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-id-required.json b/test/unified-test-format/invalid/entity-client-id-required.json new file mode 100644 index 000000000..4be2fbf8e --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-id-required.json @@ -0,0 +1,15 @@ +{ + "description": "entity-client-id-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": {} + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-id-type.json b/test/unified-test-format/invalid/entity-client-id-type.json new file mode 100644 index 000000000..cdc7cbc0e --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-id-type.json @@ -0,0 +1,17 @@ +{ + "description": "entity-client-id-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-items.json b/test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-items.json new file mode 100644 index 000000000..1252ac82d --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-items.json @@ -0,0 +1,20 @@ +{ + "description": "entity-client-ignoreCommandMonitoringEvents-items", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "ignoreCommandMonitoringEvents": [ + 0 + ] + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-minItems.json b/test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-minItems.json new file mode 100644 index 000000000..e78068a44 --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-minItems.json @@ -0,0 +1,18 @@ +{ + "description": "entity-client-ignoreCommandMonitoringEvents-minItems", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "ignoreCommandMonitoringEvents": [] + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-type.json b/test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-type.json new file mode 100644 index 000000000..5ac2b340c --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-ignoreCommandMonitoringEvents-type.json @@ -0,0 +1,18 @@ +{ + "description": "entity-client-ignoreCommandMonitoringEvents-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "ignoreCommandMonitoringEvents": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-observeEvents-enum.json b/test/unified-test-format/invalid/entity-client-observeEvents-enum.json new file mode 100644 index 000000000..c39c94eee --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-observeEvents-enum.json @@ -0,0 +1,20 @@ +{ + "description": "entity-client-observeEvents-enum", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "foo" + ] + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-observeEvents-items.json b/test/unified-test-format/invalid/entity-client-observeEvents-items.json new file mode 100644 index 000000000..3aee11e3d --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-observeEvents-items.json @@ -0,0 +1,20 @@ +{ + "description": "entity-client-observeEvents-items", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + 0 + ] + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-observeEvents-minItems.json b/test/unified-test-format/invalid/entity-client-observeEvents-minItems.json new file mode 100644 index 000000000..e70d90c0a --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-observeEvents-minItems.json @@ -0,0 +1,18 @@ +{ + "description": "entity-client-observeEvents-minItems", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [] + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-observeEvents-type.json b/test/unified-test-format/invalid/entity-client-observeEvents-type.json new file mode 100644 index 000000000..c144e3236 --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-observeEvents-type.json @@ -0,0 +1,18 @@ +{ + "description": "entity-client-observeEvents-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-uriOptions-type.json b/test/unified-test-format/invalid/entity-client-uriOptions-type.json new file mode 100644 index 000000000..4252480e9 --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-uriOptions-type.json @@ -0,0 +1,18 @@ +{ + "description": "entity-client-uriOptions-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "uriOptions": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-client-useMultipleMongoses-type.json b/test/unified-test-format/invalid/entity-client-useMultipleMongoses-type.json new file mode 100644 index 000000000..e429cd71f --- /dev/null +++ b/test/unified-test-format/invalid/entity-client-useMultipleMongoses-type.json @@ -0,0 +1,18 @@ +{ + "description": "entity-client-useMultipleMongoses-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-collection-additionalProperties.json b/test/unified-test-format/invalid/entity-collection-additionalProperties.json new file mode 100644 index 000000000..90ee2b1ca --- /dev/null +++ b/test/unified-test-format/invalid/entity-collection-additionalProperties.json @@ -0,0 +1,32 @@ +{ + "description": "entity-collection-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "foo", + "foo": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-collection-collectionName-required.json b/test/unified-test-format/invalid/entity-collection-collectionName-required.json new file mode 100644 index 000000000..2446722e5 --- /dev/null +++ b/test/unified-test-format/invalid/entity-collection-collectionName-required.json @@ -0,0 +1,30 @@ +{ + "description": "entity-collection-collectionName-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-collection-collectionName-type.json b/test/unified-test-format/invalid/entity-collection-collectionName-type.json new file mode 100644 index 000000000..ccad66aac --- /dev/null +++ b/test/unified-test-format/invalid/entity-collection-collectionName-type.json @@ -0,0 +1,31 @@ +{ + "description": "entity-collection-collectionName-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-collection-collectionOptions-type.json b/test/unified-test-format/invalid/entity-collection-collectionOptions-type.json new file mode 100644 index 000000000..52220c1cd --- /dev/null +++ b/test/unified-test-format/invalid/entity-collection-collectionOptions-type.json @@ -0,0 +1,32 @@ +{ + "description": "entity-collection-collectionOptions-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "foo", + "collectionOptions": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-collection-database-required.json b/test/unified-test-format/invalid/entity-collection-database-required.json new file mode 100644 index 000000000..ba96b43f7 --- /dev/null +++ b/test/unified-test-format/invalid/entity-collection-database-required.json @@ -0,0 +1,30 @@ +{ + "description": "entity-collection-database-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "collectionName": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-collection-database-type.json b/test/unified-test-format/invalid/entity-collection-database-type.json new file mode 100644 index 000000000..b87134498 --- /dev/null +++ b/test/unified-test-format/invalid/entity-collection-database-type.json @@ -0,0 +1,31 @@ +{ + "description": "entity-collection-database-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection0", + "database": 0, + "collectionName": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-collection-id-required.json b/test/unified-test-format/invalid/entity-collection-id-required.json new file mode 100644 index 000000000..84e5352ea --- /dev/null +++ b/test/unified-test-format/invalid/entity-collection-id-required.json @@ -0,0 +1,30 @@ +{ + "description": "entity-collection-id-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "database": "database0", + "collectionName": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-collection-id-type.json b/test/unified-test-format/invalid/entity-collection-id-type.json new file mode 100644 index 000000000..f0821e525 --- /dev/null +++ b/test/unified-test-format/invalid/entity-collection-id-type.json @@ -0,0 +1,31 @@ +{ + "description": "entity-collection-id-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + }, + { + "collection": { + "id": 0, + "database": "database0", + "collectionName": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-database-additionalProperties.json b/test/unified-test-format/invalid/entity-database-additionalProperties.json new file mode 100644 index 000000000..964cd2796 --- /dev/null +++ b/test/unified-test-format/invalid/entity-database-additionalProperties.json @@ -0,0 +1,25 @@ +{ + "description": "entity-database-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo", + "foo": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-database-client-required.json b/test/unified-test-format/invalid/entity-database-client-required.json new file mode 100644 index 000000000..54f99cf13 --- /dev/null +++ b/test/unified-test-format/invalid/entity-database-client-required.json @@ -0,0 +1,23 @@ +{ + "description": "entity-database-client-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "databaseName": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-database-client-type.json b/test/unified-test-format/invalid/entity-database-client-type.json new file mode 100644 index 000000000..ff4584c40 --- /dev/null +++ b/test/unified-test-format/invalid/entity-database-client-type.json @@ -0,0 +1,24 @@ +{ + "description": "entity-database-client-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": 0, + "databaseName": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-database-databaseName-required.json b/test/unified-test-format/invalid/entity-database-databaseName-required.json new file mode 100644 index 000000000..64cca95c4 --- /dev/null +++ b/test/unified-test-format/invalid/entity-database-databaseName-required.json @@ -0,0 +1,23 @@ +{ + "description": "entity-database-databaseName-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-database-databaseName-type.json b/test/unified-test-format/invalid/entity-database-databaseName-type.json new file mode 100644 index 000000000..bd01aef78 --- /dev/null +++ b/test/unified-test-format/invalid/entity-database-databaseName-type.json @@ -0,0 +1,24 @@ +{ + "description": "entity-database-databaseName-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-database-databaseOptions-type.json b/test/unified-test-format/invalid/entity-database-databaseOptions-type.json new file mode 100644 index 000000000..bc22ad312 --- /dev/null +++ b/test/unified-test-format/invalid/entity-database-databaseOptions-type.json @@ -0,0 +1,25 @@ +{ + "description": "entity-database-databaseOptions-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo", + "databaseOptions": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-database-id-required.json b/test/unified-test-format/invalid/entity-database-id-required.json new file mode 100644 index 000000000..0b65cf115 --- /dev/null +++ b/test/unified-test-format/invalid/entity-database-id-required.json @@ -0,0 +1,23 @@ +{ + "description": "entity-database-id-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "client": "client0", + "databaseName": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-database-id-type.json b/test/unified-test-format/invalid/entity-database-id-type.json new file mode 100644 index 000000000..98b5789d0 --- /dev/null +++ b/test/unified-test-format/invalid/entity-database-id-type.json @@ -0,0 +1,24 @@ +{ + "description": "entity-database-id-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": 0, + "client": "client0", + "databaseName": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-maxProperties.json b/test/unified-test-format/invalid/entity-maxProperties.json new file mode 100644 index 000000000..f4a6b7c91 --- /dev/null +++ b/test/unified-test-format/invalid/entity-maxProperties.json @@ -0,0 +1,22 @@ +{ + "description": "entity-maxProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + }, + "database": { + "id": "database0", + "client": "client0", + "databaseName": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-minProperties.json b/test/unified-test-format/invalid/entity-minProperties.json new file mode 100644 index 000000000..d89949ce3 --- /dev/null +++ b/test/unified-test-format/invalid/entity-minProperties.json @@ -0,0 +1,13 @@ +{ + "description": "entity-minProperties", + "schemaVersion": "1.0", + "createEntities": [ + {} + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-session-additionalProperties.json b/test/unified-test-format/invalid/entity-session-additionalProperties.json new file mode 100644 index 000000000..ab4cd2014 --- /dev/null +++ b/test/unified-test-format/invalid/entity-session-additionalProperties.json @@ -0,0 +1,24 @@ +{ + "description": "entity-session-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "session": { + "id": "session0", + "client": "client0", + "foo": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-session-client-required.json b/test/unified-test-format/invalid/entity-session-client-required.json new file mode 100644 index 000000000..8c9ed72e9 --- /dev/null +++ b/test/unified-test-format/invalid/entity-session-client-required.json @@ -0,0 +1,22 @@ +{ + "description": "entity-session-client-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "session": { + "id": "session0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-session-client-type.json b/test/unified-test-format/invalid/entity-session-client-type.json new file mode 100644 index 000000000..b5ccc3f60 --- /dev/null +++ b/test/unified-test-format/invalid/entity-session-client-type.json @@ -0,0 +1,23 @@ +{ + "description": "entity-session-client-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "session": { + "id": "session0", + "client": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-session-id-required.json b/test/unified-test-format/invalid/entity-session-id-required.json new file mode 100644 index 000000000..3e5d5c543 --- /dev/null +++ b/test/unified-test-format/invalid/entity-session-id-required.json @@ -0,0 +1,22 @@ +{ + "description": "entity-session-id-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "session": { + "client": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-session-id-type.json b/test/unified-test-format/invalid/entity-session-id-type.json new file mode 100644 index 000000000..dcd46e5be --- /dev/null +++ b/test/unified-test-format/invalid/entity-session-id-type.json @@ -0,0 +1,23 @@ +{ + "description": "entity-session-id-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "session": { + "id": 0, + "client": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-session-sessionOptions-type.json b/test/unified-test-format/invalid/entity-session-sessionOptions-type.json new file mode 100644 index 000000000..0ee15891e --- /dev/null +++ b/test/unified-test-format/invalid/entity-session-sessionOptions-type.json @@ -0,0 +1,24 @@ +{ + "description": "entity-session-sessionOptions-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "session": { + "id": "session0", + "client": "client0", + "sessionOptions": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-stream-additionalProperties.json b/test/unified-test-format/invalid/entity-stream-additionalProperties.json new file mode 100644 index 000000000..c8e76e998 --- /dev/null +++ b/test/unified-test-format/invalid/entity-stream-additionalProperties.json @@ -0,0 +1,19 @@ +{ + "description": "entity-stream-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "stream": { + "id": "stream0", + "hexBytes": "FF", + "foo": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-stream-hexBytes-pattern.json b/test/unified-test-format/invalid/entity-stream-hexBytes-pattern.json new file mode 100644 index 000000000..7381893b5 --- /dev/null +++ b/test/unified-test-format/invalid/entity-stream-hexBytes-pattern.json @@ -0,0 +1,18 @@ +{ + "description": "entity-stream-hexBytes-pattern", + "schemaVersion": "1.0", + "createEntities": [ + { + "stream": { + "id": "stream0", + "hexBytes": "FFF" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-stream-hexBytes-required.json b/test/unified-test-format/invalid/entity-stream-hexBytes-required.json new file mode 100644 index 000000000..cc3bf09b2 --- /dev/null +++ b/test/unified-test-format/invalid/entity-stream-hexBytes-required.json @@ -0,0 +1,17 @@ +{ + "description": "entity-stream-hexBytes-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "stream": { + "id": "stream0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-stream-hexBytes-type.json b/test/unified-test-format/invalid/entity-stream-hexBytes-type.json new file mode 100644 index 000000000..e6e2299ea --- /dev/null +++ b/test/unified-test-format/invalid/entity-stream-hexBytes-type.json @@ -0,0 +1,18 @@ +{ + "description": "entity-stream-hexBytes-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "stream": { + "id": "stream0", + "hexBytes": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-stream-id-required.json b/test/unified-test-format/invalid/entity-stream-id-required.json new file mode 100644 index 000000000..ff814d4e9 --- /dev/null +++ b/test/unified-test-format/invalid/entity-stream-id-required.json @@ -0,0 +1,17 @@ +{ + "description": "entity-stream-id-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "stream": { + "hexBytes": "FF" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/entity-stream-id-type.json b/test/unified-test-format/invalid/entity-stream-id-type.json new file mode 100644 index 000000000..5fc654d97 --- /dev/null +++ b/test/unified-test-format/invalid/entity-stream-id-type.json @@ -0,0 +1,18 @@ +{ + "description": "entity-stream-id-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "stream": { + "id": 0, + "hexBytes": "FF" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-additionalProperties.json b/test/unified-test-format/invalid/expectedError-additionalProperties.json new file mode 100644 index 000000000..3a79df8e3 --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-additionalProperties.json @@ -0,0 +1,25 @@ +{ + "description": "expectedError-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "foo": 0 + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-errorCode-type.json b/test/unified-test-format/invalid/expectedError-errorCode-type.json new file mode 100644 index 000000000..b6b6f5d05 --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-errorCode-type.json @@ -0,0 +1,25 @@ +{ + "description": "expectedError-errorCode-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "errorCode": "foo" + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-errorCodeName-type.json b/test/unified-test-format/invalid/expectedError-errorCodeName-type.json new file mode 100644 index 000000000..3ac5e4304 --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-errorCodeName-type.json @@ -0,0 +1,25 @@ +{ + "description": "expectedError-errorCodeName-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "errorCodeName": 0 + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-errorContains-type.json b/test/unified-test-format/invalid/expectedError-errorContains-type.json new file mode 100644 index 000000000..847a987df --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-errorContains-type.json @@ -0,0 +1,25 @@ +{ + "description": "expectedError-errorContains-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "errorContains": 0 + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-errorLabelsContain-items.json b/test/unified-test-format/invalid/expectedError-errorLabelsContain-items.json new file mode 100644 index 000000000..4eab56ad1 --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-errorLabelsContain-items.json @@ -0,0 +1,27 @@ +{ + "description": "expectedError-errorLabelsContain-items", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "errorLabelsContain": [ + 0 + ] + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-errorLabelsContain-minItems.json b/test/unified-test-format/invalid/expectedError-errorLabelsContain-minItems.json new file mode 100644 index 000000000..48162110a --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-errorLabelsContain-minItems.json @@ -0,0 +1,25 @@ +{ + "description": "expectedError-errorLabelsContain-minItems", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "errorLabelsContain": [] + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-errorLabelsContain-type.json b/test/unified-test-format/invalid/expectedError-errorLabelsContain-type.json new file mode 100644 index 000000000..a0aba918b --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-errorLabelsContain-type.json @@ -0,0 +1,25 @@ +{ + "description": "expectedError-errorLabelsContain-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "errorLabelsContain": 0 + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-errorLabelsOmit-items.json b/test/unified-test-format/invalid/expectedError-errorLabelsOmit-items.json new file mode 100644 index 000000000..6c94d0713 --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-errorLabelsOmit-items.json @@ -0,0 +1,27 @@ +{ + "description": "expectedError-errorLabelsOmit-items", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "errorLabelsOmit": [ + 0 + ] + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-errorLabelsOmit-minItems.json b/test/unified-test-format/invalid/expectedError-errorLabelsOmit-minItems.json new file mode 100644 index 000000000..88c658202 --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-errorLabelsOmit-minItems.json @@ -0,0 +1,25 @@ +{ + "description": "expectedError-errorLabelsOmit-minItems", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "errorLabelsOmit": [] + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-errorLabelsOmit-type.json b/test/unified-test-format/invalid/expectedError-errorLabelsOmit-type.json new file mode 100644 index 000000000..5f57114fe --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-errorLabelsOmit-type.json @@ -0,0 +1,25 @@ +{ + "description": "expectedError-errorLabelsOmit-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "errorLabelsOmit": 0 + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-isClientError-type.json b/test/unified-test-format/invalid/expectedError-isClientError-type.json new file mode 100644 index 000000000..bfcc06679 --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-isClientError-type.json @@ -0,0 +1,25 @@ +{ + "description": "expectedError-isClientError-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "isClientError": 0 + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-isError-const.json b/test/unified-test-format/invalid/expectedError-isError-const.json new file mode 100644 index 000000000..6a398bbf2 --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-isError-const.json @@ -0,0 +1,25 @@ +{ + "description": "expectedError-isError-const", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "isError": false + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-isError-type.json b/test/unified-test-format/invalid/expectedError-isError-type.json new file mode 100644 index 000000000..354aff31f --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-isError-type.json @@ -0,0 +1,25 @@ +{ + "description": "expectedError-isError-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "isError": 0 + } + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedError-minProperties.json b/test/unified-test-format/invalid/expectedError-minProperties.json new file mode 100644 index 000000000..10e0b89ab --- /dev/null +++ b/test/unified-test-format/invalid/expectedError-minProperties.json @@ -0,0 +1,23 @@ +{ + "description": "expectedError-minProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": {} + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEvent-additionalProperties.json b/test/unified-test-format/invalid/expectedEvent-additionalProperties.json new file mode 100644 index 000000000..2c4f7d27e --- /dev/null +++ b/test/unified-test-format/invalid/expectedEvent-additionalProperties.json @@ -0,0 +1,32 @@ +{ + "description": "expectedEvent-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "foo": 0 + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEvent-commandFailedEvent-commandName-type.json b/test/unified-test-format/invalid/expectedEvent-commandFailedEvent-commandName-type.json new file mode 100644 index 000000000..ea6078faa --- /dev/null +++ b/test/unified-test-format/invalid/expectedEvent-commandFailedEvent-commandName-type.json @@ -0,0 +1,34 @@ +{ + "description": "expectedEvent-commandFailedEvent-commandName-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandFailedEvent": { + "commandName": 0 + } + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-additionalProperties.json b/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-additionalProperties.json new file mode 100644 index 000000000..ee6eb5065 --- /dev/null +++ b/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-additionalProperties.json @@ -0,0 +1,34 @@ +{ + "description": "expectedEvent-commandStartedEvent-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "foo": 0 + } + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-command-type.json b/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-command-type.json new file mode 100644 index 000000000..4c9483caf --- /dev/null +++ b/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-command-type.json @@ -0,0 +1,34 @@ +{ + "description": "expectedEvent-commandStartedEvent-command-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": 0 + } + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-commandName-type.json b/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-commandName-type.json new file mode 100644 index 000000000..a5a66096a --- /dev/null +++ b/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-commandName-type.json @@ -0,0 +1,34 @@ +{ + "description": "expectedEvent-commandStartedEvent-commandName-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": 0 + } + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-databaseName-type.json b/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-databaseName-type.json new file mode 100644 index 000000000..dc040ec10 --- /dev/null +++ b/test/unified-test-format/invalid/expectedEvent-commandStartedEvent-databaseName-type.json @@ -0,0 +1,34 @@ +{ + "description": "expectedEvent-commandStartedEvent-databaseName-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "databaseName": 0 + } + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEvent-commandSucceededEvent-commandName-type.json b/test/unified-test-format/invalid/expectedEvent-commandSucceededEvent-commandName-type.json new file mode 100644 index 000000000..4a20e906b --- /dev/null +++ b/test/unified-test-format/invalid/expectedEvent-commandSucceededEvent-commandName-type.json @@ -0,0 +1,34 @@ +{ + "description": "expectedEvent-commandSucceededEvent-commandName-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandSucceededEvent": { + "commandName": 0 + } + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEvent-commandSucceededEvent-reply-type.json b/test/unified-test-format/invalid/expectedEvent-commandSucceededEvent-reply-type.json new file mode 100644 index 000000000..546454275 --- /dev/null +++ b/test/unified-test-format/invalid/expectedEvent-commandSucceededEvent-reply-type.json @@ -0,0 +1,34 @@ +{ + "description": "expectedEvent-commandSucceededEvent-reply-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandSucceededEvent": { + "reply": 0 + } + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEvent-maxProperties.json b/test/unified-test-format/invalid/expectedEvent-maxProperties.json new file mode 100644 index 000000000..f01441946 --- /dev/null +++ b/test/unified-test-format/invalid/expectedEvent-maxProperties.json @@ -0,0 +1,33 @@ +{ + "description": "expectedEvent-maxProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": {}, + "commandSucceededEvent": {} + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEvent-minProperties.json b/test/unified-test-format/invalid/expectedEvent-minProperties.json new file mode 100644 index 000000000..ebcc49489 --- /dev/null +++ b/test/unified-test-format/invalid/expectedEvent-minProperties.json @@ -0,0 +1,30 @@ +{ + "description": "expectedEvent-minProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [ + {} + ] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEventsForClient-additionalProperties.json b/test/unified-test-format/invalid/expectedEventsForClient-additionalProperties.json new file mode 100644 index 000000000..6ecf5931f --- /dev/null +++ b/test/unified-test-format/invalid/expectedEventsForClient-additionalProperties.json @@ -0,0 +1,29 @@ +{ + "description": "expectedEventsForClient-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [], + "foo": 0 + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEventsForClient-client-required.json b/test/unified-test-format/invalid/expectedEventsForClient-client-required.json new file mode 100644 index 000000000..b879db859 --- /dev/null +++ b/test/unified-test-format/invalid/expectedEventsForClient-client-required.json @@ -0,0 +1,27 @@ +{ + "description": "expectedEventsForClient-client-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "events": [] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEventsForClient-client-type.json b/test/unified-test-format/invalid/expectedEventsForClient-client-type.json new file mode 100644 index 000000000..4ee5427df --- /dev/null +++ b/test/unified-test-format/invalid/expectedEventsForClient-client-type.json @@ -0,0 +1,28 @@ +{ + "description": "expectedEventsForClient-client-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": 0, + "events": [] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEventsForClient-events-items.json b/test/unified-test-format/invalid/expectedEventsForClient-events-items.json new file mode 100644 index 000000000..ee8ce4a40 --- /dev/null +++ b/test/unified-test-format/invalid/expectedEventsForClient-events-items.json @@ -0,0 +1,30 @@ +{ + "description": "expectedEventsForClient-events-items", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": [ + 0 + ] + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEventsForClient-events-required.json b/test/unified-test-format/invalid/expectedEventsForClient-events-required.json new file mode 100644 index 000000000..7f1bc6fb5 --- /dev/null +++ b/test/unified-test-format/invalid/expectedEventsForClient-events-required.json @@ -0,0 +1,27 @@ +{ + "description": "expectedEventsForClient-events-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0" + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/expectedEventsForClient-events-type.json b/test/unified-test-format/invalid/expectedEventsForClient-events-type.json new file mode 100644 index 000000000..f171fc2b9 --- /dev/null +++ b/test/unified-test-format/invalid/expectedEventsForClient-events-type.json @@ -0,0 +1,28 @@ +{ + "description": "expectedEventsForClient-events-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": [ + { + "client": "client0", + "events": 0 + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/initialData-items.json b/test/unified-test-format/invalid/initialData-items.json new file mode 100644 index 000000000..9c27d554f --- /dev/null +++ b/test/unified-test-format/invalid/initialData-items.json @@ -0,0 +1,13 @@ +{ + "description": "initialData-items", + "schemaVersion": "1.0", + "initialData": [ + 0 + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/initialData-minItems.json b/test/unified-test-format/invalid/initialData-minItems.json new file mode 100644 index 000000000..984100a2b --- /dev/null +++ b/test/unified-test-format/invalid/initialData-minItems.json @@ -0,0 +1,11 @@ +{ + "description": "initialData-minItems", + "schemaVersion": "1.0", + "initialData": [], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/initialData-type.json b/test/unified-test-format/invalid/initialData-type.json new file mode 100644 index 000000000..c33585e03 --- /dev/null +++ b/test/unified-test-format/invalid/initialData-type.json @@ -0,0 +1,11 @@ +{ + "description": "initialData-type", + "schemaVersion": "1.0", + "initialData": 0, + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/operation-additionalProperties.json b/test/unified-test-format/invalid/operation-additionalProperties.json new file mode 100644 index 000000000..8f2f1434e --- /dev/null +++ b/test/unified-test-format/invalid/operation-additionalProperties.json @@ -0,0 +1,23 @@ +{ + "description": "operation-additionalProperties", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "foo": 0 + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/operation-arguments-type.json b/test/unified-test-format/invalid/operation-arguments-type.json new file mode 100644 index 000000000..a22f3921c --- /dev/null +++ b/test/unified-test-format/invalid/operation-arguments-type.json @@ -0,0 +1,23 @@ +{ + "description": "operation-arguments-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "arguments": 0 + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/operation-expectError-conflicts_with_expectResult.json b/test/unified-test-format/invalid/operation-expectError-conflicts_with_expectResult.json new file mode 100644 index 000000000..bc15fbac7 --- /dev/null +++ b/test/unified-test-format/invalid/operation-expectError-conflicts_with_expectResult.json @@ -0,0 +1,26 @@ +{ + "description": "operation-expectError-conflicts_with_expectResult", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "isError": true + }, + "expectResult": {} + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/operation-expectError-conflicts_with_saveResultAsEntity.json b/test/unified-test-format/invalid/operation-expectError-conflicts_with_saveResultAsEntity.json new file mode 100644 index 000000000..dead4a3b9 --- /dev/null +++ b/test/unified-test-format/invalid/operation-expectError-conflicts_with_saveResultAsEntity.json @@ -0,0 +1,26 @@ +{ + "description": "operation-expectError-conflicts_with_saveResultAsEntity", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": { + "isError": true + }, + "saveResultAsEntity": "foo" + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/operation-expectError-type.json b/test/unified-test-format/invalid/operation-expectError-type.json new file mode 100644 index 000000000..b224ba353 --- /dev/null +++ b/test/unified-test-format/invalid/operation-expectError-type.json @@ -0,0 +1,23 @@ +{ + "description": "operation-expectError-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectError": 0 + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/operation-expectEvents-type.json b/test/unified-test-format/invalid/operation-expectEvents-type.json new file mode 100644 index 000000000..ecd4c011a --- /dev/null +++ b/test/unified-test-format/invalid/operation-expectEvents-type.json @@ -0,0 +1,23 @@ +{ + "description": "operation-expectEvents-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "expectEvents": 0 + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/operation-name-required.json b/test/unified-test-format/invalid/operation-name-required.json new file mode 100644 index 000000000..42fcb3a30 --- /dev/null +++ b/test/unified-test-format/invalid/operation-name-required.json @@ -0,0 +1,21 @@ +{ + "description": "operation-name-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "object": "client0" + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/operation-name-type.json b/test/unified-test-format/invalid/operation-name-type.json new file mode 100644 index 000000000..2f91da078 --- /dev/null +++ b/test/unified-test-format/invalid/operation-name-type.json @@ -0,0 +1,22 @@ +{ + "description": "operation-name-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": 0, + "object": "client0" + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/operation-object-required.json b/test/unified-test-format/invalid/operation-object-required.json new file mode 100644 index 000000000..c0410ce3f --- /dev/null +++ b/test/unified-test-format/invalid/operation-object-required.json @@ -0,0 +1,21 @@ +{ + "description": "operation-object-required", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo" + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/operation-object-type.json b/test/unified-test-format/invalid/operation-object-type.json new file mode 100644 index 000000000..edb0a0b51 --- /dev/null +++ b/test/unified-test-format/invalid/operation-object-type.json @@ -0,0 +1,22 @@ +{ + "description": "operation-object-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": 0 + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/operation-saveResultAsEntity-type.json b/test/unified-test-format/invalid/operation-saveResultAsEntity-type.json new file mode 100644 index 000000000..65ead94c7 --- /dev/null +++ b/test/unified-test-format/invalid/operation-saveResultAsEntity-type.json @@ -0,0 +1,23 @@ +{ + "description": "operation-saveResultAsEntity-type", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [ + { + "name": "foo", + "object": "client0", + "saveResultAsEntity": 0 + } + ] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirement-additionalProperties.json b/test/unified-test-format/invalid/runOnRequirement-additionalProperties.json new file mode 100644 index 000000000..79fa687e4 --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirement-additionalProperties.json @@ -0,0 +1,16 @@ +{ + "description": "runOnRequirement-additionalProperties", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "foo": 0 + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirement-maxServerVersion-pattern.json b/test/unified-test-format/invalid/runOnRequirement-maxServerVersion-pattern.json new file mode 100644 index 000000000..78766eb92 --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirement-maxServerVersion-pattern.json @@ -0,0 +1,15 @@ +{ + "description": "runOnRequirement-maxServerVersion-pattern", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "maxServerVersion": "1.2.3.4" + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirement-maxServerVersion-type.json b/test/unified-test-format/invalid/runOnRequirement-maxServerVersion-type.json new file mode 100644 index 000000000..ffc9118ba --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirement-maxServerVersion-type.json @@ -0,0 +1,15 @@ +{ + "description": "runOnRequirement-maxServerVersion-type", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "maxServerVersion": 0 + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirement-minProperties.json b/test/unified-test-format/invalid/runOnRequirement-minProperties.json new file mode 100644 index 000000000..c2bfed3be --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirement-minProperties.json @@ -0,0 +1,13 @@ +{ + "description": "runOnRequirement-minProperties", + "schemaVersion": "1.0", + "runOnRequirements": [ + {} + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirement-minServerVersion-pattern.json b/test/unified-test-format/invalid/runOnRequirement-minServerVersion-pattern.json new file mode 100644 index 000000000..19abc1755 --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirement-minServerVersion-pattern.json @@ -0,0 +1,15 @@ +{ + "description": "runOnRequirement-minServerVersion-pattern", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "1.2.3.4" + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirement-minServerVersion-type.json b/test/unified-test-format/invalid/runOnRequirement-minServerVersion-type.json new file mode 100644 index 000000000..688d1c67e --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirement-minServerVersion-type.json @@ -0,0 +1,15 @@ +{ + "description": "runOnRequirement-minServerVersion-type", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": 0 + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirement-topologies-enum.json b/test/unified-test-format/invalid/runOnRequirement-topologies-enum.json new file mode 100644 index 000000000..f62e5040d --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirement-topologies-enum.json @@ -0,0 +1,17 @@ +{ + "description": "runOnRequirement-topologies-enum", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "topologies": [ + "foo" + ] + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirement-topologies-items.json b/test/unified-test-format/invalid/runOnRequirement-topologies-items.json new file mode 100644 index 000000000..a205b3293 --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirement-topologies-items.json @@ -0,0 +1,17 @@ +{ + "description": "runOnRequirement-topologies-items", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "topologies": [ + 0 + ] + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirement-topologies-minItems.json b/test/unified-test-format/invalid/runOnRequirement-topologies-minItems.json new file mode 100644 index 000000000..16f29b3f4 --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirement-topologies-minItems.json @@ -0,0 +1,15 @@ +{ + "description": "runOnRequirement-topologies-minItems", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "topologies": [] + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirement-topologies-type.json b/test/unified-test-format/invalid/runOnRequirement-topologies-type.json new file mode 100644 index 000000000..f6d147cd6 --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirement-topologies-type.json @@ -0,0 +1,15 @@ +{ + "description": "runOnRequirement-topologies-type", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "topologies": 0 + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirements-items.json b/test/unified-test-format/invalid/runOnRequirements-items.json new file mode 100644 index 000000000..40ec84a3f --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirements-items.json @@ -0,0 +1,13 @@ +{ + "description": "runOnRequirements-items", + "schemaVersion": "1.0", + "runOnRequirements": [ + 0 + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirements-minItems.json b/test/unified-test-format/invalid/runOnRequirements-minItems.json new file mode 100644 index 000000000..4ca9f99b5 --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirements-minItems.json @@ -0,0 +1,11 @@ +{ + "description": "runOnRequirements-minItems", + "schemaVersion": "1.0", + "runOnRequirements": [], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/runOnRequirements-type.json b/test/unified-test-format/invalid/runOnRequirements-type.json new file mode 100644 index 000000000..98b859f3e --- /dev/null +++ b/test/unified-test-format/invalid/runOnRequirements-type.json @@ -0,0 +1,11 @@ +{ + "description": "runOnRequirements-type", + "schemaVersion": "1.0", + "runOnRequirements": 0, + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/schemaVersion-pattern.json b/test/unified-test-format/invalid/schemaVersion-pattern.json new file mode 100644 index 000000000..bcb898051 --- /dev/null +++ b/test/unified-test-format/invalid/schemaVersion-pattern.json @@ -0,0 +1,10 @@ +{ + "description": "schemaVersion-pattern", + "schemaVersion": "1.2.3.4", + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/schemaVersion-required.json b/test/unified-test-format/invalid/schemaVersion-required.json new file mode 100644 index 000000000..7388ff0bf --- /dev/null +++ b/test/unified-test-format/invalid/schemaVersion-required.json @@ -0,0 +1,9 @@ +{ + "description": "schemaVersion-required", + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/schemaVersion-type.json b/test/unified-test-format/invalid/schemaVersion-type.json new file mode 100644 index 000000000..646473a20 --- /dev/null +++ b/test/unified-test-format/invalid/schemaVersion-type.json @@ -0,0 +1,10 @@ +{ + "description": "schemaVersion-type", + "schemaVersion": 0, + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/invalid/test-additionalProperties.json b/test/unified-test-format/invalid/test-additionalProperties.json new file mode 100644 index 000000000..a699319c3 --- /dev/null +++ b/test/unified-test-format/invalid/test-additionalProperties.json @@ -0,0 +1,11 @@ +{ + "description": "test-additionalProperties", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [], + "foo": 0 + } + ] +} diff --git a/test/unified-test-format/invalid/test-description-required.json b/test/unified-test-format/invalid/test-description-required.json new file mode 100644 index 000000000..8bf23014d --- /dev/null +++ b/test/unified-test-format/invalid/test-description-required.json @@ -0,0 +1,9 @@ +{ + "description": "test-description-required", + "schemaVersion": "1.0", + "tests": [ + { + "operation": [] + } + ] +} diff --git a/test/unified-test-format/invalid/test-description-type.json b/test/unified-test-format/invalid/test-description-type.json new file mode 100644 index 000000000..bba369044 --- /dev/null +++ b/test/unified-test-format/invalid/test-description-type.json @@ -0,0 +1,10 @@ +{ + "description": "test-description-type", + "schemaVersion": "1.0", + "tests": [ + { + "description": 0, + "operation": [] + } + ] +} diff --git a/test/unified-test-format/invalid/test-expectEvents-items.json b/test/unified-test-format/invalid/test-expectEvents-items.json new file mode 100644 index 000000000..394f74746 --- /dev/null +++ b/test/unified-test-format/invalid/test-expectEvents-items.json @@ -0,0 +1,13 @@ +{ + "description": "test-expectEvents-items", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [], + "expectEvents": [ + 0 + ] + } + ] +} diff --git a/test/unified-test-format/invalid/test-expectEvents-type.json b/test/unified-test-format/invalid/test-expectEvents-type.json new file mode 100644 index 000000000..1569f0a0d --- /dev/null +++ b/test/unified-test-format/invalid/test-expectEvents-type.json @@ -0,0 +1,11 @@ +{ + "description": "test-expectEvents-type", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [], + "expectEvents": 0 + } + ] +} diff --git a/test/unified-test-format/invalid/test-operations-items.json b/test/unified-test-format/invalid/test-operations-items.json new file mode 100644 index 000000000..00af8e745 --- /dev/null +++ b/test/unified-test-format/invalid/test-operations-items.json @@ -0,0 +1,12 @@ +{ + "description": "test-operations-items", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [ + 0 + ] + } + ] +} diff --git a/test/unified-test-format/invalid/test-operations-required.json b/test/unified-test-format/invalid/test-operations-required.json new file mode 100644 index 000000000..67c6f8304 --- /dev/null +++ b/test/unified-test-format/invalid/test-operations-required.json @@ -0,0 +1,9 @@ +{ + "description": "test-operations-required", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo" + } + ] +} diff --git a/test/unified-test-format/invalid/test-operations-type.json b/test/unified-test-format/invalid/test-operations-type.json new file mode 100644 index 000000000..1e8b5b249 --- /dev/null +++ b/test/unified-test-format/invalid/test-operations-type.json @@ -0,0 +1,10 @@ +{ + "description": "test-operations-type", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": 0 + } + ] +} diff --git a/test/unified-test-format/invalid/test-outcome-items.json b/test/unified-test-format/invalid/test-outcome-items.json new file mode 100644 index 000000000..cf6bb54f8 --- /dev/null +++ b/test/unified-test-format/invalid/test-outcome-items.json @@ -0,0 +1,13 @@ +{ + "description": "test-outcome-items", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [], + "outcome": [ + 0 + ] + } + ] +} diff --git a/test/unified-test-format/invalid/test-outcome-minItems.json b/test/unified-test-format/invalid/test-outcome-minItems.json new file mode 100644 index 000000000..aadf8e514 --- /dev/null +++ b/test/unified-test-format/invalid/test-outcome-minItems.json @@ -0,0 +1,11 @@ +{ + "description": "test-outcome-minItems", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [], + "outcome": [] + } + ] +} diff --git a/test/unified-test-format/invalid/test-outcome-type.json b/test/unified-test-format/invalid/test-outcome-type.json new file mode 100644 index 000000000..e60c119d7 --- /dev/null +++ b/test/unified-test-format/invalid/test-outcome-type.json @@ -0,0 +1,11 @@ +{ + "description": "test-outcome-type", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [], + "outcome": 0 + } + ] +} diff --git a/test/unified-test-format/invalid/test-runOnRequirements-items.json b/test/unified-test-format/invalid/test-runOnRequirements-items.json new file mode 100644 index 000000000..866bebb51 --- /dev/null +++ b/test/unified-test-format/invalid/test-runOnRequirements-items.json @@ -0,0 +1,13 @@ +{ + "description": "test-runOnRequirements-items", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [], + "runOnRequirements": [ + 0 + ] + } + ] +} diff --git a/test/unified-test-format/invalid/test-runOnRequirements-minItems.json b/test/unified-test-format/invalid/test-runOnRequirements-minItems.json new file mode 100644 index 000000000..d61f06384 --- /dev/null +++ b/test/unified-test-format/invalid/test-runOnRequirements-minItems.json @@ -0,0 +1,11 @@ +{ + "description": "test-runOnRequirements-minItems", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [], + "runOnRequirements": [] + } + ] +} diff --git a/test/unified-test-format/invalid/test-runOnRequirements-type.json b/test/unified-test-format/invalid/test-runOnRequirements-type.json new file mode 100644 index 000000000..5b25b1005 --- /dev/null +++ b/test/unified-test-format/invalid/test-runOnRequirements-type.json @@ -0,0 +1,11 @@ +{ + "description": "test-runOnRequirements-type", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [], + "runOnRequirements": 0 + } + ] +} diff --git a/test/unified-test-format/invalid/test-skipReason-type.json b/test/unified-test-format/invalid/test-skipReason-type.json new file mode 100644 index 000000000..0408e7683 --- /dev/null +++ b/test/unified-test-format/invalid/test-skipReason-type.json @@ -0,0 +1,11 @@ +{ + "description": "test-skipReason-type", + "schemaVersion": "1.0", + "tests": [ + { + "description": "foo", + "operations": [], + "skipReason": 0 + } + ] +} diff --git a/test/unified-test-format/invalid/tests-items.json b/test/unified-test-format/invalid/tests-items.json new file mode 100644 index 000000000..11f37469e --- /dev/null +++ b/test/unified-test-format/invalid/tests-items.json @@ -0,0 +1,7 @@ +{ + "description": "tests-items", + "schemaVersion": "1.0", + "tests": [ + 0 + ] +} diff --git a/test/unified-test-format/invalid/tests-minItems.json b/test/unified-test-format/invalid/tests-minItems.json new file mode 100644 index 000000000..3f74f94af --- /dev/null +++ b/test/unified-test-format/invalid/tests-minItems.json @@ -0,0 +1,5 @@ +{ + "description": "tests-minItems", + "schemaVersion": "1.0", + "tests": [] +} diff --git a/test/unified-test-format/invalid/tests-required.json b/test/unified-test-format/invalid/tests-required.json new file mode 100644 index 000000000..de4b2fd06 --- /dev/null +++ b/test/unified-test-format/invalid/tests-required.json @@ -0,0 +1,4 @@ +{ + "description": "tests-required", + "schemaVersion": "1.0" +} diff --git a/test/unified-test-format/invalid/tests-type.json b/test/unified-test-format/invalid/tests-type.json new file mode 100644 index 000000000..62d8194a4 --- /dev/null +++ b/test/unified-test-format/invalid/tests-type.json @@ -0,0 +1,5 @@ +{ + "description": "tests-type", + "schemaVersion": "1.0", + "tests": 0 +} diff --git a/test/unified-test-format/valid-fail/entity-bucket-database-undefined.json b/test/unified-test-format/valid-fail/entity-bucket-database-undefined.json new file mode 100644 index 000000000..7f7f1978c --- /dev/null +++ b/test/unified-test-format/valid-fail/entity-bucket-database-undefined.json @@ -0,0 +1,18 @@ +{ + "description": "entity-bucket-database-undefined", + "schemaVersion": "1.0", + "createEntities": [ + { + "bucket": { + "id": "bucket0", + "database": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/valid-fail/entity-collection-database-undefined.json b/test/unified-test-format/valid-fail/entity-collection-database-undefined.json new file mode 100644 index 000000000..20b0733e3 --- /dev/null +++ b/test/unified-test-format/valid-fail/entity-collection-database-undefined.json @@ -0,0 +1,19 @@ +{ + "description": "entity-collection-database-undefined", + "schemaVersion": "1.0", + "createEntities": [ + { + "collection": { + "id": "collection0", + "database": "foo", + "collectionName": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/valid-fail/entity-database-client-undefined.json b/test/unified-test-format/valid-fail/entity-database-client-undefined.json new file mode 100644 index 000000000..0f8110e6d --- /dev/null +++ b/test/unified-test-format/valid-fail/entity-database-client-undefined.json @@ -0,0 +1,19 @@ +{ + "description": "entity-database-client-undefined", + "schemaVersion": "1.0", + "createEntities": [ + { + "database": { + "id": "database0", + "client": "foo", + "databaseName": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/valid-fail/entity-session-client-undefined.json b/test/unified-test-format/valid-fail/entity-session-client-undefined.json new file mode 100644 index 000000000..260356436 --- /dev/null +++ b/test/unified-test-format/valid-fail/entity-session-client-undefined.json @@ -0,0 +1,18 @@ +{ + "description": "entity-session-client-undefined", + "schemaVersion": "1.0", + "createEntities": [ + { + "session": { + "id": "session0", + "client": "foo" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/valid-fail/returnDocument-enum-invalid.json b/test/unified-test-format/valid-fail/returnDocument-enum-invalid.json new file mode 100644 index 000000000..ea425fb56 --- /dev/null +++ b/test/unified-test-format/valid-fail/returnDocument-enum-invalid.json @@ -0,0 +1,66 @@ +{ + "description": "returnDocument-enum-invalid", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "test" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "tests": [ + { + "description": "FindOneAndReplace returnDocument invalid enum value", + "operations": [ + { + "name": "findOneAndReplace", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + }, + "returnDocument": "invalid" + } + } + ] + }, + { + "description": "FindOneAndUpdate returnDocument invalid enum value", + "operations": [ + { + "name": "findOneAndUpdate", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "invalid" + } + } + ] + } + ] +} diff --git a/test/unified-test-format/valid-fail/schemaVersion-unsupported.json b/test/unified-test-format/valid-fail/schemaVersion-unsupported.json new file mode 100644 index 000000000..ceb553291 --- /dev/null +++ b/test/unified-test-format/valid-fail/schemaVersion-unsupported.json @@ -0,0 +1,10 @@ +{ + "description": "schemaVersion-unsupported", + "schemaVersion": "0.1", + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/test/unified-test-format/valid-pass/poc-change-streams.json b/test/unified-test-format/valid-pass/poc-change-streams.json new file mode 100644 index 000000000..2a2c41a68 --- /dev/null +++ b/test/unified-test-format/valid-pass/poc-change-streams.json @@ -0,0 +1,414 @@ +{ + "description": "poc-change-streams", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "getMore", + "killCursors" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "change-stream-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "test" + } + }, + { + "client": { + "id": "client1", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "change-stream-tests" + } + }, + { + "database": { + "id": "database2", + "client": "client1", + "databaseName": "change-stream-tests-2" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "test" + } + }, + { + "collection": { + "id": "collection2", + "database": "database1", + "collectionName": "test2" + } + }, + { + "collection": { + "id": "collection3", + "database": "database2", + "collectionName": "test" + } + } + ], + "initialData": [ + { + "collectionName": "test", + "databaseName": "change-stream-tests", + "documents": [] + }, + { + "collectionName": "test2", + "databaseName": "change-stream-tests", + "documents": [] + }, + { + "collectionName": "test", + "databaseName": "change-stream-tests-2", + "documents": [] + } + ], + "tests": [ + { + "description": "Executing a watch helper on a MongoClient results in notifications for changes to all collections in all databases in the cluster.", + "runOnRequirements": [ + { + "minServerVersion": "3.8.0", + "topologies": [ + "replicaset" + ] + } + ], + "operations": [ + { + "name": "createChangeStream", + "object": "client0", + "arguments": { + "pipeline": [] + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "insertOne", + "object": "collection2", + "arguments": { + "document": { + "x": 1 + } + } + }, + { + "name": "insertOne", + "object": "collection3", + "arguments": { + "document": { + "y": 1 + } + } + }, + { + "name": "insertOne", + "object": "collection1", + "arguments": { + "document": { + "z": 1 + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "insert", + "ns": { + "db": "change-stream-tests", + "coll": "test2" + }, + "fullDocument": { + "_id": { + "$$type": "objectId" + }, + "x": 1 + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "insert", + "ns": { + "db": "change-stream-tests-2", + "coll": "test" + }, + "fullDocument": { + "_id": { + "$$type": "objectId" + }, + "y": 1 + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "insert", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "fullDocument": { + "_id": { + "$$type": "objectId" + }, + "z": 1 + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true, + "fullDocument": { + "$$unsetOrMatches": "default" + } + } + } + ] + }, + "commandName": "aggregate", + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "Test consecutive resume", + "runOnRequirements": [ + { + "minServerVersion": "4.1.7", + "topologies": [ + "replicaset" + ] + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "getMore" + ], + "closeConnection": true + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "batchSize": 1, + "pipeline": [] + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "insertOne", + "object": "collection1", + "arguments": { + "document": { + "x": 1 + } + } + }, + { + "name": "insertOne", + "object": "collection1", + "arguments": { + "document": { + "x": 2 + } + } + }, + { + "name": "insertOne", + "object": "collection1", + "arguments": { + "document": { + "x": 3 + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "insert", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "fullDocument": { + "_id": { + "$$type": "objectId" + }, + "x": 1 + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "insert", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "fullDocument": { + "_id": { + "$$type": "objectId" + }, + "x": 2 + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "insert", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "fullDocument": { + "_id": { + "$$type": "objectId" + }, + "x": 3 + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "cursor": { + "batchSize": 1 + }, + "pipeline": [ + { + "$changeStream": { + "fullDocument": { + "$$unsetOrMatches": "default" + } + } + } + ] + }, + "commandName": "aggregate", + "databaseName": "change-stream-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "cursor": { + "batchSize": 1 + }, + "pipeline": [ + { + "$changeStream": { + "fullDocument": { + "$$unsetOrMatches": "default" + }, + "resumeAfter": { + "$$exists": true + } + } + } + ] + }, + "commandName": "aggregate", + "databaseName": "change-stream-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "cursor": { + "batchSize": 1 + }, + "pipeline": [ + { + "$changeStream": { + "fullDocument": { + "$$unsetOrMatches": "default" + }, + "resumeAfter": { + "$$exists": true + } + } + } + ] + }, + "commandName": "aggregate", + "databaseName": "change-stream-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/valid-pass/poc-command-monitoring.json b/test/unified-test-format/valid-pass/poc-command-monitoring.json new file mode 100644 index 000000000..499396e0b --- /dev/null +++ b/test/unified-test-format/valid-pass/poc-command-monitoring.json @@ -0,0 +1,222 @@ +{ + "description": "poc-command-monitoring", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent", + "commandFailedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "command-monitoring-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "test" + } + } + ], + "initialData": [ + { + "collectionName": "test", + "databaseName": "command-monitoring-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 5, + "x": 55 + } + ] + } + ], + "tests": [ + { + "description": "A successful find event with a getmore and the server kills the cursor", + "runOnRequirements": [ + { + "minServerVersion": "3.1", + "topologies": [ + "single", + "replicaset" + ] + } + ], + "operations": [ + { + "name": "find", + "object": "collection0", + "arguments": { + "filter": { + "_id": { + "$gte": 1 + } + }, + "sort": { + "_id": 1 + }, + "batchSize": 3, + "limit": 4 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "test", + "filter": { + "_id": { + "$gte": 1 + } + }, + "sort": { + "_id": 1 + }, + "batchSize": 3, + "limit": 4 + }, + "commandName": "find", + "databaseName": "command-monitoring-tests" + } + }, + { + "commandSucceededEvent": { + "reply": { + "ok": 1, + "cursor": { + "id": { + "$$type": [ + "int", + "long" + ] + }, + "ns": "command-monitoring-tests.test", + "firstBatch": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + }, + "commandName": "find" + } + }, + { + "commandStartedEvent": { + "command": { + "getMore": { + "$$type": [ + "int", + "long" + ] + }, + "collection": "test", + "batchSize": 1 + }, + "commandName": "getMore", + "databaseName": "command-monitoring-tests" + } + }, + { + "commandSucceededEvent": { + "reply": { + "ok": 1, + "cursor": { + "id": 0, + "ns": "command-monitoring-tests.test", + "nextBatch": [ + { + "_id": 4, + "x": 44 + } + ] + } + }, + "commandName": "getMore" + } + } + ] + } + ] + }, + { + "description": "A failed find event", + "operations": [ + { + "name": "find", + "object": "collection0", + "arguments": { + "filter": { + "$or": true + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "test", + "filter": { + "$or": true + } + }, + "commandName": "find", + "databaseName": "command-monitoring-tests" + } + }, + { + "commandFailedEvent": { + "commandName": "find" + } + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/valid-pass/poc-crud.json b/test/unified-test-format/valid-pass/poc-crud.json new file mode 100644 index 000000000..2ed86d615 --- /dev/null +++ b/test/unified-test-format/valid-pass/poc-crud.json @@ -0,0 +1,446 @@ +{ + "description": "poc-crud", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "database": { + "id": "database1", + "client": "client0", + "databaseName": "admin" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + }, + { + "collection": { + "id": "collection1", + "database": "database0", + "collectionName": "coll1" + } + }, + { + "collection": { + "id": "collection2", + "database": "database0", + "collectionName": "coll2", + "collectionOptions": { + "readConcern": { + "level": "majority" + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + }, + { + "collectionName": "coll1", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + }, + { + "collectionName": "coll2", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + }, + { + "collectionName": "aggregate_out", + "databaseName": "crud-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "BulkWrite with mixed ordered operations", + "operations": [ + { + "name": "bulkWrite", + "object": "collection0", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateMany": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "insertOne": { + "document": { + "_id": 4, + "x": 44 + } + } + }, + { + "deleteMany": { + "filter": { + "x": { + "$nin": [ + 24, + 34 + ] + } + } + } + }, + { + "replaceOne": { + "filter": { + "_id": 4 + }, + "replacement": { + "_id": 4, + "x": 44 + }, + "upsert": true + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 2, + "insertedCount": 2, + "insertedIds": { + "$$unsetOrMatches": { + "0": 3, + "3": 4 + } + }, + "matchedCount": 3, + "modifiedCount": 3, + "upsertedCount": 1, + "upsertedIds": { + "5": 4 + } + } + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 2, + "x": 24 + }, + { + "_id": 3, + "x": 34 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "InsertMany continue-on-error behavior with unordered (duplicate key in requests)", + "operations": [ + { + "name": "insertMany", + "object": "collection1", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "ordered": false + }, + "expectError": { + "expectResult": { + "deletedCount": 0, + "insertedCount": 2, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + } + ], + "outcome": [ + { + "collectionName": "coll1", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "ReplaceOne prohibits atomic modifiers", + "operations": [ + { + "name": "replaceOne", + "object": "collection1", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "$set": { + "x": 22 + } + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ], + "outcome": [ + { + "collectionName": "coll1", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "readConcern majority with out stage", + "runOnRequirements": [ + { + "minServerVersion": "4.1.0", + "topologies": [ + "replicaset", + "sharded-replicaset" + ] + } + ], + "operations": [ + { + "name": "aggregate", + "object": "collection2", + "arguments": { + "pipeline": [ + { + "$sort": { + "x": 1 + } + }, + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$out": "aggregate_out" + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll2", + "pipeline": [ + { + "$sort": { + "x": 1 + } + }, + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$out": "aggregate_out" + } + ], + "readConcern": { + "level": "majority" + } + }, + "commandName": "aggregate", + "databaseName": "crud-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "aggregate_out", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "Aggregate with $listLocalSessions", + "runOnRequirements": [ + { + "minServerVersion": "3.6.0" + } + ], + "operations": [ + { + "name": "aggregate", + "object": "database1", + "arguments": { + "pipeline": [ + { + "$listLocalSessions": {} + }, + { + "$limit": 1 + }, + { + "$addFields": { + "dummy": "dummy field" + } + }, + { + "$project": { + "_id": 0, + "dummy": 1 + } + } + ] + }, + "expectResult": [ + { + "dummy": "dummy field" + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/valid-pass/poc-gridfs.json b/test/unified-test-format/valid-pass/poc-gridfs.json new file mode 100644 index 000000000..1f07a19bf --- /dev/null +++ b/test/unified-test-format/valid-pass/poc-gridfs.json @@ -0,0 +1,301 @@ +{ + "description": "poc-gridfs", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "gridfs-tests" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0" + } + }, + { + "collection": { + "id": "bucket0_files_collection", + "database": "database0", + "collectionName": "fs.files" + } + }, + { + "collection": { + "id": "bucket0_chunks_collection", + "database": "database0", + "collectionName": "fs.chunks" + } + } + ], + "initialData": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000005" + }, + "length": 10, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "57d83cd477bfb1ccd975ab33d827a92b", + "filename": "length-10", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000005" + }, + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIzRA==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000006" + }, + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 1, + "data": { + "$binary": { + "base64": "VWZ3iA==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000007" + }, + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 2, + "data": { + "$binary": { + "base64": "mao=", + "subType": "00" + } + } + } + ] + } + ], + "tests": [ + { + "description": "Delete when length is 10", + "operations": [ + { + "name": "delete", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000005" + } + } + } + ], + "outcome": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [] + } + ] + }, + { + "description": "Download when there are three chunks", + "operations": [ + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000005" + } + }, + "expectResult": { + "$$matchesHexBytes": "112233445566778899aa" + } + } + ] + }, + { + "description": "Download when files entry does not exist", + "operations": [ + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000000" + } + }, + "expectError": { + "isError": true + } + } + ] + }, + { + "description": "Download when an intermediate chunk is missing", + "operations": [ + { + "name": "deleteOne", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": { + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 1 + } + }, + "expectResult": { + "deletedCount": 1 + } + }, + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000005" + } + }, + "expectError": { + "isError": true + } + } + ] + }, + { + "description": "Upload when length is 5", + "operations": [ + { + "name": "upload", + "object": "bucket0", + "arguments": { + "filename": "filename", + "source": { + "$$hexBytes": "1122334455" + }, + "chunkSizeBytes": 4 + }, + "expectResult": { + "$$type": "objectId" + }, + "saveResultAsEntity": "oid0" + }, + { + "name": "find", + "object": "bucket0_files_collection", + "arguments": { + "filter": {}, + "sort": { + "uploadDate": -1 + }, + "limit": 1 + }, + "expectResult": [ + { + "_id": { + "$$matchesEntity": "oid0" + }, + "length": 5, + "chunkSize": 4, + "uploadDate": { + "$$type": "date" + }, + "md5": { + "$$unsetOrMatches": "283d4fea5dded59cf837d3047328f5af" + }, + "filename": "filename" + } + ] + }, + { + "name": "find", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": { + "_id": { + "$gt": { + "$oid": "000000000000000000000007" + } + } + }, + "sort": { + "n": 1 + } + }, + "expectResult": [ + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "oid0" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIzRA==", + "subType": "00" + } + } + }, + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "oid0" + }, + "n": 1, + "data": { + "$binary": { + "base64": "VQ==", + "subType": "00" + } + } + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/valid-pass/poc-retryable-reads.json b/test/unified-test-format/valid-pass/poc-retryable-reads.json new file mode 100644 index 000000000..2b65d501a --- /dev/null +++ b/test/unified-test-format/valid-pass/poc-retryable-reads.json @@ -0,0 +1,433 @@ +{ + "description": "poc-retryable-reads", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "client": { + "id": "client1", + "uriOptions": { + "retryReads": false + }, + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Aggregate succeeds after InterruptedAtShutdown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 11600 + } + } + } + }, + { + "name": "aggregate", + "object": "collection0", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds on second attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "name": "find", + "object": "collection0", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 2 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 2 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 2 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find fails on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "name": "find", + "object": "collection1", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {} + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find fails on second attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "name": "find", + "object": "collection0", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {} + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {} + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds on second attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "closeConnection": true + } + } + } + }, + { + "name": "listDatabases", + "object": "client0" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/valid-pass/poc-retryable-writes.json b/test/unified-test-format/valid-pass/poc-retryable-writes.json new file mode 100644 index 000000000..3e42aacb8 --- /dev/null +++ b/test/unified-test-format/valid-pass/poc-retryable-writes.json @@ -0,0 +1,483 @@ +{ + "description": "poc-retryable-writes", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "client": { + "id": "client1", + "uriOptions": { + "retryWrites": false + }, + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndUpdate is committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "name": "findOneAndUpdate", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate is not committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "name": "findOneAndUpdate", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 2 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "name": "findOneAndUpdate", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before" + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "InsertMany succeeds after PrimarySteppedDown", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded-replicaset" + ] + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "name": "insertMany", + "object": "collection0", + "arguments": { + "documents": [ + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "ordered": true + }, + "expectResult": { + "insertedCount": { + "$$unsetOrMatches": 2 + }, + "insertedIds": { + "$$unsetOrMatches": { + "0": 3, + "1": 4 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "InsertOne fails after connection failure when retryWrites option is false", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded-replicaset" + ] + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "closeConnection": true + } + } + } + }, + { + "name": "insertOne", + "object": "collection1", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectError": { + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "InsertOne fails after multiple retryable writeConcernErrors", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded-replicaset" + ] + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "insert" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectError": { + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/valid-pass/poc-sessions.json b/test/unified-test-format/valid-pass/poc-sessions.json new file mode 100644 index 000000000..75f348942 --- /dev/null +++ b/test/unified-test-format/valid-pass/poc-sessions.json @@ -0,0 +1,466 @@ +{ + "description": "poc-sessions", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.6.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "session-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "test" + } + }, + { + "session": { + "id": "session0", + "client": "client0" + } + } + ], + "initialData": [ + { + "collectionName": "test", + "databaseName": "session-tests", + "documents": [ + { + "_id": 1 + } + ] + } + ], + "tests": [ + { + "description": "Server supports explicit sessions", + "operations": [ + { + "name": "assertSessionNotDirty", + "object": "testRunner", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "session": "session0", + "document": { + "_id": 2 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 2 + } + } + } + }, + { + "name": "assertSessionNotDirty", + "object": "testRunner", + "arguments": { + "session": "session0" + } + }, + { + "name": "endSession", + "object": "session0" + }, + { + "name": "find", + "object": "collection0", + "arguments": { + "filter": { + "_id": -1 + } + }, + "expectResult": [] + }, + { + "name": "assertSameLsidOnLastTwoCommands", + "object": "testRunner", + "arguments": { + "client": "client0" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "lsid": { + "$$sessionLsid": "session0" + } + }, + "commandName": "insert", + "databaseName": "session-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "test", + "filter": { + "_id": -1 + }, + "lsid": { + "$$sessionLsid": "session0" + } + }, + "commandName": "find", + "databaseName": "session-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "session-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ] + }, + { + "description": "Server supports implicit sessions", + "operations": [ + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "document": { + "_id": 2 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 2 + } + } + } + }, + { + "name": "find", + "object": "collection0", + "arguments": { + "filter": { + "_id": -1 + } + }, + "expectResult": [] + }, + { + "name": "assertSameLsidOnLastTwoCommands", + "object": "testRunner", + "arguments": { + "client": "client0" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "lsid": { + "$$type": "object" + } + }, + "commandName": "insert", + "databaseName": "session-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "test", + "filter": { + "_id": -1 + }, + "lsid": { + "$$type": "object" + } + }, + "commandName": "find", + "databaseName": "session-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "session-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ] + }, + { + "description": "Dirty explicit session is discarded", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.8", + "topologies": [ + "sharded-replicaset" + ] + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "closeConnection": true + } + } + } + }, + { + "name": "assertSessionNotDirty", + "object": "testRunner", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "session": "session0", + "document": { + "_id": 2 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 2 + } + } + } + }, + { + "name": "assertSessionDirty", + "object": "testRunner", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "session": "session0", + "document": { + "_id": 3 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 3 + } + } + } + }, + { + "name": "assertSessionDirty", + "object": "testRunner", + "arguments": { + "session": "session0" + } + }, + { + "name": "endSession", + "object": "session0" + }, + { + "name": "find", + "object": "collection0", + "arguments": { + "filter": { + "_id": -1 + } + }, + "expectResult": [] + }, + { + "name": "assertDifferentLsidOnLastTwoCommands", + "object": "testRunner", + "arguments": { + "client": "client0" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1 + }, + "commandName": "insert", + "databaseName": "session-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1 + }, + "commandName": "insert", + "databaseName": "session-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 3 + } + ], + "ordered": true, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 2 + }, + "commandName": "insert", + "databaseName": "session-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "test", + "filter": { + "_id": -1 + }, + "lsid": { + "$$type": "object" + } + }, + "commandName": "find", + "databaseName": "session-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "session-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/valid-pass/poc-transactions-convenient-api.json b/test/unified-test-format/valid-pass/poc-transactions-convenient-api.json new file mode 100644 index 000000000..820ed6592 --- /dev/null +++ b/test/unified-test-format/valid-pass/poc-transactions-convenient-api.json @@ -0,0 +1,505 @@ +{ + "description": "poc-transactions-convenient-api", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.8", + "topologies": [ + "sharded-replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": true, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "client": { + "id": "client1", + "uriOptions": { + "readConcernLevel": "local", + "w": 1 + }, + "useMultipleMongoses": true, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "transaction-tests" + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "transaction-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "test" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "test" + } + }, + { + "session": { + "id": "session0", + "client": "client0" + } + }, + { + "session": { + "id": "session1", + "client": "client1" + } + }, + { + "session": { + "id": "session2", + "client": "client0", + "sessionOptions": { + "defaultTransactionOptions": { + "readConcern": { + "level": "majority" + }, + "writeConcern": { + "w": 1 + } + } + } + } + } + ], + "initialData": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "withTransaction and no transaction options set", + "operations": [ + { + "name": "withTransaction", + "object": "session0", + "arguments": { + "callback": [ + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "session": "session0", + "document": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "$$exists": false + }, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "insert", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "commitTransaction": 1, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "autocommit": false, + "readConcern": { + "$$exists": false + }, + "startTransaction": { + "$$exists": false + }, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "commitTransaction", + "databaseName": "admin" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1 + } + ] + } + ] + }, + { + "description": "withTransaction inherits transaction options from client", + "operations": [ + { + "name": "withTransaction", + "object": "session1", + "arguments": { + "callback": [ + { + "name": "insertOne", + "object": "collection1", + "arguments": { + "session": "session1", + "document": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": { + "$$sessionLsid": "session1" + }, + "txnNumber": 1, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "local" + }, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "insert", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "commitTransaction": 1, + "lsid": { + "$$sessionLsid": "session1" + }, + "txnNumber": 1, + "autocommit": false, + "writeConcern": { + "w": 1 + }, + "readConcern": { + "$$exists": false + }, + "startTransaction": { + "$$exists": false + } + }, + "commandName": "commitTransaction", + "databaseName": "admin" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1 + } + ] + } + ] + }, + { + "description": "withTransaction inherits transaction options from defaultTransactionOptions", + "operations": [ + { + "name": "withTransaction", + "object": "session2", + "arguments": { + "callback": [ + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "session": "session2", + "document": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": { + "$$sessionLsid": "session2" + }, + "txnNumber": 1, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "majority" + }, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "insert", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "commitTransaction": 1, + "lsid": { + "$$sessionLsid": "session2" + }, + "txnNumber": 1, + "autocommit": false, + "writeConcern": { + "w": 1 + }, + "readConcern": { + "$$exists": false + }, + "startTransaction": { + "$$exists": false + } + }, + "commandName": "commitTransaction", + "databaseName": "admin" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1 + } + ] + } + ] + }, + { + "description": "withTransaction explicit transaction options", + "operations": [ + { + "name": "withTransaction", + "object": "session0", + "arguments": { + "callback": [ + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "session": "session0", + "document": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "readConcern": { + "level": "majority" + }, + "writeConcern": { + "w": 1 + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "majority" + }, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "insert", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "commitTransaction": 1, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "autocommit": false, + "writeConcern": { + "w": 1 + }, + "readConcern": { + "$$exists": false + }, + "startTransaction": { + "$$exists": false + } + }, + "commandName": "commitTransaction", + "databaseName": "admin" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1 + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/valid-pass/poc-transactions-mongos-pin-auto.json b/test/unified-test-format/valid-pass/poc-transactions-mongos-pin-auto.json new file mode 100644 index 000000000..a0b297d59 --- /dev/null +++ b/test/unified-test-format/valid-pass/poc-transactions-mongos-pin-auto.json @@ -0,0 +1,409 @@ +{ + "description": "poc-transactions-mongos-pin-auto", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "4.1.8", + "topologies": [ + "sharded-replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": true, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "transaction-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "test" + } + }, + { + "session": { + "id": "session0", + "client": "client0" + } + } + ], + "initialData": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "remain pinned after non-transient Interrupted error on insertOne", + "operations": [ + { + "name": "startTransaction", + "object": "session0" + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "session": "session0", + "document": { + "_id": 3 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 3 + } + } + } + }, + { + "name": "targetedFailPoint", + "object": "testRunner", + "arguments": { + "session": "session0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 11601 + } + } + } + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "session": "session0", + "document": { + "_id": 4 + } + }, + "expectError": { + "errorLabelsOmit": [ + "TransientTransactionError", + "UnknownTransactionCommitResult" + ], + "errorCodeName": "Interrupted" + } + }, + { + "name": "assertSessionPinned", + "object": "testRunner", + "arguments": { + "session": "session0" + } + }, + { + "name": "commitTransaction", + "object": "session0" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 3 + } + ], + "ordered": true, + "readConcern": { + "$$exists": false + }, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": true, + "autocommit": false, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "insert", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 4 + } + ], + "ordered": true, + "readConcern": { + "$$exists": false + }, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": { + "$$exists": false + }, + "autocommit": false, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "insert", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "commitTransaction": 1, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": { + "$$exists": false + }, + "autocommit": false, + "writeConcern": { + "$$exists": false + }, + "recoveryToken": { + "$$type": "object" + } + }, + "commandName": "commitTransaction", + "databaseName": "admin" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + } + ] + } + ] + }, + { + "description": "unpin after transient error within a transaction", + "operations": [ + { + "name": "startTransaction", + "object": "session0" + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "session": "session0", + "document": { + "_id": 3 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 3 + } + } + } + }, + { + "name": "targetedFailPoint", + "object": "testRunner", + "arguments": { + "session": "session0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "closeConnection": true + } + } + } + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "session": "session0", + "document": { + "_id": 4 + } + }, + "expectError": { + "errorLabelsContain": [ + "TransientTransactionError" + ], + "errorLabelsOmit": [ + "UnknownTransactionCommitResult" + ] + } + }, + { + "name": "assertSessionUnpinned", + "object": "testRunner", + "arguments": { + "session": "session0" + } + }, + { + "name": "abortTransaction", + "object": "session0" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 3 + } + ], + "ordered": true, + "readConcern": { + "$$exists": false + }, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": true, + "autocommit": false, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "insert", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 4 + } + ], + "ordered": true, + "readConcern": { + "$$exists": false + }, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": { + "$$exists": false + }, + "autocommit": false, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "insert", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "abortTransaction": 1, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": { + "$$exists": false + }, + "autocommit": false, + "writeConcern": { + "$$exists": false + }, + "recoveryToken": { + "$$type": "object" + } + }, + "commandName": "abortTransaction", + "databaseName": "admin" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ] + } + ] +} diff --git a/test/unified-test-format/valid-pass/poc-transactions.json b/test/unified-test-format/valid-pass/poc-transactions.json new file mode 100644 index 000000000..62528f9ce --- /dev/null +++ b/test/unified-test-format/valid-pass/poc-transactions.json @@ -0,0 +1,322 @@ +{ + "description": "poc-transactions", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.8", + "topologies": [ + "sharded-replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "transaction-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "test" + } + }, + { + "session": { + "id": "session0", + "client": "client0" + } + } + ], + "initialData": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "Client side error in command starting transaction", + "operations": [ + { + "name": "startTransaction", + "object": "session0" + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "session": "session0", + "document": { + "_id": { + ".": "." + } + } + }, + "expectError": { + "isClientError": true + } + }, + { + "name": "assertSessionTransactionState", + "object": "testRunner", + "arguments": { + "session": "session0", + "state": "starting" + } + } + ] + }, + { + "description": "explicitly create collection using create command", + "runOnRequirements": [ + { + "minServerVersion": "4.3.4", + "topologies": [ + "replicaset", + "sharded-replicaset" + ] + } + ], + "operations": [ + { + "name": "dropCollection", + "object": "database0", + "arguments": { + "collection": "test" + } + }, + { + "name": "startTransaction", + "object": "session0" + }, + { + "name": "createCollection", + "object": "database0", + "arguments": { + "session": "session0", + "collection": "test" + } + }, + { + "name": "assertCollectionNotExists", + "object": "testRunner", + "arguments": { + "databaseName": "transaction-tests", + "collectionName": "test" + } + }, + { + "name": "commitTransaction", + "object": "session0" + }, + { + "name": "assertCollectionExists", + "object": "testRunner", + "arguments": { + "databaseName": "transaction-tests", + "collectionName": "test" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "drop": "test", + "writeConcern": { + "$$exists": false + } + }, + "commandName": "drop", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "create": "test", + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": true, + "autocommit": false, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "create", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "commitTransaction": 1, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": { + "$$exists": false + }, + "autocommit": false, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "commitTransaction", + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "create index on a non-existing collection", + "runOnRequirements": [ + { + "minServerVersion": "4.3.4", + "topologies": [ + "replicaset", + "sharded-replicaset" + ] + } + ], + "operations": [ + { + "name": "dropCollection", + "object": "database0", + "arguments": { + "collection": "test" + } + }, + { + "name": "startTransaction", + "object": "session0" + }, + { + "name": "createIndex", + "object": "collection0", + "arguments": { + "session": "session0", + "name": "x_1", + "keys": { + "x": 1 + } + } + }, + { + "name": "assertIndexNotExists", + "object": "testRunner", + "arguments": { + "databaseName": "transaction-tests", + "collectionName": "test", + "indexName": "x_1" + } + }, + { + "name": "commitTransaction", + "object": "session0" + }, + { + "name": "assertIndexExists", + "object": "testRunner", + "arguments": { + "databaseName": "transaction-tests", + "collectionName": "test", + "indexName": "x_1" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "drop": "test", + "writeConcern": { + "$$exists": false + } + }, + "commandName": "drop", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "createIndexes": "test", + "indexes": [ + { + "name": "x_1", + "key": { + "x": 1 + } + } + ], + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": true, + "autocommit": false, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "createIndexes", + "databaseName": "transaction-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "commitTransaction": 1, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": { + "$$exists": false + }, + "autocommit": false, + "writeConcern": { + "$$exists": false + } + }, + "commandName": "commitTransaction", + "databaseName": "admin" + } + } + ] + } + ] + } + ] +} diff --git a/test/unified_format.py b/test/unified_format.py new file mode 100644 index 000000000..3500b5634 --- /dev/null +++ b/test/unified_format.py @@ -0,0 +1,1032 @@ +# Copyright 2020-present MongoDB, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Unified test format runner. + +https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.rst +""" + +import copy +import datetime +import functools +import os +import re +import sys +import types + +from bson import json_util, Code, Decimal128, DBRef, SON, Int64, MaxKey, MinKey +from bson.binary import Binary +from bson.objectid import ObjectId +from bson.py3compat import abc, integer_types, iteritems, text_type, PY3 +from bson.regex import Regex, RE_TYPE + +from gridfs import GridFSBucket + +from pymongo import ASCENDING, MongoClient +from pymongo.client_session import ClientSession, TransactionOptions, _TxnState +from pymongo.change_stream import ChangeStream +from pymongo.collection import Collection +from pymongo.database import Database +from pymongo.errors import BulkWriteError, InvalidOperation, PyMongoError +from pymongo.monitoring import ( + CommandFailedEvent, CommandListener, CommandStartedEvent, + CommandSucceededEvent, _SENSITIVE_COMMANDS) +from pymongo.read_concern import ReadConcern +from pymongo.read_preferences import ReadPreference +from pymongo.results import BulkWriteResult +from pymongo.write_concern import WriteConcern + +from test import client_context, unittest, IntegrationTest +from test.utils import ( + camel_to_snake, rs_or_single_client, single_client, snake_to_camel) + +from test.version import Version +from test.utils import ( + camel_to_snake_args, parse_collection_options, parse_spec_options, + prepare_spec_arguments) + + +JSON_OPTS = json_util.JSONOptions(tz_aware=False) + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass. + + Vendored from six: https://github.com/benjaminp/six/blob/master/six.py + """ + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(type): + + def __new__(cls, name, this_bases, d): + if sys.version_info[:2] >= (3, 7): + # This version introduced PEP 560 that requires a bit + # of extra care (we mimic what is done by __build_class__). + resolved_bases = types.resolve_bases(bases) + if resolved_bases is not bases: + d['__orig_bases__'] = bases + else: + resolved_bases = bases + return meta(name, resolved_bases, d) + + @classmethod + def __prepare__(cls, name, this_bases): + return meta.__prepare__(name, bases) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def is_run_on_requirement_satisfied(requirement): + topology_satisfied = True + req_topologies = requirement.get('topologies') + if req_topologies: + topology_satisfied = client_context.is_topology_type( + req_topologies) + + min_version_satisfied = True + req_min_server_version = requirement.get('minServerVersion') + if req_min_server_version: + min_version_satisfied = Version.from_string( + req_min_server_version) <= client_context.version + + max_version_satisfied = True + req_max_server_version = requirement.get('maxServerVersion') + if req_max_server_version: + max_version_satisfied = Version.from_string( + req_max_server_version) >= client_context.version + + return (topology_satisfied and min_version_satisfied and + max_version_satisfied) + + +def parse_collection_or_database_options(options): + return parse_collection_options(options) + + +def parse_bulk_write_result(result): + upserted_ids = {str(int_idx): result.upserted_ids[int_idx] + for int_idx in result.upserted_ids} + return { + 'deletedCount': result.deleted_count, + 'insertedCount': result.inserted_count, + 'matchedCount': result.matched_count, + 'modifiedCount': result.modified_count, + 'upsertedCount': result.upserted_count, + 'upsertedIds': upserted_ids} + + +def parse_bulk_write_error_result(error): + write_result = BulkWriteResult(error.details, True) + return parse_bulk_write_result(write_result) + + +class EventListenerUtil(CommandListener): + def __init__(self, observe_events, ignore_commands): + self._event_types = set(observe_events) + self._ignore_commands = _SENSITIVE_COMMANDS | set(ignore_commands) + self._ignore_commands.add('configurefailpoint') + self.results = [] + + def _observe_event(self, event): + if event.command_name.lower() not in self._ignore_commands: + self.results.append(event) + + def started(self, event): + if 'commandStartedEvent' in self._event_types: + self._observe_event(event) + + def succeeded(self, event): + if 'commandSucceededEvent' in self._event_types: + self._observe_event(event) + + def failed(self, event): + if 'commandFailedEvent' in self._event_types: + self._observe_event(event) + + +class EntityMapUtil(object): + """Utility class that implements an entity map as per the unified + test format specification.""" + def __init__(self, test_class): + self._entities = {} + self._listeners = {} + self._session_lsids = {} + self._test_class = test_class + + def __getitem__(self, item): + try: + return self._entities[item] + except KeyError: + self._test_class.fail('Could not find entity named %s in map' % ( + item,)) + + def __setitem__(self, key, value): + if not isinstance(key, text_type): + self._test_class.fail( + 'Expected entity name of type str, got %s' % (type(key))) + + if key in self._entities: + self._test_class.fail('Entity named %s already in map' % (key,)) + + self._entities[key] = value + + def _create_entity(self, entity_spec): + if len(entity_spec) != 1: + self._test_class.fail( + "Entity spec %s did not contain exactly one top-level key" % ( + entity_spec,)) + + entity_type, spec = next(iteritems(entity_spec)) + if entity_type == 'client': + kwargs = {} + observe_events = spec.get('observeEvents', []) + ignore_commands = spec.get('ignoreCommandMonitoringEvents', []) + if len(observe_events) or len(ignore_commands): + ignore_commands = [cmd.lower() for cmd in ignore_commands] + listener = EventListenerUtil(observe_events, ignore_commands) + self._listeners[spec['id']] = listener + kwargs['event_listeners'] = [listener] + if client_context.is_mongos and spec.get('useMultipleMongoses'): + kwargs['h'] = client_context.mongos_seeds() + kwargs.update(spec.get('uriOptions', {})) + client = rs_or_single_client(**kwargs) + self[spec['id']] = client + self._test_class.addCleanup(client.close) + return + elif entity_type == 'database': + client = self[spec['client']] + if not isinstance(client, MongoClient): + self._test_class.fail( + 'Expected entity %s to be of type MongoClient, got %s' % ( + spec['client'], type(client))) + options = parse_collection_or_database_options( + spec.get('databaseOptions', {})) + self[spec['id']] = client.get_database( + spec['databaseName'], **options) + return + elif entity_type == 'collection': + database = self[spec['database']] + if not isinstance(database, Database): + self._test_class.fail( + 'Expected entity %s to be of type Database, got %s' % ( + spec['database'], type(database))) + options = parse_collection_or_database_options( + spec.get('collectionOptions', {})) + self[spec['id']] = database.get_collection( + spec['collectionName'], **options) + return + elif entity_type == 'session': + client = self[spec['client']] + if not isinstance(client, MongoClient): + self._test_class.fail( + 'Expected entity %s to be of type MongoClient, got %s' % ( + spec['client'], type(client))) + opts = camel_to_snake_args(spec.get('sessionOptions', {})) + if 'default_transaction_options' in opts: + txn_opts = parse_spec_options( + opts['default_transaction_options']) + txn_opts = TransactionOptions(**txn_opts) + opts = copy.deepcopy(opts) + opts['default_transaction_options'] = txn_opts + session = client.start_session(**dict(opts)) + self[spec['id']] = session + self._session_lsids[spec['id']] = copy.deepcopy(session.session_id) + self._test_class.addCleanup(session.end_session) + return + elif entity_type == 'bucket': + # TODO: implement the 'bucket' entity type + self._test_class.skipTest( + 'GridFS is not currently supported (PYTHON-2459)') + self._test_class.fail( + 'Unable to create entity of unknown type %s' % (entity_type,)) + + def create_entities_from_spec(self, entity_spec): + for spec in entity_spec: + self._create_entity(spec) + + def get_listener_for_client(self, client_name): + client = self[client_name] + if not isinstance(client, MongoClient): + self._test_class.fail( + 'Expected entity %s to be of type MongoClient, got %s' % ( + client_name, type(client))) + + listener = self._listeners.get(client_name) + if not listener: + self._test_class.fail( + 'No listeners configured for client %s' % (client_name,)) + + return listener + + def get_lsid_for_session(self, session_name): + session = self[session_name] + if not isinstance(session, ClientSession): + self._test_class.fail( + 'Expected entity %s to be of type ClientSession, got %s' % ( + session_name, type(session))) + + try: + return session.session_id + except InvalidOperation: + # session has been closed. + return self._session_lsids[session_name] + + +if not PY3: + binary_types = (Binary,) + long_types = (Int64, long) + unicode_type = unicode +else: + binary_types = (Binary, bytes) + long_types = (Int64,) + unicode_type = str + + +BSON_TYPE_ALIAS_MAP = { + # https://docs.mongodb.com/manual/reference/operator/query/type/ + # https://pymongo.readthedocs.io/en/stable/api/bson/index.html + 'double': (float,), + 'string': (text_type,), + 'object': (abc.Mapping,), + 'array': (abc.MutableSequence,), + 'binData': binary_types, + 'undefined': (type(None),), + 'objectId': (ObjectId,), + 'bool': (bool,), + 'date': (datetime.datetime,), + 'null': (type(None),), + 'regex': (Regex, RE_TYPE), + 'dbPointer': (DBRef,), + 'javascript': (unicode_type, Code), + 'symbol': (unicode_type,), + 'javascriptWithScope': (unicode_type, Code), + 'int': (int,), + 'long': (Int64,), + 'decimal': (Decimal128,), + 'maxKey': (MaxKey,), + 'minKey': (MinKey,), +} + + +class MatchEvaluatorUtil(object): + """Utility class that implements methods for evaluating matches as per + the unified test format specification.""" + def __init__(self, test_class): + self._test_class = test_class + + def _operation_exists(self, spec, actual, key_to_compare): + if spec is True: + self._test_class.assertIn(key_to_compare, actual) + elif spec is False: + self._test_class.assertNotIn(key_to_compare, actual) + else: + self._test_class.fail( + 'Expected boolean value for $$exists operator, got %s' % ( + spec,)) + + def __type_alias_to_type(self, alias): + if alias not in BSON_TYPE_ALIAS_MAP: + self._test_class.fail('Unrecognized BSON type alias %s' % (alias,)) + return BSON_TYPE_ALIAS_MAP[alias] + + def _operation_type(self, spec, actual, key_to_compare): + if isinstance(spec, abc.MutableSequence): + permissible_types = tuple([ + t for alias in spec for t in self.__type_alias_to_type(alias)]) + else: + permissible_types = self.__type_alias_to_type(spec) + self._test_class.assertIsInstance( + actual[key_to_compare], permissible_types) + + def _operation_matchesEntity(self, spec, actual, key_to_compare): + expected_entity = self._test_class.entity_map[spec] + self._test_class.assertIsInstance(expected_entity, abc.Mapping) + self._test_class.assertEqual(expected_entity, actual[key_to_compare]) + + def _operation_matchesHexBytes(self, spec, actual, key_to_compare): + raise NotImplementedError + + def _operation_unsetOrMatches(self, spec, actual, key_to_compare): + if key_to_compare is None and not actual: + # top-level document can be None when unset + return + + if key_to_compare not in actual: + # we add a dummy value for the compared key to pass map size check + actual[key_to_compare] = 'dummyValue' + return + self.match_result(spec, actual[key_to_compare], in_recursive_call=True) + + def _operation_sessionLsid(self, spec, actual, key_to_compare): + expected_lsid = self._test_class.entity_map.get_lsid_for_session(spec) + self._test_class.assertEqual(expected_lsid, actual[key_to_compare]) + + def _evaluate_special_operation(self, opname, spec, actual, + key_to_compare): + method_name = '_operation_%s' % (opname.strip('$'),) + try: + method = getattr(self, method_name) + except AttributeError: + self._test_class.fail( + 'Unsupported special matching operator %s' % (opname,)) + else: + method(spec, actual, key_to_compare) + + def _evaluate_if_special_operation(self, expectation, actual, + key_to_compare=None): + """Returns True if a special operation is evaluated, False + otherwise. If the ``expectation`` map contains a single key, + value pair we check it for a special operation. + If given, ``key_to_compare`` is assumed to be the key in + ``expectation`` whose corresponding value needs to be + evaluated for a possible special operation. ``key_to_compare`` + is ignored when ``expectation`` has only one key.""" + if not isinstance(expectation, abc.Mapping): + return False + + is_special_op, opname, spec = False, False, False + + if key_to_compare is not None: + if key_to_compare.startswith('$$'): + is_special_op = True + opname = key_to_compare + spec = expectation[key_to_compare] + key_to_compare = None + else: + nested = expectation[key_to_compare] + if isinstance(nested, abc.Mapping) and len(nested) == 1: + opname, spec = next(iteritems(nested)) + if opname.startswith('$$'): + is_special_op = True + elif len(expectation) == 1: + opname, spec = next(iteritems(expectation)) + if opname.startswith('$$'): + is_special_op = True + key_to_compare = None + + if is_special_op: + self._evaluate_special_operation( + opname=opname, + spec=spec, + actual=actual, + key_to_compare=key_to_compare) + return True + + return False + + def _match_document(self, expectation, actual, is_root): + if self._evaluate_if_special_operation(expectation, actual): + return + + self._test_class.assertIsInstance(actual, abc.Mapping) + for key, value in iteritems(expectation): + if self._evaluate_if_special_operation(expectation, actual, key): + continue + + self._test_class.assertIn(key, actual) + self.match_result(value, actual[key], in_recursive_call=True) + + if not is_root: + self._test_class.assertEqual( + set(expectation.keys()), set(actual.keys())) + + def match_result(self, expectation, actual, + in_recursive_call=False): + if isinstance(expectation, abc.Mapping): + return self._match_document( + expectation, actual, is_root=not in_recursive_call) + + if isinstance(expectation, abc.MutableSequence): + self._test_class.assertIsInstance(actual, abc.MutableSequence) + for e, a in zip(expectation, actual): + if isinstance(e, abc.Mapping): + self._match_document( + e, a, is_root=not in_recursive_call) + else: + self.match_result(e, a, in_recursive_call=True) + return + + # account for flexible numerics in element-wise comparison + if (isinstance(expectation, integer_types) or + isinstance(expectation, float)): + self._test_class.assertEqual(expectation, actual) + else: + self._test_class.assertIsInstance(actual, type(expectation)) + self._test_class.assertEqual(expectation, actual) + + def match_event(self, expectation, actual): + event_type, spec = next(iteritems(expectation)) + + # every event type has the commandName field + command_name = spec.get('commandName') + if command_name: + self._test_class.assertEqual(command_name, actual.command_name) + + if event_type == 'commandStartedEvent': + self._test_class.assertIsInstance(actual, CommandStartedEvent) + command = spec.get('command') + database_name = spec.get('databaseName') + if command: + self.match_result(command, actual.command) + if database_name: + self._test_class.assertEqual( + database_name, actual.database_name) + elif event_type == 'commandSucceededEvent': + self._test_class.assertIsInstance(actual, CommandSucceededEvent) + reply = spec.get('reply') + if reply: + self.match_result(reply, actual.reply) + elif event_type == 'commandFailedEvent': + self._test_class.assertIsInstance(actual, CommandFailedEvent) + else: + self._test_class.fail( + 'Unsupported event type %s' % (event_type,)) + + +class UnifiedSpecTestMixinV1(IntegrationTest): + """Mixin class to run test cases from test specification files. + + Assumes that tests conform to the `unified test format + `_. + + Specification of the test suite being currently run is available as + a class attribute ``TEST_SPEC``. + """ + SCHEMA_VERSION = Version.from_string('1.0') + + @staticmethod + def should_run_on(run_on_spec): + if not run_on_spec: + # Always run these tests. + return True + + for req in run_on_spec: + if is_run_on_requirement_satisfied(req): + return True + return False + + def insert_initial_data(self, initial_data): + for collection_data in initial_data: + coll_name = collection_data['collectionName'] + db_name = collection_data['databaseName'] + documents = collection_data['documents'] + + coll = self.client.get_database(db_name).get_collection( + coll_name, write_concern=WriteConcern(w="majority")) + coll.drop() + + if len(documents) > 0: + coll.insert_many(documents) + else: + # ensure collection exists + result = coll.insert_one({}) + coll.delete_one({'_id': result.inserted_id}) + + @classmethod + def setUpClass(cls): + # super call creates internal client cls.client + super(UnifiedSpecTestMixinV1, cls).setUpClass() + + # process file-level runOnRequirements + run_on_spec = cls.TEST_SPEC.get('runOnRequirements', []) + if not cls.should_run_on(run_on_spec): + raise unittest.SkipTest( + '%s runOnRequirements not satisfied' % (cls.__name__,)) + + # add any special-casing for skipping tests here + if client_context.storage_engine == 'mmapv1': + if 'retryable-writes' in cls.TEST_SPEC['description']: + raise unittest.SkipTest( + "MMAPv1 does not support retryWrites=True") + + @classmethod + def tearDownClass(cls): + super(UnifiedSpecTestMixinV1, cls).tearDownClass() + cls.client.close() + + def setUp(self): + super(UnifiedSpecTestMixinV1, self).setUp() + + # process schemaVersion + # note: we check major schema version during class generation + # note: we do this here because we cannot run assertions in setUpClass + version = Version.from_string(self.TEST_SPEC['schemaVersion']) + self.assertLessEqual( + version, self.SCHEMA_VERSION, + 'expected schema version %s or lower, got %s' % ( + self.SCHEMA_VERSION, version)) + + # initialize internals + self.match_evaluator = MatchEvaluatorUtil(self) + + def maybe_skip_test(self, spec): + # add any special-casing for skipping tests here + if client_context.storage_engine == 'mmapv1': + if 'Dirty explicit session is discarded' in spec['description']: + raise unittest.SkipTest( + "MMAPv1 does not support retryWrites=True") + + def process_error(self, exception, spec): + is_error = spec.get('isError') + is_client_error = spec.get('isClientError') + error_contains = spec.get('errorContains') + error_code = spec.get('errorCode') + error_code_name = spec.get('errorCodeName') + error_labels_contain = spec.get('errorLabelsContain') + error_labels_omit = spec.get('errorLabelsOmit') + expect_result = spec.get('expectResult') + + if is_error: + # already satisfied because exception was raised + pass + + if is_client_error: + self.assertNotIsInstance(exception, PyMongoError) + + if error_contains: + if isinstance(exception, BulkWriteError): + errmsg = str(exception.details).lower() + else: + errmsg = str(exception).lower() + self.assertIn(error_contains.lower(), errmsg) + + if error_code: + self.assertEqual( + error_code, exception.details.get('code')) + + if error_code_name: + self.assertEqual( + error_code_name, exception.details.get('codeName')) + + if error_labels_contain: + labels = [err_label for err_label in error_labels_contain + if exception.has_error_label(err_label)] + self.assertEqual(labels, error_labels_contain) + + if error_labels_omit: + for err_label in error_labels_omit: + if exception.has_error_label(err_label): + self.fail("Exception '%s' unexpectedly had label '%s'" % ( + exception, err_label)) + + if expect_result: + if isinstance(exception, BulkWriteError): + result = parse_bulk_write_error_result( + exception) + self.match_evaluator.match_result(expect_result, result) + else: + self.fail("expectResult can only be specified with %s " + "exceptions" % (BulkWriteError,)) + + def __raise_if_unsupported(self, opname, target, *target_types): + if not isinstance(target, target_types): + self.fail('Operation %s not supported for entity ' + 'of type %s' % (opname, type(target))) + + def __entityOperation_createChangeStream(self, target, *args, **kwargs): + if client_context.storage_engine == 'mmapv1': + self.skipTest("MMAPv1 does not support change streams") + self.__raise_if_unsupported( + 'createChangeStream', target, MongoClient, Database, Collection) + return target.watch(*args, **kwargs) + + def _clientOperation_createChangeStream(self, target, *args, **kwargs): + return self.__entityOperation_createChangeStream( + target, *args, **kwargs) + + def _databaseOperation_createChangeStream(self, target, *args, **kwargs): + return self.__entityOperation_createChangeStream( + target, *args, **kwargs) + + def _collectionOperation_createChangeStream(self, target, *args, **kwargs): + return self.__entityOperation_createChangeStream( + target, *args, **kwargs) + + def _databaseOperation_runCommand(self, target, *args, **kwargs): + self.__raise_if_unsupported('runCommand', target, Database) + return target.command(*args, **kwargs) + + def __entityOperation_aggregate(self, target, *args, **kwargs): + self.__raise_if_unsupported('aggregate', target, Database, Collection) + return list(target.aggregate(*args, **kwargs)) + + def _databaseOperation_aggregate(self, target, *args, **kwargs): + return self.__entityOperation_aggregate(target, *args, **kwargs) + + def _collectionOperation_aggregate(self, target, *args, **kwargs): + return self.__entityOperation_aggregate(target, *args, **kwargs) + + def _collectionOperation_bulkWrite(self, target, *args, **kwargs): + self.__raise_if_unsupported('bulkWrite', target, Collection) + write_result = target.bulk_write(*args, **kwargs) + return parse_bulk_write_result(write_result) + + def _collectionOperation_find(self, target, *args, **kwargs): + self.__raise_if_unsupported('find', target, Collection) + find_cursor = target.find(*args, **kwargs) + return list(find_cursor) + + def _collectionOperation_findOneAndReplace(self, target, *args, **kwargs): + self.__raise_if_unsupported('findOneAndReplace', target, Collection) + return target.find_one_and_replace(*args, **kwargs) + + def _collectionOperation_findOneAndUpdate(self, target, *args, **kwargs): + self.__raise_if_unsupported('findOneAndReplace', target, Collection) + return target.find_one_and_update(*args, **kwargs) + + def _collectionOperation_insertMany(self, target, *args, **kwargs): + self.__raise_if_unsupported('insertMany', target, Collection) + result = target.insert_many(*args, **kwargs) + return {idx: _id for idx, _id in enumerate(result.inserted_ids)} + + def _collectionOperation_insertOne(self, target, *args, **kwargs): + self.__raise_if_unsupported('insertOne', target, Collection) + result = target.insert_one(*args, **kwargs) + return {'insertedId': result.inserted_id} + + def _sessionOperation_withTransaction(self, target, *args, **kwargs): + if client_context.storage_engine == 'mmapv1': + self.skipTest('MMAPv1 does not support document-level locking') + self.__raise_if_unsupported('withTransaction', target, ClientSession) + return target.with_transaction(*args, **kwargs) + + def _sessionOperation_startTransaction(self, target, *args, **kwargs): + if client_context.storage_engine == 'mmapv1': + self.skipTest('MMAPv1 does not support document-level locking') + self.__raise_if_unsupported('startTransaction', target, ClientSession) + return target.start_transaction(*args, **kwargs) + + def _changeStreamOperation_iterateUntilDocumentOrError(self, target, + *args, **kwargs): + self.__raise_if_unsupported( + 'iterateUntilDocumentOrError', target, ChangeStream) + return next(target) + + def run_entity_operation(self, spec): + target = self.entity_map[spec['object']] + opname = spec['name'] + opargs = spec.get('arguments') + expect_error = spec.get('expectError') + if opargs: + arguments = parse_spec_options(copy.deepcopy(opargs)) + prepare_spec_arguments(spec, arguments, camel_to_snake(opname), + self.entity_map, self.run_operations) + else: + arguments = tuple() + + if isinstance(target, MongoClient): + method_name = '_clientOperation_%s' % (opname,) + elif isinstance(target, Database): + method_name = '_databaseOperation_%s' % (opname,) + elif isinstance(target, Collection): + method_name = '_collectionOperation_%s' % (opname,) + elif isinstance(target, ChangeStream): + method_name = '_changeStreamOperation_%s' % (opname,) + elif isinstance(target, ClientSession): + method_name = '_sessionOperation_%s' % (opname,) + elif isinstance(target, GridFSBucket): + raise NotImplementedError + else: + method_name = 'doesNotExist' + + try: + method = getattr(self, method_name) + except AttributeError: + try: + cmd = getattr(target, camel_to_snake(opname)) + except AttributeError: + self.fail('Unsupported operation %s on entity %s' % ( + opname, target)) + else: + cmd = functools.partial(method, target) + + try: + result = cmd(**dict(arguments)) + except Exception as exc: + if expect_error: + return self.process_error(exc, expect_error) + raise + + if 'expectResult' in spec: + self.match_evaluator.match_result(spec['expectResult'], result) + + save_as_entity = spec.get('saveResultAsEntity') + if save_as_entity: + self.entity_map[save_as_entity] = result + + def __set_fail_point(self, client, command_args): + if not client_context.test_commands_enabled: + self.skipTest('Test commands must be enabled') + + cmd_on = SON([('configureFailPoint', 'failCommand')]) + cmd_on.update(command_args) + client.admin.command(cmd_on) + self.addCleanup( + client.admin.command, + 'configureFailPoint', cmd_on['configureFailPoint'], mode='off') + + def _testOperation_failPoint(self, spec): + self.__set_fail_point( + client=self.entity_map[spec['client']], + command_args=spec['failPoint']) + + def _testOperation_targetedFailPoint(self, spec): + session = self.entity_map[spec['session']] + if not session._pinned_address: + self.fail("Cannot use targetedFailPoint operation with unpinned " + "session %s" % (spec['session'],)) + + client = single_client('%s:%s' % session._pinned_address) + self.__set_fail_point( + client=client, command_args=spec['failPoint']) + self.addCleanup(client.close) + + def _testOperation_assertSessionTransactionState(self, spec): + session = self.entity_map[spec['session']] + expected_state = getattr(_TxnState, spec['state'].upper()) + self.assertEqual(expected_state, session._transaction.state) + + def _testOperation_assertSessionPinned(self, spec): + session = self.entity_map[spec['session']] + self.assertIsNotNone(session._pinned_address) + + def _testOperation_assertSessionUnpinned(self, spec): + session = self.entity_map[spec['session']] + self.assertIsNone(session._pinned_address) + + def __get_last_two_command_lsids(self, listener): + cmd_started_events = [] + for event in reversed(listener.results): + if isinstance(event, CommandStartedEvent): + cmd_started_events.append(event) + if len(cmd_started_events) < 2: + self.fail('Needed 2 CommandStartedEvents to compare lsids, ' + 'got %s' % (len(cmd_started_events))) + return tuple([e.command['lsid'] for e in cmd_started_events][:2]) + + def _testOperation_assertDifferentLsidOnLastTwoCommands(self, spec): + listener = self.entity_map.get_listener_for_client(spec['client']) + self.assertNotEqual(*self.__get_last_two_command_lsids(listener)) + + def _testOperation_assertSameLsidOnLastTwoCommands(self, spec): + listener = self.entity_map.get_listener_for_client(spec['client']) + self.assertEqual(*self.__get_last_two_command_lsids(listener)) + + def _testOperation_assertSessionDirty(self, spec): + session = self.entity_map[spec['session']] + self.assertTrue(session._server_session.dirty) + + def _testOperation_assertSessionNotDirty(self, spec): + session = self.entity_map[spec['session']] + return self.assertFalse(session._server_session.dirty) + + def _testOperation_assertCollectionExists(self, spec): + database_name = spec['databaseName'] + collection_name = spec['collectionName'] + collection_name_list = list( + self.client.get_database(database_name).list_collection_names()) + self.assertIn(collection_name, collection_name_list) + + def _testOperation_assertCollectionNotExists(self, spec): + database_name = spec['databaseName'] + collection_name = spec['collectionName'] + collection_name_list = list( + self.client.get_database(database_name).list_collection_names()) + self.assertNotIn(collection_name, collection_name_list) + + def _testOperation_assertIndexExists(self, spec): + collection = self.client[spec['databaseName']][spec['collectionName']] + index_names = [idx['name'] for idx in collection.list_indexes()] + self.assertIn(spec['indexName'], index_names) + + def _testOperation_assertIndexNotExists(self, spec): + collection = self.client[spec['databaseName']][spec['collectionName']] + for index in collection.list_indexes(): + self.assertNotEqual(spec['indexName'], index['name']) + + def run_special_operation(self, spec): + opname = spec['name'] + method_name = '_testOperation_%s' % (opname,) + try: + method = getattr(self, method_name) + except AttributeError: + self.fail('Unsupported special test operation %s' % (opname,)) + else: + method(spec['arguments']) + + def run_operations(self, spec): + for op in spec: + target = op['object'] + if target != 'testRunner': + self.run_entity_operation(op) + else: + self.run_special_operation(op) + + def check_events(self, spec): + for event_spec in spec: + client_name = event_spec['client'] + events = event_spec['events'] + listener = self.entity_map.get_listener_for_client(client_name) + + if len(events) == 0: + self.assertEqual(listener.results, []) + continue + + if len(events) > len(listener.results): + self.fail('Expected to see %s events, got %s' % ( + len(events), len(listener.results))) + + for idx, expected_event in enumerate(events): + self.match_evaluator.match_event( + expected_event, listener.results[idx]) + + def verify_outcome(self, spec): + for collection_data in spec: + coll_name = collection_data['collectionName'] + db_name = collection_data['databaseName'] + expected_documents = collection_data['documents'] + + coll = self.client.get_database(db_name).get_collection( + coll_name, + read_preference=ReadPreference.PRIMARY, + read_concern=ReadConcern(level='local')) + + if expected_documents: + sorted_expected_documents = sorted( + expected_documents, key=lambda doc: doc['_id']) + actual_documents = list( + coll.find({}, sort=[('_id', ASCENDING)])) + self.assertListEqual(sorted_expected_documents, + actual_documents) + + def run_scenario(self, spec): + # maybe skip test manually + self.maybe_skip_test(spec) + + # process test-level runOnRequirements + run_on_spec = spec.get('runOnRequirements', []) + if not self.should_run_on(run_on_spec): + raise unittest.SkipTest('runOnRequirements not satisfied') + + # process skipReason + skip_reason = spec.get('skipReason', None) + if skip_reason is not None: + raise unittest.SkipTest('%s' % (skip_reason,)) + + # process createEntities + self.entity_map = EntityMapUtil(self) + self.entity_map.create_entities_from_spec( + self.TEST_SPEC.get('createEntities', [])) + + # process initialData + self.insert_initial_data(self.TEST_SPEC.get('initialData', [])) + + # process operations + self.run_operations(spec['operations']) + + # process expectEvents + self.check_events(spec.get('expectEvents', [])) + + # process outcome + self.verify_outcome(spec.get('outcome', [])) + + +class UnifiedSpecTestMeta(type): + """Metaclass for generating test classes.""" + def __init__(cls, *args, **kwargs): + super(UnifiedSpecTestMeta, cls).__init__(*args, **kwargs) + + def create_test(spec): + def test_case(self): + self.run_scenario(spec) + return test_case + + for test_spec in cls.TEST_SPEC['tests']: + description = test_spec['description'] + test_name = 'test_%s' % (description.strip('. '). + replace(' ', '_').replace('.', '_'),) + test_method = create_test(copy.deepcopy(test_spec)) + test_method.__name__ = str(test_name) + + for fail_pattern in cls.EXPECTED_FAILURES: + if re.search(fail_pattern, description): + test_method = unittest.expectedFailure(test_method) + break + + setattr(cls, test_name, test_method) + + +_ALL_MIXIN_CLASSES = [ + UnifiedSpecTestMixinV1, + # add mixin classes for new schema major versions here +] + + +_SCHEMA_VERSION_MAJOR_TO_MIXIN_CLASS = { + KLASS.SCHEMA_VERSION[0]: KLASS for KLASS in _ALL_MIXIN_CLASSES} + + +def generate_test_classes(test_path, module=__name__, class_name_prefix='', + expected_failures=[], + bypass_test_generation_errors=False): + """Method for generating test classes. Returns a dictionary where keys are + the names of test classes and values are the test class objects.""" + test_klasses = {} + + def test_base_class_factory(test_spec): + """Utility that creates the base class to use for test generation. + This is needed to ensure that cls.TEST_SPEC is appropriately set when + the metaclass __init__ is invoked.""" + class SpecTestBase(with_metaclass(UnifiedSpecTestMeta)): + TEST_SPEC = test_spec + EXPECTED_FAILURES = expected_failures + return SpecTestBase + + for dirpath, _, filenames in os.walk(test_path): + dirname = os.path.split(dirpath)[-1] + + for filename in filenames: + fpath = os.path.join(dirpath, filename) + with open(fpath) as scenario_stream: + # Use tz_aware=False to match how CodecOptions decodes + # dates. + opts = json_util.JSONOptions(tz_aware=False) + scenario_def = json_util.loads( + scenario_stream.read(), json_options=opts) + + test_type = os.path.splitext(filename)[0] + snake_class_name = 'Test%s_%s_%s' % ( + class_name_prefix, dirname.replace('-', '_'), + test_type.replace('-', '_').replace('.', '_')) + class_name = snake_to_camel(snake_class_name) + + try: + schema_version = Version.from_string( + scenario_def['schemaVersion']) + mixin_class = _SCHEMA_VERSION_MAJOR_TO_MIXIN_CLASS.get( + schema_version[0]) + if mixin_class is None: + raise ValueError( + "test file '%s' has unsupported schemaVersion '%s'" % ( + fpath, schema_version)) + test_klasses[class_name] = type( + class_name, + (mixin_class, test_base_class_factory(scenario_def),), + {'__module__': module}) + except Exception: + if bypass_test_generation_errors: + continue + raise + + return test_klasses diff --git a/test/utils.py b/test/utils.py index 3e24c684f..cf38e76e6 100644 --- a/test/utils.py +++ b/test/utils.py @@ -17,6 +17,7 @@ import collections import contextlib +import copy import functools import os import re @@ -31,10 +32,12 @@ from functools import partial from bson import json_util, py3compat from bson.objectid import ObjectId +from bson.py3compat import iteritems, string_type from bson.son import SON from pymongo import (MongoClient, - monitoring, read_preferences) + monitoring, operations, read_preferences) +from pymongo.collection import ReturnDocument from pymongo.errors import ConfigurationError, OperationFailure from pymongo.monitoring import _SENSITIVE_COMMANDS, ConnectionPoolListener from pymongo.pool import (_CancellationContext, @@ -563,6 +566,11 @@ def camel_to_snake_args(arguments): return arguments +def snake_to_camel(snake): + # Regex to convert snake_case to lowerCamelCase. + return re.sub(r'_([a-z])', lambda m: m.group(1).upper(), snake) + + def parse_collection_options(opts): if 'readPreference' in opts: opts['read_preference'] = parse_read_preference( @@ -949,3 +957,124 @@ def assertion_context(msg): except AssertionError as exc: msg = '%s (%s)' % (exc, msg) py3compat.reraise(type(exc), msg, sys.exc_info()[2]) + + +def parse_spec_options(opts): + if 'readPreference' in opts: + opts['read_preference'] = parse_read_preference( + opts.pop('readPreference')) + + if 'writeConcern' in opts: + opts['write_concern'] = WriteConcern( + **dict(opts.pop('writeConcern'))) + + if 'readConcern' in opts: + opts['read_concern'] = ReadConcern( + **dict(opts.pop('readConcern'))) + + if 'maxTimeMS' in opts: + opts['max_time_ms'] = opts.pop('maxTimeMS') + + if 'maxCommitTimeMS' in opts: + opts['max_commit_time_ms'] = opts.pop('maxCommitTimeMS') + + if 'hint' in opts: + hint = opts.pop('hint') + if not isinstance(hint, string_type): + hint = list(iteritems(hint)) + opts['hint'] = hint + + # Properly format 'hint' arguments for the Bulk API tests. + if 'requests' in opts: + reqs = opts.pop('requests') + for req in reqs: + if 'name' in req: + # CRUD v2 format + args = req.pop('arguments', {}) + if 'hint' in args: + hint = args.pop('hint') + if not isinstance(hint, string_type): + hint = list(iteritems(hint)) + args['hint'] = hint + req['arguments'] = args + else: + # Unified test format + bulk_model, spec = next(iteritems(req)) + if 'hint' in spec: + hint = spec.pop('hint') + if not isinstance(hint, string_type): + hint = list(iteritems(hint)) + spec['hint'] = hint + opts['requests'] = reqs + + return dict(opts) + + +def prepare_spec_arguments(spec, arguments, opname, entity_map, + with_txn_callback): + for arg_name in list(arguments): + c2s = camel_to_snake(arg_name) + # PyMongo accepts sort as list of tuples. + if arg_name == "sort": + sort_dict = arguments[arg_name] + arguments[arg_name] = list(iteritems(sort_dict)) + # Named "key" instead not fieldName. + if arg_name == "fieldName": + arguments["key"] = arguments.pop(arg_name) + # Aggregate uses "batchSize", while find uses batch_size. + elif ((arg_name == "batchSize" or arg_name == "allowDiskUse") and + opname == "aggregate"): + continue + # Requires boolean returnDocument. + elif arg_name == "returnDocument": + arguments[c2s] = getattr(ReturnDocument, arguments.pop(arg_name).upper()) + elif c2s == "requests": + # Parse each request into a bulk write model. + requests = [] + for request in arguments["requests"]: + if 'name' in request: + # CRUD v2 format + bulk_model = camel_to_upper_camel(request["name"]) + bulk_class = getattr(operations, bulk_model) + bulk_arguments = camel_to_snake_args(request["arguments"]) + else: + # Unified test format + bulk_model, spec = next(iteritems(request)) + bulk_class = getattr(operations, camel_to_upper_camel(bulk_model)) + bulk_arguments = camel_to_snake_args(spec) + requests.append(bulk_class(**dict(bulk_arguments))) + arguments["requests"] = requests + elif arg_name == "session": + arguments['session'] = entity_map[arguments['session']] + elif (opname in ('command', 'run_admin_command') and + arg_name == 'command'): + # Ensure the first key is the command name. + ordered_command = SON([(spec['command_name'], 1)]) + ordered_command.update(arguments['command']) + arguments['command'] = ordered_command + elif opname == 'open_download_stream' and arg_name == 'id': + arguments['file_id'] = arguments.pop(arg_name) + elif opname != 'find' and c2s == 'max_time_ms': + # find is the only method that accepts snake_case max_time_ms. + # All other methods take kwargs which must use the server's + # camelCase maxTimeMS. See PYTHON-1855. + arguments['maxTimeMS'] = arguments.pop('max_time_ms') + elif opname == 'with_transaction' and arg_name == 'callback': + if 'operations' in arguments[arg_name]: + # CRUD v2 format + callback_ops = arguments[arg_name]['operations'] + else: + # Unified test format + callback_ops = arguments[arg_name] + arguments['callback'] = lambda _: with_txn_callback( + copy.deepcopy(callback_ops)) + elif opname == 'drop_collection' and arg_name == 'collection': + arguments['name_or_collection'] = arguments.pop(arg_name) + elif opname == 'create_collection' and arg_name == 'collection': + arguments['name'] = arguments.pop(arg_name) + elif opname == 'create_index' and arg_name == 'keys': + arguments['keys'] = list(arguments.pop(arg_name).items()) + elif opname == 'drop_index' and arg_name == 'name': + arguments['index_or_name'] = arguments.pop(arg_name) + else: + arguments[c2s] = arguments.pop(arg_name) diff --git a/test/utils_spec_runner.py b/test/utils_spec_runner.py index 09798fb80..2e2318591 100644 --- a/test/utils_spec_runner.py +++ b/test/utils_spec_runner.py @@ -15,6 +15,7 @@ """Utilities for testing driver specs.""" import copy +import functools import threading @@ -50,7 +51,9 @@ from test.utils import (camel_to_snake, CompareType, CMAPListener, OvertCommandListener, + parse_spec_options, parse_read_preference, + prepare_spec_arguments, rs_client, ServerAndTopologyEventListener, HeartbeatEventListener) @@ -249,44 +252,7 @@ class SpecRunner(IntegrationTest): @staticmethod def parse_options(opts): - if 'readPreference' in opts: - opts['read_preference'] = parse_read_preference( - opts.pop('readPreference')) - - if 'writeConcern' in opts: - opts['write_concern'] = WriteConcern( - **dict(opts.pop('writeConcern'))) - - if 'readConcern' in opts: - opts['read_concern'] = ReadConcern( - **dict(opts.pop('readConcern'))) - - if 'maxTimeMS' in opts: - opts['max_time_ms'] = opts.pop('maxTimeMS') - - if 'maxCommitTimeMS' in opts: - opts['max_commit_time_ms'] = opts.pop('maxCommitTimeMS') - - if 'hint' in opts: - hint = opts.pop('hint') - if not isinstance(hint, string_type): - hint = list(iteritems(hint)) - opts['hint'] = hint - - # Properly format 'hint' arguments for the Bulk API tests. - if 'requests' in opts: - reqs = opts.pop('requests') - for req in reqs: - args = req.pop('arguments') - if 'hint' in args: - hint = args.pop('hint') - if not isinstance(hint, string_type): - hint = list(iteritems(hint)) - args['hint'] = hint - req['arguments'] = args - opts['requests'] = reqs - - return dict(opts) + return parse_spec_options(opts) def run_operation(self, sessions, collection, operation): original_collection = collection @@ -328,61 +294,11 @@ class SpecRunner(IntegrationTest): cmd = getattr(obj, name) - for arg_name in list(arguments): - c2s = camel_to_snake(arg_name) - # PyMongo accepts sort as list of tuples. - if arg_name == "sort": - sort_dict = arguments[arg_name] - arguments[arg_name] = list(iteritems(sort_dict)) - # Named "key" instead not fieldName. - if arg_name == "fieldName": - arguments["key"] = arguments.pop(arg_name) - # Aggregate uses "batchSize", while find uses batch_size. - elif ((arg_name == "batchSize" or arg_name == "allowDiskUse") and - name == "aggregate"): - continue - # Requires boolean returnDocument. - elif arg_name == "returnDocument": - arguments[c2s] = arguments.pop(arg_name) == "After" - elif c2s == "requests": - # Parse each request into a bulk write model. - requests = [] - for request in arguments["requests"]: - bulk_model = camel_to_upper_camel(request["name"]) - bulk_class = getattr(operations, bulk_model) - bulk_arguments = camel_to_snake_args(request["arguments"]) - requests.append(bulk_class(**dict(bulk_arguments))) - arguments["requests"] = requests - elif arg_name == "session": - arguments['session'] = sessions[arguments['session']] - elif (name in ('command', 'run_admin_command') and - arg_name == 'command'): - # Ensure the first key is the command name. - ordered_command = SON([(operation['command_name'], 1)]) - ordered_command.update(arguments['command']) - arguments['command'] = ordered_command - elif name == 'open_download_stream' and arg_name == 'id': - arguments['file_id'] = arguments.pop(arg_name) - elif name != 'find' and c2s == 'max_time_ms': - # find is the only method that accepts snake_case max_time_ms. - # All other methods take kwargs which must use the server's - # camelCase maxTimeMS. See PYTHON-1855. - arguments['maxTimeMS'] = arguments.pop('max_time_ms') - elif name == 'with_transaction' and arg_name == 'callback': - callback_ops = arguments[arg_name]['operations'] - arguments['callback'] = lambda _: self.run_operations( - sessions, original_collection, copy.deepcopy(callback_ops), - in_with_transaction=True) - elif name == 'drop_collection' and arg_name == 'collection': - arguments['name_or_collection'] = arguments.pop(arg_name) - elif name == 'create_collection' and arg_name == 'collection': - arguments['name'] = arguments.pop(arg_name) - elif name == 'create_index' and arg_name == 'keys': - arguments['keys'] = list(arguments.pop(arg_name).items()) - elif name == 'drop_index' and arg_name == 'name': - arguments['index_or_name'] = arguments.pop(arg_name) - else: - arguments[c2s] = arguments.pop(arg_name) + with_txn_callback = functools.partial( + self.run_operations, sessions, original_collection, + in_with_transaction=True) + prepare_spec_arguments(operation, arguments, name, sessions, + with_txn_callback) if name == 'run_on_thread': args = {'sessions': sessions, 'collection': collection}