diff --git a/test/functional/spec/transactions/README.rst b/test/functional/spec/transactions/README.rst new file mode 100644 index 0000000000..577b17f914 --- /dev/null +++ b/test/functional/spec/transactions/README.rst @@ -0,0 +1,164 @@ +================== +Transactions Tests +================== + +.. contents:: + +---- + +Introduction +============ + +The YAML and JSON files in this directory are platform-independent tests that +drivers can use to prove their conformance to the Transactions Spec. They are +designed with the intention of sharing some test-runner code with the CRUD Spec +tests and the Command Monitoring Spec tests. + +Several prose tests, which are not easily expressed in YAML, are also presented +in this file. Those tests will need to be manually implemented by each driver. + +Test Format +=========== + +Each YAML file has the following keys: + +- ``data``: The data that should exist in the collection under test before each + test run. (TODO: not used yet.) + +- ``tests``: An array of tests that are to be run independently of each other. + Each test will have some or all of the following fields: + + - ``description``: The name of the test. + + - ``clientOptions``: Optional, parameters to pass to MongoClient(). + + - ``sessionOptions``: Optional, parameters to pass to + MongoClient.startSession(). + + - ``operations``: Array of documents, each describing an operation to be + executed. Each document has the following fields: + + - ``name``: The name of the operation. + + - ``arguments``: The names and values of arguments. + + - ``result``: The return value from the operation, if any. If the + operation is expected to return an error, the ``result`` has one field, + ``errorContains``, which is a substring of the expected error message + or ``errorCodeName``, which is the expected server error "codeName". + + - ``expectations``: Optional list of command-started events. + + - ``outcome``: Document describing the return value and/or expected state of + the collection after the operation is executed. Contains the following + fields: + + - ``collection``: + + - ``data``: The data that should exist in the collection after the + operations have run. + +Use as integration tests +======================== + +Run a MongoDB replica set with a primary, two secondaries, and an arbiter, +server version 4.0 or later. (Including two secondaries ensures that transaction +pinning works properly. Include an arbiter to ensure no new bugs have been +introduced related to arbiters.) + +For each YAML file, for each element in ``tests``: + +#. Create a MongoClient and call + ``client.admin.runCommand({killAllSessions: []})`` to clean up any open + transactions from previous test failures. The command will fail with message + "operation was interrupted", because it kills its own implicit session. Catch + the exception and continue. +#. Drop the test collection, using writeConcern "majority". +#. Execute the "create" command to recreate the collection, using writeConcern + "majority". (Creating the collection inside a transaction is prohibited, so + create it explicitly.) +#. If the YAML file contains a ``data`` array, insert the documents in ``data`` + into the test collection, using writeConcern "majority". +#. Create a **new** MongoClient ``client``, with Command Monitoring listeners + enabled. (Using a new MongoClient for each test ensures a fresh session pool + that hasn't executed any transactions previously, so the tests can assert + actual txnNumbers, starting from 1.) Pass this test's ``clientOptions`` if + present. +#. Call ``client.startSession`` twice to create ClientSession objects + ``session0`` and ``session1``, using the test's "sessionOptions" if they + are present. Save their lsids so they are available after calling + ``endSession``, see `Logical Session Id`. +#. For each element in ``operations``: + + - Enter a "try" block or your programming language's closest equivalent. + - If ``name`` is "startTransaction", "commitTransaction", or + "abortTransaction", call the named method on ``session0`` or + ``session1``, depending on the "session" argument. + - Otherwise, ``name`` refers to a CRUD method, such as ``insertOne``. + Execute the named method on the "transactions-tests" database on the "test" + collection, passing the arguments listed. Pass ``session0`` or ``session1`` + to the method, depending on which session's name is in the arguments list. + If ``arguments`` contains no "session", pass no explicit session to the + method. If ``arguments`` includes "readPreference", configure the specified + read preference in whatever manner the driver supports. + - If the driver throws an exception / returns an error while executing this + series of operations, store the error message and server error code. + - If the result document has an "errorContains" field, verify that the + method threw an exception or returned an error, and that the value of the + "errorContains" field matches the error string. If the result document has + an "errorCodeName" field, verify that the method threw a command failed + exception or returned an error, and that the value of the "errorCodeName" + field matches the "codeName" in the server error response. + Otherwise, compare the method's return value to ``result`` using the same + logic as the CRUD Spec Tests runner. key is a substring (case-insensitive) + of the actual error message. + +#. Call ``session0.endSession()`` and ``session1.endSession``. +#. If the test includes a list of command-started events in ``expectations``, + compare them to the actual command-started events using the + same logic as the Command Monitoring Spec Tests runner, plus the rules in + the Command-Started Events instructions below. +#. For each element in ``outcome``: + + - If ``name`` is "collection", verify that the test collection contains + exactly the documents in the ``data`` array. + +TODO: + +- drivers MUST NOT retry writes in a transaction even when retryWrites=true, needs to use failpoint. +- drivers MUST retry commit/abort, needs to use failpoint. +- test writeConcernErrors + +Command-Started Events +`````````````````````` + +Logical Session Id +~~~~~~~~~~~~~~~~~~ + +Each command-started event in ``expectations`` includes an ``lsid`` with the +value "session0" or "session1". Tests MUST assert that the command's actual +``lsid`` matches the id of the correct ClientSession named ``session0`` or +``session1``. + +Null Values +~~~~~~~~~~~ + +Some command-started events in ``expectations`` include ``null`` values for +fields such as ``txnNumber``, ``autocommit``, ``writeConcern``, and ``stmtId``. +Tests MUST assert that the actual command **omits** any field that has a +``null`` value in the expected command. + +Cursor Id +^^^^^^^^^ + +A ``getMore`` value of ``"42"`` in a command-started event is a fake cursorId +that MUST be ignored. (In the Command Monitoring Spec tests, fake cursorIds are +correlated with real ones, but that is not necessary for Transactions Spec +tests.) + +afterClusterTime +^^^^^^^^^^^^^^^^ + +A ``readConcern.afterClusterTime`` value of ``42`` in a command-started event +is a fake cluster time. Drivers MUST assert that the actual command includes an +afterClusterTime. diff --git a/test/functional/spec/transactions/abort.json b/test/functional/spec/transactions/abort.json new file mode 100644 index 0000000000..484818ebf1 --- /dev/null +++ b/test/functional/spec/transactions/abort.json @@ -0,0 +1,556 @@ +{ + "data": [], + "tests": [ + { + "description": "abort", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": { + "afterClusterTime": 42 + }, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + }, + { + "description": "implicit abort", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + }, + { + "description": "two aborts", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + }, + "result": { + "errorContains": "no transaction started" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + }, + { + "description": "abort without start", + "operations": [ + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + }, + "result": { + "errorContains": "no transaction started" + } + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [] + } + } + }, + { + "description": "commit after abort", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + }, + "result": { + "errorContains": "no transaction started" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ] + }, + { + "description": "abort ignores TransactionAborted", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "errorCodeName": "DuplicateKey" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "errorCodeName": "NoSuchTransaction" + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 3, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + } + ] +} diff --git a/test/functional/spec/transactions/abort.yml b/test/functional/spec/transactions/abort.yml new file mode 100644 index 0000000000..8ebd583a07 --- /dev/null +++ b/test/functional/spec/transactions/abort.yml @@ -0,0 +1,369 @@ +data: [] + +tests: + - description: abort + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: abortTransaction + arguments: + session: session0 + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: abortTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + "$numberLong": "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: abortTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + afterClusterTime: 42 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: abortTransaction + database_name: admin + + outcome: + collection: + data: [] + + - description: implicit abort + + operations: + # Start a transaction but don't commit - the driver calls abortTransaction + # from ClientSession.endSession(). + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: abortTransaction + database_name: admin + + outcome: + collection: + data: [] + + - description: two aborts + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: abortTransaction + arguments: + session: session0 + - name: abortTransaction + arguments: + session: session0 + result: + errorContains: no transaction started + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: abortTransaction + database_name: admin + + outcome: + collection: + data: [] + + - description: abort without start + + operations: + - name: abortTransaction + arguments: + session: session0 + result: + errorContains: no transaction started + + expectations: [] + + outcome: + collection: + data: [] + + - description: commit after abort + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: abortTransaction + arguments: + session: session0 + - name: commitTransaction + arguments: + session: session0 + result: + errorContains: no transaction started + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: abortTransaction + database_name: admin + + - description: abort ignores TransactionAborted + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + # Abort the server transaction with a duplicate key error. + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + errorCodeName: DuplicateKey + # Make sure the server aborted the transaction. + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + errorCodeName: NoSuchTransaction + # abortTransaction must ignore the TransactionAborted and succeed. + - name: abortTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 3 + startTransaction: + autocommit: false + writeConcern: + command_name: abortTransaction + database_name: admin + + + outcome: + collection: + data: [] diff --git a/test/functional/spec/transactions/auto-start.json b/test/functional/spec/transactions/auto-start.json new file mode 100644 index 0000000000..8f1df0fdec --- /dev/null +++ b/test/functional/spec/transactions/auto-start.json @@ -0,0 +1,760 @@ +{ + "data": [], + "tests": [ + { + "description": "commit", + "sessionOptions": { + "session0": { + "autoStartTransaction": true + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 3 + }, + "session": "session0" + }, + "result": { + "insertedId": 3 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "readConcern": { + "afterClusterTime": 42 + }, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 3 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + } + ] + } + } + }, + { + "description": "explicit start succeeds", + "sessionOptions": { + "session0": { + "autoStartTransaction": true + } + }, + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "3" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "3" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "explicit start fails", + "sessionOptions": { + "session0": { + "autoStartTransaction": true + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + }, + "result": { + "errorContains": "transaction already in progress" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "abort", + "sessionOptions": { + "session0": { + "autoStartTransaction": true + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "readConcern": { + "afterClusterTime": 42 + }, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 2 + } + ] + } + } + }, + { + "description": "commit empty transaction", + "sessionOptions": { + "session0": { + "autoStartTransaction": true + } + }, + "operations": [ + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "isolation", + "sessionOptions": { + "session0": { + "autoStartTransaction": true + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session1" + }, + "result": [] + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session1" + }, + "result": [ + { + "_id": 1 + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "find": "test", + "filter": { + "_id": 1 + }, + "lsid": "session1", + "txnNumber": null, + "stmtId": null, + "startTransaction": null, + "autocommit": null + }, + "command_name": "find", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "find": "test", + "filter": { + "_id": 1 + }, + "readConcern": { + "afterClusterTime": 42 + }, + "lsid": "session1", + "txnNumber": null, + "stmtId": null, + "startTransaction": null, + "autocommit": null + }, + "command_name": "find", + "database_name": "transaction-tests" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + } + ] +} diff --git a/test/functional/spec/transactions/auto-start.yml b/test/functional/spec/transactions/auto-start.yml new file mode 100644 index 0000000000..797052efbf --- /dev/null +++ b/test/functional/spec/transactions/auto-start.yml @@ -0,0 +1,491 @@ +data: [] +tests: + - description: commit + + sessionOptions: + session0: + autoStartTransaction: true + + operations: + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 2 + session: session0 + result: + insertedId: 2 + - name: insertOne + arguments: + document: + _id: 3 + session: session0 + result: + insertedId: 3 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + readConcern: + afterClusterTime: 42 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + insert: test + documents: + - _id: 3 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 2 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - _id: 1 + - _id: 2 + - _id: 3 + + - description: explicit start succeeds + + sessionOptions: + session0: + autoStartTransaction: true + + operations: + - name: startTransaction + arguments: + session: session0 + - name: commitTransaction + arguments: + session: session0 + - name: startTransaction + arguments: + session: session0 + - name: abortTransaction + arguments: + session: session0 + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "3" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "3" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - {_id: 1} + + - description: explicit start fails + + sessionOptions: + session0: + autoStartTransaction: true + + operations: + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: startTransaction + arguments: + session: session0 + result: + # Client-side error. + errorContains: transaction already in progress + # For cleanup. + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - {_id: 1} + + - description: abort + + sessionOptions: + session0: + autoStartTransaction: true + + operations: + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: abortTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 2 + session: session0 + result: + insertedId: 2 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: abortTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + readConcern: + afterClusterTime: 42 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - _id: 2 + + - description: commit empty transaction + + sessionOptions: + session0: + autoStartTransaction: true + + operations: + # Commit before any operations. + - name: commitTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + # Commit again with no active transaction. + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - _id: 1 + + - description: isolation + + sessionOptions: + session0: + autoStartTransaction: true + + operations: + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + # Not visible in session1 yet. + - name: find + arguments: + filter: + _id: 1 + session: session1 + result: [] + - name: commitTransaction + arguments: + session: session0 + - name: find + arguments: + filter: + _id: 1 + session: session1 + result: + - {_id: 1} + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + find: test + filter: + _id: 1 + lsid: session1 + txnNumber: + stmtId: + startTransaction: + autocommit: + command_name: find + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + find: test + filter: + _id: 1 + readConcern: + afterClusterTime: 42 + lsid: session1 + txnNumber: + stmtId: + startTransaction: + autocommit: + command_name: find + database_name: transaction-tests + + outcome: + collection: + data: + - _id: 1 diff --git a/test/functional/spec/transactions/bulk.json b/test/functional/spec/transactions/bulk.json new file mode 100644 index 0000000000..c381401179 --- /dev/null +++ b/test/functional/spec/transactions/bulk.json @@ -0,0 +1,513 @@ +{ + "data": [], + "tests": [ + { + "description": "bulk", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "deletedCount": 1 + } + }, + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + } + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + } + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 2 + }, + "update": { + "$set": { + "x": 2 + } + }, + "upsert": true + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 3 + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 4 + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 5 + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 6 + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 7 + } + } + }, + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "y": 1 + } + } + }, + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 2 + }, + "replacement": { + "y": 2 + } + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 3 + } + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 4 + } + } + }, + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gte": 6 + } + } + } + }, + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gte": 2 + } + }, + "update": { + "$set": { + "z": 1 + } + } + } + } + ], + "session": "session0" + }, + "result": { + "deletedCount": 4, + "insertedIds": { + "0": 1, + "3": 3, + "4": 4, + "5": 5, + "6": 6, + "7": 7 + }, + "matchedCount": 5, + "modifiedCount": 5, + "upsertedCount": 1, + "upsertedIds": { + "2": 2 + } + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "delete": "test", + "deletes": [ + { + "q": { + "_id": 1 + }, + "limit": 1 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "delete", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "$set": { + "x": 1 + } + }, + "multi": false, + "upsert": false + }, + { + "q": { + "_id": 2 + }, + "u": { + "$set": { + "x": 2 + } + }, + "multi": false, + "upsert": true + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 3, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + }, + { + "_id": 5 + }, + { + "_id": 6 + }, + { + "_id": 7 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 5, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "y": 1 + }, + "multi": false, + "upsert": false + }, + { + "q": { + "_id": 2 + }, + "u": { + "y": 2 + }, + "multi": false, + "upsert": false + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 10, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "delete": "test", + "deletes": [ + { + "q": { + "_id": 3 + }, + "limit": 1 + }, + { + "q": { + "_id": 4 + }, + "limit": 1 + }, + { + "q": { + "_id": { + "$gte": 6 + } + }, + "limit": 0 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 12, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "delete", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "_id": { + "$gte": 2 + } + }, + "u": { + "$set": { + "z": 1 + } + }, + "multi": true, + "upsert": false + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 15, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 16, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "y": 1 + }, + { + "_id": 2, + "y": 2, + "z": 1 + }, + { + "_id": 5, + "z": 1 + } + ] + } + } + } + ] +} diff --git a/test/functional/spec/transactions/bulk.yml b/test/functional/spec/transactions/bulk.yml new file mode 100644 index 0000000000..16f680f7ae --- /dev/null +++ b/test/functional/spec/transactions/bulk.yml @@ -0,0 +1,259 @@ +data: [] + +tests: + - description: bulk + + operations: + - name: startTransaction + arguments: + session: session0 + # A couple of commands to check that bulkWrite uses stmtId 2. + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: deleteOne + arguments: + filter: + _id: 1 + session: session0 + result: + deletedCount: 1 + - name: bulkWrite + arguments: + requests: + - name: insertOne + arguments: + document: {_id: 1} + # A series of updates allows the driver to skip stmtIds. + - name: updateOne + arguments: + filter: {_id: 1} + update: {$set: {x: 1}} + - name: updateOne + arguments: + filter: {_id: 2} + update: {$set: {x: 2}} + upsert: true # Produces upsertedIds: {2: 2} in the result. + - name: insertOne + arguments: + document: {_id: 3} + - name: insertOne + arguments: + document: {_id: 4} + - name: insertOne + arguments: + document: {_id: 5} + - name: insertOne + arguments: + document: {_id: 6} + - name: insertOne + arguments: + document: {_id: 7} + # Keep replaces segregated from updates, so that drivers that aren't able to coalesce + # adjacent updates and replaces into a single update command will still pass this test + - name: replaceOne + arguments: + filter: {_id: 1} + replacement: {y: 1} + - name: replaceOne + arguments: + filter: {_id: 2} + replacement: {y: 2} + - name: deleteOne + arguments: + filter: {_id: 3} + - name: deleteOne + arguments: + filter: {_id: 4} + - name: deleteMany + arguments: + filter: {_id: {$gte: 6}} + - name: updateMany + arguments: + filter: {_id: {$gte: 2}} + update: {$set: {z: 1}} + session: session0 + result: + deletedCount: 4 + insertedIds: {0: 1, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7} + matchedCount: 5 + modifiedCount: 5 + upsertedCount: 1 + upsertedIds: {2: 2} + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + delete: test + deletes: + - q: {_id: 1} + limit: 1 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: delete + database_name: transaction-tests + # Commands in the bulkWrite. + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + update: test + updates: + - q: {_id: 1} + u: {$set: {x: 1}} + multi: false + upsert: false + - q: {_id: 2} + u: {$set: {x: 2}} + multi: false + upsert: true + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 3 + startTransaction: + autocommit: false + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + insert: test + documents: + - _id: 3 + - _id: 4 + - _id: 5 + - _id: 6 + - _id: 7 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 5 + startTransaction: + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + update: test + updates: + - q: {_id: 1} + u: {y: 1} + multi: false + upsert: false + - q: {_id: 2} + u: {y: 2} + multi: false + upsert: false + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 10 + startTransaction: + autocommit: false + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + delete: test + deletes: + - q: {_id: 3} + limit: 1 + - q: {_id: 4} + limit: 1 + - q: {_id: {$gte: 6}} + limit: 0 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 12 + startTransaction: + autocommit: false + writeConcern: + command_name: delete + database_name: transaction-tests + - command_started_event: + command: + update: test + updates: + - q: {_id: {$gte: 2}} + u: {$set: {z: 1}} + multi: true + upsert: false + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 15 + startTransaction: + autocommit: false + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 16 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - {_id: 1, y: 1} + - {_id: 2, y: 2, z: 1} + - {_id: 5, z: 1} diff --git a/test/functional/spec/transactions/causal-consistency.json b/test/functional/spec/transactions/causal-consistency.json new file mode 100644 index 0000000000..f39f1cd7df --- /dev/null +++ b/test/functional/spec/transactions/causal-consistency.json @@ -0,0 +1,302 @@ +{ + "data": [ + { + "_id": 1, + "count": 0 + } + ], + "tests": [ + { + "description": "causal consistency", + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "count": 1 + } + }, + "upsert": false, + "session": "session0" + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "count": 1 + } + }, + "upsert": false, + "session": "session0" + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "$inc": { + "count": 1 + } + }, + "multi": false, + "upsert": false + } + ], + "ordered": true, + "lsid": "session0", + "readConcern": null, + "txnNumber": null, + "stmtId": null, + "startTransaction": null, + "autocommit": null, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "$inc": { + "count": 1 + } + }, + "multi": false, + "upsert": false + } + ], + "ordered": true, + "readConcern": { + "afterClusterTime": 42 + }, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "count": 2 + } + ] + } + } + }, + { + "description": "causal consistency disabled", + "sessionOptions": { + "session0": { + "causalConsistency": false + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "count": 1 + } + }, + "upsert": false, + "session": "session0" + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": null, + "stmtId": null, + "autocommit": null, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "$inc": { + "count": 1 + } + }, + "multi": false, + "upsert": false + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "count": 1 + }, + { + "_id": 2 + } + ] + } + } + } + ] +} diff --git a/test/functional/spec/transactions/causal-consistency.yml b/test/functional/spec/transactions/causal-consistency.yml new file mode 100644 index 0000000000..6354477c4f --- /dev/null +++ b/test/functional/spec/transactions/causal-consistency.yml @@ -0,0 +1,177 @@ +data: + - _id: 1 + count: 0 + +tests: + - description: causal consistency + + operations: + # Update a document without a transaction. + - &updateOne + name: updateOne + arguments: + filter: {_id: 1} + update: + $inc: {count: 1} + upsert: false + session: session0 + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + # Updating the same document inside a transaction. + # Casual consistency ensures that the transaction snapshot is causally + # after the first updateOne. + - name: startTransaction + arguments: + session: session0 + - *updateOne + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + update: test + updates: + - q: {_id: 1} + u: {$inc: {count: 1}} + multi: false + upsert: false + ordered: true + lsid: session0 + readConcern: + txnNumber: + stmtId: + startTransaction: + autocommit: + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + update: test + updates: + - q: {_id: 1} + u: {$inc: {count: 1}} + multi: false + upsert: false + ordered: true + readConcern: + afterClusterTime: 42 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - _id: 1 + count: 2 + + - description: causal consistency disabled + + sessionOptions: + session0: + causalConsistency: false + + operations: + # Insert a document without a transaction. + - name: insertOne + arguments: + document: + _id: 2 + session: session0 + result: + insertedId: 2 + - name: startTransaction + arguments: + session: session0 + - name: updateOne + arguments: + filter: {_id: 1} + update: + $inc: {count: 1} + upsert: false + session: session0 + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + readConcern: + lsid: session0 + txnNumber: + stmtId: + autocommit: + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + update: test + updates: + - q: {_id: 1} + u: {$inc: {count: 1}} + multi: false + upsert: false + ordered: true + # No afterClusterTime + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - _id: 1 + count: 1 + - _id: 2 diff --git a/test/functional/spec/transactions/commit.json b/test/functional/spec/transactions/commit.json new file mode 100644 index 0000000000..e60c88ec70 --- /dev/null +++ b/test/functional/spec/transactions/commit.json @@ -0,0 +1,246 @@ +{ + "data": [], + "tests": [ + { + "description": "commit", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "readConcern": { + "afterClusterTime": 42 + }, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + } + }, + { + "description": "two commits in a row", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + }, + "result": { + "errorContains": "no transaction started" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + } + ] +} diff --git a/test/functional/spec/transactions/commit.yml b/test/functional/spec/transactions/commit.yml new file mode 100644 index 0000000000..8f704a0ec2 --- /dev/null +++ b/test/functional/spec/transactions/commit.yml @@ -0,0 +1,155 @@ +data: [] +tests: + - description: commit + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + # Again, to verify that txnNumber is incremented. + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 2 + session: session0 + result: + insertedId: 2 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + readConcern: + afterClusterTime: 42 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - _id: 1 + - _id: 2 + + - description: two commits in a row + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + - name: commitTransaction + arguments: + session: session0 + result: + # Client-side error. + errorContains: no transaction started + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - _id: 1 diff --git a/test/functional/spec/transactions/delete.json b/test/functional/spec/transactions/delete.json new file mode 100644 index 0000000000..093fd03252 --- /dev/null +++ b/test/functional/spec/transactions/delete.json @@ -0,0 +1,315 @@ +{ + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + }, + { + "_id": 5 + } + ], + "tests": [ + { + "description": "delete", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "deletedCount": 1 + } + }, + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$lte": 3 + } + }, + "session": "session0" + }, + "result": { + "deletedCount": 2 + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 4 + }, + "session": "session0" + }, + "result": { + "deletedCount": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "test", + "deletes": [ + { + "q": { + "_id": 1 + }, + "limit": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "delete", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "delete": "test", + "deletes": [ + { + "q": { + "_id": { + "$lte": 3 + } + }, + "limit": 0 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "delete", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "delete": "test", + "deletes": [ + { + "q": { + "_id": 4 + }, + "limit": 1 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "delete", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 3, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 5 + } + ] + } + } + }, + { + "description": "operation writeConcern ignored for delete", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "writeConcern": { + "w": "majority" + } + } + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "writeConcern": { + "w": "majority" + }, + "session": "session0" + }, + "result": { + "deletedCount": 1 + } + }, + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$lte": 3 + } + }, + "writeConcern": { + "w": "majority" + }, + "session": "session0" + }, + "result": { + "deletedCount": 2 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "test", + "deletes": [ + { + "q": { + "_id": 1 + }, + "limit": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "delete", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "delete": "test", + "deletes": [ + { + "q": { + "_id": { + "$lte": 3 + } + }, + "limit": 0 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "delete", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ] + } + ] +} diff --git a/test/functional/spec/transactions/delete.yml b/test/functional/spec/transactions/delete.yml new file mode 100644 index 0000000000..f402167dbe --- /dev/null +++ b/test/functional/spec/transactions/delete.yml @@ -0,0 +1,184 @@ +data: + - _id: 1 + - _id: 2 + - _id: 3 + - _id: 4 + - _id: 5 + +tests: + - description: delete + + operations: + - name: startTransaction + arguments: + session: session0 + - name: deleteOne + arguments: + filter: + _id: 1 + session: session0 + result: + deletedCount: 1 + - name: deleteMany + arguments: + filter: + _id: {$lte: 3} + session: session0 + result: + deletedCount: 2 + - name: deleteOne + arguments: + filter: + _id: 4 + session: session0 + result: + deletedCount: 1 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + delete: test + deletes: + - q: {_id: 1} + limit: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: delete + database_name: transaction-tests + - command_started_event: + command: + delete: test + deletes: + - q: {_id: {$lte: 3}} + limit: 0 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: delete + database_name: transaction-tests + - command_started_event: + command: + delete: test + deletes: + - q: {_id: 4} + limit: 1 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + writeConcern: + command_name: delete + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 3 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - _id: 5 + + - description: operation writeConcern ignored for delete + operations: + - name: startTransaction + arguments: + session: session0 + options: + writeConcern: + w: majority + - name: deleteOne + arguments: + filter: + _id: 1 + writeConcern: + w: majority + session: session0 + result: + deletedCount: 1 + - name: deleteMany + arguments: + filter: + _id: {$lte: 3} + writeConcern: + w: majority + session: session0 + result: + deletedCount: 2 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + delete: test + deletes: + - q: {_id: 1} + limit: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: delete + database_name: transaction-tests + - command_started_event: + command: + delete: test + deletes: + - q: {_id: {$lte: 3}} + limit: 0 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: delete + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + writeConcern: + w: majority + command_name: commitTransaction + database_name: admin diff --git a/test/functional/spec/transactions/errors.json b/test/functional/spec/transactions/errors.json new file mode 100644 index 0000000000..7de861d96d --- /dev/null +++ b/test/functional/spec/transactions/errors.json @@ -0,0 +1,216 @@ +{ + "data": [], + "tests": [ + { + "description": "start insert start", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + }, + "result": { + "errorContains": "transaction already in progress" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ] + }, + { + "description": "start twice", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + }, + "result": { + "errorContains": "transaction already in progress" + } + } + ] + }, + { + "description": "commit and start twice", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + }, + "result": { + "errorContains": "transaction already in progress" + } + } + ] + }, + { + "description": "write conflict commit", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session1" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session1" + }, + "result": { + "errorCodeName": "WriteConflict" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session1" + }, + "result": { + "errorCodeName": "NoSuchTransaction" + } + } + ] + }, + { + "description": "write conflict abort", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session1" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session1" + }, + "result": { + "errorCodeName": "WriteConflict" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session1" + } + } + ] + } + ] +} diff --git a/test/functional/spec/transactions/errors.yml b/test/functional/spec/transactions/errors.yml new file mode 100644 index 0000000000..2e01199c27 --- /dev/null +++ b/test/functional/spec/transactions/errors.yml @@ -0,0 +1,127 @@ +data: [] +tests: + - description: start insert start + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: startTransaction + arguments: + session: session0 + result: + # Client-side error. + errorContains: transaction already in progress + # Just to clean up. + - name: commitTransaction + arguments: + session: session0 + + - description: start twice + + operations: + - name: startTransaction + arguments: + session: session0 + - name: startTransaction + arguments: + session: session0 + result: + # Client-side error. + errorContains: transaction already in progress + + - description: commit and start twice + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + - name: startTransaction + arguments: + session: session0 + - name: startTransaction + arguments: + session: session0 + result: + # Client-side error. + errorContains: transaction already in progress + + - description: write conflict commit + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: startTransaction + arguments: + session: session1 + - name: insertOne + arguments: + document: + _id: 1 + session: session1 + result: + errorCodeName: WriteConflict + - name: commitTransaction + arguments: + session: session0 + - name: commitTransaction + arguments: + session: session1 + result: + errorCodeName: NoSuchTransaction + + - description: write conflict abort + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: startTransaction + arguments: + session: session1 + - name: insertOne + arguments: + document: + _id: 1 + session: session1 + result: + errorCodeName: WriteConflict + - name: commitTransaction + arguments: + session: session0 + # Driver ignores "NoSuchTransaction" error. + - name: abortTransaction + arguments: + session: session1 diff --git a/test/functional/spec/transactions/findOneAndDelete.json b/test/functional/spec/transactions/findOneAndDelete.json new file mode 100644 index 0000000000..d5602dd179 --- /dev/null +++ b/test/functional/spec/transactions/findOneAndDelete.json @@ -0,0 +1,211 @@ +{ + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + } + ], + "tests": [ + { + "description": "findOneAndDelete", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": 3 + }, + "session": "session0" + }, + "result": { + "_id": 3 + } + }, + { + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": 4 + }, + "session": "session0" + }, + "result": null + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "test", + "query": { + "_id": 3 + }, + "remove": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "findAndModify", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "findAndModify": "test", + "query": { + "_id": 4 + }, + "remove": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "findAndModify", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + } + }, + { + "description": "operation writeConcern ignored for findOneAndDelete", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "writeConcern": { + "w": "majority" + } + } + } + }, + { + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": 3 + }, + "session": "session0", + "writeConcern": { + "w": "majority" + } + }, + "result": { + "_id": 3 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "test", + "query": { + "_id": 3 + }, + "remove": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "findAndModify", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ] + } + ] +} diff --git a/test/functional/spec/transactions/findOneAndDelete.yml b/test/functional/spec/transactions/findOneAndDelete.yml new file mode 100644 index 0000000000..9dcf1f9c56 --- /dev/null +++ b/test/functional/spec/transactions/findOneAndDelete.yml @@ -0,0 +1,127 @@ +data: + - _id: 1 + - _id: 2 + - _id: 3 + +tests: + - description: findOneAndDelete + + operations: + - name: startTransaction + arguments: + session: session0 + - name: findOneAndDelete + arguments: + filter: {_id: 3} + session: session0 + result: {_id: 3} + - name: findOneAndDelete + arguments: + filter: {_id: 4} + session: session0 + result: + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + findAndModify: test + query: {_id: 3} + remove: True + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + writeConcern: + command_name: findAndModify + database_name: transaction-tests + - command_started_event: + command: + findAndModify: test + query: {_id: 4} + remove: True + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: findAndModify + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - {_id: 1} + - {_id: 2} + + - description: operation writeConcern ignored for findOneAndDelete + + operations: + - name: startTransaction + arguments: + session: session0 + options: + writeConcern: + w: majority + - name: findOneAndDelete + arguments: + filter: {_id: 3} + session: session0 + writeConcern: + w: majority + result: {_id: 3} + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + findAndModify: test + query: {_id: 3} + remove: True + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + writeConcern: + command_name: findAndModify + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: majority + command_name: commitTransaction + database_name: admin diff --git a/test/functional/spec/transactions/findOneAndReplace.json b/test/functional/spec/transactions/findOneAndReplace.json new file mode 100644 index 0000000000..66110f8f73 --- /dev/null +++ b/test/functional/spec/transactions/findOneAndReplace.json @@ -0,0 +1,245 @@ +{ + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + } + ], + "tests": [ + { + "description": "findOneAndReplace", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 3 + }, + "replacement": { + "x": 1 + }, + "returnDocument": "Before", + "session": "session0" + }, + "result": { + "_id": 3 + } + }, + { + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "x": 1 + }, + "upsert": true, + "returnDocument": "After", + "session": "session0" + }, + "result": { + "_id": 4, + "x": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "test", + "query": { + "_id": 3 + }, + "update": { + "x": 1 + }, + "new": false, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "findAndModify", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "findAndModify": "test", + "query": { + "_id": 4 + }, + "update": { + "x": 1 + }, + "new": true, + "upsert": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "findAndModify", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3, + "x": 1 + }, + { + "_id": 4, + "x": 1 + } + ] + } + } + }, + { + "description": "operation writeConcern ignored for findOneAndReplace", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "writeConcern": { + "w": "majority" + } + } + } + }, + { + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 3 + }, + "replacement": { + "x": 1 + }, + "returnDocument": "Before", + "session": "session0", + "writeConcern": { + "w": "majority" + } + }, + "result": { + "_id": 3 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "test", + "query": { + "_id": 3 + }, + "update": { + "x": 1 + }, + "new": false, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "findAndModify", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ] + } + ] +} diff --git a/test/functional/spec/transactions/findOneAndReplace.yml b/test/functional/spec/transactions/findOneAndReplace.yml new file mode 100644 index 0000000000..d4403539ac --- /dev/null +++ b/test/functional/spec/transactions/findOneAndReplace.yml @@ -0,0 +1,141 @@ +data: + - _id: 1 + - _id: 2 + - _id: 3 + +tests: + - description: findOneAndReplace + + operations: + - name: startTransaction + arguments: + session: session0 + - name: findOneAndReplace + arguments: + filter: {_id: 3} + replacement: {x: 1} + returnDocument: Before + session: session0 + result: {_id: 3} + - name: findOneAndReplace + arguments: + filter: {_id: 4} + replacement: {x: 1} + upsert: true + returnDocument: After + session: session0 + result: {_id: 4, x: 1} + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + findAndModify: test + query: {_id: 3} + update: {x: 1} + new: false + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + writeConcern: + command_name: findAndModify + database_name: transaction-tests + - command_started_event: + command: + findAndModify: test + query: {_id: 4} + update: {x: 1} + new: true + upsert: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: findAndModify + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - {_id: 1} + - {_id: 2} + - {_id: 3, x: 1} + - {_id: 4, x: 1} + + - description: operation writeConcern ignored for findOneAndReplace + + operations: + - name: startTransaction + arguments: + session: session0 + options: + writeConcern: + w: majority + - name: findOneAndReplace + arguments: + filter: {_id: 3} + replacement: {x: 1} + returnDocument: Before + session: session0 + writeConcern: + w: majority + result: {_id: 3} + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + findAndModify: test + query: {_id: 3} + update: {x: 1} + new: false + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + writeConcern: + command_name: findAndModify + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: majority + command_name: commitTransaction + database_name: admin + diff --git a/test/functional/spec/transactions/findOneAndUpdate.json b/test/functional/spec/transactions/findOneAndUpdate.json new file mode 100644 index 0000000000..24ac94f1af --- /dev/null +++ b/test/functional/spec/transactions/findOneAndUpdate.json @@ -0,0 +1,413 @@ +{ + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + } + ], + "tests": [ + { + "description": "findOneAndUpdate", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 3 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before", + "session": "session0" + }, + "result": { + "_id": 3 + } + }, + { + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "upsert": true, + "returnDocument": "After", + "session": "session0" + }, + "result": { + "_id": 4, + "x": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 3 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before", + "session": "session0" + }, + "result": { + "_id": 3, + "x": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 3 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before", + "session": "session0" + }, + "result": { + "_id": 3, + "x": 2 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "test", + "query": { + "_id": 3 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "new": false, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "findAndModify", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "findAndModify": "test", + "query": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "new": true, + "upsert": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "findAndModify", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "findAndModify": "test", + "query": { + "_id": 3 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "new": false, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "afterClusterTime": 42 + }, + "writeConcern": null + }, + "command_name": "findAndModify", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "findAndModify": "test", + "query": { + "_id": 3 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "new": false, + "lsid": "session0", + "txnNumber": { + "$numberLong": "3" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "afterClusterTime": 42 + }, + "writeConcern": null + }, + "command_name": "findAndModify", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "3" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3, + "x": 2 + }, + { + "_id": 4, + "x": 1 + } + ] + } + } + }, + { + "description": "operation writeConcern ignored for findOneAndUpdate", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "writeConcern": { + "w": "majority" + } + } + } + }, + { + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 3 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before", + "session": "session0", + "writeConcern": { + "w": "majority" + } + }, + "result": { + "_id": 3 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "test", + "query": { + "_id": 3 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "new": false, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "findAndModify", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ] + } + ] +} diff --git a/test/functional/spec/transactions/findOneAndUpdate.yml b/test/functional/spec/transactions/findOneAndUpdate.yml new file mode 100644 index 0000000000..68cf074b1f --- /dev/null +++ b/test/functional/spec/transactions/findOneAndUpdate.yml @@ -0,0 +1,235 @@ +data: + - _id: 1 + - _id: 2 + - _id: 3 + +tests: + - description: findOneAndUpdate + + operations: + - name: startTransaction + arguments: + session: session0 + - name: findOneAndUpdate + arguments: + filter: {_id: 3} + update: + $inc: {x: 1} + returnDocument: Before + session: session0 + result: {_id: 3} + - name: findOneAndUpdate + arguments: + filter: {_id: 4} + update: + $inc: {x: 1} + upsert: true + returnDocument: After + session: session0 + result: {_id: 4, x: 1} + - name: commitTransaction + arguments: + session: session0 + - name: startTransaction + arguments: + session: session0 + # Test a second time to ensure txnNumber is incremented. + - name: findOneAndUpdate + arguments: + filter: {_id: 3} + update: + $inc: {x: 1} + returnDocument: Before + session: session0 + result: {_id: 3, x: 1} + - name: commitTransaction + arguments: + session: session0 + # Test a third time to ensure abort works. + - name: startTransaction + arguments: + session: session0 + - name: findOneAndUpdate + arguments: + filter: {_id: 3} + update: + $inc: {x: 1} + returnDocument: Before + session: session0 + result: {_id: 3, x: 2} + - name: abortTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + findAndModify: test + query: {_id: 3} + update: {$inc: {x: 1}} + new: false + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + writeConcern: + command_name: findAndModify + database_name: transaction-tests + - command_started_event: + command: + findAndModify: test + query: {_id: 4} + update: {$inc: {x: 1}} + new: true + upsert: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: findAndModify + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + findAndModify: test + query: {_id: 3} + update: {$inc: {x: 1}} + new: false + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + afterClusterTime: 42 + writeConcern: + command_name: findAndModify + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + findAndModify: test + query: {_id: 3} + update: {$inc: {x: 1}} + new: false + lsid: session0 + txnNumber: + $numberLong: "3" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + afterClusterTime: 42 + writeConcern: + command_name: findAndModify + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "3" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: abortTransaction + database_name: admin + + outcome: + collection: + data: + - {_id: 1} + - {_id: 2} + - {_id: 3, x: 2} + - {_id: 4, x: 1} + + - description: operation writeConcern ignored for findOneAndUpdate + + operations: + - name: startTransaction + arguments: + session: session0 + options: + writeConcern: + w: majority + - name: findOneAndUpdate + arguments: + filter: {_id: 3} + update: + $inc: {x: 1} + returnDocument: Before + session: session0 + writeConcern: + w: majority + result: {_id: 3} + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + findAndModify: test + query: {_id: 3} + update: + $inc: {x: 1} + new: false + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + writeConcern: + command_name: findAndModify + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: majority + command_name: commitTransaction + database_name: admin + diff --git a/test/functional/spec/transactions/insert.json b/test/functional/spec/transactions/insert.json new file mode 100644 index 0000000000..4bde5ed676 --- /dev/null +++ b/test/functional/spec/transactions/insert.json @@ -0,0 +1,376 @@ +{ + "data": [], + "tests": [ + { + "description": "insert", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2 + }, + { + "_id": 3 + } + ], + "session": "session0" + }, + "result": { + "insertedIds": { + "0": 2, + "1": 3 + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 4 + }, + "session": "session0" + }, + "result": { + "insertedId": 4 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 5 + }, + "session": "session0" + }, + "result": { + "insertedId": 5 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + }, + { + "_id": 3 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 4 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 3, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 4, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 5 + } + ], + "ordered": true, + "readConcern": { + "afterClusterTime": 42 + }, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + }, + { + "_id": 5 + } + ] + } + } + }, + { + "description": "operation writeConcern ignored for insert", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "writeConcern": { + "w": "majority" + } + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0", + "writeConcern": { + "w": "majority" + } + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2 + }, + { + "_id": 3 + } + ], + "session": "session0", + "writeConcern": { + "w": "majority" + } + }, + "result": { + "insertedIds": { + "0": 2, + "1": 3 + } + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + }, + { + "_id": 3 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 3, + "startTransaction": null, + "autocommit": false, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ] + } + ] +} diff --git a/test/functional/spec/transactions/insert.yml b/test/functional/spec/transactions/insert.yml new file mode 100644 index 0000000000..14aaf5dbda --- /dev/null +++ b/test/functional/spec/transactions/insert.yml @@ -0,0 +1,223 @@ +data: [] + +tests: + - description: insert + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: insertMany + arguments: + documents: + - _id: 2 + - _id: 3 + session: session0 + result: + insertedIds: {0: 2, 1: 3} + - name: insertOne + arguments: + document: + _id: 4 + session: session0 + result: + insertedId: 4 + - name: commitTransaction + arguments: + session: session0 + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 5 + session: session0 + result: + insertedId: 5 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + insert: test + documents: + - _id: 2 + - _id: 3 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + insert: test + documents: + - _id: 4 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 3 # Skip statement id 2. + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 4 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 5 + ordered: true + readConcern: + afterClusterTime: 42 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - _id: 1 + - _id: 2 + - _id: 3 + - _id: 4 + - _id: 5 + + - description: operation writeConcern ignored for insert + operations: + - name: startTransaction + arguments: + session: session0 + options: + writeConcern: + w: majority + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + writeConcern: + w: majority + result: + insertedId: 1 + - name: insertMany + arguments: + documents: + - _id: 2 + - _id: 3 + session: session0 + writeConcern: + w: majority + result: + insertedIds: {0: 2, 1: 3} + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + insert: test + documents: + - _id: 2 + - _id: 3 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 3 + startTransaction: + autocommit: false + writeConcern: + w: majority + command_name: commitTransaction + database_name: admin diff --git a/test/functional/spec/transactions/isolation.json b/test/functional/spec/transactions/isolation.json new file mode 100644 index 0000000000..279699ff6f --- /dev/null +++ b/test/functional/spec/transactions/isolation.json @@ -0,0 +1,209 @@ +{ + "data": [], + "tests": [ + { + "description": "one transaction", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session0" + }, + "result": [ + { + "_id": 1 + } + ] + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session1" + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + } + }, + "result": [] + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session1" + }, + "result": [ + { + "_id": 1 + } + ] + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + } + }, + "result": [ + { + "_id": 1 + } + ] + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "two transactions", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session1" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session0" + }, + "result": [ + { + "_id": 1 + } + ] + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session1" + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + } + }, + "result": [] + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session1" + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + } + }, + "result": [ + { + "_id": 1 + } + ] + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session1" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + } + ] +} diff --git a/test/functional/spec/transactions/isolation.yml b/test/functional/spec/transactions/isolation.yml new file mode 100644 index 0000000000..53cd961bf3 --- /dev/null +++ b/test/functional/spec/transactions/isolation.yml @@ -0,0 +1,116 @@ +# Test snapshot isolation. +# This test doesn't check contents of command-started events. +data: [] + +tests: + - description: one transaction + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: find + arguments: + filter: + _id: 1 + session: session0 + result: + - {_id: 1} + - name: find + arguments: + filter: + _id: 1 + session: session1 + result: [] + - name: find + arguments: + filter: + _id: 1 + result: [] + - name: commitTransaction + arguments: + session: session0 + - name: find + arguments: + filter: + _id: 1 + session: session1 + result: + - {_id: 1} + - name: find + arguments: + filter: + _id: 1 + result: + - {_id: 1} + + outcome: + collection: + data: + - _id: 1 + + - description: two transactions + + operations: + - name: startTransaction + arguments: + session: session0 + - name: startTransaction + arguments: + session: session1 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: find + arguments: + filter: + _id: 1 + session: session0 + result: + - {_id: 1} + - name: find + arguments: + filter: + _id: 1 + session: session1 + result: [] + - name: find + arguments: + filter: + _id: 1 + result: [] + - name: commitTransaction + arguments: + session: session0 + # Snapshot isolation in session1, not read-committed. + - name: find + arguments: + filter: + _id: 1 + session: session1 + result: [] + - name: find + arguments: + filter: + _id: 1 + result: + - {_id: 1} + - name: commitTransaction + arguments: + session: session1 + + outcome: + collection: + data: + - {_id: 1} diff --git a/test/functional/spec/transactions/read-pref.json b/test/functional/spec/transactions/read-pref.json new file mode 100644 index 0000000000..ff1636ea26 --- /dev/null +++ b/test/functional/spec/transactions/read-pref.json @@ -0,0 +1,307 @@ +{ + "data": [], + "tests": [ + { + "description": "primary", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "count", + "arguments": { + "filter": { + "_id": 1 + }, + "readPreference": { + "mode": "primary" + }, + "session": "session0" + }, + "result": 1 + }, + { + "name": "find", + "arguments": { + "session": "session0" + }, + "result": [ + { + "_id": 1 + } + ] + }, + { + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$project": { + "_id": 1 + } + } + ], + "batchSize": 3, + "session": "session0" + }, + "result": [ + { + "_id": 1 + } + ] + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "write and read", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "count", + "arguments": { + "readPreference": { + "mode": "secondary" + }, + "session": "session0" + }, + "result": { + "errorContains": "read preference in a transaction must be primary" + } + }, + { + "name": "find", + "arguments": { + "readPreference": { + "mode": "secondary" + }, + "session": "session0" + }, + "result": { + "errorContains": "read preference in a transaction must be primary" + } + }, + { + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$project": { + "_id": 1 + } + } + ], + "readPreference": { + "mode": "secondary" + }, + "session": "session0" + }, + "result": { + "errorContains": "read preference in a transaction must be primary" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "non-primary readPreference", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "count", + "arguments": { + "readPreference": { + "mode": "secondary" + }, + "session": "session0" + }, + "result": { + "errorContains": "read preference in a transaction must be primary" + } + }, + { + "name": "find", + "arguments": { + "readPreference": { + "mode": "secondary" + }, + "session": "session0" + }, + "result": { + "errorContains": "read preference in a transaction must be primary" + } + }, + { + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$project": { + "_id": 1 + } + } + ], + "readPreference": { + "mode": "secondary" + }, + "session": "session0" + }, + "result": { + "errorContains": "read preference in a transaction must be primary" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + }, + { + "description": "conflict", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "count", + "arguments": { + "readPreference": { + "mode": "primary" + }, + "session": "session0" + }, + "result": 0 + }, + { + "name": "count", + "arguments": { + "readPreference": { + "mode": "secondary" + }, + "session": "session0" + }, + "result": { + "errorContains": "read preference in a transaction must be primary" + } + }, + { + "name": "find", + "arguments": { + "session": "session0", + "readPreference": { + "mode": "secondary" + } + }, + "result": { + "errorContains": "read preference in a transaction must be primary" + } + }, + { + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$project": { + "_id": 1 + } + } + ], + "readPreference": { + "mode": "secondary" + }, + "session": "session0" + }, + "result": { + "errorContains": "read preference in a transaction must be primary" + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + } + ] +} diff --git a/test/functional/spec/transactions/read-pref.yml b/test/functional/spec/transactions/read-pref.yml new file mode 100644 index 0000000000..506203707c --- /dev/null +++ b/test/functional/spec/transactions/read-pref.yml @@ -0,0 +1,177 @@ +# This test doesn't check contents of command-started events. +data: [] +tests: + - description: primary + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: count + arguments: + filter: + _id: 1 + readPreference: + mode: primary + session: session0 + result: 1 + - name: find + arguments: + session: session0 + result: + - _id: 1 + - name: aggregate + arguments: + pipeline: + - $project: + _id: 1 + batchSize: 3 + session: session0 + result: + - _id: 1 + - name: commitTransaction + arguments: + session: session0 + + outcome: + collection: + data: + - _id: 1 + + - description: write and read + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: count + arguments: + readPreference: + mode: secondary + session: session0 + result: + # Client-side error. + errorContains: read preference in a transaction must be primary + - name: find + arguments: + readPreference: + mode: secondary + session: session0 + result: + errorContains: read preference in a transaction must be primary + - name: aggregate + arguments: + pipeline: + - $project: + _id: 1 + readPreference: + mode: secondary + session: session0 + result: + errorContains: read preference in a transaction must be primary + - name: commitTransaction + arguments: + session: session0 + + outcome: + collection: + data: + - _id: 1 + + - description: non-primary readPreference + + operations: + - name: startTransaction + arguments: + session: session0 + - name: count + arguments: + readPreference: + mode: secondary + session: session0 + result: + # Client-side error. + errorContains: read preference in a transaction must be primary + - name: find + arguments: + readPreference: + mode: secondary + session: session0 + result: + errorContains: read preference in a transaction must be primary + - name: aggregate + arguments: + pipeline: + - $project: + _id: 1 + readPreference: + mode: secondary + session: session0 + result: + errorContains: read preference in a transaction must be primary + - name: commitTransaction + arguments: + session: session0 + + outcome: + collection: + data: [] + + - description: conflict + + operations: + - name: startTransaction + arguments: + session: session0 + - name: count + arguments: + readPreference: + mode: primary + session: session0 + result: 0 + - name: count + arguments: + readPreference: + mode: secondary + session: session0 + result: + # Client-side error. + errorContains: read preference in a transaction must be primary + - name: find + arguments: + session: session0 + readPreference: + mode: secondary + result: + errorContains: read preference in a transaction must be primary + - name: aggregate + arguments: + pipeline: + - $project: + _id: 1 + readPreference: + mode: secondary + session: session0 + result: + errorContains: read preference in a transaction must be primary + - name: commitTransaction + arguments: + session: session0 + + outcome: + collection: + data: [] diff --git a/test/functional/spec/transactions/reads.json b/test/functional/spec/transactions/reads.json new file mode 100644 index 0000000000..2917fe0234 --- /dev/null +++ b/test/functional/spec/transactions/reads.json @@ -0,0 +1,594 @@ +{ + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ], + "tests": [ + { + "description": "count", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "count", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session0" + }, + "result": 1 + }, + { + "name": "count", + "arguments": { + "filter": { + "_id": 1 + }, + "session": "session0" + }, + "result": 1 + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "count": "test", + "query": { + "_id": 1 + }, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "count", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "count": "test", + "query": { + "_id": 1 + }, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "count", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + } + }, + { + "description": "find", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "find", + "arguments": { + "batchSize": 3, + "session": "session0" + }, + "result": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + { + "name": "find", + "arguments": { + "batchSize": 3, + "session": "session0" + }, + "result": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "find": "test", + "batchSize": 3, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false + }, + "command_name": "find", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "getMore": { + "$numberLong": "42" + }, + "collection": "test", + "batchSize": 3, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false + }, + "command_name": "getMore", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "find": "test", + "batchSize": 3, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false + }, + "command_name": "find", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "getMore": { + "$numberLong": "42" + }, + "collection": "test", + "batchSize": 3, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 3, + "startTransaction": null, + "autocommit": false + }, + "command_name": "getMore", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 4, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + } + }, + { + "description": "aggregate", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$project": { + "_id": 1 + } + } + ], + "batchSize": 3, + "session": "session0" + }, + "result": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + { + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$project": { + "_id": 1 + } + } + ], + "batchSize": 3, + "session": "session0" + }, + "result": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$project": { + "_id": 1 + } + } + ], + "cursor": { + "batchSize": 3 + }, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false + }, + "command_name": "aggregate", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "getMore": { + "$numberLong": "42" + }, + "collection": "test", + "batchSize": 3, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false + }, + "command_name": "getMore", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$project": { + "_id": 1 + } + } + ], + "cursor": { + "batchSize": 3 + }, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false + }, + "command_name": "aggregate", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "getMore": { + "$numberLong": "42" + }, + "collection": "test", + "batchSize": 3, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 3, + "startTransaction": null, + "autocommit": false + }, + "command_name": "getMore", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 4, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + } + }, + { + "description": "distinct", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "distinct", + "arguments": { + "fieldName": "_id", + "session": "session0" + }, + "result": [ + 1, + 2, + 3, + 4 + ] + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "distinct": "test", + "key": "_id", + "lsid": "session0", + "readConcern": null, + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "distinct", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "readConcern": null, + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + } + } + ] +} diff --git a/test/functional/spec/transactions/reads.yml b/test/functional/spec/transactions/reads.yml new file mode 100644 index 0000000000..887f9ee5b9 --- /dev/null +++ b/test/functional/spec/transactions/reads.yml @@ -0,0 +1,296 @@ +# Test all read operations' txnNumbers and stmtIds. +# Aggregate not yet supported in transactions. +data: &data + - {_id: 1} + - {_id: 2} + - {_id: 3} + - {_id: 4} + +tests: + - description: count + + operations: + - &startTransaction + name: startTransaction + arguments: + session: session0 + - &count + name: count + arguments: + filter: + _id: 1 + session: session0 + result: 1 + - *count + - &commitTransaction + name: commitTransaction + arguments: + session: session0 + + + expectations: + - command_started_event: + command: + count: test + query: + _id: 1 + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: count + database_name: transaction-tests + - command_started_event: + command: + count: test + query: + _id: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: count + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: &outcome + collection: + data: + *data + + - description: find + + operations: + - *startTransaction + - &find + name: find + arguments: + batchSize: 3 + session: session0 + result: *data + - *find + - *commitTransaction + + expectations: + - command_started_event: + command: + find: test + batchSize: 3 + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + command_name: find + database_name: transaction-tests + - command_started_event: + command: + getMore: + # 42 is a fake placeholder value for the cursorId. + $numberLong: '42' + collection: test + batchSize: 3 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + command_name: getMore + database_name: transaction-tests + - command_started_event: + command: + find: test + batchSize: 3 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + command_name: find + database_name: transaction-tests + - command_started_event: + command: + getMore: + $numberLong: '42' + collection: test + batchSize: 3 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 3 + startTransaction: + autocommit: false + command_name: getMore + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 4 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: *outcome + + - description: aggregate + + operations: + - *startTransaction + - &aggregate + name: aggregate + arguments: + pipeline: + - $project: + _id: 1 + batchSize: 3 + session: session0 + result: *data + - *aggregate + - *commitTransaction + + expectations: + - command_started_event: + command: + aggregate: test + pipeline: + - $project: + _id: 1 + cursor: + batchSize: 3 + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + command_name: aggregate + database_name: transaction-tests + - command_started_event: + command: + getMore: + # 42 is a fake placeholder value for the cursorId. + $numberLong: '42' + collection: test + batchSize: 3 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + command_name: getMore + database_name: transaction-tests + - command_started_event: + command: + aggregate: test + pipeline: + - $project: + _id: 1 + cursor: + batchSize: 3 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + command_name: aggregate + database_name: transaction-tests + - command_started_event: + command: + getMore: + $numberLong: '42' + collection: test + batchSize: 3 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 3 + startTransaction: + autocommit: false + command_name: getMore + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 4 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: *outcome + + - description: distinct + + operations: + - *startTransaction + - name: distinct + arguments: + fieldName: _id + session: session0 + result: [1, 2, 3, 4] + - *commitTransaction + + expectations: + - command_started_event: + command: + distinct: test + key: _id + lsid: session0 + readConcern: + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: distinct + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + readConcern: + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: *outcome diff --git a/test/functional/spec/transactions/retryable-writes.json b/test/functional/spec/transactions/retryable-writes.json new file mode 100644 index 0000000000..389fd7f9e6 --- /dev/null +++ b/test/functional/spec/transactions/retryable-writes.json @@ -0,0 +1,248 @@ +{ + "data": [], + "tests": [ + { + "description": "increment txnNumber", + "clientOptions": { + "retryWrites": true + }, + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 3 + }, + "session": "session0" + }, + "result": { + "insertedId": 3 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 4 + }, + { + "_id": 5 + } + ], + "session": "session0" + }, + "result": { + "insertedIds": { + "0": 4, + "1": 5 + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": null, + "startTransaction": null, + "autocommit": null, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 3 + } + ], + "ordered": true, + "readConcern": { + "afterClusterTime": 42 + }, + "lsid": "session0", + "txnNumber": { + "$numberLong": "3" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "3" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 4 + }, + { + "_id": 5 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "4" + }, + "stmtId": null, + "startTransaction": null, + "autocommit": null, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 4 + }, + { + "_id": 5 + } + ] + } + } + } + ] +} diff --git a/test/functional/spec/transactions/retryable-writes.yml b/test/functional/spec/transactions/retryable-writes.yml new file mode 100644 index 0000000000..0b6db7d9a7 --- /dev/null +++ b/test/functional/spec/transactions/retryable-writes.yml @@ -0,0 +1,153 @@ +data: [] + +tests: + - description: increment txnNumber + + clientOptions: + retryWrites: true + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + # Retryable write should include the next txnNumber + - name: insertOne + arguments: + document: + _id: 2 + session: session0 + result: + insertedId: 2 + # Next transaction should include the next txnNumber + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 3 + session: session0 + result: + insertedId: 3 + - name: abortTransaction + arguments: + session: session0 + # Retryable write should include the next txnNumber + - name: insertMany + arguments: + documents: + - _id: 4 + - _id: 5 + session: session0 + result: + insertedIds: {0: 4, 1: 5} + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: + startTransaction: + autocommit: + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + insert: test + documents: + - _id: 3 + ordered: true + readConcern: + afterClusterTime: 42 + lsid: session0 + txnNumber: + $numberLong: "3" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "3" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: abortTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 4 + - _id: 5 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "4" + stmtId: + startTransaction: + autocommit: + writeConcern: + command_name: insert + database_name: transaction-tests + + outcome: + collection: + data: + - _id: 1 + - _id: 2 + - _id: 4 + - _id: 5 diff --git a/test/functional/spec/transactions/transaction-options.json b/test/functional/spec/transactions/transaction-options.json new file mode 100644 index 0000000000..f8b3aa1c21 --- /dev/null +++ b/test/functional/spec/transactions/transaction-options.json @@ -0,0 +1,1293 @@ +{ + "data": [], + "tests": [ + { + "description": "no transaction options set", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "afterClusterTime": 42 + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "transaction options inherited from client", + "clientOptions": { + "w": 1, + "readConcernLevel": "local" + }, + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "local" + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": 1 + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "local", + "afterClusterTime": 42 + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": 1 + } + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "transaction options inherited from defaultTransactionOptions", + "sessionOptions": { + "session0": { + "defaultTransactionOptions": { + "readConcern": { + "level": "snapshot" + }, + "writeConcern": { + "w": 1 + } + } + } + }, + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "snapshot" + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": 1 + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "snapshot", + "afterClusterTime": 42 + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": 1 + } + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "startTransaction options override defaults", + "clientOptions": { + "readConcernLevel": "local", + "w": 1 + }, + "sessionOptions": { + "session0": { + "defaultTransactionOptions": { + "readConcern": { + "level": "majority" + }, + "writeConcern": { + "w": 1 + } + } + } + }, + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "readConcern": { + "level": "snapshot" + }, + "writeConcern": { + "w": "majority" + } + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "readConcern": { + "level": "snapshot" + }, + "writeConcern": { + "w": "majority" + } + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "snapshot" + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "snapshot", + "afterClusterTime": 42 + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "defaultTransactionOptions override client options", + "clientOptions": { + "readConcernLevel": "local", + "w": 1 + }, + "sessionOptions": { + "session0": { + "defaultTransactionOptions": { + "readConcern": { + "level": "snapshot" + }, + "writeConcern": { + "w": "majority" + } + } + } + }, + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "snapshot" + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "snapshot", + "afterClusterTime": 42 + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "readConcern local in defaultTransactionOptions", + "clientOptions": { + "w": 1 + }, + "sessionOptions": { + "session0": { + "defaultTransactionOptions": { + "readConcern": { + "level": "local" + } + } + } + }, + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "local" + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": 1 + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "local", + "afterClusterTime": 42 + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": { + "w": 1 + } + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "readConcern local in startTransaction options", + "sessionOptions": { + "session0": { + "defaultTransactionOptions": { + "readConcern": { + "level": "majority" + } + } + } + }, + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "readConcern": { + "level": "snapshot" + } + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "readConcern": { + "level": "snapshot" + } + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2 + }, + "session": "session0" + }, + "result": { + "insertedId": 2 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "snapshot" + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + }, + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 2 + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "readConcern": { + "level": "snapshot", + "afterClusterTime": 42 + }, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "2" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "readConcern": null, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "client writeConcern ignored for bulk", + "clientOptions": { + "w": "majority" + }, + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "writeConcern": { + "w": 1 + } + } + } + }, + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + } + } + } + ], + "session": "session0" + }, + "result": { + "deletedCount": 0, + "insertedIds": { + "0": 1 + }, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": { + "w": 1 + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + } + ] +} diff --git a/test/functional/spec/transactions/transaction-options.yml b/test/functional/spec/transactions/transaction-options.yml new file mode 100644 index 0000000000..85b98be7f1 --- /dev/null +++ b/test/functional/spec/transactions/transaction-options.yml @@ -0,0 +1,707 @@ +data: [] + +tests: + - description: no transaction options set + + operations: &commitAbortOperations + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + # Now test abort. + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 2 + session: session0 + result: + insertedId: 2 + - name: abortTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + afterClusterTime: 42 + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: abortTransaction + database_name: admin + + outcome: &outcome + collection: + data: + - _id: 1 + + - description: transaction options inherited from client + + clientOptions: + w: 1 + readConcernLevel: local + + operations: *commitAbortOperations + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: local + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: 1 + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: local + afterClusterTime: 42 + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: 1 + command_name: abortTransaction + database_name: admin + + outcome: *outcome + + - description: transaction options inherited from defaultTransactionOptions + + sessionOptions: + session0: + defaultTransactionOptions: + readConcern: + level: snapshot + writeConcern: + w: 1 + + operations: *commitAbortOperations + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: snapshot + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: 1 + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: snapshot + afterClusterTime: 42 + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: 1 + command_name: abortTransaction + database_name: admin + + outcome: *outcome + + - description: startTransaction options override defaults + + clientOptions: + readConcernLevel: local + w: 1 + + sessionOptions: + session0: + defaultTransactionOptions: + readConcern: + level: majority + writeConcern: + w: 1 + + operations: + - name: startTransaction + arguments: + session: session0 + options: + readConcern: + level: snapshot + writeConcern: + w: majority + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + - name: startTransaction + arguments: + session: session0 + options: + readConcern: + level: snapshot + writeConcern: + w: majority + - name: insertOne + arguments: + document: + _id: 2 + session: session0 + result: + insertedId: 2 + - name: abortTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: snapshot + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: majority + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: snapshot + afterClusterTime: 42 + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: majority + command_name: abortTransaction + database_name: admin + + outcome: *outcome + + - description: defaultTransactionOptions override client options + + clientOptions: + readConcernLevel: local + w: 1 + + sessionOptions: + session0: + defaultTransactionOptions: + readConcern: + level: snapshot + writeConcern: + w: majority + + operations: *commitAbortOperations + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: snapshot + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: majority + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: snapshot + afterClusterTime: 42 + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: majority + command_name: abortTransaction + database_name: admin + + outcome: *outcome + + - description: readConcern local in defaultTransactionOptions + + clientOptions: + w: 1 + + sessionOptions: + session0: + defaultTransactionOptions: + readConcern: + level: local + + operations: *commitAbortOperations + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: local + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: 1 + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: local + afterClusterTime: 42 + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + w: 1 + command_name: abortTransaction + database_name: admin + + outcome: *outcome + + - description: readConcern local in startTransaction options + + sessionOptions: + session0: + defaultTransactionOptions: + readConcern: + level: majority # Overridden. + + operations: + - name: startTransaction + arguments: + session: session0 + options: + readConcern: + level: snapshot + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + # Now test abort. + - name: startTransaction + arguments: + session: session0 + options: + readConcern: + level: snapshot + - name: insertOne + arguments: + document: + _id: 2 + session: session0 + result: + insertedId: 2 + - name: abortTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: snapshot + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: commitTransaction + database_name: admin + - command_started_event: + command: + insert: test + documents: + - _id: 2 + ordered: true + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 0 + startTransaction: true + autocommit: false + readConcern: + level: snapshot + afterClusterTime: 42 + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "2" + stmtId: 1 + startTransaction: + autocommit: false + readConcern: + writeConcern: + command_name: abortTransaction + database_name: admin + + outcome: *outcome + + - description: client writeConcern ignored for bulk + + clientOptions: + w: majority + + operations: + - name: startTransaction + arguments: + session: session0 + options: + writeConcern: + w: 1 + - name: bulkWrite + arguments: + requests: + - name: insertOne + arguments: + document: {_id: 1} + session: session0 + result: + deletedCount: 0 + insertedIds: {0: 1} + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: {} + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + # No writeConcern. + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + w: 1 + command_name: commitTransaction + database_name: admin + + outcome: *outcome diff --git a/test/functional/spec/transactions/update.json b/test/functional/spec/transactions/update.json new file mode 100644 index 0000000000..1a2aefa958 --- /dev/null +++ b/test/functional/spec/transactions/update.json @@ -0,0 +1,436 @@ +{ + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + } + ], + "tests": [ + { + "description": "update", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "upsert": true, + "session": "session0" + }, + "result": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 1, + "upsertedId": 4 + } + }, + { + "name": "replaceOne", + "arguments": { + "filter": { + "x": 1 + }, + "replacement": { + "y": 1 + }, + "session": "session0" + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gte": 3 + } + }, + "update": { + "$set": { + "z": 1 + } + }, + "session": "session0" + }, + "result": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "_id": 4 + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": false, + "upsert": true + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "x": 1 + }, + "u": { + "y": 1 + }, + "multi": false, + "upsert": false + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "_id": { + "$gte": 3 + } + }, + "u": { + "$set": { + "z": 1 + } + }, + "multi": true, + "upsert": false + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 3, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3, + "z": 1 + }, + { + "_id": 4, + "y": 1, + "z": 1 + } + ] + } + } + }, + { + "description": "operation writeConcern ignored for update", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "writeConcern": { + "w": "majority" + } + } + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "upsert": true, + "writeConcern": { + "w": "majority" + }, + "session": "session0" + }, + "result": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 1, + "upsertedId": 4 + } + }, + { + "name": "replaceOne", + "arguments": { + "filter": { + "x": 1 + }, + "replacement": { + "y": 1 + }, + "writeConcern": { + "w": "majority" + }, + "session": "session0" + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gte": 3 + } + }, + "update": { + "$set": { + "z": 1 + } + }, + "writeConcern": { + "w": "majority" + }, + "session": "session0" + }, + "result": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "_id": 4 + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": false, + "upsert": true + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "x": 1 + }, + "u": { + "y": 1 + }, + "multi": false, + "upsert": false + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": { + "_id": { + "$gte": 3 + } + }, + "u": { + "$set": { + "z": 1 + } + }, + "multi": true, + "upsert": false + } + ], + "ordered": true, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 2, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "update", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 3, + "startTransaction": null, + "autocommit": false, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ] + } + ] +} diff --git a/test/functional/spec/transactions/update.yml b/test/functional/spec/transactions/update.yml new file mode 100644 index 0000000000..0b85aa99bb --- /dev/null +++ b/test/functional/spec/transactions/update.yml @@ -0,0 +1,245 @@ +data: + - _id: 1 + - _id: 2 + - _id: 3 + +tests: + - description: update + + operations: + - name: startTransaction + arguments: + session: session0 + - name: updateOne + arguments: + filter: {_id: 4} + update: + $inc: {x: 1} + upsert: true + session: session0 + result: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 1 + upsertedId: 4 + - name: replaceOne + arguments: + filter: {x: 1} + replacement: {y: 1} + session: session0 + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateMany + arguments: + filter: + _id: {$gte: 3} + update: + $set: {z: 1} + session: session0 + result: + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + update: test + updates: + - q: {_id: 4} + u: {$inc: {x: 1}} + multi: false + upsert: true + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + update: test + updates: + - q: {x: 1} + u: {y: 1} + multi: false + upsert: false + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + update: test + updates: + - q: {_id: {$gte: 3}} + u: {$set: {z: 1}} + multi: true + upsert: false + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 3 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - {_id: 1} + - {_id: 2} + - {_id: 3, z: 1} + - {_id: 4, y: 1, z: 1} + + - description: operation writeConcern ignored for update + + operations: + - name: startTransaction + arguments: + session: session0 + options: + writeConcern: + w: majority + - name: updateOne + arguments: + filter: {_id: 4} + update: + $inc: {x: 1} + upsert: true + writeConcern: + w: majority + session: session0 + result: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 1 + upsertedId: 4 + - name: replaceOne + arguments: + filter: {x: 1} + replacement: {y: 1} + writeConcern: + w: majority + session: session0 + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateMany + arguments: + filter: + _id: {$gte: 3} + update: + $set: {z: 1} + writeConcern: + w: majority + session: session0 + result: + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + update: test + updates: + - q: {_id: 4} + u: {$inc: {x: 1}} + multi: false + upsert: true + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + update: test + updates: + - q: {x: 1} + u: {y: 1} + multi: false + upsert: false + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + update: test + updates: + - q: {_id: {$gte: 3}} + u: {$set: {z: 1}} + multi: true + upsert: false + ordered: true + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 2 + startTransaction: + autocommit: false + writeConcern: + command_name: update + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 3 + startTransaction: + autocommit: false + writeConcern: + w: majority + command_name: commitTransaction + database_name: admin diff --git a/test/functional/spec/transactions/write-concern.json b/test/functional/spec/transactions/write-concern.json new file mode 100644 index 0000000000..1fa5fdcbea --- /dev/null +++ b/test/functional/spec/transactions/write-concern.json @@ -0,0 +1,335 @@ +{ + "data": [], + "tests": [ + { + "description": "commit with majority", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "writeConcern": { + "w": "majority" + } + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "commit with default", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "commitTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "commitTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "commitTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "abort with majority", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0", + "options": { + "writeConcern": { + "w": "majority" + } + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": { + "w": "majority" + } + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + }, + { + "description": "abort with default", + "operations": [ + { + "name": "startTransaction", + "arguments": { + "session": "session0" + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + }, + "session": "session0" + }, + "result": { + "insertedId": 1 + } + }, + { + "name": "abortTransaction", + "arguments": { + "session": "session0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "test", + "documents": [ + { + "_id": 1 + } + ], + "ordered": true, + "readConcern": null, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 0, + "startTransaction": true, + "autocommit": false, + "writeConcern": null + }, + "command_name": "insert", + "database_name": "transaction-tests" + } + }, + { + "command_started_event": { + "command": { + "abortTransaction": 1, + "lsid": "session0", + "txnNumber": { + "$numberLong": "1" + }, + "stmtId": 1, + "startTransaction": null, + "autocommit": false, + "writeConcern": null + }, + "command_name": "abortTransaction", + "database_name": "admin" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + } + ] +} diff --git a/test/functional/spec/transactions/write-concern.yml b/test/functional/spec/transactions/write-concern.yml new file mode 100644 index 0000000000..b95e441d78 --- /dev/null +++ b/test/functional/spec/transactions/write-concern.yml @@ -0,0 +1,218 @@ +# Assumes the default for transactions is the same as for all ops, tests +# setting the writeConcern to "majority". +data: [] + +tests: + - description: commit with majority + operations: + - name: startTransaction + arguments: + session: session0 + options: + writeConcern: + w: majority + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + w: majority + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + - _id: 1 + + - description: commit with default + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: commitTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + commitTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: commitTransaction + database_name: admin + + outcome: + collection: + data: + + - _id: 1 + + - description: abort with majority + + operations: + - name: startTransaction + arguments: + session: session0 + options: + writeConcern: + w: majority + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: abortTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + w: majority + command_name: abortTransaction + database_name: admin + + outcome: + collection: + data: [] + + - description: abort with default + + operations: + - name: startTransaction + arguments: + session: session0 + - name: insertOne + arguments: + document: + _id: 1 + session: session0 + result: + insertedId: 1 + - name: abortTransaction + arguments: + session: session0 + + expectations: + - command_started_event: + command: + insert: test + documents: + - _id: 1 + ordered: true + readConcern: + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 0 + startTransaction: true + autocommit: false + writeConcern: + command_name: insert + database_name: transaction-tests + - command_started_event: + command: + abortTransaction: 1 + lsid: session0 + txnNumber: + $numberLong: "1" + stmtId: 1 + startTransaction: + autocommit: false + writeConcern: + command_name: abortTransaction + database_name: admin + + outcome: + collection: + data: []