jecsand838 commented on code in PR #8292:
URL: https://github.com/apache/arrow-rs/pull/8292#discussion_r2338011238


##########
arrow-avro/src/codec.rs:
##########
@@ -1712,4 +2032,440 @@ mod tests {
             panic!("Top-level schema is not a struct");
         }
     }
+
+    fn json_string(s: &str) -> Value {
+        Value::String(s.to_string())
+    }
+
+    fn assert_default_stored(dt: &AvroDataType, default_json: &Value) {
+        let stored = dt
+            .metadata
+            .get(AVRO_FIELD_DEFAULT_METADATA_KEY)
+            .cloned()
+            .unwrap_or_default();
+        let expected = serde_json::to_string(default_json).unwrap();
+        assert_eq!(stored, expected, "stored default metadata should match");
+    }
+
+    #[test]
+    fn test_validate_and_store_default_null_and_nullability_rules() {
+        let mut dt_null = AvroDataType::new(Codec::Null, HashMap::new(), None);
+        let lit = dt_null.parse_and_store_default(&Value::Null).unwrap();
+        assert_eq!(lit, AvroLiteral::Null);
+        assert_default_stored(&dt_null, &Value::Null);
+        let mut dt_int = AvroDataType::new(Codec::Int32, HashMap::new(), None);
+        let err = dt_int.parse_and_store_default(&Value::Null).unwrap_err();
+        assert!(
+            err.to_string()
+                .contains("JSON null default is only valid for `null` type"),
+            "unexpected error: {err}"
+        );
+        let mut dt_int_nf =
+            AvroDataType::new(Codec::Int32, HashMap::new(), 
Some(Nullability::NullFirst));
+        let lit2 = dt_int_nf.parse_and_store_default(&Value::Null).unwrap();
+        assert_eq!(lit2, AvroLiteral::Null);
+        assert_default_stored(&dt_int_nf, &Value::Null);
+        let mut dt_int_ns =
+            AvroDataType::new(Codec::Int32, HashMap::new(), 
Some(Nullability::NullSecond));
+        let err2 = 
dt_int_ns.parse_and_store_default(&Value::Null).unwrap_err();
+        assert!(
+            err2.to_string()
+                .contains("JSON null default is only valid for `null` type"),
+            "unexpected error: {err2}"
+        );
+    }
+
+    #[test]
+    fn test_validate_and_store_default_primitives_and_temporal() {
+        let mut dt_bool = AvroDataType::new(Codec::Boolean, HashMap::new(), 
None);
+        let lit = dt_bool.parse_and_store_default(&Value::Bool(true)).unwrap();
+        assert_eq!(lit, AvroLiteral::Boolean(true));
+        assert_default_stored(&dt_bool, &Value::Bool(true));
+        let mut dt_i32 = AvroDataType::new(Codec::Int32, HashMap::new(), None);
+        let lit = dt_i32
+            .parse_and_store_default(&serde_json::json!(123))
+            .unwrap();
+        assert_eq!(lit, AvroLiteral::Int(123));
+        assert_default_stored(&dt_i32, &serde_json::json!(123));
+        let err = dt_i32
+            .parse_and_store_default(&serde_json::json!(i64::from(i32::MAX) + 
1))
+            .unwrap_err();
+        assert!(format!("{err}").contains("out of i32 range"));
+        let mut dt_i64 = AvroDataType::new(Codec::Int64, HashMap::new(), None);
+        let lit = dt_i64
+            .parse_and_store_default(&serde_json::json!(1234567890))
+            .unwrap();
+        assert_eq!(lit, AvroLiteral::Long(1234567890));
+        assert_default_stored(&dt_i64, &serde_json::json!(1234567890));
+        let mut dt_f32 = AvroDataType::new(Codec::Float32, HashMap::new(), 
None);
+        let lit = dt_f32
+            .parse_and_store_default(&serde_json::json!(1.25))
+            .unwrap();
+        assert_eq!(lit, AvroLiteral::Float(1.25));
+        assert_default_stored(&dt_f32, &serde_json::json!(1.25));
+        let err = dt_f32
+            .parse_and_store_default(&serde_json::json!(1e39))
+            .unwrap_err();
+        assert!(format!("{err}").contains("out of f32 range"));
+        let mut dt_f64 = AvroDataType::new(Codec::Float64, HashMap::new(), 
None);
+        let lit = dt_f64
+            .parse_and_store_default(&serde_json::json!(std::f64::consts::PI))
+            .unwrap();
+        assert_eq!(lit, AvroLiteral::Double(std::f64::consts::PI));
+        assert_default_stored(&dt_f64, 
&serde_json::json!(std::f64::consts::PI));
+        let mut dt_str = AvroDataType::new(Codec::Utf8, HashMap::new(), None);
+        let l = dt_str
+            .parse_and_store_default(&json_string("hello"))
+            .unwrap();
+        assert_eq!(l, AvroLiteral::String("hello".into()));
+        assert_default_stored(&dt_str, &json_string("hello"));
+        let mut dt_strv = AvroDataType::new(Codec::Utf8View, HashMap::new(), 
None);
+        let l = dt_strv
+            .parse_and_store_default(&json_string("view"))
+            .unwrap();
+        assert_eq!(l, AvroLiteral::String("view".into()));
+        assert_default_stored(&dt_strv, &json_string("view"));
+        let mut dt_uuid = AvroDataType::new(Codec::Uuid, HashMap::new(), None);
+        let l = dt_uuid
+            
.parse_and_store_default(&json_string("00000000-0000-0000-0000-000000000000"))
+            .unwrap();
+        assert_eq!(
+            l,
+            AvroLiteral::String("00000000-0000-0000-0000-000000000000".into())
+        );
+        let mut dt_bin = AvroDataType::new(Codec::Binary, HashMap::new(), 
None);
+        let l = dt_bin.parse_and_store_default(&json_string("ABC")).unwrap();
+        assert_eq!(l, AvroLiteral::Bytes(vec![65, 66, 67]));
+        let err = dt_bin
+            .parse_and_store_default(&json_string("€")) // U+20AC
+            .unwrap_err();
+        assert!(format!("{err}").contains("Invalid codepoint"));
+        let mut dt_date = AvroDataType::new(Codec::Date32, HashMap::new(), 
None);
+        let ld = dt_date
+            .parse_and_store_default(&serde_json::json!(1))
+            .unwrap();
+        assert_eq!(ld, AvroLiteral::Int(1));
+        let mut dt_tmill = AvroDataType::new(Codec::TimeMillis, 
HashMap::new(), None);
+        let lt = dt_tmill
+            .parse_and_store_default(&serde_json::json!(86_400_000))
+            .unwrap();
+        assert_eq!(lt, AvroLiteral::Int(86_400_000));
+        let mut dt_tmicros = AvroDataType::new(Codec::TimeMicros, 
HashMap::new(), None);
+        let ltm = dt_tmicros
+            .parse_and_store_default(&serde_json::json!(1_000_000))
+            .unwrap();
+        assert_eq!(ltm, AvroLiteral::Long(1_000_000));
+        let mut dt_ts_milli = AvroDataType::new(Codec::TimestampMillis(true), 
HashMap::new(), None);
+        let l1 = dt_ts_milli
+            .parse_and_store_default(&serde_json::json!(123))
+            .unwrap();
+        assert_eq!(l1, AvroLiteral::Long(123));
+        let mut dt_ts_micro =
+            AvroDataType::new(Codec::TimestampMicros(false), HashMap::new(), 
None);
+        let l2 = dt_ts_micro
+            .parse_and_store_default(&serde_json::json!(456))
+            .unwrap();
+        assert_eq!(l2, AvroLiteral::Long(456));
+    }
+
+    #[test]
+    fn test_validate_and_store_default_fixed_decimal_interval() {
+        let mut dt_fixed = AvroDataType::new(Codec::Fixed(4), HashMap::new(), 
None);
+        let l = dt_fixed
+            .parse_and_store_default(&json_string("WXYZ"))
+            .unwrap();
+        assert_eq!(l, AvroLiteral::Bytes(vec![87, 88, 89, 90]));
+        let err = dt_fixed
+            .parse_and_store_default(&json_string("TOO LONG"))
+            .unwrap_err();
+        assert!(format!("{err}").contains("Default length"));

Review Comment:
   @alamb That's a good callout! I just pushed up a commit with the other 
instances of this changed.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to