Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion spec/runners/unified/assertions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,12 @@ def assert_matches(actual, expected, msg)
end
end
else
actual = actual.value if expected.is_a?(Integer) && actual.is_a?(BSON::Int64)
# Numbers match by value regardless of BSON integer width. Normalize
# BSON::Int64/Int32 wrappers to their plain numeric value on both sides
# so e.g. BSON::Int64(3) and 3 compare equal (the unified format only
# distinguishes numeric types via $$type assertions).
actual = actual.value if actual.is_a?(BSON::Int64) || actual.is_a?(BSON::Int32)
expected = expected.value if expected.is_a?(BSON::Int64) || expected.is_a?(BSON::Int32)
raise Error::ResultMismatch, "#{msg}: expected #{expected}, actual #{actual}" unless actual == expected
end
end
Expand Down
12 changes: 10 additions & 2 deletions spec/runners/unified/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,13 @@ def generate_entities(es)
await_min_pool_size_ms = spec.use('awaitMinPoolSizeMS')

if (auto_encrypt_opts = spec.use('autoEncryptOpts'))
opts.merge!(Utils.convert_client_options('autoEncryptOpts' => auto_encrypt_opts))
# Unified fixtures are parsed in :bson mode, so the maps in
# autoEncryptOpts already hold BSON types.
opts.merge!(
Utils.convert_client_options(
{ 'autoEncryptOpts' => auto_encrypt_opts }, parsed: true
)
)
end

create_client(**opts).tap do |client|
Expand Down Expand Up @@ -529,7 +535,9 @@ def execute_operation(op, propagate_errors: false)
if (code_name = expected_error.use('errorCodeName')) && !(e.code_name == code_name)
raise Error::ErrorMismatch, "Expected #{code_name} code name but had #{e.code_name}"
end
if (text = expected_error.use('errorContains')) && !e.to_s.include?(text)
# The unified test format requires a case-insensitive match for
# errorContains.
if (text = expected_error.use('errorContains')) && !e.to_s.downcase.include?(text.downcase)
raise Error::ErrorMismatch, "Expected #{text} in the message but had #{e}"
end

Expand Down
6 changes: 5 additions & 1 deletion spec/runners/unified/test_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ def initialize(path, **opts)
else
path
end
@spec = BSON::ExtJSON.parse_obj(data)
# Parse in :bson mode so extended-JSON types are preserved as their BSON
# equivalents (e.g. $numberLong -> BSON::Int64, $date -> Time). QE range
# tests require this: the server rejects a range field whose configured
# min/max type does not match the field type (e.g. long field with int min).
@spec = BSON::ExtJSON.parse_obj(data, mode: :bson)
@options = opts
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
description: fle2v2-Rangev2-Compact
schemaVersion: "1.25"
runOnRequirements:
- minServerVersion: "8.0.0" # Require range v2 support on server.
# FLE 2 Encrypted collections are not supported on standalone.
topologies: ["replicaset", "sharded", "load-balanced"]
csfle:
minLibmongocryptVersion: "1.15.1"
createEntities:
- client:
id: "client0"
autoEncryptOpts:
keyVaultNamespace: keyvault.datakeys
kmsProviders:
local:
key: Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk
observeEvents:
- commandStartedEvent
- commandSucceededEvent
- database:
id: "db"
client: "client0"
databaseName: default
- collection:
id: "coll"
database: "db"
collectionName: default
initialData:
- databaseName: default
collectionName: default
documents: []
createOptions:
encryptedFields:
&encrypted_fields {
"fields":
[
{
"keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } },
"path": "encryptedInt",
"bsonType": "int",
"queries":
{
"queryType": "range",
"contention": { "$numberLong": "0" },
"trimFactor": { "$numberInt": "1" },
"sparsity": { "$numberLong": "1" },
"min": { "$numberInt": "0" },
"max": { "$numberInt": "200" },
},
},
],
}
- databaseName: keyvault
collectionName: datakeys
documents:
[
{
"_id": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } },
"keyMaterial":
{
"$binary":
{
"base64": "sHe0kz57YW7v8g9VP9sf/+K1ex4JqKc5rf/URX3n3p8XdZ6+15uXPaSayC6adWbNxkFskuMCOifDoTT+rkqMtFkDclOy884RuGGtUysq3X7zkAWYTKi8QAfKkajvVbZl2y23UqgVasdQu3OVBQCrH/xY00nNAs/52e958nVjBuzQkSb1T8pKJAyjZsHJ60+FtnfafDZSTAIBJYn7UWBCwQ==",
"subType": "00",
},
},
"creationDate": { "$date": { "$numberLong": "1648914851981" } },
"updateDate": { "$date": { "$numberLong": "1648914851981" } },
"status": { "$numberInt": "0" },
"masterKey": { "provider": "local" },
},
]
tests:
- description: "Compact works with 'range' fields"
operations:
# Insert before running compact to ensure the server errors if `encryptionInformation` is incorrectly omitted.
- name: insertOne
arguments:
document: { _id: 0, encryptedInt: { $numberInt: "0" } }
object: "coll"
- name: runCommand
object: "db"
arguments:
command:
compactStructuredEncryptionData: &collection_name "default"
commandName: compactStructuredEncryptionData
expectEvents:
- client: "client0"
events:
- commandStartedEvent:
command:
listCollections: 1
filter:
name: *collection_name
commandName: listCollections
- commandSucceededEvent:
commandName: listCollections
reply:
ok: 1
- commandStartedEvent:
command:
find: datakeys
filter:
{
"$or":
[
"_id": { "$in": ["$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" }] },
"keyAltNames": { "$in": [] },
],
}
$db: keyvault
readConcern: { level: "majority" }
commandName: find
- commandSucceededEvent:
commandName: find
reply:
ok: 1
- commandStartedEvent:
command:
insert: *collection_name
documents:
- { "_id": 0, "encryptedInt": { $$type: "binData" } }
ordered: true
encryptionInformation: &encryptionInformation
type: 1
schema:
default.default:
# libmongocrypt applies escCollection and ecocCollection to outgoing command.
escCollection: "enxcol_.default.esc"
ecocCollection: "enxcol_.default.ecoc"
<<: *encrypted_fields
commandName: insert
- commandSucceededEvent:
commandName: insert
reply:
ok: 1
- commandStartedEvent:
command:
compactStructuredEncryptionData: *collection_name
compactionTokens:
"encryptedInt":
{
"ecoc":
{ "$binary": { "base64": "noN+05JsuO1oDg59yypIGj45i+eFH6HOTXOPpeZ//Mk=", "subType": "00" } },
"anchorPaddingToken":
{ "$binary": { "base64": "QxKJD2If48p0l8NAXf2Kr0aleMd/dATSjBK6hTpNMyc=", "subType": "00" } },
}
encryptionInformation: *encryptionInformation
commandName: compactStructuredEncryptionData
- commandSucceededEvent:
commandName: compactStructuredEncryptionData
reply:
ok: 1
Loading
Loading