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 is retried after WriteConcernFailed timeout error
    failPoint:
      configureFailPoint: failCommand
      mode: { times: 2 }
      data:
          failCommands: ["commitTransaction"]
          # Do not specify closeConnection: false, since that would conflict
          # with writeConcernError (see: SERVER-39292)
          writeConcernError:
            code: 64
            codeName: WriteConcernFailed
            errmsg: "waiting for replication timed out"
            errInfo: { wtimeout: true }
    operations:
      - &operation
        name: withTransaction
        object: session0
        arguments:
          callback:
            operations:
              -
                name: insertOne
                object: collection
                arguments:
                  session: session0
                  document: { _id: 1 }
                result:
                  insertedId: 1
    expectations: &expectations_with_retries
      -
        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
    # The write operation is still applied despite the write concern error
    outcome: &outcome
      collection:
        data:
          - { _id: 1 }
  -
    # This test configures the fail point to return an error with the
    # WriteConcernFailed code but without errInfo that would identify it as a
    # wtimeout error. This tests that drivers do not assume that all
    # WriteConcernFailed errors are due to a replication timeout.
    description: commitTransaction is retried after WriteConcernFailed non-timeout error
    failPoint:
      configureFailPoint: failCommand
      mode: { times: 2 }
      data:
          failCommands: ["commitTransaction"]
          # Do not specify closeConnection: false, since that would conflict
          # with writeConcernError (see: SERVER-39292)
          writeConcernError:
            code: 64
            codeName: WriteConcernFailed
            errmsg: "multiple errors reported"
    operations:
      - *operation
    expectations: *expectations_with_retries
    outcome: *outcome
  -
    description: commitTransaction is not retried after UnknownReplWriteConcern error
    failPoint:
      configureFailPoint: failCommand
      mode: { times: 1 }
      data:
          failCommands: ["commitTransaction"]
          writeConcernError:
            code: 79
            codeName: UnknownReplWriteConcern
            errmsg: "No write concern mode named 'foo' found in replica set configuration"
    operations:
      - <<: *operation
        result:
          errorCodeName: UnknownReplWriteConcern
          errorLabelsOmit: ["TransientTransactionError", "UnknownTransactionCommitResult"]
    expectations: &expectations_without_retries
      -
        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
    # failCommand with writeConcernError still applies the write operation(s)
    outcome: *outcome

  -
    description: commitTransaction is not retried after UnsatisfiableWriteConcern error
    failPoint:
      configureFailPoint: failCommand
      mode: { times: 1 }
      data:
          failCommands: ["commitTransaction"]
          writeConcernError:
            code: 100
            codeName: UnsatisfiableWriteConcern
            errmsg: "Not enough data-bearing nodes"
    operations:
      - <<: *operation
        result:
          errorCodeName: UnsatisfiableWriteConcern
          errorLabelsOmit: ["TransientTransactionError", "UnknownTransactionCommitResult"]
    expectations: *expectations_without_retries
    # failCommand with writeConcernError still applies the write operation(s)
    outcome: *outcome

  -
    description: commitTransaction is not retried after MaxTimeMSExpired error
    failPoint:
      configureFailPoint: failCommand
      mode: { times: 1 }
      data:
          failCommands: ["commitTransaction"]
          writeConcernError:
            code: 50
            codeName: MaxTimeMSExpired
            errmsg: "operation exceeded time limit"
    operations:
      - <<: *operation
        result:
          errorCodeName: MaxTimeMSExpired
          errorLabelsContain: ["UnknownTransactionCommitResult"]
          errorLabelsOmit: ["TransientTransactionError"]
    expectations: *expectations_without_retries
    # failCommand with writeConcernError still applies the write operation(s)
    outcome: *outcome