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

alamb 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 c258274aef test(parquet): move nested writer roundtrips —— Part II 
(#11183)
c258274aef is described below

commit c258274aef28810584f1ef356fe145348a075d59
Author: Phoenix <[email protected]>
AuthorDate: Sat Sep 26 00:53:27 2026 +0800

    test(parquet): move nested writer roundtrips —— Part II (#11183)
    
    # Which issue does this PR close?
    
    Part of apache/arrow-rs#10540.
    
    # Stack base
    
    This draft PR targets `apache/arrow-rs:main`. It follows the first
    stage, which was merged in apache/arrow-rs#11128. The branch now
    contains only the three stage-II commits on top of `main`, so this PR's
    diff is the stage-II change.
    
    # Rationale for this change
    
    Keep the next group of writer roundtrip tests together in the
    integration suite, following the shared harness and scalar tests in
    #11128.
    
    # What changes are included in this PR?
    
    Move nested list/map/struct and dictionary roundtrip tests from the
    writer unit-test module to `parquet/tests/arrow_writer/roundtrip.rs`.
    The three commits preserve the existing assertions and test
    configurations.
    
    # Are these changes tested?
    
    - `cargo test --locked -p parquet --test arrow_writer` — 88 passed.
    - `cargo test --locked -p parquet --lib -- arrow::arrow_writer::tests` —
    80 passed.
    - `cargo fmt --all -- --check`
    - `git diff --check upstream/main..HEAD`
    
    # Are there any user-facing changes?
    
    No. This is a test-only move.
---
 parquet/src/arrow/arrow_writer/mod.rs   | 921 +-----------------------------
 parquet/tests/arrow_writer/roundtrip.rs | 972 +++++++++++++++++++++++++++++++-
 2 files changed, 960 insertions(+), 933 deletions(-)

diff --git a/parquet/src/arrow/arrow_writer/mod.rs 
b/parquet/src/arrow/arrow_writer/mod.rs
index 0c61143948..6b5f29d0f1 100644
--- a/parquet/src/arrow/arrow_writer/mod.rs
+++ b/parquet/src/arrow/arrow_writer/mod.rs
@@ -2103,16 +2103,14 @@ mod tests {
     use crate::file::reader::SerializedPageReader;
     use crate::parquet_thrift::{ReadThrift, ThriftSliceInputProtocol};
     use crate::schema::types::ColumnPath;
-    use arrow::datatypes::ToByteSlice;
     use arrow::datatypes::{DataType, Schema};
     use arrow::error::Result as ArrowResult;
     use arrow::util::data_gen::create_random_array;
     use arrow::util::pretty::pretty_format_batches;
     use arrow::{array::*, buffer::Buffer};
-    use arrow_buffer::{IntervalDayTime, IntervalMonthDayNano, NullBuffer, 
OffsetBuffer, i256};
+    use arrow_buffer::{IntervalDayTime, IntervalMonthDayNano, NullBuffer, 
OffsetBuffer};
     use arrow_schema::Fields;
     use half::f16;
-    use num_traits::{FromPrimitive, ToPrimitive};
     use tempfile::tempfile;
 
     use crate::basic::{Encoding, EncodingMask};
@@ -2424,218 +2422,6 @@ mod tests {
             .run();
     }
 
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_list() {
-        // define schema
-        let schema = Schema::new(vec![Field::new(
-            "a",
-            DataType::List(Arc::new(Field::new_list_field(DataType::Int32, 
false))),
-            true,
-        )]);
-
-        // create some data
-        let a_values = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
-
-        // Construct a buffer for value offsets, for the nested array:
-        //  [[1], [2, 3], null, [4, 5, 6], [7, 8, 9, 10]]
-        let a_value_offsets = arrow::buffer::Buffer::from([0, 1, 3, 3, 6, 
10].to_byte_slice());
-
-        // Construct a list array from the above two
-        let a_list_data = 
ArrayData::builder(DataType::List(Arc::new(Field::new_list_field(
-            DataType::Int32,
-            false,
-        ))))
-        .len(5)
-        .add_buffer(a_value_offsets)
-        .add_child_data(a_values.into_data())
-        .null_bit_buffer(Some(Buffer::from([0b00011011])))
-        .build()
-        .unwrap();
-        let a = ListArray::from(a_list_data);
-        assert_eq!(a.null_count(), 1);
-
-        RoundTripTest::new(Arc::new(a))
-            .with_schema(Arc::new(schema))
-            .run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_list_non_null() {
-        // define schema
-        let schema = Schema::new(vec![Field::new(
-            "a",
-            DataType::List(Arc::new(Field::new_list_field(DataType::Int32, 
false))),
-            false,
-        )]);
-
-        // create some data
-        let a_values = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
-
-        // Construct a buffer for value offsets, for the nested array:
-        //  [[1], [2, 3], [], [4, 5, 6], [7, 8, 9, 10]]
-        let a_value_offsets = arrow::buffer::Buffer::from([0, 1, 3, 3, 6, 
10].to_byte_slice());
-
-        // Construct a list array from the above two
-        let a_list_data = 
ArrayData::builder(DataType::List(Arc::new(Field::new_list_field(
-            DataType::Int32,
-            false,
-        ))))
-        .len(5)
-        .add_buffer(a_value_offsets)
-        .add_child_data(a_values.into_data())
-        .build()
-        .unwrap();
-        let a = ListArray::from(a_list_data);
-        assert_eq!(a.null_count(), 0);
-
-        RoundTripTest::new(Arc::new(a))
-            .with_schema(Arc::new(schema))
-            .run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_list_view() {
-        let list_field = Arc::new(Field::new_list_field(DataType::Int32, 
false));
-        let schema = Schema::new(vec![Field::new(
-            "a",
-            DataType::ListView(list_field.clone()),
-            true,
-        )]);
-
-        //  [[1], [2, 3], null, [4, 5, 6], [7, 8, 9, 10]]
-        let a = ListViewArray::new(
-            list_field,
-            vec![0, 1, 0, 3, 6].into(),
-            vec![1, 2, 0, 3, 4].into(),
-            Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10])),
-            Some(vec![true, true, false, true, true].into()),
-        );
-        assert_eq!(a.null_count(), 1);
-
-        RoundTripTest::new(Arc::new(a))
-            .with_schema(Arc::new(schema))
-            .run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_list_view_non_null() {
-        let list_field = Arc::new(Field::new_list_field(DataType::Int32, 
false));
-        let schema = Schema::new(vec![Field::new(
-            "a",
-            DataType::ListView(list_field.clone()),
-            false,
-        )]);
-
-        //  [[1], [2, 3], [], [4, 5, 6], [7, 8, 9, 10]]
-        let a = ListViewArray::new(
-            list_field,
-            vec![0, 1, 0, 3, 6].into(),
-            vec![1, 2, 0, 3, 4].into(),
-            Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10])),
-            None,
-        );
-        assert_eq!(a.null_count(), 0);
-
-        RoundTripTest::new(Arc::new(a))
-            .with_schema(Arc::new(schema))
-            .run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_list_view_out_of_order() {
-        let list_field = Arc::new(Field::new_list_field(DataType::Int32, 
false));
-        let schema = Schema::new(vec![Field::new(
-            "a",
-            DataType::ListView(list_field.clone()),
-            false,
-        )]);
-
-        // [[1], [2, 3], [], [7, 8, 9, 10], [4, 5, 6]] - out of order offsets
-        let a = ListViewArray::new(
-            list_field,
-            vec![0, 1, 0, 6, 3].into(),
-            vec![1, 2, 0, 4, 3].into(),
-            Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10])),
-            None,
-        );
-        assert_eq!(a.null_count(), 0);
-
-        RoundTripTest::new(Arc::new(a))
-            .with_schema(Arc::new(schema))
-            .run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_large_list_view() {
-        let list_field = Arc::new(Field::new_list_field(DataType::Int32, 
false));
-        let schema = Schema::new(vec![Field::new(
-            "a",
-            DataType::LargeListView(list_field.clone()),
-            true,
-        )]);
-
-        //  [[1], [2, 3], null, [4, 5, 6], [7, 8, 9, 10]]
-        let a = LargeListViewArray::new(
-            list_field,
-            vec![0i64, 1, 0, 3, 6].into(),
-            vec![1i64, 2, 0, 3, 4].into(),
-            Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10])),
-            Some(vec![true, true, false, true, true].into()),
-        );
-        assert_eq!(a.null_count(), 1);
-
-        RoundTripTest::new(Arc::new(a))
-            .with_schema(Arc::new(schema))
-            .run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_list_view_with_struct() {
-        // Test ListView containing Struct: ListView<Struct<Int32, Utf8>>
-        let struct_fields = Fields::from(vec![
-            Field::new("id", DataType::Int32, false),
-            Field::new("name", DataType::Utf8, false),
-        ]);
-        let struct_type = DataType::Struct(struct_fields.clone());
-        let list_field = Arc::new(Field::new("item", struct_type.clone(), 
false));
-
-        let schema = Schema::new(vec![Field::new(
-            "a",
-            DataType::ListView(list_field.clone()),
-            true,
-        )]);
-
-        // Create struct values
-        let id_array = Int32Array::from(vec![1, 2, 3, 4, 5]);
-        let name_array = StringArray::from(vec!["a", "b", "c", "d", "e"]);
-        let struct_array = StructArray::new(
-            struct_fields,
-            vec![Arc::new(id_array), Arc::new(name_array)],
-            None,
-        );
-
-        // Create ListView: [{1, "a"}, {2, "b"}], null, [{3, "c"}, {4, "d"}, 
{5, "e"}]
-        let list_view = ListViewArray::new(
-            list_field,
-            vec![0, 2, 2].into(), // offsets
-            vec![2, 0, 3].into(), // sizes
-            Arc::new(struct_array),
-            Some(vec![true, false, true].into()),
-        );
-        assert_eq!(list_view.null_count(), 1);
-
-        RoundTripTest::new(Arc::new(list_view))
-            .with_schema(Arc::new(schema))
-            .run();
-    }
-
     #[test]
     #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_binary() {
