From cef840637adfb82e50537ed8cdda5d57b5b7c17b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Przytu=C5=82a?= Date: Tue, 25 Jun 2024 18:13:30 +0200 Subject: [PATCH] DeserializeValue: `allow_missing` tests New tests are added for both flavours that show how the attribute allows for successful type check and deserialization when the corresponding field is missing from the CQL UDT definition. Co-authored-by: Piotr Dulikowski --- scylla-cql/src/types/deserialize/value.rs | 78 +++++++++++++++++++---- 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/scylla-cql/src/types/deserialize/value.rs b/scylla-cql/src/types/deserialize/value.rs index 9a342c9e64..ee388d6ecc 100644 --- a/scylla-cql/src/types/deserialize/value.rs +++ b/scylla-cql/src/types/deserialize/value.rs @@ -2480,6 +2480,7 @@ pub(super) mod tests { a: &'a str, #[scylla(skip)] x: String, + #[scylla(allow_missing)] b: Option, c: i64, } @@ -2555,6 +2556,7 @@ pub(super) mod tests { a: &'a str, #[scylla(skip)] x: String, + #[scylla(allow_missing)] b: Option, } @@ -2620,6 +2622,22 @@ pub(super) mod tests { let typ = udt_def_with_fields([("b", ColumnType::Int)]); Udt::type_check(&typ).unwrap_err(); } + + // Missing non-required column + { + let udt = UdtSerializer::new().field(b"kotmaale").finalize(); + let typ = udt_def_with_fields([("a", ColumnType::Text)]); + + let udt = deserialize::>(&typ, &udt).unwrap(); + assert_eq!( + udt, + Udt { + a: "kotmaale", + x: String::new(), + b: None, + } + ); + } } #[test] @@ -3285,6 +3303,7 @@ pub(super) mod tests { a: &'a str, #[scylla(skip)] x: String, + #[scylla(allow_missing)] b: Option, c: bool, } @@ -3321,7 +3340,7 @@ pub(super) mod tests { else { panic!("unexpected error kind: {:?}", err.kind) }; - assert_eq!(missing_fields.as_slice(), &["a", "b"]); + assert_eq!(missing_fields.as_slice(), &["a"]); } // excess fields in UDT @@ -3407,6 +3426,43 @@ pub(super) mod tests { assert_eq!(err.cql_type, typ); assert_matches!(err.kind, BuiltinDeserializationErrorKind::ExpectedNonNull); } + + // UDT field deserialization failed + { + let typ = + udt_def_with_fields([("a", ColumnType::Ascii), ("c", ColumnType::Boolean)]); + + let udt_bytes = UdtSerializer::new() + .field("alamakota".as_bytes()) + .field(&42_i16.to_be_bytes()) + .finalize(); + + let err = deserialize::(&typ, &udt_bytes).unwrap_err(); + + let err = get_deser_err(&err); + assert_eq!(err.rust_name, std::any::type_name::()); + assert_eq!(err.cql_type, typ); + let BuiltinDeserializationErrorKind::UdtError( + UdtDeserializationErrorKind::FieldDeserializationFailed { + ref field_name, + ref err, + }, + ) = err.kind + else { + panic!("unexpected error kind: {:?}", err.kind) + }; + assert_eq!(field_name.as_str(), "c"); + let err = get_deser_err(err); + assert_eq!(err.rust_name, std::any::type_name::()); + assert_eq!(err.cql_type, ColumnType::Boolean); + assert_matches!( + err.kind, + BuiltinDeserializationErrorKind::ByteLengthMismatch { + expected: 1, + got: 2, + } + ); + } } } @@ -3419,6 +3475,7 @@ pub(super) mod tests { #[scylla(skip)] x: String, b: Option, + #[scylla(allow_missing)] c: bool, } @@ -3453,7 +3510,7 @@ pub(super) mod tests { else { panic!("unexpected error kind: {:?}", err.kind) }; - assert_eq!(required_fields.as_slice(), &["a", "b", "c"]); + assert_eq!(required_fields.as_slice(), &["a", "b"]); assert_eq!(present_fields.as_slice(), &["a".to_string()]); } @@ -3462,8 +3519,7 @@ pub(super) mod tests { let typ = udt_def_with_fields([ ("a", ColumnType::Text), ("b", ColumnType::Int), - ("c", ColumnType::Boolean), - ("d", ColumnType::Counter), + ("d", ColumnType::Boolean), ]); let err = Udt::type_check(&typ).unwrap_err(); let err = get_typeck_err_inner(err.0.as_ref()); @@ -3480,11 +3536,8 @@ pub(super) mod tests { // UDT fields switched - field name mismatch { - let typ = udt_def_with_fields([ - ("b", ColumnType::Int), - ("a", ColumnType::Text), - ("c", ColumnType::Boolean), - ]); + let typ = + udt_def_with_fields([("b", ColumnType::Int), ("a", ColumnType::Text)]); let err = Udt::type_check(&typ).unwrap_err(); let err = get_typeck_err_inner(err.0.as_ref()); assert_eq!(err.rust_name, std::any::type_name::()); @@ -3506,11 +3559,8 @@ pub(super) mod tests { // UDT fields incompatible types - field type check failed { - let typ = udt_def_with_fields([ - ("a", ColumnType::Blob), - ("b", ColumnType::Int), - ("c", ColumnType::Boolean), - ]); + let typ = + udt_def_with_fields([("a", ColumnType::Blob), ("b", ColumnType::Int)]); let err = Udt::type_check(&typ).unwrap_err(); let err = get_typeck_err_inner(err.0.as_ref()); assert_eq!(err.rust_name, std::any::type_name::());