---
description: cancel-server-check

schemaVersion: "1.4"

runOnRequirements:
  # General failCommand requirements (this file does not use appName
  # with failCommand).
  - minServerVersion: "4.0"
    topologies:
      - replicaset
    serverless: forbid
  - minServerVersion: "4.2"
    topologies:
      - sharded
    serverless: forbid

createEntities:
  - client:
      id: &setupClient setupClient
      useMultipleMongoses: false

initialData: &initialData
  - collectionName: &collectionName cancel-server-check
    databaseName: &databaseName sdam-tests
    documents: []

tests:
  - description: Cancel server check
    operations:
      - name: createEntities
        object: testRunner
        arguments:
          entities:
            - client:
                id: &client client
                useMultipleMongoses: false
                observeEvents:
                  - serverDescriptionChangedEvent
                  - poolClearedEvent
                uriOptions:
                  retryWrites: true
                  heartbeatFrequencyMS: 10000
                  # Server selection timeout MUST be less than heartbeatFrequencyMS for
                  # this test. This setting ensures that the retried insert will fail
                  # after 5 seconds if the driver does not properly cancel the in progress
                  # check.
                  serverSelectionTimeoutMS: 5000
                  appname: cancelServerCheckTest
            - database:
                id: &database database
                client: *client
                databaseName: *databaseName
            - collection:
                id: &collection collection
                database: *database
                collectionName: *collectionName
      # Perform an operation to ensure the node is discovered.
      - name: insertOne
        object: *collection
        arguments:
          document:
            _id: 1
      # Configure the next inserts to fail with a non-timeout network error.
      # This should:
      # 1) Mark the server Unknown
      # 2) Clear the connection pool
      # 3) Cancel the in progress hello or legacy hello check and close the Monitor
      #    connection
      # 4) The write will be then we retried, server selection will request an
      #    immediate check, and block for ~500ms until the next Monitor check
      #    proceeds.
      # 5) The write will succeed on the second attempt.
      - name: failPoint
        object: testRunner
        arguments:
          failPoint:
            configureFailPoint: failCommand
            mode:
              times: 1
            data:
              failCommands:
                - insert
              closeConnection: true
          client: *setupClient
      - name: insertOne
        object: *collection
        arguments:
          document:
            _id: 2
        expectResult:
          insertedId: 2
      # The first error should mark the server Unknown and then clear the pool.
      - name: waitForEvent
        object: testRunner
        arguments:
          client: *client
          event:
            serverDescriptionChangedEvent:
              newDescription:
                type: Unknown
          count: 1
      - name: waitForEvent
        object: testRunner
        arguments:
          client: *client
          event:
            poolClearedEvent: {}
          count: 1
      # Perform another operation to ensure the node still selectable.
      - name: insertOne
        object: *collection
        arguments:
          document:
            _id: 3
        expectResult:
          insertedId: 3
      # Assert the server was marked Unknown and pool was cleared exactly once.
      - name: assertEventCount
        object: testRunner
        arguments:
          client: *client
          event:
            serverDescriptionChangedEvent:
              newDescription:
                type: Unknown
          count: 1
      - name: assertEventCount
        object: testRunner
        arguments:
          client: *client
          event:
            poolClearedEvent: {}
          count: 1

    # Order of operations is non-deterministic so we cannot check events.
    outcome:
      - collectionName: *collectionName
        databaseName: *databaseName
        documents:
          - _id: 1
          - _id: 2
          - _id: 3
