runOn:
  - minServerVersion: "4.1.10"
database_name: &database_name "default"
collection_name: &collection_name "default"

data:
  - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==', 'subType': '06'}} }
  - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==', 'subType': '06'}} }
json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}}, 'encrypted_string': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, 'random': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}}, 'encrypted_string_equivalent': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'}
key_vault_data: [{'status': 1, '_id': {'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}, 'masterKey': {'provider': 'aws', 'key': 'arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0', 'region': 'us-east-1'}, 'updateDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyMaterial': {'$binary': {'base64': 'AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}]

# TODO: I could see an argument against having these tests of mongocryptd as part
# of driver tests. When mongocryptd introduces support for these operators, these
# tests will fail. But it's also easy enough to remove these tests when that happens.

tests:
  - description: "$text unconditionally fails"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: find
        arguments:
          filter:
            { $text: { $search: "search text" } }
        result:
          errorContains: "Unsupported match expression operator for encryption"
  - description: "$where unconditionally fails"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: find
        arguments:
          filter:
            { $where: { $code: "function() { return true }" } }
        result:
          errorContains: "Unsupported match expression operator for encryption"
  - description: "$bit operators succeed on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: find
        arguments:
          filter: { unencrypted: { $bitsAllClear: 35 }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $bitsAllClear: 35 }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $bitsAllSet: 35 }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $bitsAllSet: 35 }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $bitsAnyClear: 35 }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $bitsAnyClear: 35 }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $bitsAnySet: 35 }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $bitsAnySet: 35 }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
  - description: "geo operators succeed on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: find
        arguments:
          filter: { unencrypted: { $near: [0,0] }}
        result:
          # Still an error because no geo index, but from mongod - not mongocryptd.
          errorContains: "unable to find index"
      - name: find
        arguments:
          filter: { encrypted_string: { $near: [0,0] }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $nearSphere: [0,0] }}
        result:
          # Still an error because no geo index, but from mongod - not mongocryptd.
          errorContains: "unable to find index"
      - name: find
        arguments:
          filter: { encrypted_string: { $nearSphere: [0,0] }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $geoIntersects: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $geoIntersects: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
  - description: "inequality operators succeed on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: find
        arguments:
          filter: { unencrypted: { $gt: 1 }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $gt: 1 }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $lt: 1 }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $lt: 1 }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $gte: 1 }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $gte: 1 }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $lte: 1 }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $lte: 1 }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
  - description: "other misc operators succeed on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: find
        arguments:
          filter: { unencrypted: { $mod: [3, 1] }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $mod: [3, 1] }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $regex: "pattern", $options: "" }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $regex: "pattern", $options: "" }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $size: 2 }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $size: 2 }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $type: 2 }}
        result: []
      - name: find
        arguments:
          filter: { encrypted_string: { $type: 2 }}
        result:
          errorContains: "Invalid match expression operator on encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $eq: null }}
        result:
          - &doc0 { _id: 1, encrypted_string: "string0" }
          - &doc1 { _id: 2, encrypted_string: "string1" }
      - name: find
        arguments:
          filter: { encrypted_string: { $eq: null }}
        result:
          errorContains: "Illegal equality to null predicate for encrypted field"
      - name: find
        arguments:
          filter: { unencrypted: { $in: [null] }}
        result:
          - *doc0
          - *doc1
      - name: find
        arguments:
          filter: { encrypted_string: { $in: [null] }}
        result:
          errorContains: "Illegal equality to null inside $in against an encrypted field"
  - description: "$addToSet succeeds on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $addToSet: { "unencrypted": ["a"]}}
        result:
          matchedCount: 1
          modifiedCount: 1
          upsertedCount: 0
      - name: updateOne
        arguments:
          filter: { }
          update: { $addToSet: { "encrypted_string": ["a"]}}
        result:
          errorContains: "$addToSet not allowed on encrypted values"
  - description: "$inc succeeds on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $inc: { "unencrypted": 1}}
        result:
          matchedCount: 1
          modifiedCount: 1
          upsertedCount: 0
      - name: updateOne
        arguments:
          filter: { }
          update: { $inc: { "encrypted_string": 1}}
        result:
          errorContains: "$inc and $mul not allowed on encrypted values"
  - description: "$mul succeeds on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $mul: { "unencrypted": 1}}
        result:
          matchedCount: 1
          modifiedCount: 1
          upsertedCount: 0
      - name: updateOne
        arguments:
          filter: { }
          update: { $mul: { "encrypted_string": 1}}
        result:
          errorContains: "$inc and $mul not allowed on encrypted values"
  - description: "$max succeeds on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $max: { "unencrypted": 1}}
        result:
          matchedCount: 1
          modifiedCount: 1
          upsertedCount: 0
      - name: updateOne
        arguments:
          filter: { }
          update: { $max: { "encrypted_string": 1}}
        result:
          errorContains: "$max and $min not allowed on encrypted values"
  - description: "$min succeeds on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $min: { "unencrypted": 1}}
        result:
          matchedCount: 1
          modifiedCount: 1
          upsertedCount: 0
      - name: updateOne
        arguments:
          filter: { }
          update: { $min: { "encrypted_string": 1}}
        result:
          errorContains: "$max and $min not allowed on encrypted values"
  - description: "$currentDate succeeds on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $currentDate: { "unencrypted": true}}
        result:
          matchedCount: 1
          modifiedCount: 1
          upsertedCount: 0
      - name: updateOne
        arguments:
          filter: { }
          update: { $currentDate: { "encrypted_string": true }}
        result:
          errorContains: "$currentDate not allowed on encrypted values"
  - description: "$pop succeeds on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $pop: { "unencrypted": 1}}
        result:
          matchedCount: 1
          modifiedCount: 0
          upsertedCount: 0
      - name: updateOne
        arguments:
          filter: { }
          update: { $pop: { "encrypted_string": 1 }}
        result:
          errorContains: "$pop not allowed on encrypted values"
  - description: "$pull succeeds on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $pull: { "unencrypted": 1}}
        result:
          matchedCount: 1
          modifiedCount: 0
          upsertedCount: 0
      - name: updateOne
        arguments:
          filter: { }
          update: { $pull: { "encrypted_string": 1 }}
        result:
          errorContains: "$pull not allowed on encrypted values"
  - description: "$pullAll succeeds on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $pullAll: { "unencrypted": [1] }}
        result:
          matchedCount: 1
          modifiedCount: 0
          upsertedCount: 0
      - name: updateOne
        arguments:
          filter: { }
          update: { $pullAll: { "encrypted_string": [1] }}
        result:
          errorContains: "$pullAll not allowed on encrypted values"
  - description: "$push succeeds on unencrypted, error on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $push: { "unencrypted": 1}}
        result:
          matchedCount: 1
          modifiedCount: 1
          upsertedCount: 0
      - name: updateOne
        arguments:
          filter: { }
          update: { $push: { "encrypted_string": 1 }}
        result:
          errorContains: "$push not allowed on encrypted values"
  - description: "array filters on encrypted fields does not error in mongocryptd, but errors in mongod"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $set : { "encrypted_string.$[i].x": 1 }}
          arrayFilters: [{ i.x: 1 }]
        result:
          errorContains: "Array update operations not allowed on encrypted values"
  - description: "positional operator succeeds on unencrypted, errors on encrypted"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { "unencrypted": 1 }
          update: { $set : { "unencrypted.$": 1 }}
        result:
          matchedCount: 0
          modifiedCount: 0
          upsertedCount: 0
      - name: updateOne
        arguments:
          filter: { "encrypted_string": "abc" }
          update: { $set : { "encrypted_string.$": "abc" }}
        result:
          errorContains: "Cannot encrypt fields below '$' positional update operator"
  - description: "an update that would produce an array on an encrypted field errors"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: updateOne
        arguments:
          filter: { }
          update: { $set : { "encrypted_string": [1,2] }}
        result:
          # DRIVERS-2272: The expected error message changed in mongocryptd 6.0. Before it was:
          # "Cannot encrypt element of type array because schema requires that type is one of: [ string ]"
          # After it is:
          # "Cannot encrypt element of type: array"
          # Only check for the common prefix.
          errorContains: "Cannot encrypt element of type"
  - description: "an insert with encrypted field on _id errors"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
        schemaMap:
          "default.default": {'properties': {'_id': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}}
    operations:
      - name: insertOne
        arguments:
          document: { _id: 1 }
        result:
          errorContains: "Invalid schema containing the 'encrypt' keyword."
  - description: "an insert with an array value for an encrypted field fails"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: insertOne
        arguments:
          document: { encrypted_string: [ "123", "456"] }
        result:
          # DRIVERS-2272: The expected error message changed in mongocryptd 6.0. Before it was:
          # "Cannot encrypt element of type array because schema requires that type is one of: [ string ]"
          # After it is:
          # "Cannot encrypt element of type: array"
          # Only check for the common prefix.
          errorContains: "Cannot encrypt element of type"
  - description: "an insert with a Timestamp(0,0) value in the top-level fails"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: insertOne
        arguments:
          document: { random: {"$timestamp": {"t": 0, "i": 0 }} }
        result:
          errorContains: "A command that inserts cannot supply Timestamp(0, 0) for an encrypted"
  - description: "distinct with the key referring to a field where the keyID is a JSON Pointer errors"
    clientOptions:
      autoEncryptOpts:
        kmsProviders:
          aws: {} # Credentials filled in from environment.
    operations:
      - name: distinct
        arguments:
          filter: {}
          fieldName: "encrypted_w_altname"
        result:
          errorContains: "The distinct key is not allowed to be marked for encryption with a non-UUID keyId"