description: snapshot-sessions

schemaVersion: "1.0"

runOnRequirements:
  - minServerVersion: "5.0"
    topologies: [replicaset, sharded]

createEntities:
  - client:
      id: &client0 client0
      observeEvents: [ commandStartedEvent]
      ignoreCommandMonitoringEvents: [ findAndModify, insert, update ]
  - database:
      id: &database0 database0
      client: *client0
      databaseName: &database0Name database0
  - collection:
      id: &collection0 collection0
      database: *database0
      collectionName: &collection0Name collection0
      collectionOptions:
        writeConcern: { w: majority }
  - session:
      id: session0
      client: client0
      sessionOptions:
        snapshot: true
  - session:
      id: session1
      client: client0
      sessionOptions:
        snapshot: true

initialData:
  - collectionName: *collection0Name
    databaseName: *database0Name
    documents:
      - { _id: 1, x: 11 }
      - { _id: 2, x: 11 }

tests:
- description: Find operation with snapshot
  operations:
  - name: find
    object: collection0
    arguments:
      session: session0
      filter: { _id: 1 }
    expectResult:
      - {_id: 1, x: 11}
  - name: findOneAndUpdate
    object: collection0
    arguments:
      filter: { _id: 1 }
      update: { $inc: { x: 1 } }
      returnDocument: After
    expectResult: { _id: 1, x: 12 }
  - name: find
    object: collection0
    arguments:
      session: session1
      filter: { _id: 1 }
    expectResult:
      - { _id: 1, x: 12 }
  - name: findOneAndUpdate
    object: collection0
    arguments:
      filter: { _id: 1 }
      update: { $inc: { x: 1 } }
      returnDocument: After
    expectResult: { _id: 1, x: 13 }
  - name: find
    object: collection0
    arguments:
      filter: { _id: 1 }
    expectResult:
    - { _id: 1, x: 13 }
  - name: find
    object: collection0
    arguments:
      session: session0
      filter: { _id: 1 }
    expectResult:
    - {_id: 1, x: 11}
  - name: find
    object: collection0
    arguments:
      session: session1
      filter: { _id: 1 }
    expectResult:
    - {_id: 1, x: 12}
  expectEvents:
  - client: client0
    events:
    - commandStartedEvent:
        command:
          find: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": false
    - commandStartedEvent:
        command:
          find: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": false
    - commandStartedEvent:
        command:
          find: collection0
          readConcern:
            "$$exists": false
    - commandStartedEvent:
        command:
          find: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": true
    - commandStartedEvent:
        command:
          find: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": true

- description: Distinct operation with snapshot
  operations:
  - name: distinct
    object: collection0
    arguments:
      fieldName: x
      filter: {}
      session: session0
    expectResult:
    - 11
  - name: findOneAndUpdate
    object: collection0
    arguments:
      filter: { _id: 2 }
      update: { $inc: { x: 1 } }
      returnDocument: After
    expectResult: { _id: 2, x: 12 }
  - name: distinct
    object: collection0
    arguments:
      fieldName: x
      filter: {}
      session: session1
    expectResult: [11, 12]
  - name: findOneAndUpdate
    object: collection0
    arguments:
      filter: { _id: 2 }
      update: { $inc: { x: 1 } }
      returnDocument: After
    expectResult: { _id: 2, x: 13 }
  - name: distinct
    object: collection0
    arguments:
      fieldName: x
      filter: {}
    expectResult: [ 11, 13 ]
  - name: distinct
    object: collection0
    arguments:
      fieldName: x
      filter: {}
      session: session0
    expectResult: [ 11 ]
  - name: distinct
    object: collection0
    arguments:
      fieldName: x
      filter: {}
      session: session1
    expectResult: [ 11, 12 ]
  expectEvents:
  - client: client0
    events:
    - commandStartedEvent:
        command:
          distinct: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": false
    - commandStartedEvent:
        command:
          distinct: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": false
    - commandStartedEvent:
        command:
          distinct: collection0
          readConcern:
            "$$exists": false
    - commandStartedEvent:
        command:
          distinct: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": true
    - commandStartedEvent:
        command:
          distinct: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": true

