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

sdf-jkl pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new 8e517524bc feat(arrow-cast): move map cast tests to integration suite 
(#11041)
8e517524bc is described below

commit 8e517524bcc7854587b49790ae87482f94420f3e
Author: Arnab Mondal <[email protected]>
AuthorDate: Wed Sep 16 11:05:50 2026 -0400

    feat(arrow-cast): move map cast tests to integration suite (#11041)
    
    # Which issue does this PR close?
    
    Part of #11033.
    
    # Rationale for this change
    
    The public-behavior cast tests in `arrow-cast/src/cast/mod.rs` are being
    moved into a crate-level integration test suite so individual cast
    families are easier to locate and maintain. This is the map-test slice
    of that work.
    
    # What changes are included in this PR?
    
    - Adds the `arrow-cast` `cast` integration-test target.
    - Adds `arrow-cast/tests/cast/`.
    - Moves the four map cast tests from the inline `cast/mod.rs` test
    module to `tests/cast/map.rs`.
    
    # Are these changes tested?
    
    - `cargo test -p arrow-cast --test cast`
    - `cargo fmt --all -- --check`
    
    A targeted Clippy run is blocked by existing `arrow-data` warnings under
    the locally installed Clippy version.
    
    # Are there any user-facing changes?
    
    No. This is a test-organization-only change.
    
    # AI usage disclosure
    
    OpenAI Codex assisted with the mechanical test extraction. I reviewed
    the resulting changes and verified the targeted tests locally.
    
    Co-authored-by: Andrew Lamb <[email protected]>
---
 arrow-cast/Cargo.toml        |   4 +
 arrow-cast/src/cast/mod.rs   | 223 --------------------------------------
 arrow-cast/tests/cast/map.rs | 248 +++++++++++++++++++++++++++++++++++++++++++
 arrow-cast/tests/cast/mod.rs |  18 ++++
 4 files changed, 270 insertions(+), 223 deletions(-)

diff --git a/arrow-cast/Cargo.toml b/arrow-cast/Cargo.toml
index 79af3d3da7..9e4a43a8d9 100644
--- a/arrow-cast/Cargo.toml
+++ b/arrow-cast/Cargo.toml
@@ -61,6 +61,10 @@ insta = { workspace = true }
 num-bigint = { version = "0.5", default-features = false, features = ["std"] }
 rand = "0.10"
 
+[[test]]
+name = "cast"
+path = "./tests/cast/mod.rs"
+
 [[bench]]
 name = "parse_timestamp"
 harness = false
diff --git a/arrow-cast/src/cast/mod.rs b/arrow-cast/src/cast/mod.rs
index c0e5327c1d..6cc0eba829 100644
--- a/arrow-cast/src/cast/mod.rs
+++ b/arrow-cast/src/cast/mod.rs
@@ -10291,229 +10291,6 @@ mod tests {
         ))
     }
 
