runOn:
    -
        minServerVersion: "4.0"
        topology: ["replicaset"]
    -
        minServerVersion: "4.1.8"
        topology: ["sharded"]

database_name: &database_name "transaction-tests"
collection_name: &collection_name "test"

data: []

tests:
  - description: no transaction options set

    operations: &commitAbortOperations
      - name: startTransaction
        object: session0
      - name: insertOne
        object: collection
        arguments:
          session: session0
          document:
            _id: 1
        result:
          insertedId: 1
      - name: commitTransaction
        object: session0
      # Now test abort.
      - name: startTransaction
        object: session0
      - name: insertOne
        object: collection
        arguments:
          session: session0
          document:
            _id: 2
        result:
          insertedId: 2
      - name: abortTransaction
        object: session0

    expectations:
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 1
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction: true
            autocommit: false
            readConcern:
            writeConcern:
            maxTimeMS:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
            maxTimeMS:
          command_name: commitTransaction
          database_name: admin
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 2
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction: true
            autocommit: false
            readConcern:
              afterClusterTime: 42
            writeConcern:
            maxTimeMS:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            abortTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
            maxTimeMS:
          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: *collection_name
            documents:
              - _id: 1
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction: true
            autocommit: false
            readConcern:
              level: local
            writeConcern:
            maxTimeMS:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
              w: 1
            maxTimeMS:
          command_name: commitTransaction
          database_name: admin
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 2
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction: true
            autocommit: false
            readConcern:
              level: local
              afterClusterTime: 42
            writeConcern:
            maxTimeMS:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            abortTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
              w: 1
            maxTimeMS:
          command_name: abortTransaction
          database_name: admin

    outcome: *outcome

  - description: transaction options inherited from defaultTransactionOptions

    sessionOptions:
      session0:
        defaultTransactionOptions:
          readConcern:
            level: snapshot
          writeConcern:
            w: 1
          maxCommitTimeMS: 60000

    operations: *commitAbortOperations

    expectations:
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 1
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction: true
            autocommit: false
            readConcern:
              level: snapshot
            writeConcern:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
              w: 1
            maxTimeMS: 60000
          command_name: commitTransaction
          database_name: admin
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 2
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction: true
            autocommit: false
            readConcern:
              level: snapshot
              afterClusterTime: 42
            writeConcern:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            abortTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "2"
            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
          maxCommitTimeMS: 30000

    operations:
      - name: startTransaction
        object: session0
        arguments:
          options:
            readConcern:
              level: snapshot
            writeConcern:
              w: majority
            maxCommitTimeMS: 60000
      - name: insertOne
        object: collection
        arguments:
          session: session0
          document:
            _id: 1
        result:
          insertedId: 1
      - name: commitTransaction
        object: session0
      - name: startTransaction
        object: session0
        arguments:
          options:
            readConcern:
              level: snapshot
            writeConcern:
              w: majority
      - name: insertOne
        object: collection
        arguments:
          session: session0
          document:
            _id: 2
        result:
          insertedId: 2
      - name: abortTransaction
        object: session0

    expectations:
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 1
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction: true
            autocommit: false
            readConcern:
              level: snapshot
            writeConcern:
            maxTimeMS:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
              w: majority
            maxTimeMS: 60000
          command_name: commitTransaction
          database_name: admin
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 2
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction: true
            autocommit: false
            readConcern:
              level: snapshot
              afterClusterTime: 42
            writeConcern:
            maxTimeMS:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            abortTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
              w: majority
            maxTimeMS:
          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
          maxCommitTimeMS: 60000

    operations: *commitAbortOperations

    expectations:
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 1
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction: true
            autocommit: false
            readConcern:
              level: snapshot
            writeConcern:
            maxTimeMS:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
              w: majority
            maxTimeMS: 60000
          command_name: commitTransaction
          database_name: admin
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 2
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction: true
            autocommit: false
            readConcern:
              level: snapshot
              afterClusterTime: 42
            writeConcern:
            maxTimeMS:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            abortTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
              w: majority
            maxTimeMS:
          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: *collection_name
            documents:
              - _id: 1
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction: true
            autocommit: false
            readConcern:
              level: local
            writeConcern:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
              w: 1
          command_name: commitTransaction
          database_name: admin
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 2
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction: true
            autocommit: false
            readConcern:
              level: local
              afterClusterTime: 42
            writeConcern:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            abortTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
              w: 1
          command_name: abortTransaction
          database_name: admin

    outcome: *outcome

  - description: readConcern snapshot in startTransaction options

    sessionOptions:
      session0:
        defaultTransactionOptions:
          readConcern:
            level: majority # Overridden.

    operations:
      - name: startTransaction
        object: session0
        arguments:
          options:
            readConcern:
              level: snapshot
      - name: insertOne
        object: collection
        arguments:
          session: session0
          document:
            _id: 1
        result:
          insertedId: 1
      - name: commitTransaction
        object: session0
      # Now test abort.
      - name: startTransaction
        object: session0
        arguments:
          options:
            readConcern:
              level: snapshot
      - name: insertOne
        object: collection
        arguments:
          session: session0
          document:
            _id: 2
        result:
          insertedId: 2
      - name: abortTransaction
        object: session0

    expectations:
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 1
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction: true
            autocommit: false
            readConcern:
              level: snapshot
            writeConcern:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
          command_name: commitTransaction
          database_name: admin
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 2
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "2"
            startTransaction: true
            autocommit: false
            readConcern:
              level: snapshot
              afterClusterTime: 42
            writeConcern:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            abortTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "2"
            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
        object: session0
        arguments:
          options:
            writeConcern:
              w: 1
      - name: bulkWrite
        object: collection
        arguments:
          requests:
            - name: insertOne
              arguments:
                document: {_id: 1}
          session: session0
        result:
          deletedCount: 0
          insertedCount: 1
          insertedIds: {0: 1}
          matchedCount: 0
          modifiedCount: 0
          upsertedCount: 0
          upsertedIds: {}
      - name: commitTransaction
        object: session0

    expectations:
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 1
            ordered: true
            readConcern:
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction: true
            autocommit: false
            # No writeConcern.
            writeConcern:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction:
            autocommit: false
            writeConcern:
              w: 1
          command_name: commitTransaction
          database_name: admin

    outcome: *outcome

  - description: readPreference inherited from client

    clientOptions:
      readPreference: secondary

    operations:
      - name: startTransaction
        object: session0
      - name: insertOne
        object: collection
        arguments:
          session: session0
          document:
            _id: 1
        result:
          insertedId: 1
      - name: find
        object: collection
        arguments:
          session: session0
          filter:
            _id: 1
        result:
          errorContains: read preference in a transaction must be primary
      - name: commitTransaction
        object: session0

    expectations:
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 1
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction: true
            autocommit: false
            readConcern:
            writeConcern:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
          command_name: commitTransaction
          database_name: admin

    outcome:
      collection:
        data:
          - _id: 1

  - description: readPreference inherited from defaultTransactionOptions

    clientOptions:
      readPreference: primary

    sessionOptions:
      session0:
        defaultTransactionOptions:
          readPreference:
            mode: Secondary

    operations:
      - name: startTransaction
        object: session0
      - name: insertOne
        object: collection
        arguments:
          session: session0
          document:
            _id: 1
        result:
          insertedId: 1
      - name: find
        object: collection
        arguments:
          session: session0
          filter:
            _id: 1
        result:
          errorContains: read preference in a transaction must be primary
      - name: commitTransaction
        object: session0

    expectations:
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 1
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction: true
            autocommit: false
            readConcern:
            writeConcern:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
          command_name: commitTransaction
          database_name: admin

    outcome:
      collection:
        data:
          - _id: 1

  - description: startTransaction overrides readPreference

    clientOptions:
      readPreference: primary

    sessionOptions:
      session0:
        defaultTransactionOptions:
          readPreference:
            mode: Primary

    operations:
      - name: startTransaction
        object: session0
        arguments:
          options:
            readPreference:
              mode: Secondary
      - name: insertOne
        object: collection
        arguments:
          session: session0
          document:
            _id: 1
        result:
          insertedId: 1
      - name: find
        object: collection
        arguments:
          session: session0
          filter:
            _id: 1
        result:
          errorContains: read preference in a transaction must be primary
      - name: commitTransaction
        object: session0

    expectations:
      - command_started_event:
          command:
            insert: *collection_name
            documents:
              - _id: 1
            ordered: true
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction: true
            autocommit: false
            readConcern:
            writeConcern:
          command_name: insert
          database_name: *database_name
      - command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber:
              $numberLong: "1"
            startTransaction:
            autocommit: false
            readConcern:
            writeConcern:
          command_name: commitTransaction
          database_name: admin

    outcome:
      collection:
        data:
          - _id: 1