From e444c30a6fc371b96072fc2b449c35921e4143a2 Mon Sep 17 00:00:00 2001 From: Isabel Atkinson Date: Tue, 11 Feb 2025 11:56:54 -0700 Subject: [PATCH 1/4] sync tests --- .../spec/json/bson-binary-vector/README.md | 7 ++++-- .../spec/json/bson-binary-vector/float32.json | 18 +++++++++++++-- .../spec/json/bson-binary-vector/int8.json | 4 ++-- .../json/bson-binary-vector/packed_bit.json | 23 ++++--------------- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/tests/spec/json/bson-binary-vector/README.md b/src/tests/spec/json/bson-binary-vector/README.md index 3357ebb2..1a2cd871 100644 --- a/src/tests/spec/json/bson-binary-vector/README.md +++ b/src/tests/spec/json/bson-binary-vector/README.md @@ -29,7 +29,7 @@ Each JSON file contains three top-level keys. - `description`: string describing the test. - `valid`: boolean indicating if the vector, dtype, and padding should be considered a valid input. -- `vector`: list of numbers +- `vector`: (required if valid is true) list of numbers - `dtype_hex`: string defining the data type in hex (e.g. "0x10", "0x27") - `dtype_alias`: (optional) string defining the data dtype, perhaps as Enum. - `padding`: (optional) integer for byte padding. Defaults to 0. @@ -50,7 +50,10 @@ MUST assert that the input float array is the same after encoding and decoding. #### To prove correct in an invalid case (`valid:false`), one MUST -- raise an exception when attempting to encode a document from the numeric values, dtype, and padding. +- if the vector field is present, raise an exception when attempting to encode a document from the numeric values, + dtype, and padding. +- if the canonical_bson field is present, raise an exception when attempting to deserialize it into the corresponding + numeric values, as the field contains corrupted data. ## FAQ diff --git a/src/tests/spec/json/bson-binary-vector/float32.json b/src/tests/spec/json/bson-binary-vector/float32.json index 872c4353..845f504f 100644 --- a/src/tests/spec/json/bson-binary-vector/float32.json +++ b/src/tests/spec/json/bson-binary-vector/float32.json @@ -44,8 +44,22 @@ "vector": [127.0, 7.0], "dtype_hex": "0x27", "dtype_alias": "FLOAT32", - "padding": 3 + "padding": 3, + "canonical_bson": "1C00000005766563746F72000A0000000927030000FE420000E04000" + }, + { + "description": "Insufficient vector data with 3 bytes FLOAT32", + "valid": false, + "dtype_hex": "0x27", + "dtype_alias": "FLOAT32", + "canonical_bson": "1700000005766563746F7200050000000927002A2A2A00" + }, + { + "description": "Insufficient vector data with 5 bytes FLOAT32", + "valid": false, + "dtype_hex": "0x27", + "dtype_alias": "FLOAT32", + "canonical_bson": "1900000005766563746F7200070000000927002A2A2A2A2A00" } ] } - diff --git a/src/tests/spec/json/bson-binary-vector/int8.json b/src/tests/spec/json/bson-binary-vector/int8.json index 7529721e..29524fb6 100644 --- a/src/tests/spec/json/bson-binary-vector/int8.json +++ b/src/tests/spec/json/bson-binary-vector/int8.json @@ -42,7 +42,8 @@ "vector": [127, 7], "dtype_hex": "0x03", "dtype_alias": "INT8", - "padding": 3 + "padding": 3, + "canonical_bson": "1600000005766563746F7200040000000903037F0700" }, { "description": "INT8 with float inputs", @@ -54,4 +55,3 @@ } ] } - diff --git a/src/tests/spec/json/bson-binary-vector/packed_bit.json b/src/tests/spec/json/bson-binary-vector/packed_bit.json index 035776e8..a220e7e3 100644 --- a/src/tests/spec/json/bson-binary-vector/packed_bit.json +++ b/src/tests/spec/json/bson-binary-vector/packed_bit.json @@ -8,7 +8,8 @@ "vector": [], "dtype_hex": "0x10", "dtype_alias": "PACKED_BIT", - "padding": 1 + "padding": 1, + "canonical_bson": "1400000005766563746F72000200000009100100" }, { "description": "Simple Vector PACKED_BIT", @@ -61,21 +62,14 @@ "dtype_alias": "PACKED_BIT", "padding": 0 }, - { - "description": "Padding specified with no vector data PACKED_BIT", - "valid": false, - "vector": [], - "dtype_hex": "0x10", - "dtype_alias": "PACKED_BIT", - "padding": 1 - }, { "description": "Exceeding maximum padding PACKED_BIT", "valid": false, "vector": [1], "dtype_hex": "0x10", "dtype_alias": "PACKED_BIT", - "padding": 8 + "padding": 8, + "canonical_bson": "1500000005766563746F7200030000000910080100" }, { "description": "Negative padding PACKED_BIT", @@ -84,15 +78,6 @@ "dtype_hex": "0x10", "dtype_alias": "PACKED_BIT", "padding": -1 - }, - { - "description": "Vector with float values PACKED_BIT", - "valid": false, - "vector": [127.5], - "dtype_hex": "0x10", - "dtype_alias": "PACKED_BIT", - "padding": 0 } ] } - From c40406d55fcc513e4cee4da826a23e93fe5e10bd Mon Sep 17 00:00:00 2001 From: Isabel Atkinson Date: Tue, 11 Feb 2025 15:53:59 -0700 Subject: [PATCH 2/4] RUST-2149 Sync additional vector tests --- src/tests/spec/vector.rs | 78 ++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/src/tests/spec/vector.rs b/src/tests/spec/vector.rs index c297e285..666ce25e 100644 --- a/src/tests/spec/vector.rs +++ b/src/tests/spec/vector.rs @@ -31,7 +31,7 @@ struct TestFile { struct Test { description: String, valid: bool, - vector: Vec, + vector: Option>, #[serde( rename = "dtype_hex", deserialize_with = "deserialize_u8_from_hex_string" @@ -131,51 +131,69 @@ fn vector_from_numbers( } } +// Only return the binary if it represents a valid vector; otherwise, return an error. +fn binary_from_bytes(bson: &str, test_key: &str, description: &str) -> Result { + let bytes = hex::decode(bson).expect(description); + let mut test_document = Document::from_reader(bytes.as_slice()).expect(description); + let bson = test_document.remove(test_key).expect(description); + let binary = match bson { + Bson::Binary(binary) => binary, + other => panic!("{}: expected binary, got {}", description, other), + }; + // TryFrom for Vector + if let Err(error) = Vector::try_from(&binary) { + Err(error.to_string()) + } else { + Ok(binary) + } +} + fn run_test_file(test_file: TestFile) { for test in test_file.tests { let description = format!("{} ({})", test.description, test_file.description); - let test_vector = match ( - vector_from_numbers(test.vector, test.d_type, test.padding), - test.valid, - ) { - (Ok(vector), true) => vector, - (Err(_), false) => return, - (Ok(vector), false) => panic!( - "{}: valid was false but successfully constructed vector {:?}", - description, vector - ), - (Err(error), true) => panic!( - "{}: valid was true but vector construction failed with error {}", - description, error - ), + let test_vector = match test.vector { + Some(vector) => match vector_from_numbers(vector, test.d_type, test.padding) { + Ok(vector) => { + assert!(test.valid, "{}", description); + Some(vector) + } + Err(_) => { + assert!(!test.valid, "{}", description); + None + } + }, + None => None, + }; + + let test_binary = match test.canonical_bson { + Some(bson) => match binary_from_bytes(&bson, &test_file.test_key, &description) { + Ok(vector) => { + assert!(test.valid, "{}", description); + Some(vector) + } + Err(error) => { + assert!(!test.valid, "{}: {}", description, error); + None + } + }, + None => None, }; - let Some(canonical_bson) = test.canonical_bson else { + let (Some(test_vector), Some(test_binary)) = (test_vector, test_binary) else { return; }; - let bytes = hex::decode(canonical_bson).expect(&description); - let mut test_document = Document::from_reader(bytes.as_slice()).expect(&description); - // Rename the field to match the name used in the struct below. - let vector = test_document - .remove(&test_file.test_key) - .expect(&description); - test_document.insert("vector", vector); - let bson = test_document.get("vector").expect(&description); - let test_binary = match bson { - Bson::Binary(binary) => binary, - other => panic!("{}: expected binary, got {}", description, other), - }; + let test_document = doc! { "vector": &test_binary }; // TryFrom for Vector - let parsed_vector = Vector::try_from(test_binary).expect(&description); + let parsed_vector = Vector::try_from(&test_binary).expect(&description); assert_eq!(parsed_vector, test_vector); // From for Binary let binary = Binary::from(&test_vector); assert_eq!(binary.subtype, BinarySubtype::Vector); - assert_eq!(&binary, test_binary); + assert_eq!(binary, test_binary); // From for Bson let document = doc! { "vector": &test_vector }; From 729df2d64d91b5f608b119a02b178099a36545ee Mon Sep 17 00:00:00 2001 From: Isabel Atkinson Date: Tue, 11 Feb 2025 15:55:30 -0700 Subject: [PATCH 3/4] remove stray comment --- src/tests/spec/vector.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tests/spec/vector.rs b/src/tests/spec/vector.rs index 666ce25e..af4fcbfd 100644 --- a/src/tests/spec/vector.rs +++ b/src/tests/spec/vector.rs @@ -140,7 +140,6 @@ fn binary_from_bytes(bson: &str, test_key: &str, description: &str) -> Result binary, other => panic!("{}: expected binary, got {}", description, other), }; - // TryFrom for Vector if let Err(error) = Vector::try_from(&binary) { Err(error.to_string()) } else { From 384dfbde654d551711592f6ef2b06d86471381af Mon Sep 17 00:00:00 2001 From: Isabel Atkinson Date: Wed, 12 Feb 2025 09:43:34 -0700 Subject: [PATCH 4/4] add error to assert --- src/tests/spec/vector.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/spec/vector.rs b/src/tests/spec/vector.rs index af4fcbfd..8a9b9b0d 100644 --- a/src/tests/spec/vector.rs +++ b/src/tests/spec/vector.rs @@ -157,8 +157,8 @@ fn run_test_file(test_file: TestFile) { assert!(test.valid, "{}", description); Some(vector) } - Err(_) => { - assert!(!test.valid, "{}", description); + Err(error) => { + assert!(!test.valid, "{}: {}", description, error); None } },