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

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

data: []

tests:
  -
    description: commitTransaction succeeds after multiple connection errors
    failPoint:
      configureFailPoint: failCommand
      mode: { times: 2 }
      data:
          failCommands: ["commitTransaction"]
          closeConnection: true
    operations:
      - &withTransaction
        name: withTransaction
        object: session0
        arguments:
          callback:
            operations:
              -
                name: insertOne
                object: collection
                arguments:
                  session: session0
                  document: { _id: 1 }
                result:
                  insertedId: 1
    expectations:
      -
        command_started_event:
          command:
            insert: *collection_name
            documents:
              - { _id: 1 }
            ordered: true
            lsid: session0
            txnNumber: { $numberLong: "1" }
            startTransaction: true
            autocommit: false
            # omitted fields
            readConcern: ~
            writeConcern: ~
          command_name: insert
          database_name: *database_name
      -
        command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber: { $numberLong: "1" }
            autocommit: false
            # omitted fields
            readConcern: ~
            startTransaction: ~
            writeConcern: ~
          command_name: commitTransaction
          database_name: admin
      -
        command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber: { $numberLong: "1" }
            autocommit: false
            # commitTransaction applies w:majority on retries (SPEC-1185)
            writeConcern: { w: majority, wtimeout: 10000 }
            # omitted fields
            readConcern: ~
            startTransaction: ~
          command_name: commitTransaction
          database_name: admin
      -
        command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber: { $numberLong: "1" }
            autocommit: false
            # commitTransaction applies w:majority on retries (SPEC-1185)
            writeConcern: { w: majority, wtimeout: 10000 }
            # omitted fields
            readConcern: ~
            startTransaction: ~
          command_name: commitTransaction
          database_name: admin
    outcome:
      collection:
        data:
          - { _id: 1 }
  -
    description: commitTransaction retry only overwrites write concern w option
    failPoint:
      configureFailPoint: failCommand
      mode: { times: 2 }
      data:
          failCommands: ["commitTransaction"]
          closeConnection: true
    operations:
      -
        name: withTransaction
        object: session0
        arguments:
          callback:
            operations:
              -
                name: insertOne
                object: collection
                arguments:
                  session: session0
                  document: { _id: 1 }
                result:
                  insertedId: 1
          options:
            writeConcern: { w: 2, j: true, wtimeout: 5000 }
    expectations:
      -
        command_started_event:
          command:
            insert: *collection_name
            documents:
              - { _id: 1 }
            ordered: true
            lsid: session0
            txnNumber: { $numberLong: "1" }
            startTransaction: true
            autocommit: false
            # omitted fields
            readConcern: ~
            writeConcern: ~
          command_name: insert
          database_name: *database_name
      -
        command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber: { $numberLong: "1" }
            autocommit: false
            writeConcern: { w: 2, j: true, wtimeout: 5000 }
            # omitted fields
            readConcern: ~
            startTransaction: ~
          command_name: commitTransaction
          database_name: admin
      -
        command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber: { $numberLong: "1" }
            autocommit: false
            # commitTransaction applies w:majority on retries (SPEC-1185)
            writeConcern: { w: majority, j: true, wtimeout: 5000 }
            # omitted fields
            readConcern: ~
            startTransaction: ~
          command_name: commitTransaction
          database_name: admin
      -
        command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber: { $numberLong: "1" }
            autocommit: false
            # commitTransaction applies w:majority on retries (SPEC-1185)
            writeConcern: { w: majority, j: true, wtimeout: 5000 }
            # omitted fields
            readConcern: ~
            startTransaction: ~
          command_name: commitTransaction
          database_name: admin
    outcome:
      collection:
        data:
          - { _id: 1 }
  -
    description: commit is retried after commitTransaction UnknownTransactionCommitResult (NotMaster)
    failPoint:
      configureFailPoint: failCommand
      mode: { times: 2 }
      data:
          failCommands: ["commitTransaction"]
          errorCode: 10107 # NotMaster
          errorLabels: ["RetryableWriteError"] # SPEC-1565
          closeConnection: false
    operations:
      - *withTransaction
    expectations:
      -
        command_started_event:
          command:
            insert: *collection_name
            documents:
              - { _id: 1 }
            ordered: true
            lsid: session0
            txnNumber: { $numberLong: "1" }
            startTransaction: true
            autocommit: false
            # omitted fields
            readConcern: ~
            writeConcern: ~
          command_name: insert
          database_name: *database_name
      -
        command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber: { $numberLong: "1" }
            autocommit: false
            # omitted fields
            readConcern: ~
            startTransaction: ~
            writeConcern: ~
          command_name: commitTransaction
          database_name: admin
      -
        command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber: { $numberLong: "1" }
            autocommit: false
            # commitTransaction applies w:majority on retries (SPEC-1185)
            writeConcern: { w: majority, wtimeout: 10000 }
            # omitted fields
            readConcern: ~
            startTransaction: ~
          command_name: commitTransaction
          database_name: admin
      -
        command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber: { $numberLong: "1" }
            autocommit: false
            # commitTransaction applies w:majority on retries (SPEC-1185)
            writeConcern: { w: majority, wtimeout: 10000 }
            # omitted fields
            readConcern: ~
            startTransaction: ~
          command_name: commitTransaction
          database_name: admin
    outcome:
      collection:
        data:
          - { _id: 1 }
  -
    description: commit is not retried after MaxTimeMSExpired error
    failPoint:
      configureFailPoint: failCommand
      mode: { times: 1 }
      data:
          failCommands: ["commitTransaction"]
          errorCode: 50 # MaxTimeMSExpired
    operations:
      - name: withTransaction
        object: session0
        arguments:
          callback:
            operations:
              -
                name: insertOne
                object: collection
                arguments:
                  session: session0
                  document: { _id: 1 }
                result:
                  insertedId: 1
          options:
            maxCommitTimeMS: 60000
        result:
          errorCodeName: MaxTimeMSExpired
          errorLabelsContain: ["UnknownTransactionCommitResult"]
          errorLabelsOmit: ["TransientTransactionError"]
    expectations:
      -
        command_started_event:
          command:
            insert: *collection_name
            documents:
              - { _id: 1 }
            ordered: true
            lsid: session0
            txnNumber: { $numberLong: "1" }
            startTransaction: true
            autocommit: false
            # omitted fields
            readConcern: ~
            writeConcern: ~
          command_name: insert
          database_name: *database_name
      -
        command_started_event:
          command:
            commitTransaction: 1
            lsid: session0
            txnNumber: { $numberLong: "1" }
            autocommit: false
            maxTimeMS: 60000
            # omitted fields
            readConcern: ~
            startTransaction: ~
            writeConcern: ~
          command_name: commitTransaction
          database_name: admin
    outcome:
      collection:
        # In reality, the outcome of the commit is unknown but we fabricate
        # the error with failCommand.errorCode which does not apply the commit
        # operation.
        data: []
