description: "replicaset-logging"

schemaVersion: "1.16"

runOnRequirements:
  - topologies:
      - replicaset
    minServerVersion: "4.4" # awaitable hello

createEntities:
  - client:
      id: &setupClient setupClient

tests:
  - description: "Topology lifecycle"
    operations:
      - name: createEntities
        object: testRunner
        arguments:
          entities:
            - client:
                id: &client client
                observeLogMessages:
                  topology: debug
                observeEvents:
                  - topologyDescriptionChangedEvent
      # ensure the topology has been fully discovered before closing the client.
      # expected events are initial cluster type change from unknown to ReplicaSet, and connect events for each of 3 servers.
      - name: waitForEvent
        object: testRunner
        arguments:
          client: *client
          event:
            topologyDescriptionChangedEvent: {}
          count: 4
      - name: close
        object: *client
    expectLogMessages:
      - client: *client
        ignoreMessages:
          - level: debug
            component: topology
            data:
              message: "Starting server monitoring"
          - level: debug
            component: topology
            data:
              message: "Server heartbeat started"
          - level: debug
            component: topology
            data:
              message: "Server heartbeat succeeded"
          - level: debug
            component: topology
            data:
              message: "Server heartbeat failed"
        messages:
          - level: debug
            component: topology
            data:
              message: "Starting topology monitoring"
              topologyId: { $$exists: true }
          - level: debug
            component: topology
            data:
              message: "Topology description changed"
              topologyId: { $$exists: true }
              previousDescription:  { $$exists: true } # unknown topology
              newDescription: { $$exists: true } # ReplicaSet topology
          - level: debug
            component: topology
            data:
              message: "Topology description changed"
              topologyId: { $$exists: true }
              previousDescription:  { $$exists: true }
              newDescription: { $$exists: true } # server connected
          - level: debug
            component: topology
            data:
              message: "Topology description changed"
              topologyId: { $$exists: true }
              previousDescription:  { $$exists: true }
              newDescription: { $$exists: true } # server connected
          - level: debug
            component: topology
            data:
              message: "Topology description changed"
              topologyId: { $$exists: true }
              previousDescription:  { $$exists: true }
              newDescription: { $$exists: true } # server connected
          - level: debug
            component: topology
            data:
              message: "Stopped server monitoring"
              topologyId: { $$exists: true }
              serverHost: { $$type: string }
              serverPort: { $$type: [int, long] }
          - level: debug
            component: topology
            data:
              message: "Stopped server monitoring"
              topologyId: { $$exists: true }
              serverHost: { $$type: string }
              serverPort: { $$type: [int, long] }
          - level: debug
            component: topology
            data:
              message: "Stopped server monitoring"
              topologyId: { $$exists: true }
              serverHost: { $$type: string }
              serverPort: { $$type: [int, long] }
          # TODO(GODRIVER-2967): The following log message has been removed from
          # the JSON analogue because it assumes that 
          # "TopologyDescriptionChangedEvent" should occur when a topolgoy is 
          # closed. This behavior is not clearly defined anywhere and some 
          # drivers support and some don't.
          #
          # Need to sync whenever GODRIVER-2967 is unblocked.
          - level: debug
            component: topology
            data:
              message: "Topology description changed"
              topologyId: { $$exists: true }
              previousDescription:  { $$exists: true } # ReplicaSet topology
              newDescription: { $$exists: true } # unknown topology
          - level: debug
            component: topology
            data:
              message: "Stopped topology monitoring"
              topologyId: { $$exists: true }
  - description: Successful heartbeat
    operations:
      - name: createEntities
        object: testRunner
        arguments:
          entities:
          - client:
              id: *client
              observeLogMessages:
                topology: debug
              observeEvents:
              - serverHeartbeatSucceededEvent
      - name: waitForEvent
        object: testRunner
        arguments:
          client: *client
          event:
            serverHeartbeatSucceededEvent: {}
          count: 3
    expectLogMessages:
      - client: *client
        ignoreExtraMessages: true
        ignoreMessages:
          - level: debug
            component: topology
            data:
              message: "Server heartbeat started"
          - level: debug
            component: topology
            data:
              message: "Starting server monitoring"
          - level: debug
            component: topology
            data:
              message: "Stopped server monitoring"
          - level: debug
            component: topology
            data:
              message: "Topology description changed"
        messages:
          - level: debug
            component: topology
            data:
              message: "Starting topology monitoring"
              topologyId: { $$exists: true }
          - level: debug
            component: topology
            data:
              message: "Server heartbeat succeeded"
              awaited: { $$exists: true }
              topologyId: { $$exists: true }
              serverHost: { $$type: string }
              serverPort: { $$type: [int, long] }
              driverConnectionId: { $$exists: true }
              serverConnectionId: { $$exists: true }
              durationMS: { $$type: [int, long] }
              reply:
                $$matchAsDocument:
                  "$$matchAsRoot":
                    ok: 1
          - level: debug
            component: topology
            data:
              message: "Server heartbeat succeeded"
              awaited: { $$exists: true }
              topologyId: { $$exists: true }
              serverHost: { $$type: string }
              serverPort: { $$type: [int, long] }
              driverConnectionId: { $$exists: true }
              serverConnectionId: { $$exists: true }
              durationMS: { $$type: [int, long] }
              reply:
                $$matchAsDocument:
                  "$$matchAsRoot":
                    ok: 1
          - level: debug
            component: topology
            data:
              message: "Server heartbeat succeeded"
              awaited: { $$exists: true }
              topologyId: { $$exists: true }
              serverHost: { $$type: string }
              serverPort: { $$type: [int, long] }
              driverConnectionId: { $$exists: true }
              serverConnectionId: { $$exists: true }
              durationMS: { $$type: [int, long] }
              reply:
                $$matchAsDocument:
                  "$$matchAsRoot":
                    ok: 1
  - description: Failing heartbeat
    operations:
    - name: createEntities
      object: testRunner
      arguments:
        entities:
        - client:
            id: *client
            observeLogMessages:
              topology: debug
            observeEvents:
            - serverHeartbeatFailedEvent
            uriOptions:
              appname: failingHeartbeatLoggingTest
    - name: failPoint
      object: testRunner
      arguments:
        failPoint:
          configureFailPoint: failCommand
          mode: "alwaysOn"
          data:
            failCommands:
            - hello
            - isMaster
            appName: failingHeartbeatLoggingTest
            closeConnection: true
        client: *setupClient
    - name: waitForEvent
      object: testRunner
      arguments:
        client: *client
        event:
          serverHeartbeatFailedEvent: {}
        count: 1
    expectLogMessages:
      - client: *client
        ignoreExtraMessages: true
        ignoreMessages:
          - level: debug
            component: topology
            data:
              message: "Server heartbeat started"
          - level: debug
            component: topology
            data:
              message: "Server heartbeat succeeded"
          - level: debug
            component: topology
            data:
              message: "Starting server monitoring"
          - level: debug
            component: topology
            data:
              message: "Stopped server monitoring"
          - level: debug
            component: topology
            data:
              message: "Topology description changed"
        messages:
        - level: debug
          component: topology
          data:
            message: "Starting topology monitoring"
            topologyId:
              "$$exists": true
        - level: debug
          component: topology
          data:
            message: "Server heartbeat failed"
            awaited: { $$exists: true }
            topologyId: { $$exists: true }
            serverHost: { $$type: string }
            serverPort: { $$type: [int, long] }
            driverConnectionId: { $$exists: true }
            durationMS: { $$type: [int, long] }
            failure: { $$exists: true }
