From 53deb07648fe77f7ff917d7c7b24ac7b56a1b9a8 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 24 Jul 2025 11:26:46 -0400 Subject: [PATCH 01/15] add QE text spec tests --- ...E-Text-cleanupStructuredEncryptionData.yml | 128 +++++ ...E-Text-compactStructuredEncryptionData.yml | 137 +++++ .../tests/unified/QE-Text-prefixPreview.yml | 225 +++++++++ .../unified/QE-Text-substringPreview.yml | 472 ++++++++++++++++++ .../tests/unified/QE-Text-suffixPreview.yml | 221 ++++++++ 5 files changed, 1183 insertions(+) create mode 100644 source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.yml create mode 100644 source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.yml create mode 100644 source/client-side-encryption/tests/unified/QE-Text-prefixPreview.yml create mode 100644 source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml create mode 100644 source/client-side-encryption/tests/unified/QE-Text-suffixPreview.yml diff --git a/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.yml b/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.yml new file mode 100644 index 0000000000..c15aa3bcdf --- /dev/null +++ b/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.yml @@ -0,0 +1,128 @@ +description: QE-Text-cleanupStructuredEncryptionData +schemaVersion: "1.23" +runOnRequirements: + # Requires libmongocrypt 1.15.0 for SPM-4158. + - minServerVersion: "8.2.0" # Server 8.2.0 adds preview support for QE text queries. + topologies: ["replicaset", "sharded", "load-balanced"] # QE does not support standalone. + csfle: true +createEntities: + - client: + id: &client "client" + autoEncryptOpts: + keyVaultNamespace: keyvault.datakeys + kmsProviders: + local: + key: Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk + observeEvents: + - commandStartedEvent + - database: + id: &db "db" + client: *client + databaseName: *db + - collection: + id: &coll "coll" + database: *db + collectionName: *coll +initialData: + # Insert data encryption key: + - databaseName: keyvault + collectionName: datakeys + documents: + [ + { + "_id": &keyid { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, + "keyMaterial": + { + "$binary": + { + "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", + "subType": "00", + }, + }, + "creationDate": { "$date": { "$numberLong": "1648914851981" } }, + "updateDate": { "$date": { "$numberLong": "1648914851981" } }, + "status": { "$numberInt": "0" }, + "masterKey": { "provider": "local" }, + }, + ] + # Create encrypted collection: + - databaseName: *db + collectionName: *coll + documents: [] + createOptions: + encryptedFields: + { + "fields": + [ + { + "keyId": *keyid, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "suffixPreview", + "contention": { "$numberLong": "0" }, + "strMinQueryLength": { "$numberLong": "3" }, + "strMaxQueryLength": { "$numberLong": "30" }, + "caseSensitive": true, + "diacriticSensitive": true, + }, + ], + }, + ], + } +tests: + - description: "QE Text cleanupStructuredEncryptionData works" + operations: + - name: runCommand + object: *db + arguments: + command: + cleanupStructuredEncryptionData: *coll + commandName: cleanupStructuredEncryptionData + expectResult: { ok: 1 } + expectEvents: + - client: *client + events: + - commandStartedEvent: + command: + listCollections: 1 + filter: + name: *coll + commandName: listCollections + - commandStartedEvent: + command: + find: datakeys + filter: + { + "$or": + [ + "_id": { "$in": [ *keyid ] }, + "keyAltNames": { "$in": [] }, + ], + } + $db: keyvault + readConcern: { level: "majority" } + commandName: find + - commandStartedEvent: + command: + { + "cleanupStructuredEncryptionData": *coll, + "cleanupTokens": { + "encryptedText": { + "ecoc": { + "$binary": { + "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", + "subType": "00" + } + }, + "anchorPaddingToken": { + "$binary": { + "base64": "YAiF7Iwhqq1UyfxPvm70xfQJtrIRPrjfD2yRLG1+saQ=", + "subType": "00" + } + } + } + } + } + commandName: cleanupStructuredEncryptionData diff --git a/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.yml b/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.yml new file mode 100644 index 0000000000..49b5d83453 --- /dev/null +++ b/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.yml @@ -0,0 +1,137 @@ +description: QE-Text-compactStructuredEncryptionData +schemaVersion: "1.23" +runOnRequirements: + # Requires libmongocrypt 1.15.0 for SPM-4158. + - minServerVersion: "8.2.0" # Server 8.2.0 adds preview support for QE text queries. + topologies: ["replicaset", "sharded", "load-balanced"] # QE does not support standalone. + csfle: true +createEntities: + - client: + id: &client "client" + autoEncryptOpts: + keyVaultNamespace: keyvault.datakeys + kmsProviders: + local: + key: Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk + observeEvents: + - commandStartedEvent + - database: + id: &db "db" + client: *client + databaseName: *db + - collection: + id: &coll "coll" + database: *db + collectionName: *coll +initialData: + # Insert data encryption key: + - databaseName: keyvault + collectionName: datakeys + documents: + [ + { + "_id": &keyid { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, + "keyMaterial": + { + "$binary": + { + "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", + "subType": "00", + }, + }, + "creationDate": { "$date": { "$numberLong": "1648914851981" } }, + "updateDate": { "$date": { "$numberLong": "1648914851981" } }, + "status": { "$numberInt": "0" }, + "masterKey": { "provider": "local" }, + }, + ] + # Create encrypted collection: + - databaseName: *db + collectionName: *coll + documents: [] + createOptions: + encryptedFields: &encryptedFields + { + "fields": + [ + { + "keyId": *keyid, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "suffixPreview", + "contention": { "$numberLong": "0" }, + "strMinQueryLength": { "$numberLong": "3" }, + "strMaxQueryLength": { "$numberLong": "30" }, + "caseSensitive": true, + "diacriticSensitive": true, + }, + ], + }, + ], + } +tests: + - description: "QE Text compactStructuredEncryptionData works" + operations: + - name: runCommand + object: *db + arguments: + command: + compactStructuredEncryptionData: *coll + commandName: compactStructuredEncryptionData + expectResult: { ok: 1 } + expectEvents: + - client: *client + events: + - commandStartedEvent: + command: + listCollections: 1 + filter: + name: *coll + commandName: listCollections + - commandStartedEvent: + command: + find: datakeys + filter: + { + "$or": + [ + "_id": { "$in": [ *keyid ] }, + "keyAltNames": { "$in": [] }, + ], + } + $db: keyvault + readConcern: { level: "majority" } + commandName: find + - commandStartedEvent: + command: + compactStructuredEncryptionData: *coll + encryptionInformation: + type: { "$numberInt": "1" } + schema: + db.coll: + <<: *encryptedFields + # libmongocrypt applies strEncodeVersion, escCollection, and ecocCollection: + strEncodeVersion: { "$numberInt": "1" } + escCollection: "enxcol_.coll.esc" + ecocCollection: "enxcol_.coll.ecoc" + compactionTokens: + encryptedText: + ecoc: + { + "$binary": + { + "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", + "subType": "00", + }, + } + anchorPaddingToken: + { + "$binary": + { + "base64": "YAiF7Iwhqq1UyfxPvm70xfQJtrIRPrjfD2yRLG1+saQ=", + "subType": "00", + }, + } + commandName: compactStructuredEncryptionData diff --git a/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.yml b/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.yml new file mode 100644 index 0000000000..ad61635423 --- /dev/null +++ b/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.yml @@ -0,0 +1,225 @@ +description: QE-Text-prefixPreview +schemaVersion: "1.23" +runOnRequirements: + # Requires libmongocrypt 1.15.0 for SPM-4158. + - minServerVersion: "8.2.0" # Server 8.2.0 adds preview support for QE text queries. + topologies: ["replicaset", "sharded", "load-balanced"] # QE does not support standalone. + csfle: true +createEntities: + - client: + id: &client "client" + autoEncryptOpts: + keyVaultNamespace: keyvault.datakeys + kmsProviders: + local: + key: Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk + observeEvents: + - commandStartedEvent + - database: + id: &db "db" + client: *client + databaseName: *db + - collection: + id: &coll "coll" + database: *db + collectionName: *coll +initialData: + # Insert data encryption key: + - databaseName: keyvault + collectionName: datakeys + documents: + [ + { + "_id": &keyid { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, + "keyMaterial": + { + "$binary": + { + "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", + "subType": "00", + }, + }, + "creationDate": { "$date": { "$numberLong": "1648914851981" } }, + "updateDate": { "$date": { "$numberLong": "1648914851981" } }, + "status": { "$numberInt": "0" }, + "masterKey": { "provider": "local" }, + }, + ] + # Create encrypted collection: + - databaseName: *db + collectionName: *coll + documents: [] + createOptions: + encryptedFields: + { + "fields": + [ + { + "keyId": *keyid, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + # Use zero contention for deterministic __safeContent__: + { + "queryType": "prefixPreview", + "contention": { "$numberLong": "0" }, + "strMinQueryLength": { "$numberLong": "3" }, + "strMaxQueryLength": { "$numberLong": "30" }, + "caseSensitive": true, + "diacriticSensitive": true, + }, + ], + }, + ], + } +tests: + - description: "Insert QE prefixPreview" + operations: + - name: insertOne + arguments: + document: { _id: 1, encryptedText: "foobar" } + object: *coll + expectEvents: + - client: "client" + events: + - commandStartedEvent: + command: + listCollections: 1 + filter: + name: *coll + commandName: listCollections + - commandStartedEvent: + command: + find: datakeys + filter: + { + "$or": + [ + "_id": { "$in": [ *keyid ] }, + "keyAltNames": { "$in": [] }, + ], + } + $db: keyvault + readConcern: { level: "majority" } + commandName: find + - commandStartedEvent: + command: + insert: *coll + documents: + - { "_id": 1, "encryptedText": { $$type: "binData" } } # Sends encrypted payload + ordered: true + commandName: insert + - description: "Query with matching $encStrStartsWith" + operations: + - name: insertOne + arguments: + document: { _id: 1, encryptedText: "foobar" } + object: *coll + - name: find + arguments: + filter: + { + $expr: + { + $encStrStartsWith: { input: "$encryptedText", prefix: "foo" }, + }, + } + object: *coll + expectResult: + [ + { + "_id": { "$numberInt": "1" }, + "encryptedText": "foobar", + "__safeContent__": + [ + { + "$binary": + { + "base64": "wpaMBVDjL4bHf9EtSP52PJFzyNn1R19+iNI/hWtvzdk=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "fmUMXTMV/XRiN0IL3VXxSEn6SQG9E6Po30kJKB8JJlQ=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "vZIDMiFDgjmLNYVrrbnq1zT4hg7sGpe/PMtighSsnRc=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "26Z5G+sHTzV3D7F8Y0m08389USZ2afinyFV3ez9UEBQ=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "q/JEq8of7bE0QE5Id0XuOsNQ4qVpANYymcPQDUL2Ywk=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "Uvvv46LkfbgLoPqZ6xTBzpgoYRTM6FUgRdqZ9eaVojI=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "nMxdq2lladuBJA3lv3JC2MumIUtRJBNJVLp3PVE6nQk=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "hS3V0qq5CF/SkTl3ZWWWgXcAJ8G5yGtkY2RwcHNc5Oc=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "McgwYUxfKj5+4D0vskZymy4KA82s71MR25iV/Enutww=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "Ciqdk1b+t+Vrr6oIlFFk0Zdym5BPmwN3glQ0/VcsVdM=", + "subType": "00", + }, + }, + ], + }, + ] + + - description: "Query with non-matching $encStrStartsWith" + operations: + - name: insertOne + arguments: + document: { _id: 1, encryptedText: "foobar" } + object: *coll + - name: find + arguments: + filter: + { + $expr: + { + $encStrStartsWith: { input: "$encryptedText", prefix: "bar" }, + }, + } + object: *coll + expectResult: [] diff --git a/source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml new file mode 100644 index 0000000000..f47c9cc5ae --- /dev/null +++ b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml @@ -0,0 +1,472 @@ +description: QE-Text-suffixPreview +schemaVersion: "1.23" +runOnRequirements: + # Requires libmongocrypt 1.15.0 for SPM-4158. + - minServerVersion: "8.2.0" # Server 8.2.0 adds preview support for QE text queries. + topologies: ["replicaset", "sharded", "load-balanced"] # QE does not support standalone. + csfle: true +createEntities: + - client: + id: &client "client" + autoEncryptOpts: + keyVaultNamespace: keyvault.datakeys + kmsProviders: + local: + key: Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk + observeEvents: + - commandStartedEvent + - database: + id: &db "db" + client: *client + databaseName: *db + - collection: + id: &coll "coll" + database: *db + collectionName: *coll +initialData: + # Insert data encryption key: + - databaseName: keyvault + collectionName: datakeys + documents: + [ + { + "_id": &keyid { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, + "keyMaterial": + { + "$binary": + { + "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", + "subType": "00", + }, + }, + "creationDate": { "$date": { "$numberLong": "1648914851981" } }, + "updateDate": { "$date": { "$numberLong": "1648914851981" } }, + "status": { "$numberInt": "0" }, + "masterKey": { "provider": "local" }, + }, + ] + # Create encrypted collection: + - databaseName: *db + collectionName: *coll + documents: [] + createOptions: + encryptedFields: + { + "fields": + [ + { + "keyId": *keyid, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + # Use zero contention for deterministic __safeContent__: + { + "queryType": "substringPreview", + "contention": { "$numberLong": "0" }, + "strMinQueryLength": { "$numberLong": "3" }, + "strMaxQueryLength": { "$numberLong": "10" }, + "strMaxLength": { "$numberLong": "20" }, + "caseSensitive": true, + "diacriticSensitive": true, + }, + ], + }, + ], + } +tests: + - description: "Insert QE suffixPreview" + operations: + - name: insertOne + arguments: + document: { _id: 1, encryptedText: "foobar" } + object: *coll + expectEvents: + - client: "client" + events: + - commandStartedEvent: + command: + listCollections: 1 + filter: + name: *coll + commandName: listCollections + - commandStartedEvent: + command: + find: datakeys + filter: + { + "$or": + [ + "_id": { "$in": [ *keyid ] }, + "keyAltNames": { "$in": [] }, + ], + } + $db: keyvault + readConcern: { level: "majority" } + commandName: find + - commandStartedEvent: + command: + insert: *coll + documents: + - { "_id": 1, "encryptedText": { $$type: "binData" } } # Sends encrypted payload + ordered: true + commandName: insert + - description: "Query with matching $encStrContains" + operations: + - name: insertOne + arguments: + document: { _id: 1, encryptedText: "foobar" } + object: *coll + - name: find + arguments: + filter: + { + $expr: + { + $encStrContains: + { input: "$encryptedText", substring: "oba" }, + }, + } + object: *coll + expectResult: + [ + { + "_id": { "$numberInt": "1" }, + "encryptedText": "foobar", + "__safeContent__": + [ + { + "$binary": + { + "base64": "wpaMBVDjL4bHf9EtSP52PJFzyNn1R19+iNI/hWtvzdk=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "IpY3x/jjm8j/74jAdUhgxdM5hk68zR0zv/lTKm/72Vg=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "G+ky260C6QiOfIxKz14FmaMbAxvui1BKJO/TnLOHlGk=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "7dv3gAKe9vwJMZmpB40pRCwRTmc7ds9UkGhxH8j084E=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "o0V+Efn6x8XQdE80F1tztNaT3qxHjcsd9DOQ47BtmQk=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "sJvrCjyVot7PIZFsdRehWFANKAj6fmBaj3FLbz/dZLE=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "e98auxFmu02h5MfBIARk29MI7hSmvN3F9DaQ0xjqoEM=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "US83krGNov/ezL6IhsY5eEOCxv1xUPDIEL/nmY0IKi0=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "P2Aq5+OHZPG0CWIdmZvWq9c/18ZKVYW3vbxd+WU/TXU=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "8AdPRPnSzcd5uhq4TZfNvNeF0XjLNVwAsJJMTtktw84=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "9O6u/G51I4ZHFLhL4ZLuudbr0s202A2QnPfThmOXPhI=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "N7AjYVyVlv6+lVSTM+cIxRL3SMgs3G5LgxSs+jrgDkI=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "RbGF7dQbPGYQFd9DDO1hPz1UlLOJ77FAC6NsjGwJeos=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "m7srHMgKm6kZwsNx8rc45pmw0/9Qro6xuQ8lZS3+RYk=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "K75CNU3JyKFqZWPiIsVi4+n7DhYmcPl/nEhQ3d88mVI=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "c7bwGpUZc/7JzEnMS7qQ/TPuXZyrmMihFaAV6zIqbZc=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "rDvEdUgEk8u4Srt3ETokWs2FXcnyJaRGQ+NbkFwi2rQ=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "VcdZj9zfveRBRlpCR2OYWau2+GokOFb73TE3gpElNiU=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "eOa9o2xfA6OgkbYUxd6wQJicaeN6guhy2V66W3ALsaA=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "1xGkJh+um70XiRd8lKLDtyHgDqrf7/59Mg7X0+KZh8k=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "OSvllqHxycbcZN4phR6NDujY3ttA59o7nQJ6V9eJpX0=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "ZTX1pyk8Vdw0BSbJx7GeJNcQf3tGKxbrrNSTqBqUWkg=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "cn7V05zb5iXwYrePGMHztC+GRq+Tj8IMpRDraauPhSE=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "E9bV9KyrZxHJSUmMg0HrDK4gGN+75ruelAnrM6hXQgY=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "WrssTNmdgXoTGpbaF0JLRCGH6cDQuz1XEFNTy98nrb0=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "jZmyOJP35dsxQ/OY5U4ISpVRIYr8iedNfcwZiKt29Qc=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "d2mocORMbX9MX+/itAW8r1kxVw2/uii4vzXtc+2CIRQ=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "JBnJy58eRPhDo3DuZvsHbvQDiHXxdtAx1Eif66k5SfA=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "OjbDulC8s62v0pgweBSsQqtJjJBwH5JinfJpj7nVr+A=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "85i7KT2GP9nSda3Gsil5LKubhq0LDtc22pxBxHpR+nE=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "u9Fvsclwrs9lwIcMPV/fMZD7L3d5anSfJQVjQb9mgLg=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "LZ32ttmLJGOIw9oFaUCn3Sx5uHPTYJPSFpeGRWNqlUc=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "mMsZvGEePTqtl0FJAL/jAdyWNQIlpwN61YIlZsSIZ6s=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "XZcu1a/ZGsIzAl3j4MXQlLo4v2p7kvIqRHtIQYFmL6k=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "Zse27LinlYCEnX6iTmJceI33mEJxFb0LdPxp0RiMOaQ=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "vOv2Hgb2/sBpnX9XwFbIN6yDxhjchwlmczUf82W2tp4=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "oQxZ9A6j3x5j6x1Jqw/N9tpP4rfWMjcV3y+a3PkrL7c=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "/D7ew3EijyUnmT22awVFspcuyo3JChJcDeCPwpljzVM=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "BEmmwqyamt9X3bcWDld61P01zquy8fBHAXq3SHAPP0M=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "wygD9/kAo1KsRvtr1v+9/lvqoWdKwgh6gDHvAQfXPPk=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "pRTKgF/uksrF1c1AcfSTY6ZhqBKVud1vIztQ4/36SLs=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "C4iUo8oNJsjJ37BqnBgIgSQpf99X2Bb4W5MZEAmakHU=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "icoE53jIq6Fu/YGKUiSUTYyZ8xdiTQY9jJiGxVJObpw=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "oubCwk0V6G2RFWtcOnYDU4uUBoXBrhBRi4nZgrYj9JY=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "IyqhQ9nGhzEi5YW2W6v1kGU5DY2u2qSqbM/qXdLdWVU=", + "subType": "00", + }, + }, + ], + }, + ] + + - description: "Query with non-matching $encStrContains" + operations: + - name: insertOne + arguments: + document: { _id: 1, encryptedText: "foobar" } + object: *coll + - name: find + arguments: + filter: + { + $expr: + { + $encStrContains: { input: "$encryptedText", substring: "blah" }, + }, + } + object: *coll + expectResult: [] diff --git a/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.yml b/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.yml new file mode 100644 index 0000000000..18ac4c6553 --- /dev/null +++ b/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.yml @@ -0,0 +1,221 @@ +description: QE-Text-suffixPreview +schemaVersion: "1.23" +runOnRequirements: + # Requires libmongocrypt 1.15.0 for SPM-4158. + - minServerVersion: "8.2.0" # Server 8.2.0 adds preview support for QE text queries. + topologies: ["replicaset", "sharded", "load-balanced"] # QE does not support standalone. + csfle: true +createEntities: + - client: + id: &client "client" + autoEncryptOpts: + keyVaultNamespace: keyvault.datakeys + kmsProviders: + local: + key: Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk + observeEvents: + - commandStartedEvent + - database: + id: &db "db" + client: *client + databaseName: *db + - collection: + id: &coll "coll" + database: *db + collectionName: *coll +initialData: + # Insert data encryption key: + - databaseName: keyvault + collectionName: datakeys + documents: + [ + { + "_id": &keyid { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, + "keyMaterial": + { + "$binary": + { + "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", + "subType": "00", + }, + }, + "creationDate": { "$date": { "$numberLong": "1648914851981" } }, + "updateDate": { "$date": { "$numberLong": "1648914851981" } }, + "status": { "$numberInt": "0" }, + "masterKey": { "provider": "local" }, + }, + ] + # Create encrypted collection: + - databaseName: *db + collectionName: *coll + documents: [] + createOptions: + encryptedFields: + { + "fields": + [ + { + "keyId": *keyid, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + # Use zero contention for deterministic __safeContent__: + { + "queryType": "suffixPreview", + "contention": { "$numberLong": "0" }, + "strMinQueryLength": { "$numberLong": "3" }, + "strMaxQueryLength": { "$numberLong": "30" }, + "caseSensitive": true, + "diacriticSensitive": true, + }, + ], + }, + ], + } +tests: + - description: "Insert QE suffixPreview" + operations: + - name: insertOne + arguments: + document: { _id: 1, encryptedText: "foobar" } + object: *coll + expectEvents: + - client: "client" + events: + - commandStartedEvent: + command: + listCollections: 1 + filter: + name: *coll + commandName: listCollections + - commandStartedEvent: + command: + find: datakeys + filter: + { + "$or": + [ + "_id": { "$in": [ *keyid ] }, + "keyAltNames": { "$in": [] }, + ], + } + $db: keyvault + readConcern: { level: "majority" } + commandName: find + - commandStartedEvent: + command: + insert: *coll + documents: + - { "_id": 1, "encryptedText": { $$type: "binData" } } # Sends encrypted payload + ordered: true + commandName: insert + - description: "Query with matching $encStrStartsWith" + operations: + - name: insertOne + arguments: + document: { _id: 1, encryptedText: "foobar" } + object: *coll + - name: find + arguments: + filter: + { + $expr: + { $encStrEndsWith: { input: "$encryptedText", suffix: "bar" } }, + } + object: *coll + expectResult: + [ + { + "_id": { "$numberInt": "1" }, + "encryptedText": "foobar", + "__safeContent__": + [ + { + "$binary": + { + "base64": "wpaMBVDjL4bHf9EtSP52PJFzyNn1R19+iNI/hWtvzdk=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "uDCWsucUsJemUP7pmeb+Kd8B9qupVzI8wnLFqX1rkiU=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "W3E1x4bHZ8SEHFz4zwXM0G5Z5WSwBhnxE8x5/qdP6JM=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "6g/TXVDDf6z+ntResIvTKWdmIy4ajQ1rhwdNZIiEG7A=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "hU+u/T3D6dHDpT3d/v5AlgtRoAufCXCAyO2jQlgsnCw=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "vrPnq0AtBIURNgNGA6HJL+5/p5SBWe+qz8505TRo/dE=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "W5pylBxdv2soY2NcBfPiHDVLTS6tx+0ULkI8gysBeFY=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "oWO3xX3x0bYUJGK2S1aPAmlU3Xtfsgb9lTZ6flGAlsg=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "SjZGucTEUbdpd86O8yj1pyMyBOOKxvAQ9C8ngZ9C5UE=", + "subType": "00", + }, + }, + { + "$binary": + { + "base64": "CEaMZkxVDVbnXr+To0DOyvsva04UQkIYP3KtgYVVwf8=", + "subType": "00", + }, + }, + ], + }, + ] + + - description: "Query with non-matching $encStrEndsWith" + operations: + - name: insertOne + arguments: + document: { _id: 1, encryptedText: "foobar" } + object: *coll + - name: find + arguments: + filter: + { + $expr: + { $encStrEndsWith: { input: "$encryptedText", suffix: "foo" } }, + } + object: *coll + expectResult: [] From 7ea175db445818d4bb7119b9fe8398462a93dac5 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 24 Jul 2025 09:37:33 -0400 Subject: [PATCH 02/15] generate JSON from YML tests --- ...-Text-cleanupStructuredEncryptionData.json | 217 +++++++ ...-Text-compactStructuredEncryptionData.json | 259 +++++++++ .../tests/unified/QE-Text-prefixPreview.json | 336 +++++++++++ .../unified/QE-Text-substringPreview.json | 549 ++++++++++++++++++ .../tests/unified/QE-Text-suffixPreview.json | 336 +++++++++++ 5 files changed, 1697 insertions(+) create mode 100644 source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.json create mode 100644 source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.json create mode 100644 source/client-side-encryption/tests/unified/QE-Text-prefixPreview.json create mode 100644 source/client-side-encryption/tests/unified/QE-Text-substringPreview.json create mode 100644 source/client-side-encryption/tests/unified/QE-Text-suffixPreview.json diff --git a/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.json b/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.json new file mode 100644 index 0000000000..a6c70c5086 --- /dev/null +++ b/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.json @@ -0,0 +1,217 @@ +{ + "description": "QE-Text-cleanupStructuredEncryptionData", + "schemaVersion": "1.23", + "runOnRequirements": [ + { + "minServerVersion": "8.2.0", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ], + "csfle": true + } + ], + "createEntities": [ + { + "client": { + "id": "client", + "autoEncryptOpts": { + "keyVaultNamespace": "keyvault.datakeys", + "kmsProviders": { + "local": { + "key": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk" + } + } + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "db", + "client": "client", + "databaseName": "db" + } + }, + { + "collection": { + "id": "coll", + "database": "db", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "databaseName": "keyvault", + "collectionName": "datakeys", + "documents": [ + { + "_id": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "keyMaterial": { + "$binary": { + "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1648914851981" + } + }, + "updateDate": { + "$date": { + "$numberLong": "1648914851981" + } + }, + "status": { + "$numberInt": "0" + }, + "masterKey": { + "provider": "local" + } + } + ] + }, + { + "databaseName": "db", + "collectionName": "coll", + "documents": [], + "createOptions": { + "encryptedFields": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "suffixPreview", + "contention": { + "$numberLong": "0" + }, + "strMinQueryLength": { + "$numberLong": "3" + }, + "strMaxQueryLength": { + "$numberLong": "30" + }, + "caseSensitive": true, + "diacriticSensitive": true + } + ] + } + ] + } + } + } + ], + "tests": [ + { + "description": "QE Text cleanupStructuredEncryptionData works", + "operations": [ + { + "name": "runCommand", + "object": "db", + "arguments": { + "command": { + "cleanupStructuredEncryptionData": "coll" + }, + "commandName": "cleanupStructuredEncryptionData" + }, + "expectResult": { + "ok": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1, + "filter": { + "name": "coll" + } + }, + "commandName": "listCollections" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "keyvault", + "readConcern": { + "level": "majority" + } + }, + "commandName": "find" + } + }, + { + "commandStartedEvent": { + "command": { + "cleanupStructuredEncryptionData": "coll", + "cleanupTokens": { + "encryptedText": { + "ecoc": { + "$binary": { + "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", + "subType": "00" + } + }, + "anchorPaddingToken": { + "$binary": { + "base64": "YAiF7Iwhqq1UyfxPvm70xfQJtrIRPrjfD2yRLG1+saQ=", + "subType": "00" + } + } + } + } + }, + "commandName": "cleanupStructuredEncryptionData" + } + } + ] + } + ] + } + ] +} diff --git a/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.json b/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.json new file mode 100644 index 0000000000..9e0045bb2d --- /dev/null +++ b/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.json @@ -0,0 +1,259 @@ +{ + "description": "QE-Text-compactStructuredEncryptionData", + "schemaVersion": "1.23", + "runOnRequirements": [ + { + "minServerVersion": "8.2.0", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ], + "csfle": true + } + ], + "createEntities": [ + { + "client": { + "id": "client", + "autoEncryptOpts": { + "keyVaultNamespace": "keyvault.datakeys", + "kmsProviders": { + "local": { + "key": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk" + } + } + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "db", + "client": "client", + "databaseName": "db" + } + }, + { + "collection": { + "id": "coll", + "database": "db", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "databaseName": "keyvault", + "collectionName": "datakeys", + "documents": [ + { + "_id": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "keyMaterial": { + "$binary": { + "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1648914851981" + } + }, + "updateDate": { + "$date": { + "$numberLong": "1648914851981" + } + }, + "status": { + "$numberInt": "0" + }, + "masterKey": { + "provider": "local" + } + } + ] + }, + { + "databaseName": "db", + "collectionName": "coll", + "documents": [], + "createOptions": { + "encryptedFields": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "suffixPreview", + "contention": { + "$numberLong": "0" + }, + "strMinQueryLength": { + "$numberLong": "3" + }, + "strMaxQueryLength": { + "$numberLong": "30" + }, + "caseSensitive": true, + "diacriticSensitive": true + } + ] + } + ] + } + } + } + ], + "tests": [ + { + "description": "QE Text compactStructuredEncryptionData works", + "operations": [ + { + "name": "runCommand", + "object": "db", + "arguments": { + "command": { + "compactStructuredEncryptionData": "coll" + }, + "commandName": "compactStructuredEncryptionData" + }, + "expectResult": { + "ok": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1, + "filter": { + "name": "coll" + } + }, + "commandName": "listCollections" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "keyvault", + "readConcern": { + "level": "majority" + } + }, + "commandName": "find" + } + }, + { + "commandStartedEvent": { + "command": { + "compactStructuredEncryptionData": "coll", + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.coll": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "suffixPreview", + "contention": { + "$numberLong": "0" + }, + "strMinQueryLength": { + "$numberLong": "3" + }, + "strMaxQueryLength": { + "$numberLong": "30" + }, + "caseSensitive": true, + "diacriticSensitive": true + } + ] + } + ], + "strEncodeVersion": { + "$numberInt": "1" + }, + "escCollection": "enxcol_.coll.esc", + "ecocCollection": "enxcol_.coll.ecoc" + } + } + }, + "compactionTokens": { + "encryptedText": { + "ecoc": { + "$binary": { + "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", + "subType": "00" + } + }, + "anchorPaddingToken": { + "$binary": { + "base64": "YAiF7Iwhqq1UyfxPvm70xfQJtrIRPrjfD2yRLG1+saQ=", + "subType": "00" + } + } + } + } + }, + "commandName": "compactStructuredEncryptionData" + } + } + ] + } + ] + } + ] +} diff --git a/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.json b/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.json new file mode 100644 index 0000000000..8eccf32c77 --- /dev/null +++ b/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.json @@ -0,0 +1,336 @@ +{ + "description": "QE-Text-prefixPreview", + "schemaVersion": "1.23", + "runOnRequirements": [ + { + "minServerVersion": "8.2.0", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ], + "csfle": true + } + ], + "createEntities": [ + { + "client": { + "id": "client", + "autoEncryptOpts": { + "keyVaultNamespace": "keyvault.datakeys", + "kmsProviders": { + "local": { + "key": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk" + } + } + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "db", + "client": "client", + "databaseName": "db" + } + }, + { + "collection": { + "id": "coll", + "database": "db", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "databaseName": "keyvault", + "collectionName": "datakeys", + "documents": [ + { + "_id": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "keyMaterial": { + "$binary": { + "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1648914851981" + } + }, + "updateDate": { + "$date": { + "$numberLong": "1648914851981" + } + }, + "status": { + "$numberInt": "0" + }, + "masterKey": { + "provider": "local" + } + } + ] + }, + { + "databaseName": "db", + "collectionName": "coll", + "documents": [], + "createOptions": { + "encryptedFields": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "prefixPreview", + "contention": { + "$numberLong": "0" + }, + "strMinQueryLength": { + "$numberLong": "3" + }, + "strMaxQueryLength": { + "$numberLong": "30" + }, + "caseSensitive": true, + "diacriticSensitive": true + } + ] + } + ] + } + } + } + ], + "tests": [ + { + "description": "Insert QE prefixPreview", + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encryptedText": "foobar" + } + }, + "object": "coll" + } + ], + "expectEvents": [ + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1, + "filter": { + "name": "coll" + } + }, + "commandName": "listCollections" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "keyvault", + "readConcern": { + "level": "majority" + } + }, + "commandName": "find" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 1, + "encryptedText": { + "$$type": "binData" + } + } + ], + "ordered": true + }, + "commandName": "insert" + } + } + ] + } + ] + }, + { + "description": "Query with matching $encStrStartsWith", + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encryptedText": "foobar" + } + }, + "object": "coll" + }, + { + "name": "find", + "arguments": { + "filter": { + "$expr": { + "$encStrStartsWith": { + "input": "$encryptedText", + "prefix": "foo" + } + } + } + }, + "object": "coll", + "expectResult": [ + { + "_id": { + "$numberInt": "1" + }, + "encryptedText": "foobar", + "__safeContent__": [ + { + "$binary": { + "base64": "wpaMBVDjL4bHf9EtSP52PJFzyNn1R19+iNI/hWtvzdk=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "fmUMXTMV/XRiN0IL3VXxSEn6SQG9E6Po30kJKB8JJlQ=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "vZIDMiFDgjmLNYVrrbnq1zT4hg7sGpe/PMtighSsnRc=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "26Z5G+sHTzV3D7F8Y0m08389USZ2afinyFV3ez9UEBQ=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "q/JEq8of7bE0QE5Id0XuOsNQ4qVpANYymcPQDUL2Ywk=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "Uvvv46LkfbgLoPqZ6xTBzpgoYRTM6FUgRdqZ9eaVojI=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "nMxdq2lladuBJA3lv3JC2MumIUtRJBNJVLp3PVE6nQk=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "hS3V0qq5CF/SkTl3ZWWWgXcAJ8G5yGtkY2RwcHNc5Oc=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "McgwYUxfKj5+4D0vskZymy4KA82s71MR25iV/Enutww=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "Ciqdk1b+t+Vrr6oIlFFk0Zdym5BPmwN3glQ0/VcsVdM=", + "subType": "00" + } + } + ] + } + ] + } + ] + }, + { + "description": "Query with non-matching $encStrStartsWith", + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encryptedText": "foobar" + } + }, + "object": "coll" + }, + { + "name": "find", + "arguments": { + "filter": { + "$expr": { + "$encStrStartsWith": { + "input": "$encryptedText", + "prefix": "bar" + } + } + } + }, + "object": "coll", + "expectResult": [] + } + ] + } + ] +} diff --git a/source/client-side-encryption/tests/unified/QE-Text-substringPreview.json b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.json new file mode 100644 index 0000000000..248a050bd5 --- /dev/null +++ b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.json @@ -0,0 +1,549 @@ +{ + "description": "QE-Text-suffixPreview", + "schemaVersion": "1.23", + "runOnRequirements": [ + { + "minServerVersion": "8.2.0", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ], + "csfle": true + } + ], + "createEntities": [ + { + "client": { + "id": "client", + "autoEncryptOpts": { + "keyVaultNamespace": "keyvault.datakeys", + "kmsProviders": { + "local": { + "key": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk" + } + } + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "db", + "client": "client", + "databaseName": "db" + } + }, + { + "collection": { + "id": "coll", + "database": "db", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "databaseName": "keyvault", + "collectionName": "datakeys", + "documents": [ + { + "_id": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "keyMaterial": { + "$binary": { + "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1648914851981" + } + }, + "updateDate": { + "$date": { + "$numberLong": "1648914851981" + } + }, + "status": { + "$numberInt": "0" + }, + "masterKey": { + "provider": "local" + } + } + ] + }, + { + "databaseName": "db", + "collectionName": "coll", + "documents": [], + "createOptions": { + "encryptedFields": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "substringPreview", + "contention": { + "$numberLong": "0" + }, + "strMinQueryLength": { + "$numberLong": "3" + }, + "strMaxQueryLength": { + "$numberLong": "10" + }, + "strMaxLength": { + "$numberLong": "20" + }, + "caseSensitive": true, + "diacriticSensitive": true + } + ] + } + ] + } + } + } + ], + "tests": [ + { + "description": "Insert QE suffixPreview", + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encryptedText": "foobar" + } + }, + "object": "coll" + } + ], + "expectEvents": [ + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1, + "filter": { + "name": "coll" + } + }, + "commandName": "listCollections" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "keyvault", + "readConcern": { + "level": "majority" + } + }, + "commandName": "find" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 1, + "encryptedText": { + "$$type": "binData" + } + } + ], + "ordered": true + }, + "commandName": "insert" + } + } + ] + } + ] + }, + { + "description": "Query with matching $encStrContains", + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encryptedText": "foobar" + } + }, + "object": "coll" + }, + { + "name": "find", + "arguments": { + "filter": { + "$expr": { + "$encStrContains": { + "input": "$encryptedText", + "substring": "oba" + } + } + } + }, + "object": "coll", + "expectResult": [ + { + "_id": { + "$numberInt": "1" + }, + "encryptedText": "foobar", + "__safeContent__": [ + { + "$binary": { + "base64": "wpaMBVDjL4bHf9EtSP52PJFzyNn1R19+iNI/hWtvzdk=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "IpY3x/jjm8j/74jAdUhgxdM5hk68zR0zv/lTKm/72Vg=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "G+ky260C6QiOfIxKz14FmaMbAxvui1BKJO/TnLOHlGk=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "7dv3gAKe9vwJMZmpB40pRCwRTmc7ds9UkGhxH8j084E=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "o0V+Efn6x8XQdE80F1tztNaT3qxHjcsd9DOQ47BtmQk=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "sJvrCjyVot7PIZFsdRehWFANKAj6fmBaj3FLbz/dZLE=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "e98auxFmu02h5MfBIARk29MI7hSmvN3F9DaQ0xjqoEM=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "US83krGNov/ezL6IhsY5eEOCxv1xUPDIEL/nmY0IKi0=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "P2Aq5+OHZPG0CWIdmZvWq9c/18ZKVYW3vbxd+WU/TXU=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "8AdPRPnSzcd5uhq4TZfNvNeF0XjLNVwAsJJMTtktw84=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "9O6u/G51I4ZHFLhL4ZLuudbr0s202A2QnPfThmOXPhI=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "N7AjYVyVlv6+lVSTM+cIxRL3SMgs3G5LgxSs+jrgDkI=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "RbGF7dQbPGYQFd9DDO1hPz1UlLOJ77FAC6NsjGwJeos=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "m7srHMgKm6kZwsNx8rc45pmw0/9Qro6xuQ8lZS3+RYk=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "K75CNU3JyKFqZWPiIsVi4+n7DhYmcPl/nEhQ3d88mVI=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "c7bwGpUZc/7JzEnMS7qQ/TPuXZyrmMihFaAV6zIqbZc=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "rDvEdUgEk8u4Srt3ETokWs2FXcnyJaRGQ+NbkFwi2rQ=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "VcdZj9zfveRBRlpCR2OYWau2+GokOFb73TE3gpElNiU=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "eOa9o2xfA6OgkbYUxd6wQJicaeN6guhy2V66W3ALsaA=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "1xGkJh+um70XiRd8lKLDtyHgDqrf7/59Mg7X0+KZh8k=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "OSvllqHxycbcZN4phR6NDujY3ttA59o7nQJ6V9eJpX0=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "ZTX1pyk8Vdw0BSbJx7GeJNcQf3tGKxbrrNSTqBqUWkg=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "cn7V05zb5iXwYrePGMHztC+GRq+Tj8IMpRDraauPhSE=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "E9bV9KyrZxHJSUmMg0HrDK4gGN+75ruelAnrM6hXQgY=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "WrssTNmdgXoTGpbaF0JLRCGH6cDQuz1XEFNTy98nrb0=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "jZmyOJP35dsxQ/OY5U4ISpVRIYr8iedNfcwZiKt29Qc=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "d2mocORMbX9MX+/itAW8r1kxVw2/uii4vzXtc+2CIRQ=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "JBnJy58eRPhDo3DuZvsHbvQDiHXxdtAx1Eif66k5SfA=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "OjbDulC8s62v0pgweBSsQqtJjJBwH5JinfJpj7nVr+A=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "85i7KT2GP9nSda3Gsil5LKubhq0LDtc22pxBxHpR+nE=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "u9Fvsclwrs9lwIcMPV/fMZD7L3d5anSfJQVjQb9mgLg=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "LZ32ttmLJGOIw9oFaUCn3Sx5uHPTYJPSFpeGRWNqlUc=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "mMsZvGEePTqtl0FJAL/jAdyWNQIlpwN61YIlZsSIZ6s=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "XZcu1a/ZGsIzAl3j4MXQlLo4v2p7kvIqRHtIQYFmL6k=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "Zse27LinlYCEnX6iTmJceI33mEJxFb0LdPxp0RiMOaQ=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "vOv2Hgb2/sBpnX9XwFbIN6yDxhjchwlmczUf82W2tp4=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "oQxZ9A6j3x5j6x1Jqw/N9tpP4rfWMjcV3y+a3PkrL7c=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "/D7ew3EijyUnmT22awVFspcuyo3JChJcDeCPwpljzVM=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "BEmmwqyamt9X3bcWDld61P01zquy8fBHAXq3SHAPP0M=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "wygD9/kAo1KsRvtr1v+9/lvqoWdKwgh6gDHvAQfXPPk=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "pRTKgF/uksrF1c1AcfSTY6ZhqBKVud1vIztQ4/36SLs=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "C4iUo8oNJsjJ37BqnBgIgSQpf99X2Bb4W5MZEAmakHU=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "icoE53jIq6Fu/YGKUiSUTYyZ8xdiTQY9jJiGxVJObpw=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "oubCwk0V6G2RFWtcOnYDU4uUBoXBrhBRi4nZgrYj9JY=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "IyqhQ9nGhzEi5YW2W6v1kGU5DY2u2qSqbM/qXdLdWVU=", + "subType": "00" + } + } + ] + } + ] + } + ] + }, + { + "description": "Query with non-matching $encStrContains", + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encryptedText": "foobar" + } + }, + "object": "coll" + }, + { + "name": "find", + "arguments": { + "filter": { + "$expr": { + "$encStrContains": { + "input": "$encryptedText", + "substring": "blah" + } + } + } + }, + "object": "coll", + "expectResult": [] + } + ] + } + ] +} diff --git a/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.json b/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.json new file mode 100644 index 0000000000..efa95edae2 --- /dev/null +++ b/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.json @@ -0,0 +1,336 @@ +{ + "description": "QE-Text-suffixPreview", + "schemaVersion": "1.23", + "runOnRequirements": [ + { + "minServerVersion": "8.2.0", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ], + "csfle": true + } + ], + "createEntities": [ + { + "client": { + "id": "client", + "autoEncryptOpts": { + "keyVaultNamespace": "keyvault.datakeys", + "kmsProviders": { + "local": { + "key": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk" + } + } + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "db", + "client": "client", + "databaseName": "db" + } + }, + { + "collection": { + "id": "coll", + "database": "db", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "databaseName": "keyvault", + "collectionName": "datakeys", + "documents": [ + { + "_id": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "keyMaterial": { + "$binary": { + "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1648914851981" + } + }, + "updateDate": { + "$date": { + "$numberLong": "1648914851981" + } + }, + "status": { + "$numberInt": "0" + }, + "masterKey": { + "provider": "local" + } + } + ] + }, + { + "databaseName": "db", + "collectionName": "coll", + "documents": [], + "createOptions": { + "encryptedFields": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "suffixPreview", + "contention": { + "$numberLong": "0" + }, + "strMinQueryLength": { + "$numberLong": "3" + }, + "strMaxQueryLength": { + "$numberLong": "30" + }, + "caseSensitive": true, + "diacriticSensitive": true + } + ] + } + ] + } + } + } + ], + "tests": [ + { + "description": "Insert QE suffixPreview", + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encryptedText": "foobar" + } + }, + "object": "coll" + } + ], + "expectEvents": [ + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1, + "filter": { + "name": "coll" + } + }, + "commandName": "listCollections" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "keyvault", + "readConcern": { + "level": "majority" + } + }, + "commandName": "find" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 1, + "encryptedText": { + "$$type": "binData" + } + } + ], + "ordered": true + }, + "commandName": "insert" + } + } + ] + } + ] + }, + { + "description": "Query with matching $encStrStartsWith", + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encryptedText": "foobar" + } + }, + "object": "coll" + }, + { + "name": "find", + "arguments": { + "filter": { + "$expr": { + "$encStrEndsWith": { + "input": "$encryptedText", + "suffix": "bar" + } + } + } + }, + "object": "coll", + "expectResult": [ + { + "_id": { + "$numberInt": "1" + }, + "encryptedText": "foobar", + "__safeContent__": [ + { + "$binary": { + "base64": "wpaMBVDjL4bHf9EtSP52PJFzyNn1R19+iNI/hWtvzdk=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "uDCWsucUsJemUP7pmeb+Kd8B9qupVzI8wnLFqX1rkiU=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "W3E1x4bHZ8SEHFz4zwXM0G5Z5WSwBhnxE8x5/qdP6JM=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "6g/TXVDDf6z+ntResIvTKWdmIy4ajQ1rhwdNZIiEG7A=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "hU+u/T3D6dHDpT3d/v5AlgtRoAufCXCAyO2jQlgsnCw=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "vrPnq0AtBIURNgNGA6HJL+5/p5SBWe+qz8505TRo/dE=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "W5pylBxdv2soY2NcBfPiHDVLTS6tx+0ULkI8gysBeFY=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "oWO3xX3x0bYUJGK2S1aPAmlU3Xtfsgb9lTZ6flGAlsg=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "SjZGucTEUbdpd86O8yj1pyMyBOOKxvAQ9C8ngZ9C5UE=", + "subType": "00" + } + }, + { + "$binary": { + "base64": "CEaMZkxVDVbnXr+To0DOyvsva04UQkIYP3KtgYVVwf8=", + "subType": "00" + } + } + ] + } + ] + } + ] + }, + { + "description": "Query with non-matching $encStrEndsWith", + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encryptedText": "foobar" + } + }, + "object": "coll" + }, + { + "name": "find", + "arguments": { + "filter": { + "$expr": { + "$encStrEndsWith": { + "input": "$encryptedText", + "suffix": "foo" + } + } + } + }, + "object": "coll", + "expectResult": [] + } + ] + } + ] +} From 2147d11a6365d4ee7af12729f729338c37227dda Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 09:38:00 -0400 Subject: [PATCH 03/15] copy schema-1.24 to schema-1.25 Does not make any changes yet. --- source/unified-test-format/schema-1.25.json | 1163 +++++++++++++++++++ 1 file changed, 1163 insertions(+) create mode 100644 source/unified-test-format/schema-1.25.json diff --git a/source/unified-test-format/schema-1.25.json b/source/unified-test-format/schema-1.25.json new file mode 100644 index 0000000000..77d4aaed14 --- /dev/null +++ b/source/unified-test-format/schema-1.25.json @@ -0,0 +1,1163 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema#", + "title": "Unified Test Format", + "type": "object", + "additionalProperties": false, + "required": [ + "description", + "schemaVersion", + "tests" + ], + "properties": { + "description": { + "type": "string" + }, + "schemaVersion": { + "$ref": "#/definitions/version" + }, + "runOnRequirements": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/runOnRequirement" + } + }, + "createEntities": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/entity" + } + }, + "initialData": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/collectionData" + } + }, + "tests": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/test" + } + }, + "_yamlAnchors": { + "type": "object", + "additionalProperties": true + } + }, + "definitions": { + "version": { + "type": "string", + "pattern": "^[0-9]+(\\.[0-9]+){1,2}$" + }, + "runOnRequirement": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "maxServerVersion": { + "$ref": "#/definitions/version" + }, + "minServerVersion": { + "$ref": "#/definitions/version" + }, + "topologies": { + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "enum": [ + "single", + "replicaset", + "sharded", + "sharded-replicaset", + "load-balanced" + ] + } + }, + "serverless": { + "type": "string", + "enum": [ + "require", + "forbid", + "allow" + ] + }, + "serverParameters": { + "type": "object", + "minProperties": 1 + }, + "auth": { + "type": "boolean" + }, + "authMechanism": { + "type": "string" + }, + "csfle": { + "type": "boolean" + } + } + }, + "entity": { + "type": "object", + "additionalProperties": false, + "maxProperties": 1, + "minProperties": 1, + "properties": { + "client": { + "type": "object", + "additionalProperties": false, + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "uriOptions": { + "type": "object" + }, + "useMultipleMongoses": { + "type": "boolean" + }, + "observeEvents": { + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "enum": [ + "commandStartedEvent", + "commandSucceededEvent", + "commandFailedEvent", + "poolCreatedEvent", + "poolReadyEvent", + "poolClearedEvent", + "poolClosedEvent", + "connectionCreatedEvent", + "connectionReadyEvent", + "connectionClosedEvent", + "connectionCheckOutStartedEvent", + "connectionCheckOutFailedEvent", + "connectionCheckedOutEvent", + "connectionCheckedInEvent", + "serverDescriptionChangedEvent", + "topologyDescriptionChangedEvent", + "topologyOpeningEvent", + "topologyClosedEvent" + ] + } + }, + "ignoreCommandMonitoringEvents": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "storeEventsAsEntities": { + "deprecated": true, + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/storeEventsAsEntity" + } + }, + "observeLogMessages": { + "type": "object", + "minProperties": 1, + "additionalProperties": false, + "properties": { + "command": { + "$ref": "#/definitions/logSeverityLevel" + }, + "topology": { + "$ref": "#/definitions/logSeverityLevel" + }, + "serverSelection": { + "$ref": "#/definitions/logSeverityLevel" + }, + "connection": { + "$ref": "#/definitions/logSeverityLevel" + } + } + }, + "serverApi": { + "$ref": "#/definitions/serverApi" + }, + "observeSensitiveCommands": { + "type": "boolean" + }, + "autoEncryptOpts": { + "type": "object", + "additionalProperties": false, + "required": [ + "keyVaultNamespace", + "kmsProviders" + ], + "properties": { + "keyVaultNamespace": { + "type": "string" + }, + "bypassAutoEncryption": { + "type": "boolean" + }, + "kmsProviders": { + "$ref": "#/definitions/kmsProviders" + }, + "schemaMap": { + "type": "object", + "additionalProperties": { + "type": "object" + } + }, + "extraOptions": { + "type": "object" + }, + "encryptedFieldsMap": { + "type": "object", + "additionalProperties": { + "type": "object" + } + }, + "bypassQueryAnalysis": { + "type": "boolean" + }, + "keyExpirationMS": { + "type": "integer" + } + } + } + } + }, + "clientEncryption": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "clientEncryptionOpts" + ], + "properties": { + "id": { + "type": "string" + }, + "clientEncryptionOpts": { + "$ref": "#/definitions/clientEncryptionOpts" + } + } + }, + "database": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "client", + "databaseName" + ], + "properties": { + "id": { + "type": "string" + }, + "client": { + "type": "string" + }, + "databaseName": { + "type": "string" + }, + "databaseOptions": { + "$ref": "#/definitions/collectionOrDatabaseOptions" + } + } + }, + "collection": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "database", + "collectionName" + ], + "properties": { + "id": { + "type": "string" + }, + "database": { + "type": "string" + }, + "collectionName": { + "type": "string" + }, + "collectionOptions": { + "$ref": "#/definitions/collectionOrDatabaseOptions" + } + } + }, + "session": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "client" + ], + "properties": { + "id": { + "type": "string" + }, + "client": { + "type": "string" + }, + "sessionOptions": { + "type": "object" + } + } + }, + "bucket": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "database" + ], + "properties": { + "id": { + "type": "string" + }, + "database": { + "type": "string" + }, + "bucketOptions": { + "type": "object" + } + } + }, + "thread": { + "type": "object", + "additionalProperties": false, + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string" + } + } + } + } + }, + "logComponent": { + "type": "string", + "enum": [ + "command", + "topology", + "serverSelection", + "connection" + ] + }, + "logSeverityLevel": { + "type": "string", + "enum": [ + "emergency", + "alert", + "critical", + "error", + "warning", + "notice", + "info", + "debug", + "trace" + ] + }, + "clientEncryptionOpts": { + "type": "object", + "additionalProperties": false, + "required": [ + "keyVaultClient", + "keyVaultNamespace", + "kmsProviders" + ], + "properties": { + "keyVaultClient": { + "type": "string" + }, + "keyVaultNamespace": { + "type": "string" + }, + "kmsProviders": { + "$ref": "#/definitions/kmsProviders" + }, + "keyExpirationMS": { + "type": "integer" + } + } + }, + "kmsProviders": { + "$defs": { + "stringOrPlaceholder": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "$$placeholder" + ], + "properties": { + "$$placeholder": {} + } + } + ] + } + }, + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^aws(:[a-zA-Z0-9_]+)?$": { + "type": "object", + "additionalProperties": false, + "properties": { + "accessKeyId": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + }, + "secretAccessKey": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + }, + "sessionToken": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + } + } + }, + "^azure(:[a-zA-Z0-9_]+)?$": { + "type": "object", + "additionalProperties": false, + "properties": { + "tenantId": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + }, + "clientId": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + }, + "clientSecret": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + }, + "identityPlatformEndpoint": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + } + } + }, + "^gcp(:[a-zA-Z0-9_]+)?$": { + "type": "object", + "additionalProperties": false, + "properties": { + "email": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + }, + "privateKey": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + }, + "endpoint": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + } + } + }, + "^kmip(:[a-zA-Z0-9_]+)?$": { + "type": "object", + "additionalProperties": false, + "properties": { + "endpoint": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + } + } + }, + "^local(:[a-zA-Z0-9_]+)?$": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "$ref": "#/definitions/kmsProviders/$defs/stringOrPlaceholder" + } + } + } + } + }, + "storeEventsAsEntity": { + "deprecated": true, + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "events" + ], + "properties": { + "id": { + "type": "string" + }, + "events": { + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "enum": [ + "PoolCreatedEvent", + "PoolReadyEvent", + "PoolClearedEvent", + "PoolClosedEvent", + "ConnectionCreatedEvent", + "ConnectionReadyEvent", + "ConnectionClosedEvent", + "ConnectionCheckOutStartedEvent", + "ConnectionCheckOutFailedEvent", + "ConnectionCheckedOutEvent", + "ConnectionCheckedInEvent", + "CommandStartedEvent", + "CommandSucceededEvent", + "CommandFailedEvent", + "ServerDescriptionChangedEvent", + "TopologyDescriptionChangedEvent" + ] + } + } + } + }, + "collectionData": { + "type": "object", + "additionalProperties": false, + "required": [ + "collectionName", + "databaseName", + "documents" + ], + "properties": { + "collectionName": { + "type": "string" + }, + "databaseName": { + "type": "string" + }, + "createOptions": { + "type": "object", + "properties": { + "writeConcern": false + } + }, + "documents": { + "type": "array", + "items": { + "type": "object" + } + } + } + }, + "expectedEventsForClient": { + "type": "object", + "additionalProperties": false, + "required": [ + "client", + "events" + ], + "properties": { + "client": { + "type": "string" + }, + "eventType": { + "type": "string", + "enum": [ + "command", + "cmap", + "sdam" + ] + }, + "events": { + "type": "array" + }, + "ignoreExtraEvents": { + "type": "boolean" + } + }, + "oneOf": [ + { + "required": [ + "eventType" + ], + "properties": { + "eventType": { + "const": "command" + }, + "events": { + "type": "array", + "items": { + "$ref": "#/definitions/expectedCommandEvent" + } + } + } + }, + { + "required": [ + "eventType" + ], + "properties": { + "eventType": { + "const": "cmap" + }, + "events": { + "type": "array", + "items": { + "$ref": "#/definitions/expectedCmapEvent" + } + } + } + }, + { + "required": [ + "eventType" + ], + "properties": { + "eventType": { + "const": "sdam" + }, + "events": { + "type": "array", + "items": { + "$ref": "#/definitions/expectedSdamEvent" + } + } + } + }, + { + "additionalProperties": false, + "properties": { + "client": { + "type": "string" + }, + "events": { + "type": "array", + "items": { + "$ref": "#/definitions/expectedCommandEvent" + } + }, + "ignoreExtraEvents": { + "type": "boolean" + } + } + } + ] + }, + "expectedCommandEvent": { + "type": "object", + "additionalProperties": false, + "maxProperties": 1, + "minProperties": 1, + "properties": { + "commandStartedEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "command": { + "type": "object" + }, + "commandName": { + "type": "string" + }, + "databaseName": { + "type": "string" + }, + "hasServiceId": { + "type": "boolean" + }, + "hasServerConnectionId": { + "type": "boolean" + } + } + }, + "commandSucceededEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "reply": { + "type": "object" + }, + "commandName": { + "type": "string" + }, + "databaseName": { + "type": "string" + }, + "hasServiceId": { + "type": "boolean" + }, + "hasServerConnectionId": { + "type": "boolean" + } + } + }, + "commandFailedEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "commandName": { + "type": "string" + }, + "databaseName": { + "type": "string" + }, + "hasServiceId": { + "type": "boolean" + }, + "hasServerConnectionId": { + "type": "boolean" + } + } + } + } + }, + "expectedCmapEvent": { + "type": "object", + "additionalProperties": false, + "maxProperties": 1, + "minProperties": 1, + "properties": { + "poolCreatedEvent": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "poolReadyEvent": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "poolClearedEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "hasServiceId": { + "type": "boolean" + }, + "interruptInUseConnections": { + "type": "boolean" + } + } + }, + "poolClosedEvent": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "connectionCreatedEvent": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "connectionReadyEvent": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "connectionClosedEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "reason": { + "type": "string" + } + } + }, + "connectionCheckOutStartedEvent": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "connectionCheckOutFailedEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "reason": { + "type": "string" + } + } + }, + "connectionCheckedOutEvent": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "connectionCheckedInEvent": { + "type": "object", + "additionalProperties": false, + "properties": {} + } + } + }, + "expectedSdamEvent": { + "type": "object", + "additionalProperties": false, + "maxProperties": 1, + "minProperties": 1, + "properties": { + "serverDescriptionChangedEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "previousDescription": { + "$ref": "#/definitions/serverDescription" + }, + "newDescription": { + "$ref": "#/definitions/serverDescription" + } + } + }, + "topologyDescriptionChangedEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "previousDescription": { + "$ref": "#/definitions/topologyDescription" + }, + "newDescription": { + "$ref": "#/definitions/topologyDescription" + } + } + }, + "serverHeartbeatStartedEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "awaited": { + "type": "boolean" + } + } + }, + "serverHeartbeatSucceededEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "awaited": { + "type": "boolean" + } + } + }, + "serverHeartbeatFailedEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "awaited": { + "type": "boolean" + } + } + }, + "topologyOpeningEvent": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "topologyClosedEvent": { + "type": "object", + "additionalProperties": false, + "properties": {} + } + } + }, + "serverDescription": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "Standalone", + "Mongos", + "PossiblePrimary", + "RSPrimary", + "RSSecondary", + "RSOther", + "RSArbiter", + "RSGhost", + "LoadBalancer", + "Unknown" + ] + } + } + }, + "topologyDescription": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "Single", + "Unknown", + "ReplicaSetNoPrimary", + "ReplicaSetWithPrimary", + "Sharded", + "LoadBalanced" + ] + } + } + }, + "expectedLogMessagesForClient": { + "type": "object", + "additionalProperties": false, + "required": [ + "client", + "messages" + ], + "properties": { + "client": { + "type": "string" + }, + "messages": { + "type": "array", + "items": { + "$ref": "#/definitions/expectedLogMessage" + } + }, + "ignoreExtraMessages": { + "type": "boolean" + }, + "ignoreMessages": { + "type": "array", + "items": { + "$ref": "#/definitions/expectedLogMessage" + } + } + } + }, + "expectedLogMessage": { + "type": "object", + "additionalProperties": false, + "required": [ + "level", + "component", + "data" + ], + "properties": { + "level": { + "$ref": "#/definitions/logSeverityLevel" + }, + "component": { + "$ref": "#/definitions/logComponent" + }, + "data": { + "type": "object" + }, + "failureIsRedacted": { + "type": "boolean" + } + } + }, + "collectionOrDatabaseOptions": { + "type": "object", + "additionalProperties": false, + "properties": { + "readConcern": { + "type": "object" + }, + "readPreference": { + "type": "object" + }, + "writeConcern": { + "type": "object" + }, + "timeoutMS": { + "type": "integer" + } + } + }, + "serverApi": { + "type": "object", + "additionalProperties": false, + "required": [ + "version" + ], + "properties": { + "version": { + "type": "string" + }, + "strict": { + "type": "boolean" + }, + "deprecationErrors": { + "type": "boolean" + } + } + }, + "operation": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "object" + ], + "properties": { + "name": { + "type": "string" + }, + "object": { + "type": "string" + }, + "arguments": { + "type": "object" + }, + "ignoreResultAndError": { + "type": "boolean" + }, + "expectError": { + "$ref": "#/definitions/expectedError" + }, + "expectResult": {}, + "saveResultAsEntity": { + "type": "string" + } + }, + "allOf": [ + { + "not": { + "required": [ + "expectError", + "expectResult" + ] + } + }, + { + "not": { + "required": [ + "expectError", + "saveResultAsEntity" + ] + } + }, + { + "not": { + "required": [ + "ignoreResultAndError", + "expectResult" + ] + } + }, + { + "not": { + "required": [ + "ignoreResultAndError", + "expectError" + ] + } + }, + { + "not": { + "required": [ + "ignoreResultAndError", + "saveResultAsEntity" + ] + } + } + ] + }, + "expectedError": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "isError": { + "type": "boolean", + "const": true + }, + "isClientError": { + "type": "boolean" + }, + "isTimeoutError": { + "type": "boolean" + }, + "errorContains": { + "type": "string" + }, + "errorCode": { + "type": "integer" + }, + "errorCodeName": { + "type": "string" + }, + "errorLabelsContain": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "errorLabelsOmit": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "writeErrors": { + "type": "object" + }, + "writeConcernErrors": { + "type": "array", + "items": { + "type": "object" + } + }, + "errorResponse": { + "type": "object" + }, + "expectResult": {} + } + }, + "test": { + "type": "object", + "additionalProperties": false, + "required": [ + "description", + "operations" + ], + "properties": { + "description": { + "type": "string" + }, + "runOnRequirements": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/runOnRequirement" + } + }, + "skipReason": { + "type": "string" + }, + "operations": { + "type": "array", + "items": { + "$ref": "#/definitions/operation" + } + }, + "expectEvents": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/expectedEventsForClient" + } + }, + "expectLogMessages": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/expectedLogMessagesForClient" + } + }, + "outcome": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/collectionData" + } + } + } + } + } +} From 712ea0eb5367af0b9820f0a049a25a5eed32d25e Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 09:38:23 -0400 Subject: [PATCH 04/15] add `minLibmongocryptVersion` add alternative form of `csfle` to support a `minLibmongocryptVersion` --- source/unified-test-format/schema-1.25.json | 16 +++++++++++++++- .../unified-test-format/unified-test-format.md | 10 ++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/source/unified-test-format/schema-1.25.json b/source/unified-test-format/schema-1.25.json index 77d4aaed14..117c07de6d 100644 --- a/source/unified-test-format/schema-1.25.json +++ b/source/unified-test-format/schema-1.25.json @@ -97,7 +97,21 @@ "type": "string" }, "csfle": { - "type": "boolean" + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "object", + "properties": { + "additionalProperties": false, + "minProperties": 1, + "minLibmongocryptVersion": { + "$ref": "#/definitions/version" + } + } + } + ] } } }, diff --git a/source/unified-test-format/unified-test-format.md b/source/unified-test-format/unified-test-format.md index e8944e14f9..aedaeb6ae2 100644 --- a/source/unified-test-format/unified-test-format.md +++ b/source/unified-test-format/unified-test-format.md @@ -366,8 +366,8 @@ The structure of this object is as follows: [authenticationMechanisms](https://www.mongodb.com/docs/manual/reference/parameters/#mongodb-parameter-param.authenticationMechanisms) server parameter. If this field is omitted, there is no authentication mechanism requirement. -- `csfle`: Optional boolean. If true, the tests MUST only run if the driver and server support Client-Side Field Level - Encryption. CSFLE is supported when all of the following are true: +- `csfle`: Optional object or boolean. If not false, tests MUST only run if the driver and server support Client-Side + Field Level Encryption. CSFLE is supported when all of the following are true: - Server version is 4.2.0 or higher - Driver has libmongocrypt enabled @@ -376,6 +376,12 @@ The structure of this object is as follows: If false, tests MUST NOT run if CSFLE is supported. If this field is omitted, there is no CSFLE requirement. + The structure of the `csfle` object is as follows: + + - `minLibmongocryptVersion`: Optional string. The minimum libmongocrypt (inclusive) required to successfully run the + tests. If this field is omitted, there is no lower bound on the required libmongocrypt version. The format of this + string is defined in [Version String](#version-string). + Test runners MAY evaluate these conditions in any order. For example, it may be more efficient to evaluate `serverless` or `auth` before communicating with a server to check its version. From c827d57a5da548df36ab8f79e6b2bf7a7317cb3b Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 10:41:21 -0400 Subject: [PATCH 05/15] fix wording in `runOnRequirement` --- source/unified-test-format/unified-test-format.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/unified-test-format/unified-test-format.md b/source/unified-test-format/unified-test-format.md index aedaeb6ae2..fae6862ccc 100644 --- a/source/unified-test-format/unified-test-format.md +++ b/source/unified-test-format/unified-test-format.md @@ -299,7 +299,7 @@ The top-level fields of a test file are as follows: #### runOnRequirement -A combination of server version and/or topology requirements for running the test(s). +A combination of server version, topology, and/or dependency requirements for running the test(s). The format of server version strings is defined in [Version String](#version-string). When comparing server version strings, each component SHALL be compared numerically. For example, "4.0.10" is greater than "4.0.9" and "3.6" and less From 82ad3a55730e38bc9d35f48a8862840cd0e9ca96 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 10:42:51 -0400 Subject: [PATCH 06/15] update schema-latest.json and changelog --- source/unified-test-format/schema-latest.json | 16 +++++++++++++++- .../unified-test-format/unified-test-format.md | 5 +++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/source/unified-test-format/schema-latest.json b/source/unified-test-format/schema-latest.json index 77d4aaed14..117c07de6d 100644 --- a/source/unified-test-format/schema-latest.json +++ b/source/unified-test-format/schema-latest.json @@ -97,7 +97,21 @@ "type": "string" }, "csfle": { - "type": "boolean" + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "object", + "properties": { + "additionalProperties": false, + "minProperties": 1, + "minLibmongocryptVersion": { + "$ref": "#/definitions/version" + } + } + } + ] } } }, diff --git a/source/unified-test-format/unified-test-format.md b/source/unified-test-format/unified-test-format.md index fae6862ccc..81ab286f92 100644 --- a/source/unified-test-format/unified-test-format.md +++ b/source/unified-test-format/unified-test-format.md @@ -3422,6 +3422,11 @@ other specs *and* collating spec changes developed in parallel or during the sam ## Changelog +- 2025-07-28: **Schema version 1.25.** + + Add alternate form of `csfle`. Previously it was only a bool. Now to can also be an object containing + `minLibmongocryptVersion`. + - 2025-07-15: Clarify test runner may apply a default `cryptSharedLibPath`. - 2025-06-10: **Schema version 1.24.** From df149d9fcb81d78f1d42bff5fd88fba69fc513fd Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 10:44:08 -0400 Subject: [PATCH 07/15] apply `minLibmongocryptVersion` to tests --- .../unified/QE-Text-cleanupStructuredEncryptionData.json | 6 ++++-- .../unified/QE-Text-cleanupStructuredEncryptionData.yml | 6 +++--- .../unified/QE-Text-compactStructuredEncryptionData.json | 6 ++++-- .../unified/QE-Text-compactStructuredEncryptionData.yml | 6 +++--- .../tests/unified/QE-Text-prefixPreview.json | 6 ++++-- .../tests/unified/QE-Text-prefixPreview.yml | 6 +++--- .../tests/unified/QE-Text-substringPreview.json | 6 ++++-- .../tests/unified/QE-Text-substringPreview.yml | 6 +++--- .../tests/unified/QE-Text-suffixPreview.json | 6 ++++-- .../tests/unified/QE-Text-suffixPreview.yml | 6 +++--- 10 files changed, 35 insertions(+), 25 deletions(-) diff --git a/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.json b/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.json index a6c70c5086..24f33ab3ec 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.json +++ b/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.json @@ -1,6 +1,6 @@ { "description": "QE-Text-cleanupStructuredEncryptionData", - "schemaVersion": "1.23", + "schemaVersion": "1.25", "runOnRequirements": [ { "minServerVersion": "8.2.0", @@ -9,7 +9,9 @@ "sharded", "load-balanced" ], - "csfle": true + "csfle": { + "minLibmongocryptVersion": "1.15.0" + } } ], "createEntities": [ diff --git a/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.yml b/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.yml index c15aa3bcdf..a326cca63d 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.yml +++ b/source/client-side-encryption/tests/unified/QE-Text-cleanupStructuredEncryptionData.yml @@ -1,10 +1,10 @@ description: QE-Text-cleanupStructuredEncryptionData -schemaVersion: "1.23" +schemaVersion: "1.25" runOnRequirements: - # Requires libmongocrypt 1.15.0 for SPM-4158. - minServerVersion: "8.2.0" # Server 8.2.0 adds preview support for QE text queries. topologies: ["replicaset", "sharded", "load-balanced"] # QE does not support standalone. - csfle: true + csfle: + minLibmongocryptVersion: 1.15.0 # For SPM-4158. createEntities: - client: id: &client "client" diff --git a/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.json b/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.json index 9e0045bb2d..c7abfe2d4b 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.json +++ b/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.json @@ -1,6 +1,6 @@ { "description": "QE-Text-compactStructuredEncryptionData", - "schemaVersion": "1.23", + "schemaVersion": "1.25", "runOnRequirements": [ { "minServerVersion": "8.2.0", @@ -9,7 +9,9 @@ "sharded", "load-balanced" ], - "csfle": true + "csfle": { + "minLibmongocryptVersion": "1.15.0" + } } ], "createEntities": [ diff --git a/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.yml b/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.yml index 49b5d83453..994e6209ea 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.yml +++ b/source/client-side-encryption/tests/unified/QE-Text-compactStructuredEncryptionData.yml @@ -1,10 +1,10 @@ description: QE-Text-compactStructuredEncryptionData -schemaVersion: "1.23" +schemaVersion: "1.25" runOnRequirements: - # Requires libmongocrypt 1.15.0 for SPM-4158. - minServerVersion: "8.2.0" # Server 8.2.0 adds preview support for QE text queries. topologies: ["replicaset", "sharded", "load-balanced"] # QE does not support standalone. - csfle: true + csfle: + minLibmongocryptVersion: 1.15.0 # For SPM-4158. createEntities: - client: id: &client "client" diff --git a/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.json b/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.json index 8eccf32c77..7279385743 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.json +++ b/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.json @@ -1,6 +1,6 @@ { "description": "QE-Text-prefixPreview", - "schemaVersion": "1.23", + "schemaVersion": "1.25", "runOnRequirements": [ { "minServerVersion": "8.2.0", @@ -9,7 +9,9 @@ "sharded", "load-balanced" ], - "csfle": true + "csfle": { + "minLibmongocryptVersion": "1.15.0" + } } ], "createEntities": [ diff --git a/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.yml b/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.yml index ad61635423..6f228e2d70 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.yml +++ b/source/client-side-encryption/tests/unified/QE-Text-prefixPreview.yml @@ -1,10 +1,10 @@ description: QE-Text-prefixPreview -schemaVersion: "1.23" +schemaVersion: "1.25" runOnRequirements: - # Requires libmongocrypt 1.15.0 for SPM-4158. - minServerVersion: "8.2.0" # Server 8.2.0 adds preview support for QE text queries. topologies: ["replicaset", "sharded", "load-balanced"] # QE does not support standalone. - csfle: true + csfle: + minLibmongocryptVersion: 1.15.0 # For SPM-4158. createEntities: - client: id: &client "client" diff --git a/source/client-side-encryption/tests/unified/QE-Text-substringPreview.json b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.json index 248a050bd5..6e1131cae0 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-substringPreview.json +++ b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.json @@ -1,6 +1,6 @@ { "description": "QE-Text-suffixPreview", - "schemaVersion": "1.23", + "schemaVersion": "1.25", "runOnRequirements": [ { "minServerVersion": "8.2.0", @@ -9,7 +9,9 @@ "sharded", "load-balanced" ], - "csfle": true + "csfle": { + "minLibmongocryptVersion": "1.15.0" + } } ], "createEntities": [ diff --git a/source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml index f47c9cc5ae..483da8e72a 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml +++ b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml @@ -1,10 +1,10 @@ description: QE-Text-suffixPreview -schemaVersion: "1.23" +schemaVersion: "1.25" runOnRequirements: - # Requires libmongocrypt 1.15.0 for SPM-4158. - minServerVersion: "8.2.0" # Server 8.2.0 adds preview support for QE text queries. topologies: ["replicaset", "sharded", "load-balanced"] # QE does not support standalone. - csfle: true + csfle: + minLibmongocryptVersion: 1.15.0 # For SPM-4158. createEntities: - client: id: &client "client" diff --git a/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.json b/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.json index efa95edae2..deec5e63b0 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.json +++ b/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.json @@ -1,6 +1,6 @@ { "description": "QE-Text-suffixPreview", - "schemaVersion": "1.23", + "schemaVersion": "1.25", "runOnRequirements": [ { "minServerVersion": "8.2.0", @@ -9,7 +9,9 @@ "sharded", "load-balanced" ], - "csfle": true + "csfle": { + "minLibmongocryptVersion": "1.15.0" + } } ], "createEntities": [ diff --git a/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.yml b/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.yml index 18ac4c6553..9a6925a2a1 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.yml +++ b/source/client-side-encryption/tests/unified/QE-Text-suffixPreview.yml @@ -1,10 +1,10 @@ description: QE-Text-suffixPreview -schemaVersion: "1.23" +schemaVersion: "1.25" runOnRequirements: - # Requires libmongocrypt 1.15.0 for SPM-4158. - minServerVersion: "8.2.0" # Server 8.2.0 adds preview support for QE text queries. topologies: ["replicaset", "sharded", "load-balanced"] # QE does not support standalone. - csfle: true + csfle: + minLibmongocryptVersion: 1.15.0 # For SPM-4158. createEntities: - client: id: &client "client" From fd82726272b5b7aa0cac03204d2f5c5b56b5b170 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 14:50:16 -0400 Subject: [PATCH 08/15] use schema 1.25 in makefile --- source/unified-test-format/tests/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/unified-test-format/tests/Makefile b/source/unified-test-format/tests/Makefile index b4d1bee856..a802523e4f 100644 --- a/source/unified-test-format/tests/Makefile +++ b/source/unified-test-format/tests/Makefile @@ -1,4 +1,4 @@ -SCHEMA=../schema-1.23.json +SCHEMA=../schema-1.25.json .PHONY: all \ atlas-data-lake \ From eaff583691e43788436a8189807261efb9186cce Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 14:53:10 -0400 Subject: [PATCH 09/15] fix nesting --- source/unified-test-format/schema-1.25.json | 4 ++-- source/unified-test-format/schema-latest.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/unified-test-format/schema-1.25.json b/source/unified-test-format/schema-1.25.json index 117c07de6d..3be461221e 100644 --- a/source/unified-test-format/schema-1.25.json +++ b/source/unified-test-format/schema-1.25.json @@ -103,9 +103,9 @@ }, { "type": "object", + "additionalProperties": false, + "minProperties": 1, "properties": { - "additionalProperties": false, - "minProperties": 1, "minLibmongocryptVersion": { "$ref": "#/definitions/version" } diff --git a/source/unified-test-format/schema-latest.json b/source/unified-test-format/schema-latest.json index 117c07de6d..3be461221e 100644 --- a/source/unified-test-format/schema-latest.json +++ b/source/unified-test-format/schema-latest.json @@ -103,9 +103,9 @@ }, { "type": "object", + "additionalProperties": false, + "minProperties": 1, "properties": { - "additionalProperties": false, - "minProperties": 1, "minLibmongocryptVersion": { "$ref": "#/definitions/version" } From 325e772cd5a90ebe7a1c4e770de3572a60ad6684 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 15:09:29 -0400 Subject: [PATCH 10/15] update "Current Schema Version" --- source/unified-test-format/unified-test-format.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/unified-test-format/unified-test-format.md b/source/unified-test-format/unified-test-format.md index 81ab286f92..a299783ebb 100644 --- a/source/unified-test-format/unified-test-format.md +++ b/source/unified-test-format/unified-test-format.md @@ -2,7 +2,7 @@ - Status: Accepted - Minimum Server Version: N/A -- Current Schema Version: 1.19.0 +- Current Schema Version: 1.25.0 ______________________________________________________________________ From c00f2ffaef72a6c9614159a81b0dc25126bc9b16 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 16:21:24 -0400 Subject: [PATCH 11/15] use `--spec=draft2019` in `ajv` command To fix `no schema with key or ref` error from AJV with tests using draft2019 spec. --- .github/workflows/check_schema_version.sh | 18 +++++++- source/unified-test-format/tests/Makefile | 52 +++++++++++------------ 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/.github/workflows/check_schema_version.sh b/.github/workflows/check_schema_version.sh index 67dccd03b7..a97e81a695 100755 --- a/.github/workflows/check_schema_version.sh +++ b/.github/workflows/check_schema_version.sh @@ -8,6 +8,12 @@ function get_schema_version() { js-yaml $1 | jq -r .schemaVersion } +function get_json_schema_url () { + schemaVersion=$(get_schema_version "$1") + schemaFile="source/unified-test-format/schema-$schemaVersion.json" + cat "$schemaFile" | jq -r '.["$schema"]' +} + function get_all_schemaVersion_defining_files () { # look for all yaml files with "schemaVersion: ["'][1-9]" grep --include=*.{yml,yaml} --files-with-matches --recursive --word-regexp --regexp="schemaVersion: [\"'][1-9]" source | \ @@ -20,7 +26,17 @@ function get_all_schemaVersion_defining_files () { for testFile in $(get_all_schemaVersion_defining_files) do schemaVersion=$(get_schema_version "$testFile") - if ! ajvCheck=$(ajv -s "source/unified-test-format/schema-$schemaVersion.json" -d "$testFile"); then + jsonSchemaURL=$(get_json_schema_url "$testFile") + if [ "$jsonSchemaURL" = "https://json-schema.org/draft/2019-09/schema#" ]; then + spec="draft2019" + elif [ "$jsonSchemaURL" = "http://json-schema.org/draft-07/schema#" ]; then + spec="draft7" + else + echo "Do not know how to validate $jsonSchemaURL" + exit 1 + fi + + if ! ajvCheck=$(ajv --spec="$spec" -s "source/unified-test-format/schema-$schemaVersion.json" -d "$testFile"); then exitCode=1 fi echo "$ajvCheck using schema v$schemaVersion" diff --git a/source/unified-test-format/tests/Makefile b/source/unified-test-format/tests/Makefile index a802523e4f..629559bbf5 100644 --- a/source/unified-test-format/tests/Makefile +++ b/source/unified-test-format/tests/Makefile @@ -62,91 +62,91 @@ all: atlas-data-lake \ # For specifications that contain multiple test folders, create a target for each folder # in addition to a target for the specification itself atlas-data-lake: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../atlas-data-lake-testing/tests/unified/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../atlas-data-lake-testing/tests/unified/*.yml" --valid auth: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../auth/tests/unified/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../auth/tests/unified/*.yml" --valid change-streams: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../change-streams/tests/unified/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../change-streams/tests/unified/*.yml" --valid client-side-encryption: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../client-side-encryption/tests/unified/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../client-side-encryption/tests/unified/*.yml" --valid client-side-operations-timeout: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../client-side-operations-timeout/tests/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../client-side-operations-timeout/tests/*.yml" --valid collection-management: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../collection-management/tests/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../collection-management/tests/*.yml" --valid command-logging-and-monitoring: command-logging-and-monitoring/logging command-logging-and-monitoring/monitoring command-logging-and-monitoring/logging: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../command-logging-and-monitoring/tests/logging/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../command-logging-and-monitoring/tests/logging/*.yml" --valid command-logging-and-monitoring/monitoring: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../command-logging-and-monitoring/tests/monitoring/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../command-logging-and-monitoring/tests/monitoring/*.yml" --valid connection-monitoring-and-pooling: connection-monitoring-and-pooling/logging connection-monitoring-and-pooling/logging: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../connection-monitoring-and-pooling/tests/logging/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../connection-monitoring-and-pooling/tests/logging/*.yml" --valid crud: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../crud/tests/unified/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../crud/tests/unified/*.yml" --valid gridfs: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../gridfs/tests/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../gridfs/tests/*.yml" --valid index-management: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../index-management/tests/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../index-management/tests/*.yml" --valid load-balancers: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../load-balancers/tests/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../load-balancers/tests/*.yml" --valid read-write-concern: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../read-write-concern/tests/operation/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../read-write-concern/tests/operation/*.yml" --valid retryable-reads: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../retryable-reads/tests/unified/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../retryable-reads/tests/unified/*.yml" --valid retryable-writes: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../retryable-writes/tests/unified/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../retryable-writes/tests/unified/*.yml" --valid run-command: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../run-command/tests/unified/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../run-command/tests/unified/*.yml" --valid server-discovery-and-monitoring: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../server-discovery-and-monitoring/tests/unified/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../server-discovery-and-monitoring/tests/unified/*.yml" --valid server-selection: server-selection/logging server-selection/logging: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../server-selection/tests/logging/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../server-selection/tests/logging/*.yml" --valid sessions: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../sessions/tests/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../sessions/tests/*.yml" --valid transactions-convenient-api: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../transactions-convenient-api/tests/unified/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../transactions-convenient-api/tests/unified/*.yml" --valid transactions: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../transactions/tests/unified/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../transactions/tests/unified/*.yml" --valid unified-test-format: unified-test-format/invalid unified-test-format/valid-fail unified-test-format/valid-pass unified-test-format/invalid: HAS_AJV @# Redirect stdout to hide expected validation errors - @ajv test -s $(SCHEMA) -d "invalid/*.yml" --invalid > /dev/null && echo "invalid/*.yml passed test" + @ajv --spec=draft2019 test -s $(SCHEMA) -d "invalid/*.yml" --invalid > /dev/null && echo "invalid/*.yml passed test" unified-test-format/valid-fail: HAS_AJV - @ajv test -s $(SCHEMA) -d "valid-fail/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "valid-fail/*.yml" --valid unified-test-format/valid-pass: HAS_AJV - @ajv test -s $(SCHEMA) -d "valid-pass/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "valid-pass/*.yml" --valid versioned-api: HAS_AJV - @ajv test -s $(SCHEMA) -d "../../versioned-api/tests/*.yml" --valid + @ajv --spec=draft2019 test -s $(SCHEMA) -d "../../versioned-api/tests/*.yml" --valid HAS_AJV: @if ! command -v ajv > /dev/null; then \ From 470b859c70df1252034657c941ce79f5226e9fd4 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 16:25:17 -0400 Subject: [PATCH 12/15] fix `description` Co-authored-by: Bailey Pearson --- .../tests/unified/QE-Text-substringPreview.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml index 483da8e72a..cee6a9f7ca 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml +++ b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.yml @@ -1,4 +1,4 @@ -description: QE-Text-suffixPreview +description: QE-Text-substringPreview schemaVersion: "1.25" runOnRequirements: - minServerVersion: "8.2.0" # Server 8.2.0 adds preview support for QE text queries. From b20bbb1aadfe8f7c875fafd7b9487ada8e6d390a Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 16:31:04 -0400 Subject: [PATCH 13/15] regenerate JSON --- .../tests/unified/QE-Text-substringPreview.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/client-side-encryption/tests/unified/QE-Text-substringPreview.json b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.json index 6e1131cae0..6a8f133eac 100644 --- a/source/client-side-encryption/tests/unified/QE-Text-substringPreview.json +++ b/source/client-side-encryption/tests/unified/QE-Text-substringPreview.json @@ -1,5 +1,5 @@ { - "description": "QE-Text-suffixPreview", + "description": "QE-Text-substringPreview", "schemaVersion": "1.25", "runOnRequirements": [ { From 7ccd9635cee320f55fd33ecace5670bf5540e8fd Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 28 Jul 2025 16:31:51 -0400 Subject: [PATCH 14/15] fix typo --- source/unified-test-format/unified-test-format.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/unified-test-format/unified-test-format.md b/source/unified-test-format/unified-test-format.md index a299783ebb..e5ae243cef 100644 --- a/source/unified-test-format/unified-test-format.md +++ b/source/unified-test-format/unified-test-format.md @@ -3424,7 +3424,7 @@ other specs *and* collating spec changes developed in parallel or during the sam - 2025-07-28: **Schema version 1.25.** - Add alternate form of `csfle`. Previously it was only a bool. Now to can also be an object containing + Add alternate form of `csfle`. Previously it was only a bool. Now it can also be an object containing `minLibmongocryptVersion`. - 2025-07-15: Clarify test runner may apply a default `cryptSharedLibPath`. From a49c5b74fb58854ad7361ca2140b357db079ebc8 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 4 Aug 2025 16:10:44 -0400 Subject: [PATCH 15/15] add `invalid` tests --- ...t-csfle-minLibmongocryptVersion-pattern.json | 17 +++++++++++++++++ ...nt-csfle-minLibmongocryptVersion-pattern.yml | 11 +++++++++++ ...ment-csfle-minLibmongocryptVersion-type.json | 17 +++++++++++++++++ ...ement-csfle-minLibmongocryptVersion-type.yml | 11 +++++++++++ 4 files changed, 56 insertions(+) create mode 100644 source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-pattern.json create mode 100644 source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-pattern.yml create mode 100644 source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-type.json create mode 100644 source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-type.yml diff --git a/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-pattern.json b/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-pattern.json new file mode 100644 index 0000000000..1db023bf68 --- /dev/null +++ b/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-pattern.json @@ -0,0 +1,17 @@ +{ + "description": "runOnRequirement-csfle-minLibmongocryptVersion-pattern", + "schemaVersion": "1.25", + "runOnRequirements": [ + { + "csfle": { + "minLibmongocryptVersion": "1.2.3.4" + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-pattern.yml b/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-pattern.yml new file mode 100644 index 0000000000..a95e2c6ee7 --- /dev/null +++ b/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-pattern.yml @@ -0,0 +1,11 @@ +description: "runOnRequirement-csfle-minLibmongocryptVersion-pattern" + +schemaVersion: "1.25" + +runOnRequirements: + - csfle: + minLibmongocryptVersion: "1.2.3.4" + +tests: + - description: "foo" + operations: [] diff --git a/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-type.json b/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-type.json new file mode 100644 index 0000000000..8de7b293f1 --- /dev/null +++ b/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-type.json @@ -0,0 +1,17 @@ +{ + "description": "runOnRequirement-csfle-minLibmongocryptVersion-type", + "schemaVersion": "1.25", + "runOnRequirements": [ + { + "csfle": { + "minLibmongocryptVersion": 0 + } + } + ], + "tests": [ + { + "description": "foo", + "operations": [] + } + ] +} diff --git a/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-type.yml b/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-type.yml new file mode 100644 index 0000000000..0230982ebe --- /dev/null +++ b/source/unified-test-format/tests/invalid/runOnRequirement-csfle-minLibmongocryptVersion-type.yml @@ -0,0 +1,11 @@ +description: "runOnRequirement-csfle-minLibmongocryptVersion-type" + +schemaVersion: "1.25" + +runOnRequirements: + - csfle: + minLibmongocryptVersion: 0 + +tests: + - description: "foo" + operations: []