This is an automated email from the ASF dual-hosted git repository.

nicholasjiang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-rust.git


The following commit(s) were added to refs/heads/main by this push:
     new a74ae0d  test: Use test fixtures to test data type (#50)
a74ae0d is described below

commit a74ae0da38cd6819ee4e5a20ac6b844b8f03c92e
Author: Xuanwo <[email protected]>
AuthorDate: Mon Aug 12 11:10:07 2024 +0800

    test: Use test fixtures to test data type (#50)
---
 crates/paimon/Cargo.toml         |   1 +
 crates/paimon/src/spec/schema.rs |   1 +
 crates/paimon/src/spec/types.rs  | 358 +++++++++++++++++++++++++++++++++------
 3 files changed, 305 insertions(+), 55 deletions(-)

diff --git a/crates/paimon/Cargo.toml b/crates/paimon/Cargo.toml
index 0d2b9dd..a285c2e 100644
--- a/crates/paimon/Cargo.toml
+++ b/crates/paimon/Cargo.toml
@@ -36,3 +36,4 @@ serde_with = "3.9.0"
 snafu = "0.8.3"
 typed-builder = "^0.19"
 opendal = "0.48"
+pretty_assertions = "1"
\ No newline at end of file
diff --git a/crates/paimon/src/spec/schema.rs b/crates/paimon/src/spec/schema.rs
index 349652d..4266421 100644
--- a/crates/paimon/src/spec/schema.rs
+++ b/crates/paimon/src/spec/schema.rs
@@ -48,6 +48,7 @@ pub struct DataField {
     name: String,
     #[serde(rename = "type")]
     typ: DataType,
+    #[serde(skip_serializing_if = "Option::is_none")]
     description: Option<String>,
 }
 
diff --git a/crates/paimon/src/spec/types.rs b/crates/paimon/src/spec/types.rs
index d27d9ab..65ec59e 100644
--- a/crates/paimon/src/spec/types.rs
+++ b/crates/paimon/src/spec/types.rs
@@ -164,21 +164,14 @@ impl ArrayType {
 /// Data type of an 8-byte (2^64) signed integer with values from 
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.
 ///
 /// Impl Reference: 
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/BigIntType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
+#[serde_as]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[serde(transparent)]
 pub struct BigIntType {
+    #[serde_as(as = 
"FromInto<serde_utils::NullableType<serde_utils::BIGINT>>")]
     nullable: bool,
 }
 
-impl Display for BigIntType {
-    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-        write!(f, "BIGINT")?;
-        if !self.nullable {
-            write!(f, " NOT NULL")?;
-        }
-        Ok(())
-    }
-}
-
 impl Default for BigIntType {
     fn default() -> Self {
         Self::new()
@@ -554,7 +547,7 @@ impl FloatType {
 #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
 #[serde(transparent)]
 pub struct IntType {
-    #[serde_as(as = 
"FromInto<serde_utils::NullableType<serde_utils::INTEGER>>")]
+    #[serde_as(as = "FromInto<serde_utils::NullableType<serde_utils::INT>>")]
     nullable: bool,
 }
 
@@ -1017,7 +1010,7 @@ impl MapType {
 #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
 pub struct MultisetType {
     #[serde(rename = "type")]
-    #[serde_as(as = "FromInto<serde_utils::NullableType<serde_utils::MAP>>")]
+    #[serde_as(as = 
"FromInto<serde_utils::NullableType<serde_utils::MULTISET>>")]
     nullable: bool,
     #[serde(rename = "element")]
     element_type: Box<DataType>,
@@ -1107,9 +1100,14 @@ mod serde_utils {
         const NAME: &'static str = "FLOAT";
     }
 
-    pub struct INTEGER;
-    impl DataTypeName for INTEGER {
-        const NAME: &'static str = "INTEGER";
+    pub struct INT;
+    impl DataTypeName for INT {
+        const NAME: &'static str = "INT";
+    }
+
+    pub struct BIGINT;
+    impl DataTypeName for BIGINT {
+        const NAME: &'static str = "BIGINT";
     }
 
     pub struct SMALLINT;
@@ -1196,64 +1194,314 @@ mod serde_utils {
 
 #[cfg(test)]
 mod tests {
-
     use super::*;
+    use pretty_assertions::assert_eq;
 
-    /// TODO: replace expect with exist fixture.
-    #[test]
-    fn test_data_type_serialize() {
-        // name, input, expect.
-        let cases = vec![
+    fn load_fixture(name: &str) -> String {
+        let workdir =
+            std::env::current_dir().unwrap_or_else(|err| panic!("current_dir 
must exist: {err}"));
+        let path = workdir.join(format!("tests/fixtures/{name}.json"));
+
+        let content = std::fs::read(&path)
+            .unwrap_or_else(|err| panic!("fixtures {path:?} load failed: 
{err}"));
+        String::from_utf8(content).expect("fixtures content must be valid 
utf8")
+    }
+
+    fn test_cases() -> Vec<(&'static str, DataType)> {
+        vec![
             (
-                "boolean",
-                DataType::Boolean(BooleanType::with_nullable(true)),
-                r#""BOOLEAN""#,
+                "array_type",
+                DataType::Array(ArrayType {
+                    nullable: false,
+                    element_type: 
DataType::Int(IntType::with_nullable(false)).into(),
+                }),
             ),
             (
-                "array with boolean",
+                "array_type_nullable",
                 DataType::Array(ArrayType {
+                    nullable: true,
+                    element_type: 
DataType::Int(IntType::with_nullable(true)).into(),
+                }),
+            ),
+            (
+                "bigint_type",
+                DataType::BigInt(BigIntType { nullable: false }),
+            ),
+            (
+                "bigint_type_nullable",
+                DataType::BigInt(BigIntType { nullable: true }),
+            ),
+            // FIXME: binary doesn't implement deserialize.
+            // (
+            //     "binary_type",
+            //     DataType::Binary(BinaryType {
+            //         nullable: false,
+            //         length: 22,
+            //     }),
+            // ),
+            // (
+            //     "binary_type_nullable",
+            //     DataType::Binary(BinaryType {
+            //         nullable: true,
+            //         length: 22,
+            //     }),
+            // ),
+            (
+                "boolean_type",
+                DataType::Boolean(BooleanType { nullable: false }),
+            ),
+            (
+                "boolean_type_nullable",
+                DataType::Boolean(BooleanType { nullable: true }),
+            ),
+            // FIXME: binary doesn't implement deserialize.
+            // (
+            //     "char_type",
+            //     DataType::Char(CharType {
+            //         nullable: false,
+            //         length: 33,
+            //     }),
+            // ),
+            // (
+            //     "char_type_nullable",
+            //     DataType::Char(CharType {
+            //         nullable: true,
+            //         length: 33,
+            //     }),
+            // ),
+            ("date_type", DataType::Date(DateType { nullable: false })),
+            (
+                "date_type_nullable",
+                DataType::Date(DateType { nullable: true }),
+            ),
+            // FIXME: DecimalType serialize failed.
+            // (
+            //     "decimal_type",
+            //     DataType::Decimal(DecimalType {
+            //         nullable: false,
+            //         precision: 10,
+            //         scale: 2,
+            //     }),
+            // ),
+            // (
+            //     "decimal_type_nullable",
+            //     DataType::Decimal(DecimalType {
+            //         nullable: true,
+            //         precision: 10,
+            //         scale: 2,
+            //     }),
+            // ),
+            (
+                "double_type",
+                DataType::Double(DoubleType { nullable: false }),
+            ),
+            (
+                "double_type_nullable",
+                DataType::Double(DoubleType { nullable: true }),
+            ),
+            ("float_type", DataType::Float(FloatType { nullable: false })),
+            (
+                "float_type_nullable",
+                DataType::Float(FloatType { nullable: true }),
+            ),
+            ("int_type", DataType::Int(IntType { nullable: false })),
+            (
+                "int_type_nullable",
+                DataType::Int(IntType { nullable: true }),
+            ),
+            // FIXME: LocalZonedTimestampType serialize failed.
+            // (
+            //     "local_zoned_timestamp_type",
+            //     DataType::LocalZonedTimestamp(LocalZonedTimestampType {
+            //         nullable: false,
+            //         precision: 3,
+            //     }),
+            // ),
+            // (
+            //     "local_zoned_timestamp_type_nullable",
+            //     DataType::LocalZonedTimestamp(LocalZonedTimestampType {
+            //         nullable: true,
+            //         precision: 3,
+            //     }),
+            // ),
+            // FIXME: VarCharType doesn't support deserialize.
+            // (
+            //     "map_type",
+            //     DataType::Map(MapType {
+            //         nullable: false,
+            //         key_type: DataType::VarChar(VarCharType {
+            //             nullable: true,
+            //             length: 20,
+            //         })
+            //         .into(),
+            //         value_type: DataType::Int(IntType { nullable: false 
}).into(),
+            //     }),
+            // ),
+            // (
+            //     "map_type_nullable",
+            //     DataType::Map(MapType {
+            //         nullable: true,
+            //         key_type: DataType::VarChar(VarCharType {
+            //             nullable: true,
+            //             length: 20,
+            //         })
+            //         .into(),
+            //         value_type: DataType::Int(IntType { nullable: true 
}).into(),
+            //     }),
+            // ),
+            (
+                "multiset_type",
+                DataType::Multiset(MultisetType {
                     nullable: false,
-                    element_type: 
DataType::Boolean(BooleanType::with_nullable(false)).into(),
+                    element_type: DataType::Int(IntType { nullable: false 
}).into(),
+                }),
+            ),
+            (
+                "multiset_type_nullable",
+                DataType::Multiset(MultisetType {
+                    nullable: true,
+                    element_type: DataType::Int(IntType { nullable: true 
}).into(),
                 }),
-                r#"{"type":"ARRAY NOT NULL","element":"BOOLEAN NOT NULL"}"#,
             ),
-        ];
+            // FIXME: VarChar doesn't support deserialize.
+            // (
+            //     "row_type",
+            //     DataType::Row(RowType {
+            //         nullable: false,
+            //         fields: vec![
+            //             DataField::new(0, "a".into(), DataType::Int(IntType 
{ nullable: false })),
+            //             DataField::new(
+            //                 1,
+            //                 "b".into(),
+            //                 DataType::VarChar(VarCharType {
+            //                     nullable: false,
+            //                     length: 20,
+            //                 }),
+            //             ),
+            //         ],
+            //     }),
+            // ),
+            // (
+            //     "row_type_nullable",
+            //     DataType::Row(RowType {
+            //         nullable: true,
+            //         fields: vec![
+            //             DataField::new(0, "a".into(), DataType::Int(IntType 
{ nullable: true })),
+            //             DataField::new(
+            //                 1,
+            //                 "b".into(),
+            //                 DataType::VarChar(VarCharType {
+            //                     nullable: true,
+            //                     length: 20,
+            //                 }),
+            //             ),
+            //         ],
+            //     }),
+            // ),
+            (
+                "smallint_type",
+                DataType::SmallInt(SmallIntType { nullable: false }),
+            ),
+            (
+                "smallint_type_nullable",
+                DataType::SmallInt(SmallIntType { nullable: true }),
+            ),
+            // FIXME: time and timestamp doesn't implement deserialize.
+            // (
+            //     "time_type",
+            //     DataType::Time(TimeType {
+            //         nullable: false,
+            //         precision: 9,
+            //     }),
+            // ),
+            // (
+            //     "time_type_nullable",
+            //     DataType::Time(TimeType {
+            //         nullable: true,
+            //         precision: 0,
+            //     }),
+            // ),
+            // (
+            //     "timestamp_type",
+            //     DataType::Timestamp(TimestampType {
+            //         nullable: false,
+            //         precision: 6,
+            //     }),
+            // ),
+            // (
+            //     "timestamp_type_nullable",
+            //     DataType::Timestamp(TimestampType {
+            //         nullable: true,
+            //         precision: 6,
+            //     }),
+            // ),
+            (
+                "tinyint_type",
+                DataType::TinyInt(TinyIntType { nullable: false }),
+            ),
+            (
+                "tinyint_type_nullable",
+                DataType::TinyInt(TinyIntType { nullable: true }),
+            ),
+            // FIXME: varbinary & varchar doesn't implement deserialize.
+            // (
+            //     "varbinary_type",
+            //     DataType::VarBinary(VarBinaryType {
+            //         nullable: false,
+            //         length: 233,
+            //     }),
+            // ),
+            // (
+            //     "varbinary_type_nullable",
+            //     DataType::VarBinary(VarBinaryType {
+            //         nullable: true,
+            //         length: 233,
+            //     }),
+            // ),
+            // (
+            //     "varchar_type",
+            //     DataType::VarChar(VarCharType {
+            //         nullable: false,
+            //         length: 33,
+            //     }),
+            // ),
+            // (
+            //     "varchar_type_nullable",
+            //     DataType::VarChar(VarCharType {
+            //         nullable: true,
+            //         length: 33,
+            //     }),
+            // ),
+        ]
+    }
+
+    /// Test data type serialize against with test fixtures.
+    ///
+    /// The name is the test fixtures file name.
+    #[test]
+    fn test_data_type_serialize() {
+        for (name, input) in test_cases() {
+            let actual = serde_json::to_string(&input)
+                .unwrap_or_else(|err| panic!("serialize failed for {name}: 
{err}"));
 
-        for (name, input, expect) in cases {
             assert_eq!(
-                serde_json::to_string(&input).unwrap(),
-                expect,
+                actual,
+                load_fixture(name),
                 "test data type serialize for {name}"
             )
         }
     }
 
-    /// TODO: replace expect with exist fixture.
+    /// Test data type serialize against with test fixtures.
+    ///
+    /// The name is the test fixtures file name.
     #[test]
     fn test_data_type_deserialize() {
-        // name, input, expect.
-        let cases = vec![
-            (
-                "boolean",
-                r#""BOOLEAN""#,
-                DataType::Boolean(BooleanType::with_nullable(true)),
-            ),
-            (
-                "array with boolean",
-                r#"{"type":"ARRAY NOT NULL","element":"BOOLEAN NOT NULL"}"#,
-                DataType::Array(ArrayType {
-                    nullable: false,
-                    element_type: 
DataType::Boolean(BooleanType::with_nullable(false)).into(),
-                }),
-            ),
-        ];
+        for (name, expect) in test_cases() {
+            let actual = serde_json::from_str::<DataType>(&load_fixture(name))
+                .unwrap_or_else(|err| panic!("deserialize failed for {name}: 
{err}"));
 
-        for (name, input, expect) in cases {
-            assert_eq!(
-                serde_json::from_str::<DataType>(input).unwrap(),
-                expect,
-                "test data type deserialize for {name}"
-            )
+            assert_eq!(actual, expect, "test data type deserialize for {name}")
         }
     }
 }

Reply via email to