@@ -2704,32 +2490,6 @@ mod tests {
             .run();
     }
 
-    /// Test round-trip of Dictionary<UInt32, Utf8View> and
-    /// Dictionary<UInt32, BinaryView> typed columns.
-    #[test]
-    fn arrow_writer_string_view_dictionary() {
-        let raw_string_values = vec!["a", "b", "large payload over 12 bytes"];
-        let raw_binary_values = vec![
-            b"a".to_vec(),
-            b"b".to_vec(),
-            b"large payload over 12 bytes".to_vec(),
-        ];
-
-        let keys = UInt32Array::from(vec![Some(0), None, Some(2), Some(1), 
None]);
-
-        let string_view_values = 
Arc::new(StringViewArray::from(raw_string_values));
-        let string_dict: ArrayRef = Arc::new(
-            DictionaryArray::<UInt32Type>::try_new(keys.clone(), 
string_view_values).unwrap(),
-        );
-
-        let binary_view_values = 
Arc::new(BinaryViewArray::from_iter_values(raw_binary_values));
-        let binary_dict: ArrayRef =
-            Arc::new(DictionaryArray::<UInt32Type>::try_new(keys, 
binary_view_values).unwrap());
-
-        RoundTripTest::new(string_dict).run();
-        RoundTripTest::new(binary_dict).run();
-    }
-
     fn get_decimal_batch(precision: u8, scale: i8) -> RecordBatch {
         let decimal_field = Field::new("a", DataType::Decimal128(precision, 
scale), false);
         let schema = Schema::new(vec![decimal_field]);
@@ -2757,390 +2517,6 @@ mod tests {
         roundtrip(batch_fixed_len_byte_array_decimal, Some(SMALL_SIZE / 2));
     }
 
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_complex() {
-        // define schema
-        let struct_field_d = Arc::new(Field::new("d", DataType::Float64, 
true));
-        let struct_field_f = Arc::new(Field::new("f", DataType::Float32, 
true));
-        let struct_field_g = Arc::new(Field::new_list(
-            "g",
-            Field::new_list_field(DataType::Int16, true),
-            false,
-        ));
-        let struct_field_h = Arc::new(Field::new_list(
-            "h",
-            Field::new_list_field(DataType::Int16, false),
-            true,
-        ));
-        let struct_field_e = Arc::new(Field::new_struct(
-            "e",
-            vec![
-                struct_field_f.clone(),
-                struct_field_g.clone(),
-                struct_field_h.clone(),
-            ],
-            false,
-        ));
-        let schema = Schema::new(vec![
-            Field::new("a", DataType::Int32, false),
-            Field::new("b", DataType::Int32, true),
-            Field::new_struct(
-                "c",
-                vec![struct_field_d.clone(), struct_field_e.clone()],
-                false,
-            ),
-        ]);
-
-        // create some data
-        let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
-        let b = Int32Array::from(vec![Some(1), None, None, Some(4), Some(5)]);
-        let d = Float64Array::from(vec![None, None, None, Some(1.0), None]);
-        let f = Float32Array::from(vec![Some(0.0), None, Some(333.3), None, 
Some(5.25)]);
-
-        let g_value = Int16Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
-
-        // Construct a buffer for value offsets, for the nested array:
-        //  [[1], [2, 3], [], [4, 5, 6], [7, 8, 9, 10]]
-        let g_value_offsets = arrow::buffer::Buffer::from([0, 1, 3, 3, 6, 
10].to_byte_slice());
-
-        // Construct a list array from the above two
-        let g_list_data = 
ArrayData::builder(struct_field_g.data_type().clone())
-            .len(5)
-            .add_buffer(g_value_offsets.clone())
-            .add_child_data(g_value.to_data())
-            .build()
-            .unwrap();
-        let g = ListArray::from(g_list_data);
-        // The difference between g and h is that h has a null bitmap
-        let h_list_data = 
ArrayData::builder(struct_field_h.data_type().clone())
-            .len(5)
-            .add_buffer(g_value_offsets)
-            .add_child_data(g_value.to_data())
-            .null_bit_buffer(Some(Buffer::from([0b00011011])))
-            .build()
-            .unwrap();
-        let h = ListArray::from(h_list_data);
-
-        let e = StructArray::from(vec![
-            (struct_field_f, Arc::new(f) as ArrayRef),
-            (struct_field_g, Arc::new(g) as ArrayRef),
-            (struct_field_h, Arc::new(h) as ArrayRef),
-        ]);
-
-        let c = StructArray::from(vec![
-            (struct_field_d, Arc::new(d) as ArrayRef),
-            (struct_field_e, Arc::new(e) as ArrayRef),
-        ]);
-
-        // build a record batch
-        let batch = RecordBatch::try_new(
-            Arc::new(schema),
-            vec![Arc::new(a), Arc::new(b), Arc::new(c)],
-        )
-        .unwrap();
-
-        roundtrip(batch.clone(), Some(SMALL_SIZE / 2));
-        roundtrip(batch, Some(SMALL_SIZE / 3));
-    }
-
-    #[test]
-    fn arrow_writer_complex_mixed() {
-        // This test was added while investigating 
https://github.com/apache/arrow-rs/issues/244.
-        // It was subsequently fixed while investigating 
https://github.com/apache/arrow-rs/issues/245.
-
-        // define schema
-        let offset_field = Arc::new(Field::new("offset", DataType::Int32, 
false));
-        let partition_field = Arc::new(Field::new("partition", 
DataType::Int64, true));
-        let topic_field = Arc::new(Field::new("topic", DataType::Utf8, true));
-        let schema = Schema::new(vec![Field::new(
-            "some_nested_object",
-            DataType::Struct(Fields::from(vec![
-                offset_field.clone(),
-                partition_field.clone(),
-                topic_field.clone(),
-            ])),
-            false,
-        )]);
-
-        // create some data
-        let offset = Int32Array::from(vec![1, 2, 3, 4, 5]);
-        let partition = Int64Array::from(vec![Some(1), None, None, Some(4), 
Some(5)]);
-        let topic = StringArray::from(vec![Some("A"), None, Some("A"), 
Some(""), None]);
-
-        let some_nested_object = StructArray::from(vec![
-            (offset_field, Arc::new(offset) as ArrayRef),
-            (partition_field, Arc::new(partition) as ArrayRef),
-            (topic_field, Arc::new(topic) as ArrayRef),
-        ]);
-
-        // build a record batch
-        let batch =
-            RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(some_nested_object)]).unwrap();
-
-        roundtrip(batch, Some(SMALL_SIZE / 2));
-    }
-
-    #[test]
-    fn arrow_writer_map() {
-        // Note: we are using the JSON Arrow reader for brevity
-        let json_content = r#"
-        {"stocks":{"long": "$AAA", "short": "$BBB"}}
-        {"stocks":{"long": null, "long": "$CCC", "short": null}}
-        {"stocks":{"hedged": "$YYY", "long": null, "short": "$D"}}
-        "#;
-        let entries_struct_type = DataType::Struct(Fields::from(vec![
-            Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, DataType::Utf8, 
false),
-            Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, DataType::Utf8, 
true),
-        ]));
-        let stocks_field = Field::new(
-            "stocks",
-            DataType::Map(
-                Arc::new(Field::new(
-                    Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
-                    entries_struct_type,
-                    false,
-                )),
-                false,
-            ),
-            true,
-        );
-        let schema = Arc::new(Schema::new(vec![stocks_field]));
-        let builder = 
arrow::json::ReaderBuilder::new(schema).with_batch_size(64);
-        let mut reader = 
builder.build(std::io::Cursor::new(json_content)).unwrap();
-
-        let batch = reader.next().unwrap().unwrap();
-        roundtrip(batch, None);
-    }
-
-    #[test]
-    fn arrow_writer_2_level_struct() {
-        // tests writing <struct<struct<primitive>>
-        let field_c = Field::new("c", DataType::Int32, true);
-        let field_b = Field::new("b", DataType::Struct(vec![field_c].into()), 
true);
-        let type_a = DataType::Struct(vec![field_b.clone()].into());
-        let field_a = Field::new("a", type_a, true);
-        let schema = Schema::new(vec![field_a.clone()]);
-
-        // create data
-        let c = Int32Array::from(vec![Some(1), None, Some(3), None, None, 
Some(6)]);
-        let b_data = ArrayDataBuilder::new(field_b.data_type().clone())
-            .len(6)
-            .null_bit_buffer(Some(Buffer::from([0b00100111])))
-            .add_child_data(c.into_data())
-            .build()
-            .unwrap();
-        let b = StructArray::from(b_data);
-        let a_data = ArrayDataBuilder::new(field_a.data_type().clone())
-            .len(6)
-            .null_bit_buffer(Some(Buffer::from([0b00101111])))
-            .add_child_data(b.into_data())
-            .build()
-            .unwrap();
-        let a = StructArray::from(a_data);
-
-        assert_eq!(a.null_count(), 1);
-        assert_eq!(a.column(0).null_count(), 2);
-
-        // build a racord batch
-        let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(a)]).unwrap();
-
-        roundtrip(batch, Some(SMALL_SIZE / 2));
-    }
-
-    #[test]
-    fn arrow_writer_2_level_struct_non_null() {
-        // tests writing <struct<struct<primitive>>
-        let field_c = Field::new("c", DataType::Int32, false);
-        let type_b = DataType::Struct(vec![field_c].into());
-        let field_b = Field::new("b", type_b.clone(), false);
-        let type_a = DataType::Struct(vec![field_b].into());
-        let field_a = Field::new("a", type_a.clone(), false);
-        let schema = Schema::new(vec![field_a]);
-
-        // create data
-        let c = Int32Array::from(vec![1, 2, 3, 4, 5, 6]);
-        let b_data = ArrayDataBuilder::new(type_b)
-            .len(6)
-            .add_child_data(c.into_data())
-            .build()
-            .unwrap();
-        let b = StructArray::from(b_data);
-        let a_data = ArrayDataBuilder::new(type_a)
-            .len(6)
-            .add_child_data(b.into_data())
-            .build()
-            .unwrap();
-        let a = StructArray::from(a_data);
-
-        assert_eq!(a.null_count(), 0);
-        assert_eq!(a.column(0).null_count(), 0);
-
-        // build a racord batch
-        let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(a)]).unwrap();
-
-        roundtrip(batch, Some(SMALL_SIZE / 2));
-    }
-
-    #[test]
-    fn arrow_writer_2_level_struct_mixed_null() {
-        // tests writing <struct<struct<primitive>>
-        let field_c = Field::new("c", DataType::Int32, false);
-        let type_b = DataType::Struct(vec![field_c].into());
-        let field_b = Field::new("b", type_b.clone(), true);
-        let type_a = DataType::Struct(vec![field_b].into());
-        let field_a = Field::new("a", type_a.clone(), false);
-        let schema = Schema::new(vec![field_a]);
-
-        // create data
-        let c = Int32Array::from(vec![1, 2, 3, 4, 5, 6]);
-        let b_data = ArrayDataBuilder::new(type_b)
-            .len(6)
-            .null_bit_buffer(Some(Buffer::from([0b00100111])))
-            .add_child_data(c.into_data())
-            .build()
-            .unwrap();
-        let b = StructArray::from(b_data);
-        // a intentionally has no null buffer, to test that this is handled 
correctly
-        let a_data = ArrayDataBuilder::new(type_a)
-            .len(6)
-            .add_child_data(b.into_data())
-            .build()
-            .unwrap();
-        let a = StructArray::from(a_data);
-
-        assert_eq!(a.null_count(), 0);
-        assert_eq!(a.column(0).null_count(), 2);
-
-        // build a racord batch
-        let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(a)]).unwrap();
-
-        roundtrip(batch, Some(SMALL_SIZE / 2));
-    }
-
-    #[test]
-    fn arrow_writer_2_level_struct_mixed_null_2() {
-        // tests writing <struct<struct<primitive>>, where the primitive 
columns are non-null.
-        let field_c = Field::new("c", DataType::Int32, false);
-        let field_d = Field::new("d", DataType::FixedSizeBinary(4), false);
-        let field_e = Field::new(
-            "e",
-            DataType::Dictionary(Box::new(DataType::Int32), 
Box::new(DataType::Utf8)),
-            false,
-        );
-
-        let field_b = Field::new(
-            "b",
-            DataType::Struct(vec![field_c, field_d, field_e].into()),
-            false,
-        );
-        let type_a = DataType::Struct(vec![field_b.clone()].into());
-        let field_a = Field::new("a", type_a, true);
-        let schema = Schema::new(vec![field_a.clone()]);
-
-        // create data
-        let c = Int32Array::from_iter_values(0..6);
-        let d = FixedSizeBinaryArray::try_from_iter(
-            ["aaaa", "bbbb", "cccc", "dddd", "eeee", "ffff"].into_iter(),
-        )
-        .expect("four byte values");
-        let e = Int32DictionaryArray::from_iter(["one", "two", "three", 
"four", "five", "one"]);
-        let b_data = ArrayDataBuilder::new(field_b.data_type().clone())
-            .len(6)
-            .add_child_data(c.into_data())
-            .add_child_data(d.into_data())
-            .add_child_data(e.into_data())
-            .build()
-            .unwrap();
-        let b = StructArray::from(b_data);
-        let a_data = ArrayDataBuilder::new(field_a.data_type().clone())
-            .len(6)
-            .null_bit_buffer(Some(Buffer::from([0b00100101])))
-            .add_child_data(b.into_data())
-            .build()
-            .unwrap();
-        let a = StructArray::from(a_data);
-
-        assert_eq!(a.null_count(), 3);
-        assert_eq!(a.column(0).null_count(), 0);
-
-        // build a record batch
-        let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(a)]).unwrap();
-
-        roundtrip(batch, Some(SMALL_SIZE / 2));
-    }
-
-    #[test]
-    fn test_fixed_size_binary_in_dict() {
-        fn test_fixed_size_binary_in_dict_inner<K>()
-        where
-            K: ArrowDictionaryKeyType,
-            K::Native: FromPrimitive + ToPrimitive + TryFrom<u8>,
-            <<K as arrow_array::ArrowPrimitiveType>::Native as 
TryFrom<u8>>::Error: std::fmt::Debug,
-        {
-            let field = Field::new(
-                "a",
-                DataType::Dictionary(
-                    Box::new(K::DATA_TYPE),
-                    Box::new(DataType::FixedSizeBinary(4)),
-                ),
-                false,
-            );
-            let schema = Schema::new(vec![field]);
-
-            let keys: Vec<K::Native> = vec![
-                K::Native::try_from(0u8).unwrap(),
-                K::Native::try_from(0u8).unwrap(),
-                K::Native::try_from(1u8).unwrap(),
-            ];
-            let keys = PrimitiveArray::<K>::from_iter_values(keys);
-            let values = FixedSizeBinaryArray::try_from_iter(
-                vec![vec![0, 0, 0, 0], vec![1, 1, 1, 1]].into_iter(),
-            )
-            .unwrap();
-
-            let data = DictionaryArray::<K>::new(keys, Arc::new(values));
-            let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(data)]).unwrap();
-            roundtrip(batch, None);
-        }
-
-        test_fixed_size_binary_in_dict_inner::<UInt8Type>();
-        test_fixed_size_binary_in_dict_inner::<UInt16Type>();
-        test_fixed_size_binary_in_dict_inner::<UInt32Type>();
-        test_fixed_size_binary_in_dict_inner::<UInt16Type>();
-        test_fixed_size_binary_in_dict_inner::<Int8Type>();
-        test_fixed_size_binary_in_dict_inner::<Int16Type>();
-        test_fixed_size_binary_in_dict_inner::<Int32Type>();
-        test_fixed_size_binary_in_dict_inner::<Int64Type>();
-    }
-
-    #[test]
-    fn test_empty_dict() {
-        let struct_fields = Fields::from(vec![Field::new(
-            "dict",
-            DataType::Dictionary(Box::new(DataType::Int32), 
Box::new(DataType::Utf8)),
-            false,
-        )]);
-
-        let schema = Schema::new(vec![Field::new_struct(
-            "struct",
-            struct_fields.clone(),
-            true,
-        )]);
-        let dictionary = Arc::new(DictionaryArray::new(
-            Int32Array::new_null(5),
-            Arc::new(StringArray::new_null(0)),
-        ));
-
-        let s = StructArray::new(
-            struct_fields,
-            vec![dictionary],
-            Some(NullBuffer::new_null(5)),
-        );
-
-        let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(s)]).unwrap();
-        roundtrip(batch, None);
-    }
     #[test]
     fn arrow_writer_page_size() {
         let schema = Arc::new(Schema::new(vec![Field::new("col", 
DataType::Utf8, false)]));
@@ -3738,140 +3114,6 @@ mod tests {
         check_bloom_filter(files, "col".to_string(), optional_raw_values, 
vec![""]);
     }
 
-    #[test]
-    fn null_list_single_column() {
-        let null_field = Field::new_list_field(DataType::Null, true);
-        let list_field = Field::new("emptylist", 
DataType::List(Arc::new(null_field)), true);
-
-        let schema = Schema::new(vec![list_field]);
-
-        // Build [[], null, [null, null]]
-        let a_values = NullArray::new(2);
-        let a_value_offsets = arrow::buffer::Buffer::from([0, 0, 0, 
2].to_byte_slice());
-        let a_list_data = 
ArrayData::builder(DataType::List(Arc::new(Field::new_list_field(
-            DataType::Null,
-            true,
-        ))))
-        .len(3)
-        .add_buffer(a_value_offsets)
-        .null_bit_buffer(Some(Buffer::from([0b00000101])))
-        .add_child_data(a_values.into_data())
-        .build()
-        .unwrap();
-
-        let a = ListArray::from(a_list_data);
-
-        assert!(a.is_valid(0));
-        assert!(!a.is_valid(1));
-        assert!(a.is_valid(2));
-
-        assert_eq!(a.value(0).len(), 0);
-        assert_eq!(a.value(2).len(), 2);
-        assert_eq!(a.value(2).logical_nulls().unwrap().null_count(), 2);
-
-        let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(a)]).unwrap();
-        roundtrip(batch, None);
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn list_single_column() {
-        let a_values = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
-        let a_value_offsets = arrow::buffer::Buffer::from([0, 1, 3, 3, 6, 
10].to_byte_slice());
-        let a_list_data = 
ArrayData::builder(DataType::List(Arc::new(Field::new_list_field(
-            DataType::Int32,
-            false,
-        ))))
-        .len(5)
-        .add_buffer(a_value_offsets)
-        .null_bit_buffer(Some(Buffer::from([0b00011011])))
-        .add_child_data(a_values.into_data())
-        .build()
-        .unwrap();
-
-        assert_eq!(a_list_data.null_count(), 1);
-
-        let a = ListArray::from(a_list_data);
-        let values = Arc::new(a);
-
-        RoundTripTest::new(values).run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn large_list_single_column() {
-        let a_values = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
-        let a_value_offsets = arrow::buffer::Buffer::from([0i64, 1, 3, 3, 6, 
10].to_byte_slice());
-        let a_list_data = 
ArrayData::builder(DataType::LargeList(Arc::new(Field::new(
-            "large_item",
-            DataType::Int32,
-            true,
-        ))))
-        .len(5)
-        .add_buffer(a_value_offsets)
-        .add_child_data(a_values.into_data())
-        .null_bit_buffer(Some(Buffer::from([0b00011011])))
-        .build()
-        .unwrap();
-
-        // I think this setup is incorrect because this should pass
-        assert_eq!(a_list_data.null_count(), 1);
-
-        let a = LargeListArray::from(a_list_data);
-        let values = Arc::new(a);
-
-        RoundTripTest::new(values).run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn list_nested_nulls() {
-        use arrow::datatypes::Int32Type;
-        let data = vec![
-            Some(vec![Some(1)]),
-            Some(vec![Some(2), Some(3)]),
-            None,
-            Some(vec![Some(4), Some(5), None]),
-            Some(vec![None]),
-            Some(vec![Some(6), Some(7)]),
-        ];
-
-        let list = ListArray::from_iter_primitive::<Int32Type, _, 
_>(data.clone());
-        RoundTripTest::new(Arc::new(list)).run();
-
-        let list = LargeListArray::from_iter_primitive::<Int32Type, _, 
_>(data);
-        RoundTripTest::new(Arc::new(list)).run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn list_utf8_view_selective_padding_roundtrip() {
-        let item = Arc::new(Field::new_list_field(DataType::Utf8View, true));
-        let mut builder = 
ListBuilder::new(StringViewBuilder::new()).with_field(item);
-        builder.values().append_value("a");
-        builder.values().append_null();
-        builder.append(true);
-        // The null parent list covers selective padding dropping values below
-        // the list definition level while preserving the preceding item null.
-        builder.append(false);
-        // The long string covers the non-inlined Utf8View buffer path.
-        builder.values().append_value("large payload over 12 bytes");
-        builder.append(true);
-
-        RoundTripTest::new(Arc::new(builder.finish())).run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn struct_single_column() {
-        let a_values = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
-        let struct_field_a = Arc::new(Field::new("f", DataType::Int32, false));
-        let s = StructArray::from(vec![(struct_field_a, Arc::new(a_values) as 
ArrayRef)]);
-
-        let values = Arc::new(s);
-        RoundTripTest::new(values).with_nullable(false).run();
-    }
-
     #[test]
     fn list_and_map_coerced_names() {
         // Create map and list with non-Parquet naming
@@ -3969,29 +3211,6 @@ mod tests {
         }
     }
 
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_string_dictionary() {
-        // define schema
-        #[expect(deprecated)]
-        let schema = Arc::new(Schema::new(vec![Field::new_dict(
-            "dictionary",
-            DataType::Dictionary(Box::new(DataType::Int32), 
Box::new(DataType::Utf8)),
-            true,
-            42,
-            true,
-        )]));
-
-        // create some data
-        let d: Int32DictionaryArray = [Some("alpha"), None, Some("beta"), 
Some("alpha")]
-            .iter()
-            .copied()
-            .collect();
-
-        // build a record batch
-        RoundTripTest::new(Arc::new(d)).with_schema(schema).run();
-    }
-
     #[test]
     fn arrow_writer_test_type_compatibility() {
         fn ensure_compatible_write<T1, T2>(array1: T1, array2: T2, 
expected_result: T1)
@@ -4223,144 +3442,6 @@ mod tests {
         );
     }
 
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_primitive_dictionary() {
-        // define schema
-        #[expect(deprecated)]
-        let schema = Arc::new(Schema::new(vec![Field::new_dict(
-            "dictionary",
-            DataType::Dictionary(Box::new(DataType::UInt8), 
Box::new(DataType::UInt32)),
-            true,
-            42,
-            true,
-        )]));
-
-        // create some data
-        let mut builder = PrimitiveDictionaryBuilder::<UInt8Type, 
UInt32Type>::new();
-        builder.append(12345678).unwrap();
-        builder.append_null();
-        builder.append(22345678).unwrap();
-        builder.append(12345678).unwrap();
-        let d = builder.finish();
-
-        RoundTripTest::new(Arc::new(d)).with_schema(schema).run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_decimal32_dictionary() {
-        let integers = vec![12345, 56789, 34567];
-
-        let keys = UInt8Array::from(vec![Some(0), None, Some(1), Some(2), 
Some(1)]);
-
-        let values = Decimal32Array::from(integers.clone())
-            .with_precision_and_scale(5, 2)
-            .unwrap();
-
-        let array = DictionaryArray::new(keys, Arc::new(values));
-        RoundTripTest::new(Arc::new(array.clone())).run();
-
-        let values = Decimal32Array::from(integers)
-            .with_precision_and_scale(9, 2)
-            .unwrap();
-
-        let array = array.with_values(Arc::new(values));
-        RoundTripTest::new(Arc::new(array)).run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_decimal64_dictionary() {
-        let integers = vec![12345, 56789, 34567];
-
-        let keys = UInt8Array::from(vec![Some(0), None, Some(1), Some(2), 
Some(1)]);
-
-        let values = Decimal64Array::from(integers.clone())
-            .with_precision_and_scale(5, 2)
-            .unwrap();
-
-        let array = DictionaryArray::new(keys, Arc::new(values));
-        RoundTripTest::new(Arc::new(array.clone())).run();
-
-        let values = Decimal64Array::from(integers)
-            .with_precision_and_scale(12, 2)
-            .unwrap();
-
-        let array = array.with_values(Arc::new(values));
-        RoundTripTest::new(Arc::new(array)).run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_decimal128_dictionary() {
-        let integers = vec![12345, 56789, 34567];
-
-        let keys = UInt8Array::from(vec![Some(0), None, Some(1), Some(2), 
Some(1)]);
-
-        let values = Decimal128Array::from(integers.clone())
-            .with_precision_and_scale(5, 2)
-            .unwrap();
-
-        let array = DictionaryArray::new(keys, Arc::new(values));
-        RoundTripTest::new(Arc::new(array.clone())).run();
-
-        let values = Decimal128Array::from(integers)
-            .with_precision_and_scale(12, 2)
-            .unwrap();
-
-        let array = array.with_values(Arc::new(values));
-        RoundTripTest::new(Arc::new(array)).run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_decimal256_dictionary() {
-        let integers = vec![
-            i256::from_i128(12345),
-            i256::from_i128(56789),
-            i256::from_i128(34567),
-        ];
-
-        let keys = UInt8Array::from(vec![Some(0), None, Some(1), Some(2), 
Some(1)]);
-
-        let values = Decimal256Array::from(integers.clone())
-            .with_precision_and_scale(5, 2)
-            .unwrap();
-
-        let array = DictionaryArray::new(keys, Arc::new(values));
-        RoundTripTest::new(Arc::new(array.clone())).run();
-
-        let values = Decimal256Array::from(integers)
-            .with_precision_and_scale(12, 2)
-            .unwrap();
-
-        let array = array.with_values(Arc::new(values));
-        RoundTripTest::new(Arc::new(array)).run();
-    }
-
-    #[test]
-    #[cfg_attr(miri, ignore)] // Takes too long
-    fn arrow_writer_string_dictionary_unsigned_index() {
-        // define schema
-        #[expect(deprecated)]
-        let schema = Arc::new(Schema::new(vec![Field::new_dict(
-            "dictionary",
-            DataType::Dictionary(Box::new(DataType::UInt8), 
Box::new(DataType::Utf8)),
-            true,
-            42,
-            true,
-        )]));
-
-        // create some data
-        let d: UInt8DictionaryArray = [Some("alpha"), None, Some("beta"), 
Some("alpha")]
-            .iter()
-            .copied()
-            .collect();
-
-        RoundTripTest::new(Arc::new(d)).with_schema(schema).run();
-    }
-
     #[test]
     #[cfg_attr(miri, ignore)] // Takes too long
     fn u32_min_max() {
diff --git a/parquet/tests/arrow_writer/roundtrip.rs 
b/parquet/tests/arrow_writer/roundtrip.rs
index 135dd0df77..c9199db609 100644
--- a/parquet/tests/arrow_writer/roundtrip.rs
+++ b/parquet/tests/arrow_writer/roundtrip.rs
@@ -17,34 +17,41 @@
 
 //! Round-trip tests for Arrow data written to Parquet.
 
-use super::roundtrip_helpers::{RoundTripTest, SMALL_SIZE, 
required_and_optional, values_required};
+use super::roundtrip_helpers::{
+    RoundTripTest, SMALL_SIZE, required_and_optional, roundtrip, 
values_required,
+};
 
 use std::collections::HashMap;
 use std::sync::Arc;
 
-use arrow_array::builder::FixedSizeBinaryBuilder;
+use arrow::datatypes::ToByteSlice;
+use arrow_array::builder::{
+    FixedSizeBinaryBuilder, ListBuilder, PrimitiveDictionaryBuilder, 
StringViewBuilder,
+};
 use arrow_array::cast::AsArray;
 use arrow_array::types::{
-    Date32Type, Date64Type, Decimal32Type, Decimal64Type, Decimal128Type, 
Decimal256Type,
-    DecimalType, Float16Type, Time32MillisecondType, Time64MicrosecondType,
+    ArrowDictionaryKeyType, Date32Type, Date64Type, Decimal32Type, 
Decimal64Type, Decimal128Type,
+    Decimal256Type, DecimalType, Float16Type, Int8Type, Int16Type, Int32Type, 
Int64Type,
+    Time32MillisecondType, Time64MicrosecondType, UInt8Type, UInt16Type, 
UInt32Type,
 };
 use arrow_array::{
-    Array, ArrayRef, BinaryArray, BinaryViewArray, Date32Array, Date64Array, 
Decimal128Array,
-    Decimal256Array, DictionaryArray, DurationMicrosecondArray, 
DurationMillisecondArray,
-    DurationNanosecondArray, DurationSecondArray, FixedSizeBinaryArray, 
Float16Array, Float32Array,
-    Float64Array, Int8Array, Int16Array, Int32Array, Int64Array, 
LargeBinaryArray,
-    LargeStringArray, ListArray, PrimitiveArray, RecordBatch, 
RecordBatchReader, StringArray,
-    StringViewArray, StructArray, Time32MillisecondArray, Time32SecondArray,
-    Time64MicrosecondArray, Time64NanosecondArray, TimestampMicrosecondArray,
+    Array, ArrayRef, BinaryArray, BinaryViewArray, Date32Array, Date64Array, 
Decimal32Array,
+    Decimal64Array, Decimal128Array, Decimal256Array, DictionaryArray, 
DurationMicrosecondArray,
+    DurationMillisecondArray, DurationNanosecondArray, DurationSecondArray, 
FixedSizeBinaryArray,
+    Float16Array, Float32Array, Float64Array, Int8Array, Int16Array, 
Int32Array,
+    Int32DictionaryArray, Int64Array, LargeBinaryArray, LargeListArray, 
LargeListViewArray,
+    LargeStringArray, ListArray, ListViewArray, NullArray, PrimitiveArray, 
RecordBatch,
+    RecordBatchReader, StringArray, StringViewArray, StructArray, 
Time32MillisecondArray,
+    Time32SecondArray, Time64MicrosecondArray, Time64NanosecondArray, 
TimestampMicrosecondArray,
     TimestampMillisecondArray, TimestampNanosecondArray, TimestampSecondArray, 
UInt8Array,
     UInt8DictionaryArray, UInt16Array, UInt32Array, UInt64Array,
 };
 use arrow_buffer::{ArrowNativeType, Buffer, NullBuffer, i256};
-use arrow_data::ArrayDataBuilder;
+use arrow_data::{ArrayData, ArrayDataBuilder};
 use arrow_schema::{DataType as ArrowDataType, Field, Fields, Schema, TimeUnit};
 use bytes::Bytes;
 use half::f16;
-use num_traits::PrimInt;
+use num_traits::{FromPrimitive, PrimInt, ToPrimitive};
 use parquet::arrow::ArrowWriter;
 use parquet::arrow::arrow_reader::{ParquetRecordBatchReader, 
ParquetRecordBatchReaderBuilder};
 use parquet::basic::Type as PhysicalType;
@@ -285,6 +292,945 @@ fn string_view_single_column() {
     required_and_optional::<StringViewArray, _>(raw_strs);
 }
 
+#[test]
+fn null_list_single_column() {
+    let null_field = Field::new_list_field(ArrowDataType::Null, true);
+    let list_field = Field::new("emptylist", 
ArrowDataType::List(Arc::new(null_field)), true);
+
+    let schema = Schema::new(vec![list_field]);
+
+    // Build [[], null, [null, null]]
+    let a_values = NullArray::new(2);
+    let a_value_offsets = arrow::buffer::Buffer::from([0, 0, 0, 
2].to_byte_slice());
+    let a_list_data = 
ArrayData::builder(ArrowDataType::List(Arc::new(Field::new_list_field(
+        ArrowDataType::Null,
+        true,
+    ))))
+    .len(3)
+    .add_buffer(a_value_offsets)
+    .null_bit_buffer(Some(Buffer::from([0b00000101])))
+    .add_child_data(a_values.into_data())
+    .build()
+    .unwrap();
+
+    let a = ListArray::from(a_list_data);
+
+    assert!(a.is_valid(0));
+    assert!(!a.is_valid(1));
+    assert!(a.is_valid(2));
+
+    assert_eq!(a.value(0).len(), 0);
+    assert_eq!(a.value(2).len(), 2);
+    assert_eq!(a.value(2).logical_nulls().unwrap().null_count(), 2);
+
+    let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(a)]).unwrap();
+    roundtrip(batch, None);
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn list_single_column() {
+    let a_values = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+    let a_value_offsets = arrow::buffer::Buffer::from([0, 1, 3, 3, 6, 
10].to_byte_slice());
+    let a_list_data = 
ArrayData::builder(ArrowDataType::List(Arc::new(Field::new_list_field(
+        ArrowDataType::Int32,
+        false,
+    ))))
+    .len(5)
+    .add_buffer(a_value_offsets)
+    .null_bit_buffer(Some(Buffer::from([0b00011011])))
+    .add_child_data(a_values.into_data())
+    .build()
+    .unwrap();
+
+    assert_eq!(a_list_data.null_count(), 1);
+
+    let a = ListArray::from(a_list_data);
+    let values = Arc::new(a);
+
+    RoundTripTest::new(values).run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn large_list_single_column() {
+    let a_values = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+    let a_value_offsets = arrow::buffer::Buffer::from([0i64, 1, 3, 3, 6, 
10].to_byte_slice());
+    let a_list_data = 
ArrayData::builder(ArrowDataType::LargeList(Arc::new(Field::new(
+        "large_item",
+        ArrowDataType::Int32,
+        true,
+    ))))
+    .len(5)
+    .add_buffer(a_value_offsets)
+    .add_child_data(a_values.into_data())
+    .null_bit_buffer(Some(Buffer::from([0b00011011])))
+    .build()
+    .unwrap();
+
+    // I think this setup is incorrect because this should pass
+    assert_eq!(a_list_data.null_count(), 1);
+
+    let a = LargeListArray::from(a_list_data);
+    let values = Arc::new(a);
+
+    RoundTripTest::new(values).run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn list_nested_nulls() {
+    use arrow::datatypes::Int32Type;
+    let data = vec![
+        Some(vec![Some(1)]),
+        Some(vec![Some(2), Some(3)]),
+        None,
+        Some(vec![Some(4), Some(5), None]),
+        Some(vec![None]),
+        Some(vec![Some(6), Some(7)]),
+    ];
+
+    let list = ListArray::from_iter_primitive::<Int32Type, _, _>(data.clone());
+    RoundTripTest::new(Arc::new(list)).run();
+
+    let list = LargeListArray::from_iter_primitive::<Int32Type, _, _>(data);
+    RoundTripTest::new(Arc::new(list)).run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn list_utf8_view_selective_padding_roundtrip() {
+    let item = Arc::new(Field::new_list_field(ArrowDataType::Utf8View, true));
+    let mut builder = 
ListBuilder::new(StringViewBuilder::new()).with_field(item);
+    builder.values().append_value("a");
+    builder.values().append_null();
+    builder.append(true);
+    // The null parent list covers selective padding dropping values below
+    // the list definition level while preserving the preceding item null.
+    builder.append(false);
+    // The long string covers the non-inlined Utf8View buffer path.
+    builder.values().append_value("large payload over 12 bytes");
+    builder.append(true);
+
+    RoundTripTest::new(Arc::new(builder.finish())).run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn struct_single_column() {
+    let a_values = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+    let struct_field_a = Arc::new(Field::new("f", ArrowDataType::Int32, 
false));
+    let s = StructArray::from(vec![(struct_field_a, Arc::new(a_values) as 
ArrayRef)]);
+
+    let values = Arc::new(s);
+    RoundTripTest::new(values).with_nullable(false).run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_list() {
+    // define schema
+    let schema = Schema::new(vec![Field::new(
+        "a",
+        
ArrowDataType::List(Arc::new(Field::new_list_field(ArrowDataType::Int32, 
false))),
+        true,
+    )]);
+
+    // create some data
+    let a_values = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+
+    // Construct a buffer for value offsets, for the nested array:
+    //  [[1], [2, 3], null, [4, 5, 6], [7, 8, 9, 10]]
+    let a_value_offsets = arrow::buffer::Buffer::from([0, 1, 3, 3, 6, 
10].to_byte_slice());
+
+    // Construct a list array from the above two
+    let a_list_data = 
ArrayData::builder(ArrowDataType::List(Arc::new(Field::new_list_field(
+        ArrowDataType::Int32,
+        false,
+    ))))
+    .len(5)
+    .add_buffer(a_value_offsets)
+    .add_child_data(a_values.into_data())
+    .null_bit_buffer(Some(Buffer::from([0b00011011])))
+    .build()
+    .unwrap();
+    let a = ListArray::from(a_list_data);
+    assert_eq!(a.null_count(), 1);
+
+    RoundTripTest::new(Arc::new(a))
+        .with_schema(Arc::new(schema))
+        .run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_list_non_null() {
+    // define schema
+    let schema = Schema::new(vec![Field::new(
+        "a",
+        
ArrowDataType::List(Arc::new(Field::new_list_field(ArrowDataType::Int32, 
false))),
+        false,
+    )]);
+
+    // create some data
+    let a_values = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+
+    // Construct a buffer for value offsets, for the nested array:
+    //  [[1], [2, 3], [], [4, 5, 6], [7, 8, 9, 10]]
+    let a_value_offsets = arrow::buffer::Buffer::from([0, 1, 3, 3, 6, 
10].to_byte_slice());
+
+    // Construct a list array from the above two
+    let a_list_data = 
ArrayData::builder(ArrowDataType::List(Arc::new(Field::new_list_field(
+        ArrowDataType::Int32,
+        false,
+    ))))
+    .len(5)
+    .add_buffer(a_value_offsets)
+    .add_child_data(a_values.into_data())
+    .build()
+    .unwrap();
+    let a = ListArray::from(a_list_data);
+    assert_eq!(a.null_count(), 0);
+
+    RoundTripTest::new(Arc::new(a))
+        .with_schema(Arc::new(schema))
+        .run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_list_view() {
+    let list_field = Arc::new(Field::new_list_field(ArrowDataType::Int32, 
false));
+    let schema = Schema::new(vec![Field::new(
+        "a",
+        ArrowDataType::ListView(list_field.clone()),
+        true,
+    )]);
+
+    //  [[1], [2, 3], null, [4, 5, 6], [7, 8, 9, 10]]
+    let a = ListViewArray::new(
+        list_field,
+        vec![0, 1, 0, 3, 6].into(),
+        vec![1, 2, 0, 3, 4].into(),
+        Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10])),
+        Some(vec![true, true, false, true, true].into()),
+    );
+    assert_eq!(a.null_count(), 1);
+
+    RoundTripTest::new(Arc::new(a))
+        .with_schema(Arc::new(schema))
+        .run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_list_view_non_null() {
+    let list_field = Arc::new(Field::new_list_field(ArrowDataType::Int32, 
false));
+    let schema = Schema::new(vec![Field::new(
+        "a",
+        ArrowDataType::ListView(list_field.clone()),
+        false,
+    )]);
+
+    //  [[1], [2, 3], [], [4, 5, 6], [7, 8, 9, 10]]
+    let a = ListViewArray::new(
+        list_field,
+        vec![0, 1, 0, 3, 6].into(),
+        vec![1, 2, 0, 3, 4].into(),
+        Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10])),
+        None,
+    );
+    assert_eq!(a.null_count(), 0);
+
+    RoundTripTest::new(Arc::new(a))
+        .with_schema(Arc::new(schema))
+        .run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_list_view_out_of_order() {
+    let list_field = Arc::new(Field::new_list_field(ArrowDataType::Int32, 
false));
+    let schema = Schema::new(vec![Field::new(
+        "a",
+        ArrowDataType::ListView(list_field.clone()),
+        false,
+    )]);
+
+    // [[1], [2, 3], [], [7, 8, 9, 10], [4, 5, 6]] - out of order offsets
+    let a = ListViewArray::new(
+        list_field,
+        vec![0, 1, 0, 6, 3].into(),
+        vec![1, 2, 0, 4, 3].into(),
+        Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10])),
+        None,
+    );
+    assert_eq!(a.null_count(), 0);
+
+    RoundTripTest::new(Arc::new(a))
+        .with_schema(Arc::new(schema))
+        .run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_large_list_view() {
+    let list_field = Arc::new(Field::new_list_field(ArrowDataType::Int32, 
false));
+    let schema = Schema::new(vec![Field::new(
+        "a",
+        ArrowDataType::LargeListView(list_field.clone()),
+        true,
+    )]);
+
+    //  [[1], [2, 3], null, [4, 5, 6], [7, 8, 9, 10]]
+    let a = LargeListViewArray::new(
+        list_field,
+        vec![0i64, 1, 0, 3, 6].into(),
+        vec![1i64, 2, 0, 3, 4].into(),
+        Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10])),
+        Some(vec![true, true, false, true, true].into()),
+    );
+    assert_eq!(a.null_count(), 1);
+
+    RoundTripTest::new(Arc::new(a))
+        .with_schema(Arc::new(schema))
+        .run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_list_view_with_struct() {
+    // Test ListView containing Struct: ListView<Struct<Int32, Utf8>>
+    let struct_fields = Fields::from(vec![
+        Field::new("id", ArrowDataType::Int32, false),
+        Field::new("name", ArrowDataType::Utf8, false),
+    ]);
+    let struct_type = ArrowDataType::Struct(struct_fields.clone());
+    let list_field = Arc::new(Field::new("item", struct_type.clone(), false));
+
+    let schema = Schema::new(vec![Field::new(
+        "a",
+        ArrowDataType::ListView(list_field.clone()),
+        true,
+    )]);
+
+    // Create struct values
+    let id_array = Int32Array::from(vec![1, 2, 3, 4, 5]);
+    let name_array = StringArray::from(vec!["a", "b", "c", "d", "e"]);
+    let struct_array = StructArray::new(
+        struct_fields,
+        vec![Arc::new(id_array), Arc::new(name_array)],
+        None,
+    );
+
+    // Create ListView: [{1, "a"}, {2, "b"}], null, [{3, "c"}, {4, "d"}, {5, 
"e"}]
+    let list_view = ListViewArray::new(
+        list_field,
+        vec![0, 2, 2].into(), // offsets
+        vec![2, 0, 3].into(), // sizes
+        Arc::new(struct_array),
+        Some(vec![true, false, true].into()),
+    );
+    assert_eq!(list_view.null_count(), 1);
+
+    RoundTripTest::new(Arc::new(list_view))
+        .with_schema(Arc::new(schema))
+        .run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_complex() {
+    // define schema
+    let struct_field_d = Arc::new(Field::new("d", ArrowDataType::Float64, 
true));
+    let struct_field_f = Arc::new(Field::new("f", ArrowDataType::Float32, 
true));
+    let struct_field_g = Arc::new(Field::new_list(
+        "g",
+        Field::new_list_field(ArrowDataType::Int16, true),
+        false,
+    ));
+    let struct_field_h = Arc::new(Field::new_list(
+        "h",
+        Field::new_list_field(ArrowDataType::Int16, false),
+        true,
+    ));
+    let struct_field_e = Arc::new(Field::new_struct(
+        "e",
+        vec![
+            struct_field_f.clone(),
+            struct_field_g.clone(),
+            struct_field_h.clone(),
+        ],
+        false,
+    ));
+    let schema = Schema::new(vec![
+        Field::new("a", ArrowDataType::Int32, false),
+        Field::new("b", ArrowDataType::Int32, true),
+        Field::new_struct(
+            "c",
+            vec![struct_field_d.clone(), struct_field_e.clone()],
+            false,
+        ),
+    ]);
+
+    // create some data
+    let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
+    let b = Int32Array::from(vec![Some(1), None, None, Some(4), Some(5)]);
+    let d = Float64Array::from(vec![None, None, None, Some(1.0), None]);
+    let f = Float32Array::from(vec![Some(0.0), None, Some(333.3), None, 
Some(5.25)]);
+
+    let g_value = Int16Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+
+    // Construct a buffer for value offsets, for the nested array:
+    //  [[1], [2, 3], [], [4, 5, 6], [7, 8, 9, 10]]
+    let g_value_offsets = arrow::buffer::Buffer::from([0, 1, 3, 3, 6, 
10].to_byte_slice());
+
+    // Construct a list array from the above two
+    let g_list_data = ArrayData::builder(struct_field_g.data_type().clone())
+        .len(5)
+        .add_buffer(g_value_offsets.clone())
+        .add_child_data(g_value.to_data())
+        .build()
+        .unwrap();
+    let g = ListArray::from(g_list_data);
+    // The difference between g and h is that h has a null bitmap
+    let h_list_data = ArrayData::builder(struct_field_h.data_type().clone())
+        .len(5)
+        .add_buffer(g_value_offsets)
+        .add_child_data(g_value.to_data())
+        .null_bit_buffer(Some(Buffer::from([0b00011011])))
+        .build()
+        .unwrap();
+    let h = ListArray::from(h_list_data);
+
+    let e = StructArray::from(vec![
+        (struct_field_f, Arc::new(f) as ArrayRef),
+        (struct_field_g, Arc::new(g) as ArrayRef),
+        (struct_field_h, Arc::new(h) as ArrayRef),
+    ]);
+
+    let c = StructArray::from(vec![
+        (struct_field_d, Arc::new(d) as ArrayRef),
+        (struct_field_e, Arc::new(e) as ArrayRef),
+    ]);
+
+    // build a record batch
+    let batch = RecordBatch::try_new(
+        Arc::new(schema),
+        vec![Arc::new(a), Arc::new(b), Arc::new(c)],
+    )
+    .unwrap();
+
+    roundtrip(batch.clone(), Some(SMALL_SIZE / 2));
+    roundtrip(batch, Some(SMALL_SIZE / 3));
+}
+
+#[test]
+fn arrow_writer_complex_mixed() {
+    // This test was added while investigating 
https://github.com/apache/arrow-rs/issues/244.
+    // It was subsequently fixed while investigating 
https://github.com/apache/arrow-rs/issues/245.
+
+    // define schema
+    let offset_field = Arc::new(Field::new("offset", ArrowDataType::Int32, 
false));
+    let partition_field = Arc::new(Field::new("partition", 
ArrowDataType::Int64, true));
+    let topic_field = Arc::new(Field::new("topic", ArrowDataType::Utf8, true));
+    let schema = Schema::new(vec![Field::new(
+        "some_nested_object",
+        ArrowDataType::Struct(Fields::from(vec![
+            offset_field.clone(),
+            partition_field.clone(),
+            topic_field.clone(),
+        ])),
+        false,
+    )]);
+
+    // create some data
+    let offset = Int32Array::from(vec![1, 2, 3, 4, 5]);
+    let partition = Int64Array::from(vec![Some(1), None, None, Some(4), 
Some(5)]);
+    let topic = StringArray::from(vec![Some("A"), None, Some("A"), Some(""), 
None]);
+
+    let some_nested_object = StructArray::from(vec![
+        (offset_field, Arc::new(offset) as ArrayRef),
+        (partition_field, Arc::new(partition) as ArrayRef),
+        (topic_field, Arc::new(topic) as ArrayRef),
+    ]);
+
+    // build a record batch
+    let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(some_nested_object)]).unwrap();
+
+    roundtrip(batch, Some(SMALL_SIZE / 2));
+}
+
+#[test]
+fn arrow_writer_map() {
+    // Note: we are using the JSON Arrow reader for brevity
+    let json_content = r#"
+        {"stocks":{"long": "$AAA", "short": "$BBB"}}
+        {"stocks":{"long": null, "long": "$CCC", "short": null}}
+        {"stocks":{"hedged": "$YYY", "long": null, "short": "$D"}}
+        "#;
+    let entries_struct_type = ArrowDataType::Struct(Fields::from(vec![
+        Field::new(
+            Field::MAP_KEY_FIELD_DEFAULT_NAME,
+            ArrowDataType::Utf8,
+            false,
+        ),
+        Field::new(
+            Field::MAP_VALUE_FIELD_DEFAULT_NAME,
+            ArrowDataType::Utf8,
+            true,
+        ),
+    ]));
+    let stocks_field = Field::new(
+        "stocks",
+        ArrowDataType::Map(
+            Arc::new(Field::new(
+                Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
+                entries_struct_type,
+                false,
+            )),
+            false,
+        ),
+        true,
+    );
+    let schema = Arc::new(Schema::new(vec![stocks_field]));
+    let builder = arrow::json::ReaderBuilder::new(schema).with_batch_size(64);
+    let mut reader = 
builder.build(std::io::Cursor::new(json_content)).unwrap();
+
+    let batch = reader.next().unwrap().unwrap();
+    roundtrip(batch, None);
+}
+
+#[test]
+fn arrow_writer_2_level_struct() {
+    // tests writing <struct<struct<primitive>>
+    let field_c = Field::new("c", ArrowDataType::Int32, true);
+    let field_b = Field::new("b", ArrowDataType::Struct(vec![field_c].into()), 
true);
+    let type_a = ArrowDataType::Struct(vec![field_b.clone()].into());
+    let field_a = Field::new("a", type_a, true);
+    let schema = Schema::new(vec![field_a.clone()]);
+
+    // create data
+    let c = Int32Array::from(vec![Some(1), None, Some(3), None, None, 
Some(6)]);
+    let b_data = ArrayDataBuilder::new(field_b.data_type().clone())
+        .len(6)
+        .null_bit_buffer(Some(Buffer::from([0b00100111])))
+        .add_child_data(c.into_data())
+        .build()
+        .unwrap();
+    let b = StructArray::from(b_data);
+    let a_data = ArrayDataBuilder::new(field_a.data_type().clone())
+        .len(6)
+        .null_bit_buffer(Some(Buffer::from([0b00101111])))
+        .add_child_data(b.into_data())
+        .build()
+        .unwrap();
+    let a = StructArray::from(a_data);
+
+    assert_eq!(a.null_count(), 1);
+    assert_eq!(a.column(0).null_count(), 2);
+
+    // build a racord batch
+    let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(a)]).unwrap();
+
+    roundtrip(batch, Some(SMALL_SIZE / 2));
+}
+
+#[test]
+fn arrow_writer_2_level_struct_non_null() {
+    // tests writing <struct<struct<primitive>>
+    let field_c = Field::new("c", ArrowDataType::Int32, false);
+    let type_b = ArrowDataType::Struct(vec![field_c].into());
+    let field_b = Field::new("b", type_b.clone(), false);
+    let type_a = ArrowDataType::Struct(vec![field_b].into());
+    let field_a = Field::new("a", type_a.clone(), false);
+    let schema = Schema::new(vec![field_a]);
+
+    // create data
+    let c = Int32Array::from(vec![1, 2, 3, 4, 5, 6]);
+    let b_data = ArrayDataBuilder::new(type_b)
+        .len(6)
+        .add_child_data(c.into_data())
+        .build()
+        .unwrap();
+    let b = StructArray::from(b_data);
+    let a_data = ArrayDataBuilder::new(type_a)
+        .len(6)
+        .add_child_data(b.into_data())
+        .build()
+        .unwrap();
+    let a = StructArray::from(a_data);
+
+    assert_eq!(a.null_count(), 0);
+    assert_eq!(a.column(0).null_count(), 0);
+
+    // build a racord batch
+    let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(a)]).unwrap();
+
+    roundtrip(batch, Some(SMALL_SIZE / 2));
+}
+
+#[test]
+fn arrow_writer_2_level_struct_mixed_null() {
+    // tests writing <struct<struct<primitive>>
+    let field_c = Field::new("c", ArrowDataType::Int32, false);
+    let type_b = ArrowDataType::Struct(vec![field_c].into());
+    let field_b = Field::new("b", type_b.clone(), true);
+    let type_a = ArrowDataType::Struct(vec![field_b].into());
+    let field_a = Field::new("a", type_a.clone(), false);
+    let schema = Schema::new(vec![field_a]);
+
+    // create data
+    let c = Int32Array::from(vec![1, 2, 3, 4, 5, 6]);
+    let b_data = ArrayDataBuilder::new(type_b)
+        .len(6)
+        .null_bit_buffer(Some(Buffer::from([0b00100111])))
+        .add_child_data(c.into_data())
+        .build()
+        .unwrap();
+    let b = StructArray::from(b_data);
+    // a intentionally has no null buffer, to test that this is handled 
correctly
+    let a_data = ArrayDataBuilder::new(type_a)
+        .len(6)
+        .add_child_data(b.into_data())
+        .build()
+        .unwrap();
+    let a = StructArray::from(a_data);
+
+    assert_eq!(a.null_count(), 0);
+    assert_eq!(a.column(0).null_count(), 2);
+
+    // build a racord batch
+    let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(a)]).unwrap();
+
+    roundtrip(batch, Some(SMALL_SIZE / 2));
+}
+
+#[test]
+fn arrow_writer_2_level_struct_mixed_null_2() {
+    // tests writing <struct<struct<primitive>>, where the primitive columns 
are non-null.
+    let field_c = Field::new("c", ArrowDataType::Int32, false);
+    let field_d = Field::new("d", ArrowDataType::FixedSizeBinary(4), false);
+    let field_e = Field::new(
+        "e",
+        ArrowDataType::Dictionary(
+            Box::new(ArrowDataType::Int32),
+            Box::new(ArrowDataType::Utf8),
+        ),
+        false,
+    );
+
+    let field_b = Field::new(
+        "b",
+        ArrowDataType::Struct(vec![field_c, field_d, field_e].into()),
+        false,
+    );
+    let type_a = ArrowDataType::Struct(vec![field_b.clone()].into());
+    let field_a = Field::new("a", type_a, true);
+    let schema = Schema::new(vec![field_a.clone()]);
+
+    // create data
+    let c = Int32Array::from_iter_values(0..6);
+    let d = FixedSizeBinaryArray::try_from_iter(
+        ["aaaa", "bbbb", "cccc", "dddd", "eeee", "ffff"].into_iter(),
+    )
+    .expect("four byte values");
+    let e = Int32DictionaryArray::from_iter(["one", "two", "three", "four", 
"five", "one"]);
+    let b_data = ArrayDataBuilder::new(field_b.data_type().clone())
+        .len(6)
+        .add_child_data(c.into_data())
+        .add_child_data(d.into_data())
+        .add_child_data(e.into_data())
+        .build()
+        .unwrap();
+    let b = StructArray::from(b_data);
+    let a_data = ArrayDataBuilder::new(field_a.data_type().clone())
+        .len(6)
+        .null_bit_buffer(Some(Buffer::from([0b00100101])))
+        .add_child_data(b.into_data())
+        .build()
+        .unwrap();
+    let a = StructArray::from(a_data);
+
+    assert_eq!(a.null_count(), 3);
+    assert_eq!(a.column(0).null_count(), 0);
+
+    // build a record batch
+    let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(a)]).unwrap();
+
+    roundtrip(batch, Some(SMALL_SIZE / 2));
+}
+
+/// Test round-trip of Dictionary<UInt32, Utf8View> and
+/// Dictionary<UInt32, BinaryView> typed columns.
+#[test]
+fn arrow_writer_string_view_dictionary() {
+    let raw_string_values = vec!["a", "b", "large payload over 12 bytes"];
+    let raw_binary_values = vec![
+        b"a".to_vec(),
+        b"b".to_vec(),
+        b"large payload over 12 bytes".to_vec(),
+    ];
+
+    let keys = UInt32Array::from(vec![Some(0), None, Some(2), Some(1), None]);
+
+    let string_view_values = 
Arc::new(StringViewArray::from(raw_string_values));
+    let string_dict: ArrayRef =
+        Arc::new(DictionaryArray::<UInt32Type>::try_new(keys.clone(), 
string_view_values).unwrap());
+
+    let binary_view_values = 
Arc::new(BinaryViewArray::from_iter_values(raw_binary_values));
+    let binary_dict: ArrayRef =
+        Arc::new(DictionaryArray::<UInt32Type>::try_new(keys, 
binary_view_values).unwrap());
+
+    RoundTripTest::new(string_dict).run();
+    RoundTripTest::new(binary_dict).run();
+}
+
+#[test]
+fn test_fixed_size_binary_in_dict() {
+    fn test_fixed_size_binary_in_dict_inner<K>()
+    where
+        K: ArrowDictionaryKeyType,
+        K::Native: FromPrimitive + ToPrimitive + TryFrom<u8>,
+        <<K as arrow_array::ArrowPrimitiveType>::Native as 
TryFrom<u8>>::Error: std::fmt::Debug,
+    {
+        let field = Field::new(
+            "a",
+            ArrowDataType::Dictionary(
+                Box::new(K::DATA_TYPE),
+                Box::new(ArrowDataType::FixedSizeBinary(4)),
+            ),
+            false,
+        );
+        let schema = Schema::new(vec![field]);
+
+        let keys: Vec<K::Native> = vec![
+            K::Native::try_from(0u8).unwrap(),
+            K::Native::try_from(0u8).unwrap(),
+            K::Native::try_from(1u8).unwrap(),
+        ];
+        let keys = PrimitiveArray::<K>::from_iter_values(keys);
+        let values = FixedSizeBinaryArray::try_from_iter(
+            vec![vec![0, 0, 0, 0], vec![1, 1, 1, 1]].into_iter(),
+        )
+        .unwrap();
+
+        let data = DictionaryArray::<K>::new(keys, Arc::new(values));
+        let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(data)]).unwrap();
+        roundtrip(batch, None);
+    }
+
+    test_fixed_size_binary_in_dict_inner::<UInt8Type>();
+    test_fixed_size_binary_in_dict_inner::<UInt16Type>();
+    test_fixed_size_binary_in_dict_inner::<UInt32Type>();
+    test_fixed_size_binary_in_dict_inner::<UInt16Type>();
+    test_fixed_size_binary_in_dict_inner::<Int8Type>();
+    test_fixed_size_binary_in_dict_inner::<Int16Type>();
+    test_fixed_size_binary_in_dict_inner::<Int32Type>();
+    test_fixed_size_binary_in_dict_inner::<Int64Type>();
+}
+
+#[test]
+fn test_empty_dict() {
+    let struct_fields = Fields::from(vec![Field::new(
+        "dict",
+        ArrowDataType::Dictionary(
+            Box::new(ArrowDataType::Int32),
+            Box::new(ArrowDataType::Utf8),
+        ),
+        false,
+    )]);
+
+    let schema = Schema::new(vec![Field::new_struct(
+        "struct",
+        struct_fields.clone(),
+        true,
+    )]);
+    let dictionary = Arc::new(DictionaryArray::new(
+        Int32Array::new_null(5),
+        Arc::new(StringArray::new_null(0)),
+    ));
+
+    let s = StructArray::new(
+        struct_fields,
+        vec![dictionary],
+        Some(NullBuffer::new_null(5)),
+    );
+
+    let batch = RecordBatch::try_new(Arc::new(schema), 
vec![Arc::new(s)]).unwrap();
+    roundtrip(batch, None);
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_string_dictionary() {
+    // define schema
+    #[expect(deprecated)]
+    let schema = Arc::new(Schema::new(vec![Field::new_dict(
+        "dictionary",
+        ArrowDataType::Dictionary(
+            Box::new(ArrowDataType::Int32),
+            Box::new(ArrowDataType::Utf8),
+        ),
+        true,
+        42,
+        true,
+    )]));
+
+    // create some data
+    let d: Int32DictionaryArray = [Some("alpha"), None, Some("beta"), 
Some("alpha")]
+        .iter()
+        .copied()
+        .collect();
+
+    // build a record batch
+    RoundTripTest::new(Arc::new(d)).with_schema(schema).run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_primitive_dictionary() {
+    // define schema
+    #[expect(deprecated)]
+    let schema = Arc::new(Schema::new(vec![Field::new_dict(
+        "dictionary",
+        ArrowDataType::Dictionary(
+            Box::new(ArrowDataType::UInt8),
+            Box::new(ArrowDataType::UInt32),
+        ),
+        true,
+        42,
+        true,
+    )]));
+
+    // create some data
+    let mut builder = PrimitiveDictionaryBuilder::<UInt8Type, 
UInt32Type>::new();
+    builder.append(12345678).unwrap();
+    builder.append_null();
+    builder.append(22345678).unwrap();
+    builder.append(12345678).unwrap();
+    let d = builder.finish();
+
+    RoundTripTest::new(Arc::new(d)).with_schema(schema).run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_decimal32_dictionary() {
+    let integers = vec![12345, 56789, 34567];
+
+    let keys = UInt8Array::from(vec![Some(0), None, Some(1), Some(2), 
Some(1)]);
+
+    let values = Decimal32Array::from(integers.clone())
+        .with_precision_and_scale(5, 2)
+        .unwrap();
+
+    let array = DictionaryArray::new(keys, Arc::new(values));
+    RoundTripTest::new(Arc::new(array.clone())).run();
+
+    let values = Decimal32Array::from(integers)
+        .with_precision_and_scale(9, 2)
+        .unwrap();
+
+    let array = array.with_values(Arc::new(values));
+    RoundTripTest::new(Arc::new(array)).run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_decimal64_dictionary() {
+    let integers = vec![12345, 56789, 34567];
+
+    let keys = UInt8Array::from(vec![Some(0), None, Some(1), Some(2), 
Some(1)]);
+
+    let values = Decimal64Array::from(integers.clone())
+        .with_precision_and_scale(5, 2)
+        .unwrap();
+
+    let array = DictionaryArray::new(keys, Arc::new(values));
+    RoundTripTest::new(Arc::new(array.clone())).run();
+
+    let values = Decimal64Array::from(integers)
+        .with_precision_and_scale(12, 2)
+        .unwrap();
+
+    let array = array.with_values(Arc::new(values));
+    RoundTripTest::new(Arc::new(array)).run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_decimal128_dictionary() {
+    let integers = vec![12345, 56789, 34567];
+
+    let keys = UInt8Array::from(vec![Some(0), None, Some(1), Some(2), 
Some(1)]);
+
+    let values = Decimal128Array::from(integers.clone())
+        .with_precision_and_scale(5, 2)
+        .unwrap();
+
+    let array = DictionaryArray::new(keys, Arc::new(values));
+    RoundTripTest::new(Arc::new(array.clone())).run();
+
+    let values = Decimal128Array::from(integers)
+        .with_precision_and_scale(12, 2)
+        .unwrap();
+
+    let array = array.with_values(Arc::new(values));
+    RoundTripTest::new(Arc::new(array)).run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_decimal256_dictionary() {
+    let integers = vec![
+        i256::from_i128(12345),
+        i256::from_i128(56789),
+        i256::from_i128(34567),
+    ];
+
+    let keys = UInt8Array::from(vec![Some(0), None, Some(1), Some(2), 
Some(1)]);
+
+    let values = Decimal256Array::from(integers.clone())
+        .with_precision_and_scale(5, 2)
+        .unwrap();
+
+    let array = DictionaryArray::new(keys, Arc::new(values));
+    RoundTripTest::new(Arc::new(array.clone())).run();
+
+    let values = Decimal256Array::from(integers)
+        .with_precision_and_scale(12, 2)
+        .unwrap();
+
+    let array = array.with_values(Arc::new(values));
+    RoundTripTest::new(Arc::new(array)).run();
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Takes too long
+fn arrow_writer_string_dictionary_unsigned_index() {
+    // define schema
+    #[expect(deprecated)]
+    let schema = Arc::new(Schema::new(vec![Field::new_dict(
+        "dictionary",
+        ArrowDataType::Dictionary(
+            Box::new(ArrowDataType::UInt8),
+            Box::new(ArrowDataType::Utf8),
+        ),
+        true,
+        42,
+        true,
+    )]));
+
+    // create some data
+    let d: UInt8DictionaryArray = [Some("alpha"), None, Some("beta"), 
Some("alpha")]
+        .iter()
+        .copied()
+        .collect();
+
+    RoundTripTest::new(Arc::new(d)).with_schema(schema).run();
+}
+
 #[test]
 fn test_unsigned_roundtrip() {
     let schema = Arc::new(Schema::new(vec![

Reply via email to