- description: Aggregate operation with snapshot
  operations:
  - name: aggregate
    object: collection0
    arguments:
      pipeline:
      - "$match": { _id: 1 }
      session: session0
    expectResult:
    - { _id: 1, x: 11 }
  - name: findOneAndUpdate
    object: collection0
    arguments:
      filter: { _id: 1 }
      update: { $inc: { x: 1 } }
      returnDocument: After
    expectResult: { _id: 1, x: 12 }
  - name: aggregate
    object: collection0
    arguments:
      pipeline:
      - "$match":
          _id: 1
      session: session1
    expectResult:
    - {_id: 1, x: 12}
  - name: findOneAndUpdate
    object: collection0
    arguments:
      filter: { _id: 1 }
      update: { $inc: { x: 1 } }
      returnDocument: After
    expectResult: { _id: 1, x: 13 }
  - name: aggregate
    object: collection0
    arguments:
      pipeline:
      - "$match": { _id: 1 }
    expectResult:
    - { _id: 1, x: 13 }
  - name: aggregate
    object: collection0
    arguments:
      pipeline:
      - "$match":
          _id: 1
      session: session0
    expectResult:
    - { _id: 1, x: 11 }
  - name: aggregate
    object: collection0
    arguments:
      pipeline:
      - "$match": { _id: 1 }
      session: session1
    expectResult:
    - { _id: 1, x: 12 }
  expectEvents:
  - client: client0
    events:
    - commandStartedEvent:
        command:
          aggregate: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": false
    - commandStartedEvent:
        command:
          aggregate: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": false
    - commandStartedEvent:
        command:
          aggregate: collection0
          readConcern:
            "$$exists": false
    - commandStartedEvent:
        command:
          aggregate: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": true
    - commandStartedEvent:
        command:
          aggregate: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": true

- description: countDocuments operation with snapshot
  operations:
  - name: countDocuments
    object: collection0
    arguments:
      filter: {}
      session: session0
    expectResult: 2
  - name: countDocuments
    object: collection0
    arguments:
      filter: {}
      session: session0
    expectResult: 2
  expectEvents:
  - client: client0
    events:
    - commandStartedEvent:
        command:
          aggregate: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": false
    - commandStartedEvent:
        command:
          aggregate: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": true

- description: Mixed operation with snapshot
  operations:
  - name: find
    object: collection0
    arguments:
      session: session0
      filter: { _id: 1 }
    expectResult:
    - { _id: 1, x: 11 }
  - name: findOneAndUpdate
    object: collection0
    arguments:
      filter: { _id: 1 }
      update: { $inc: { x: 1 } }
      returnDocument: After
    expectResult: { _id: 1, x: 12 }
  - name: find
    object: collection0
    arguments:
      filter: { _id: 1 }
    expectResult:
    - { _id: 1, x: 12 }
  - name: aggregate
    object: collection0
    arguments:
      pipeline:
      - "$match":
          _id: 1
      session: session0
    expectResult:
    - { _id: 1, x: 11 }
  - name: distinct
    object: collection0
    arguments:
      fieldName: x
      filter: {}
      session: session0
    expectResult: [ 11 ] 
  expectEvents:
  - client: client0
    events:
    - commandStartedEvent:
        command:
          find: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": false
    - commandStartedEvent:
        command:
          find: collection0
          readConcern:
            "$$exists": false
    - commandStartedEvent:
        command:
          aggregate: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": true
    - commandStartedEvent:
        command:
          distinct: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": true

- description: Write commands with snapshot session do not affect snapshot reads
  operations:
  - name: find
    object: collection0
    arguments:
      filter: {}
      session: session0
  - name: insertOne
    object: collection0
    arguments:
      document:
        _id: 22
        x: 33
  - name: updateOne
    object: collection0
    arguments:
      filter: { _id: 1 }
      update: { $inc: { x: 1 } }
  - name: find
    object: collection0
    arguments:
      filter: { _id: 1 }
      session: session0
    expectResult:
    - {_id: 1, x: 11}
  expectEvents:
  - client: client0
    events:
    - commandStartedEvent:
        command:
          find: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": false
    - commandStartedEvent:
        command:
          find: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": true

- description: First snapshot read does not send atClusterTime
  operations:
  - name: find
    object: collection0
    arguments:
      filter: {}
      session: session0
  expectEvents:
  - client: client0
    events:
    - commandStartedEvent:
        command:
          find: collection0
          readConcern:
            level: snapshot
            atClusterTime:
              "$$exists": false
        commandName: find
        databaseName: database0

- description: StartTransaction fails in snapshot session
  operations:
  - name: startTransaction
    object: session0
    expectError:
      isError: true
      isClientError: true
      errorContains: Transactions are not supported in snapshot sessions