-    #[test]
-    fn test_cast_map_dont_allow_change_of_order() {
-        let string_builder = StringBuilder::new();
-        let value_builder = StringBuilder::new();
-        let mut builder = MapBuilder::new(None, string_builder, value_builder);
-
-        builder.keys().append_value("0");
-        builder.values().append_value("test_val_1");
-        builder.append(true).unwrap();
-        builder.keys().append_value("1");
-        builder.values().append_value("test_val_2");
-        builder.append(true).unwrap();
-
-        // map builder returns unsorted map by default
-        let array = builder.finish();
-
-        let new_ordered = true;
-        let new_type = DataType::Map(
-            Arc::new(Field::new(
-                Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
-                DataType::Struct(
-                    vec![
-                        Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, 
DataType::Utf8, false),
-                        Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, 
DataType::Utf8, false),
-                    ]
-                    .into(),
-                ),
-                false,
-            )),
-            new_ordered,
-        );
-
-        let new_array_result = cast(&array, &new_type.clone());
-        assert!(!can_cast_types(array.data_type(), &new_type));
-        let Err(ArrowError::CastError(t)) = new_array_result else {
-            panic!();
-        };
-        assert_eq!(
-            t,
-            r#"Casting from Map("entries": non-null Struct("key": non-null 
Utf8, "value": Utf8), unsorted) to Map("entries": non-null Struct("key": 
non-null Utf8, "value": non-null Utf8), sorted) not supported"#
-        );
-    }
-
-    #[test]
-    fn test_cast_map_dont_allow_when_container_cant_cast() {
-        let string_builder = StringBuilder::new();
-        let value_builder = IntervalDayTimeArray::builder(2);
-        let mut builder = MapBuilder::new(None, string_builder, value_builder);
-
-        builder.keys().append_value("0");
-        builder.values().append_value(IntervalDayTime::new(1, 1));
-        builder.append(true).unwrap();
-        builder.keys().append_value("1");
-        builder.values().append_value(IntervalDayTime::new(2, 2));
-        builder.append(true).unwrap();
-
-        // map builder returns unsorted map by default
-        let array = builder.finish();
-
-        let new_ordered = true;
-        let new_type = DataType::Map(
-            Arc::new(Field::new(
-                Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
-                DataType::Struct(
-                    vec![
-                        Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, 
DataType::Utf8, false),
-                        Field::new(
-                            Field::MAP_VALUE_FIELD_DEFAULT_NAME,
-                            DataType::Duration(TimeUnit::Second),
-                            false,
-                        ),
-                    ]
-                    .into(),
-                ),
-                false,
-            )),
-            new_ordered,
-        );
-
-        let new_array_result = cast(&array, &new_type.clone());
-        assert!(!can_cast_types(array.data_type(), &new_type));
-        let Err(ArrowError::CastError(t)) = new_array_result else {
-            panic!();
-        };
-        assert_eq!(
-            t,
-            r#"Casting from Map("entries": non-null Struct("key": non-null 
Utf8, "value": Interval(DayTime)), unsorted) to Map("entries": non-null 
Struct("key": non-null Utf8, "value": non-null Duration(s)), sorted) not 
supported"#
-        );
-    }
-
-    #[test]
-    fn test_cast_map_field_names() {
-        let string_builder = StringBuilder::new();
-        let value_builder = StringBuilder::new();
-        let mut builder = MapBuilder::new(
-            Some(MapFieldNames {
-                // Explicitly writing the name so it will be apparent from 
what names to what names are we converting to
-                entry: Field::MAP_ENTRIES_FIELD_DEFAULT_NAME.to_string(),
-                key: Field::MAP_KEY_FIELD_DEFAULT_NAME.to_string(),
-                value: Field::MAP_VALUE_FIELD_DEFAULT_NAME.to_string(),
-            }),
-            string_builder,
-            value_builder,
-        );
-
-        builder.keys().append_value("0");
-        builder.values().append_value("test_val_1");
-        builder.append(true).unwrap();
-        builder.keys().append_value("1");
-        builder.values().append_value("test_val_2");
-        builder.append(true).unwrap();
-        builder.append(false).unwrap();
-
-        let array = builder.finish();
-
-        let new_type = DataType::Map(
-            Arc::new(Field::new(
-                "entries_new",
-                DataType::Struct(
-                    vec![
-                        Field::new("key_new", DataType::Utf8, false),
-                        Field::new("value_values", DataType::Utf8, false),
-                    ]
-                    .into(),
-                ),
-                false,
-            )),
-            false,
-        );
-
-        assert_ne!(new_type, array.data_type().clone());
-
-        let new_array = cast(&array, &new_type.clone()).unwrap();
-        assert_eq!(new_type, new_array.data_type().clone());
-        let map_array = new_array.as_map();
-
-        assert_ne!(new_type, array.data_type().clone());
-        assert_eq!(new_type, map_array.data_type().clone());
-
-        let key_string = map_array
-            .keys()
-            .as_any()
-            .downcast_ref::<StringArray>()
-            .unwrap()
-            .into_iter()
-            .flatten()
-            .collect::<Vec<_>>();
-        assert_eq!(&key_string, &vec!["0", "1"]);
-
-        let values_string_array = cast(map_array.values(), 
&DataType::Utf8).unwrap();
-        let values_string = values_string_array
-            .as_any()
-            .downcast_ref::<StringArray>()
-            .unwrap()
-            .into_iter()
-            .flatten()
-            .collect::<Vec<_>>();
-        assert_eq!(&values_string, &vec!["test_val_1", "test_val_2"]);
-
-        assert_eq!(
-            map_array.nulls(),
-            Some(&NullBuffer::from(vec![true, true, false]))
-        );
-    }
-
-    #[test]
-    fn test_cast_map_contained_values() {
-        let string_builder = StringBuilder::new();
-        let value_builder = Int8Builder::new();
-        let mut builder = MapBuilder::new(None, string_builder, value_builder);
-
-        builder.keys().append_value("0");
-        builder.values().append_value(44);
-        builder.append(true).unwrap();
-        builder.keys().append_value("1");
-        builder.values().append_value(22);
-        builder.append(true).unwrap();
-
-        let array = builder.finish();
-
-        let new_type = DataType::Map(
-            Arc::new(Field::new(
-                Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
-                DataType::Struct(
-                    vec![
-                        Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, 
DataType::Utf8, false),
-                        Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, 
DataType::Utf8, false),
-                    ]
-                    .into(),
-                ),
-                false,
-            )),
-            false,
-        );
-
-        let new_array = cast(&array, &new_type.clone()).unwrap();
-        assert_eq!(new_type, new_array.data_type().clone());
-        let map_array = new_array.as_map();
-
-        assert_ne!(new_type, array.data_type().clone());
-        assert_eq!(new_type, map_array.data_type().clone());
-
-        let key_string = map_array
-            .keys()
-            .as_any()
-            .downcast_ref::<StringArray>()
-            .unwrap()
-            .into_iter()
-            .flatten()
-            .collect::<Vec<_>>();
-        assert_eq!(&key_string, &vec!["0", "1"]);
-
-        let values_string_array = cast(map_array.values(), 
&DataType::Utf8).unwrap();
-        let values_string = values_string_array
-            .as_any()
-            .downcast_ref::<StringArray>()
-            .unwrap()
-            .into_iter()
-            .flatten()
-            .collect::<Vec<_>>();
-        assert_eq!(&values_string, &vec!["44", "22"]);
-    }
-
     #[test]
     fn test_utf8_cast_offsets() {
         // test if offset of the array is taken into account during cast
diff --git a/arrow-cast/tests/cast/map.rs b/arrow-cast/tests/cast/map.rs
new file mode 100644
index 0000000000..14aa977d45
--- /dev/null
+++ b/arrow-cast/tests/cast/map.rs
@@ -0,0 +1,248 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::sync::Arc;
+
+use arrow_array::builder::{Int8Builder, MapBuilder, MapFieldNames, 
StringBuilder};
+use arrow_array::cast::AsArray;
+use arrow_array::{Array, IntervalDayTimeArray, StringArray};
+use arrow_buffer::{IntervalDayTime, NullBuffer};
+use arrow_cast::{can_cast_types, cast};
+use arrow_schema::{ArrowError, DataType, Field, TimeUnit};
+
+#[test]
+fn test_cast_map_dont_allow_change_of_order() {
+    let string_builder = StringBuilder::new();
+    let value_builder = StringBuilder::new();
+    let mut builder = MapBuilder::new(None, string_builder, value_builder);
+
+    builder.keys().append_value("0");
+    builder.values().append_value("test_val_1");
+    builder.append(true).unwrap();
+    builder.keys().append_value("1");
+    builder.values().append_value("test_val_2");
+    builder.append(true).unwrap();
+
+    // map builder returns unsorted map by default
+    let array = builder.finish();
+
+    let new_ordered = true;
+    let new_type = DataType::Map(
+        Arc::new(Field::new(
+            Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
+            DataType::Struct(
+                vec![
+                    Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, 
DataType::Utf8, false),
+                    Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, 
DataType::Utf8, false),
+                ]
+                .into(),
+            ),
+            false,
+        )),
+        new_ordered,
+    );
+
+    let new_array_result = cast(&array, &new_type);
+    assert!(!can_cast_types(array.data_type(), &new_type));
+    let Err(ArrowError::CastError(t)) = new_array_result else {
+        panic!();
+    };
+    assert_eq!(
+        t,
+        r#"Casting from Map("entries": non-null Struct("key": non-null Utf8, 
"value": Utf8), unsorted) to Map("entries": non-null Struct("key": non-null 
Utf8, "value": non-null Utf8), sorted) not supported"#
+    );
+}
+
+#[test]
+fn test_cast_map_dont_allow_when_container_cant_cast() {
+    let string_builder = StringBuilder::new();
+    let value_builder = IntervalDayTimeArray::builder(2);
+    let mut builder = MapBuilder::new(None, string_builder, value_builder);
+
+    builder.keys().append_value("0");
+    builder.values().append_value(IntervalDayTime::new(1, 1));
+    builder.append(true).unwrap();
+    builder.keys().append_value("1");
+    builder.values().append_value(IntervalDayTime::new(2, 2));
+    builder.append(true).unwrap();
+
+    // map builder returns unsorted map by default
+    let array = builder.finish();
+
+    let new_ordered = true;
+    let new_type = DataType::Map(
+        Arc::new(Field::new(
+            Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
+            DataType::Struct(
+                vec![
+                    Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, 
DataType::Utf8, false),
+                    Field::new(
+                        Field::MAP_VALUE_FIELD_DEFAULT_NAME,
+                        DataType::Duration(TimeUnit::Second),
+                        false,
+                    ),
+                ]
+                .into(),
+            ),
+            false,
+        )),
+        new_ordered,
+    );
+
+    let new_array_result = cast(&array, &new_type);
+    assert!(!can_cast_types(array.data_type(), &new_type));
+    let Err(ArrowError::CastError(t)) = new_array_result else {
+        panic!();
+    };
+    assert_eq!(
+        t,
+        r#"Casting from Map("entries": non-null Struct("key": non-null Utf8, 
"value": Interval(DayTime)), unsorted) to Map("entries": non-null Struct("key": 
non-null Utf8, "value": non-null Duration(s)), sorted) not supported"#
+    );
+}
+
+#[test]
+fn test_cast_map_field_names() {
+    let string_builder = StringBuilder::new();
+    let value_builder = StringBuilder::new();
+    let mut builder = MapBuilder::new(
+        Some(MapFieldNames {
+            // Explicitly writing the name so it will be apparent from what 
names to what names are we converting to
+            entry: Field::MAP_ENTRIES_FIELD_DEFAULT_NAME.to_string(),
+            key: Field::MAP_KEY_FIELD_DEFAULT_NAME.to_string(),
+            value: Field::MAP_VALUE_FIELD_DEFAULT_NAME.to_string(),
+        }),
+        string_builder,
+        value_builder,
+    );
+
+    builder.keys().append_value("0");
+    builder.values().append_value("test_val_1");
+    builder.append(true).unwrap();
+    builder.keys().append_value("1");
+    builder.values().append_value("test_val_2");
+    builder.append(true).unwrap();
+    builder.append(false).unwrap();
+
+    let array = builder.finish();
+
+    let new_type = DataType::Map(
+        Arc::new(Field::new(
+            "entries_new",
+            DataType::Struct(
+                vec![
+                    Field::new("key_new", DataType::Utf8, false),
+                    Field::new("value_values", DataType::Utf8, false),
+                ]
+                .into(),
+            ),
+            false,
+        )),
+        false,
+    );
+
+    assert_ne!(new_type, array.data_type().clone());
+
+    let new_array = cast(&array, &new_type).unwrap();
+    assert_eq!(new_type, new_array.data_type().clone());
+    let map_array = new_array.as_map();
+
+    assert_ne!(new_type, array.data_type().clone());
+    assert_eq!(new_type, map_array.data_type().clone());
+
+    let key_string = map_array
+        .keys()
+        .as_any()
+        .downcast_ref::<StringArray>()
+        .unwrap()
+        .into_iter()
+        .flatten()
+        .collect::<Vec<_>>();
+    assert_eq!(&key_string, &vec!["0", "1"]);
+
+    let values_string_array = cast(map_array.values(), 
&DataType::Utf8).unwrap();
+    let values_string = values_string_array
+        .as_any()
+        .downcast_ref::<StringArray>()
+        .unwrap()
+        .into_iter()
+        .flatten()
+        .collect::<Vec<_>>();
+    assert_eq!(&values_string, &vec!["test_val_1", "test_val_2"]);
+
+    assert_eq!(
+        map_array.nulls(),
+        Some(&NullBuffer::from(vec![true, true, false]))
+    );
+}
+
+#[test]
+fn test_cast_map_contained_values() {
+    let string_builder = StringBuilder::new();
+    let value_builder = Int8Builder::new();
+    let mut builder = MapBuilder::new(None, string_builder, value_builder);
+
+    builder.keys().append_value("0");
+    builder.values().append_value(44);
+    builder.append(true).unwrap();
+    builder.keys().append_value("1");
+    builder.values().append_value(22);
+    builder.append(true).unwrap();
+
+    let array = builder.finish();
+
+    let new_type = DataType::Map(
+        Arc::new(Field::new(
+            Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
+            DataType::Struct(
+                vec![
+                    Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, 
DataType::Utf8, false),
+                    Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, 
DataType::Utf8, false),
+                ]
+                .into(),
+            ),
+            false,
+        )),
+        false,
+    );
+
+    let new_array = cast(&array, &new_type).unwrap();
+    assert_eq!(new_type, new_array.data_type().clone());
+    let map_array = new_array.as_map();
+
+    assert_ne!(new_type, array.data_type().clone());
+    assert_eq!(new_type, map_array.data_type().clone());
+
+    let key_string = map_array
+        .keys()
+        .as_any()
+        .downcast_ref::<StringArray>()
+        .unwrap()
+        .into_iter()
+        .flatten()
+        .collect::<Vec<_>>();
+    assert_eq!(&key_string, &vec!["0", "1"]);
+
+    let values_string_array = cast(map_array.values(), 
&DataType::Utf8).unwrap();
+    let values_string = values_string_array
+        .as_any()
+        .downcast_ref::<StringArray>()
+        .unwrap()
+        .into_iter()
+        .flatten()
+        .collect::<Vec<_>>();
+    assert_eq!(&values_string, &vec!["44", "22"]);
+}
diff --git a/arrow-cast/tests/cast/mod.rs b/arrow-cast/tests/cast/mod.rs
new file mode 100644
index 0000000000..1b8247adf6
--- /dev/null
+++ b/arrow-cast/tests/cast/mod.rs
@@ -0,0 +1,18 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+mod map;

Reply via email to