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

Jefffrey 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 2a1ba4107f Add new parquet tests based on updated variant/json files 
(#10785)
2a1ba4107f is described below

commit 2a1ba4107fcacf85e29588fc5625f0655df30918
Author: Kosta Tarasov <[email protected]>
AuthorDate: Tue Sep 1 19:48:53 2026 -0700

    Add new parquet tests based on updated variant/json files (#10785)
    
    # Which issue does this PR close?
    
    - Follow-up to #10786, which updated the `parquet-testing` revision.
    - No tracking issue yet; one can be added if needed.
    
    # Rationale for this change
    
    The updated `parquet-testing` revision included:
    
    -
    
[apache/parquet-testing#113](https://github.com/apache/parquet-testing/pull/113):
    malformed and edge-case Variant files.
    -
    
[apache/parquet-testing#117](https://github.com/apache/parquet-testing/pull/117):
    mark four shredded Variant cases as invalid because they omit required
    `value` columns.
    -
    
[apache/parquet-testing#118](https://github.com/apache/parquet-testing/pull/118):
    JSON and BSON logical-type files.
    -
    
[apache/parquet-testing#119](https://github.com/apache/parquet-testing/pull/119):
    an extended ALP fixture.
    
    #10786 made these fixtures available to Arrow Rust, but did not exercise
    the JSON, BSON, or malformed Variant files.
    
    The same revision also added an extended ALP fixture. That fixture is
    covered by the ALP encoder/decoder work in #9372, where the required
    decoding support exists.
    
    # What changes are included in this PR?
    
    - Read the JSON logical-type fixture and verify all decoded string
    values.
    - Read the BSON logical-type fixture and verify all decoded binary
    values.
    - Validate all 14 files under `bad_data/variants`, including the one
    valid duplicate-offset case and 13 malformed cases.
    
    The four shredded Variant cases renamed as invalid by the same
    `parquet-testing` update are already exercised by the existing Variant
    integration harness.
    
    # Are these changes tested?
    
    Yes. The Parquet and Variant integration tests pass locally, along with
    formatting and clippy checks. The PR's CI checks are also green.
    
    # Are there any user-facing changes?
    
    No. This PR only adds integration-test coverage for existing
    `parquet-testing` fixtures.
    
    # AI usage
    
    This PR was prepared with OpenAI Codex and reviewed by a human. The
    integration tests, formatting, and clippy checks described above were
    run against the final branch, and the GitHub CI checks passed.
    
    ---------
    
    Co-authored-by: cetra3 <[email protected]>
---
 parquet/tests/arrow_reader/parquet_testing.rs | 42 ++++++++++++++++++-
 parquet/tests/variant_integration.rs          | 59 +++++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/parquet/tests/arrow_reader/parquet_testing.rs 
b/parquet/tests/arrow_reader/parquet_testing.rs
index daa3ff79d2..cbc7aa3eae 100644
--- a/parquet/tests/arrow_reader/parquet_testing.rs
+++ b/parquet/tests/arrow_reader/parquet_testing.rs
@@ -20,7 +20,7 @@
 //! [parquet-testing]: https://github.com/apache/parquet-testing
 
 use arrow_array::cast::AsArray;
-use arrow_array::{Array, Int64Array, types};
+use arrow_array::{Array, BinaryArray, Int64Array, StringArray, types};
 use arrow_schema::{Field, Schema, TimeUnit};
 use parquet::arrow::arrow_reader::{ArrowReaderOptions, 
ParquetRecordBatchReaderBuilder};
 use parquet::basic::{LogicalType, Type as PhysicalType};
@@ -190,3 +190,43 @@ fn test_read_unknown_logical_type() {
     assert_eq!(out.num_rows(), 3);
     assert_eq!(out.num_columns(), 2);
 }
+
+#[test]
+fn test_json_and_bson_logical_types() {
+    let test_data = arrow::util::test_util::parquet_test_data();
+
+    let json_file = File::open(format!("{test_data}/json.parquet")).unwrap();
+    let mut json_reader = ParquetRecordBatchReaderBuilder::try_new(json_file)
+        .unwrap()
+        .build()
+        .unwrap();
+    let json_batch = json_reader.next().unwrap().unwrap();
+    assert!(json_reader.next().is_none());
+    let json = json_batch.column(0).as_string::<i32>();
+    assert_eq!(
+        json,
+        &StringArray::from(vec![
+            Some(r#"{"a":1}"#),
+            Some(r#"{"a":1,"b":null}"#),
+            Some("[1,null,3]"),
+            None,
+        ])
+    );
+
+    let bson_file = File::open(format!("{test_data}/bson.parquet")).unwrap();
+    let mut bson_reader = ParquetRecordBatchReaderBuilder::try_new(bson_file)
+        .unwrap()
+        .build()
+        .unwrap();
+    let bson_batch = bson_reader.next().unwrap().unwrap();
+    assert!(bson_reader.next().is_none());
+    let bson = bson_batch.column(0).as_binary::<i32>();
+    assert_eq!(
+        bson,
+        &BinaryArray::from(vec![
+            Some(&[12, 0, 0, 0, 16, 97, 0, 1, 0, 0, 0, 0][..]),
+            Some(&[15, 0, 0, 0, 16, 97, 0, 1, 0, 0, 0, 10, 98, 0, 0][..]),
+            None,
+        ])
+    );
+}
diff --git a/parquet/tests/variant_integration.rs 
b/parquet/tests/variant_integration.rs
index a6e56b3af6..a80428b961 100644
--- a/parquet/tests/variant_integration.rs
+++ b/parquet/tests/variant_integration.rs
@@ -24,6 +24,7 @@
 //! Inspired by the arrow-go implementation: 
<https://github.com/apache/arrow-go/pull/455/files>
 
 use arrow::util::test_util::parquet_test_data;
+use arrow::{array::BinaryArray, record_batch::RecordBatch};
 use parquet::arrow::arrow_reader::ParquetRecordBatchReaderBuilder;
 use parquet_variant::{Variant, VariantMetadata};
 use parquet_variant_compute::{VariantArray, unshred_variant};
@@ -421,3 +422,61 @@ static ALL_CASES: LazyLock<Result<Vec<VariantTestCase>>> = 
LazyLock::new(|| {
 fn all_cases() -> &'static [VariantTestCase] {
     ALL_CASES.as_ref().unwrap()
 }
+
+#[test]
+fn test_variant_validation_files() {
+    const TEST_CASES: &[(&str, bool)] = &[
+        ("duplicate_field_offsets.parquet", true),
+        ("field_id_out_of_range.parquet", false),
+        ("int_overflow_in_bounds_check.parquet", false),
+        ("malformed_child_inside_well_formed_parent.parquet", false),
+        ("negative_dictionary_size.parquet", false),
+        ("out_of_range_child_offset.parquet", false),
+        ("out_of_range_dictionary_size.parquet", false),
+        ("out_of_range_element_count.parquet", false),
+        ("over_deep_nested_children.parquet", false),
+        ("oversized_primitive_size.parquet", false),
+        ("short_string_length_exceeds_buffer.parquet", false),
+        ("truncated_primitive_size.parquet", false),
+        ("unknown_primitive_type.parquet", false),
+        ("variant_version_2_header.parquet", false),
+    ];
+
+    let test_dir = PathBuf::from(parquet_test_data())
+        .join("..")
+        .join("bad_data")
+        .join("variants");
+    for (filename, expected_valid) in TEST_CASES {
+        let path = test_dir.join(filename);
+        let file = fs::File::open(&path).unwrap();
+        let mut reader = ParquetRecordBatchReaderBuilder::try_new(file)
+            .unwrap()
+            .build()
+            .unwrap();
+        let batch = reader.next().unwrap().unwrap();
+        assert!(reader.next().is_none());
+        assert_eq!(
+            variant_is_valid(&batch, filename),
+            *expected_valid,
+            "unexpected validation result for {filename}"
+        );
+    }
+}
+
+fn variant_is_valid(batch: &RecordBatch, filename: &str) -> bool {
+    assert_eq!(batch.num_rows(), 1, "unexpected row count in {filename}");
+    let metadata = batch
+        .column_by_name("metadata")
+        .unwrap()
+        .as_any()
+        .downcast_ref::<BinaryArray>()
+        .unwrap();
+    let value = batch
+        .column_by_name("value")
+        .unwrap()
+        .as_any()
+        .downcast_ref::<BinaryArray>()
+        .unwrap();
+
+    Variant::try_new(metadata.value(0), value.value(0)).is_ok()
+}

Reply via email to