fn test_from_value_with_union()

in avro/src/de.rs [1332:1539]


    fn test_from_value_with_union() -> TestResult {
        // AVRO-3232 test for deserialize_any on missing fields on the destination struct:
        // Error: DeserializeValue("Unsupported union")
        // Error: DeserializeValue("incorrect value of type: String")
        #[derive(Debug, Deserialize, PartialEq, Eq)]
        struct RecordInUnion {
            record_in_union: i32,
        }

        #[derive(Debug, Deserialize, PartialEq, Eq)]
        enum EnumInStruct {
            Val1,
        }

        #[derive(Debug, Deserialize, PartialEq, Eq)]
        struct StructWithMissingFields {
            a_string: String,
            a_record: Option<RecordInUnion>,
            an_array: Option<[bool; 2]>,
            a_union_map: Option<HashMap<String, i64>>,
            an_enum: EnumInStruct,
        }

        let raw_map: HashMap<String, i64> = [
            ("long_one".to_string(), 1),
            ("long_two".to_string(), 2),
            ("long_three".to_string(), 3),
            ("time_micros_a".to_string(), 123),
            ("timestamp_millis_b".to_string(), 234),
            ("timestamp_micros_c".to_string(), 345),
            ("timestamp_nanos_d".to_string(), 345_001),
            ("local_timestamp_millis_d".to_string(), 678),
            ("local_timestamp_micros_e".to_string(), 789),
            ("local_timestamp_nanos_f".to_string(), 345_002),
        ]
        .iter()
        .cloned()
        .collect();

        let value_map = raw_map
            .iter()
            .map(|(k, v)| match k {
                key if key.starts_with("long_") => (k.clone(), Value::Long(*v)),
                key if key.starts_with("time_micros_") => (k.clone(), Value::TimeMicros(*v)),
                key if key.starts_with("timestamp_millis_") => {
                    (k.clone(), Value::TimestampMillis(*v))
                }
                key if key.starts_with("timestamp_micros_") => {
                    (k.clone(), Value::TimestampMicros(*v))
                }
                key if key.starts_with("timestamp_nanos_") => {
                    (k.clone(), Value::TimestampNanos(*v))
                }
                key if key.starts_with("local_timestamp_millis_") => {
                    (k.clone(), Value::LocalTimestampMillis(*v))
                }
                key if key.starts_with("local_timestamp_micros_") => {
                    (k.clone(), Value::LocalTimestampMicros(*v))
                }
                key if key.starts_with("local_timestamp_nanos_") => {
                    (k.clone(), Value::LocalTimestampNanos(*v))
                }
                _ => unreachable!("unexpected key: {:?}", k),
            })
            .collect();

        let record = Value::Record(vec![
            (
                "a_string".to_string(),
                Value::String("a valid message field".to_string()),
            ),
            (
                "a_non_existing_string".to_string(),
                Value::String("a string".to_string()),
            ),
            (
                "a_union_string".to_string(),
                Value::Union(0, Box::new(Value::String("a union string".to_string()))),
            ),
            (
                "a_union_long".to_string(),
                Value::Union(0, Box::new(Value::Long(412))),
            ),
            (
                "a_union_long".to_string(),
                Value::Union(0, Box::new(Value::Long(412))),
            ),
            (
                "a_time_micros".to_string(),
                Value::Union(0, Box::new(Value::TimeMicros(123))),
            ),
            (
                "a_non_existing_time_micros".to_string(),
                Value::Union(0, Box::new(Value::TimeMicros(-123))),
            ),
            (
                "a_timestamp_millis".to_string(),
                Value::Union(0, Box::new(Value::TimestampMillis(234))),
            ),
            (
                "a_non_existing_timestamp_millis".to_string(),
                Value::Union(0, Box::new(Value::TimestampMillis(-234))),
            ),
            (
                "a_timestamp_micros".to_string(),
                Value::Union(0, Box::new(Value::TimestampMicros(345))),
            ),
            (
                "a_non_existing_timestamp_micros".to_string(),
                Value::Union(0, Box::new(Value::TimestampMicros(-345))),
            ),
            (
                "a_timestamp_nanos".to_string(),
                Value::Union(0, Box::new(Value::TimestampNanos(345))),
            ),
            (
                "a_non_existing_timestamp_nanos".to_string(),
                Value::Union(0, Box::new(Value::TimestampNanos(-345))),
            ),
            (
                "a_local_timestamp_millis".to_string(),
                Value::Union(0, Box::new(Value::LocalTimestampMillis(678))),
            ),
            (
                "a_non_existing_local_timestamp_millis".to_string(),
                Value::Union(0, Box::new(Value::LocalTimestampMillis(-678))),
            ),
            (
                "a_local_timestamp_micros".to_string(),
                Value::Union(0, Box::new(Value::LocalTimestampMicros(789))),
            ),
            (
                "a_non_existing_local_timestamp_micros".to_string(),
                Value::Union(0, Box::new(Value::LocalTimestampMicros(-789))),
            ),
            (
                "a_local_timestamp_nanos".to_string(),
                Value::Union(0, Box::new(Value::LocalTimestampNanos(789))),
            ),
            (
                "a_non_existing_local_timestamp_nanos".to_string(),
                Value::Union(0, Box::new(Value::LocalTimestampNanos(-789))),
            ),
            (
                "a_record".to_string(),
                Value::Union(
                    0,
                    Box::new(Value::Record(vec![(
                        "record_in_union".to_string(),
                        Value::Int(-2),
                    )])),
                ),
            ),
            (
                "a_non_existing_record".to_string(),
                Value::Union(
                    0,
                    Box::new(Value::Record(vec![("blah".to_string(), Value::Int(-22))])),
                ),
            ),
            (
                "an_array".to_string(),
                Value::Union(
                    0,
                    Box::new(Value::Array(vec![
                        Value::Boolean(true),
                        Value::Boolean(false),
                    ])),
                ),
            ),
            (
                "a_non_existing_array".to_string(),
                Value::Union(
                    0,
                    Box::new(Value::Array(vec![
                        Value::Boolean(false),
                        Value::Boolean(true),
                    ])),
                ),
            ),
            (
                "a_union_map".to_string(),
                Value::Union(0, Box::new(Value::Map(value_map))),
            ),
            (
                "a_non_existing_union_map".to_string(),
                Value::Union(0, Box::new(Value::Map(HashMap::new()))),
            ),
            ("an_enum".to_string(), Value::Enum(0, "Val1".to_owned())),
            (
                "a_non_existing_enum".to_string(),
                Value::Enum(0, "AnotherVariant".to_owned()),
            ),
        ]);

        let deserialized: StructWithMissingFields = crate::from_value(&record)?;
        let reference = StructWithMissingFields {
            a_string: "a valid message field".to_string(),
            a_record: Some(RecordInUnion {
                record_in_union: -2,
            }),
            an_array: Some([true, false]),
            a_union_map: Some(raw_map),
            an_enum: EnumInStruct::Val1,
        };
        assert_eq!(deserialized, reference);
        Ok(())
    }