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 07ec038b6a enable miri workflow for parquet crate (#10803)
07ec038b6a is described below

commit 07ec038b6ab704e25f29c96963222406577c8806
Author: Ethan Tang <[email protected]>
AuthorDate: Sat Aug 29 09:36:56 2026 -0500

    enable miri workflow for parquet crate (#10803)
    
    # Which issue does this PR close?
    closes #614
    
    # Rationale for this change
    Follow-up to #10507, which added Miri coverage for the arrow crates but
    left parquet excluded because it was tracked separately in #614. This
    adds the parquet crate to the Miri workflow to detect undefined behavior
    in its unsafe code. the full parquet miri run took about 40mins on my M3
    laptop
    
    # What changes are included in this PR?
    - Adds `-p parquet` to the Miri test suite in `miri.sh`
    - Adds `parquet/**` to the workflow path filters in `miri.yaml`
    - adds ignore to tests that take too long to run under Miri
    - adds ignore to tests that hit operations Miri doesn't support: kqueue,
    fork, inline assembly, native Zstd C functions
    
    # Are these changes tested?
    i ran the following to test locally.
    
    - `MIRIFLAGS="-Zmiri-disable-isolation" cargo +nightly miri nextest run
    -p parquet`
    - `cargo test -p parquet`
    - `cargo fmt --check -p parquet`
    - `git diff --check`
    
    # Are there any user-facing changes?
    no, only tests and CI
---
 .github/workflows/miri.sh                          |  1 +
 .github/workflows/miri.yaml                        |  6 +-
 parquet/src/arrow/arrow_reader/mod.rs              | 20 ++++++
 parquet/src/arrow/arrow_reader/read_plan.rs        |  1 +
 .../src/arrow/arrow_reader/selection/algebra.rs    |  4 ++
 .../src/arrow/arrow_reader/selection/boolean.rs    |  3 +
 parquet/src/arrow/arrow_writer/mod.rs              | 77 ++++++++++++++++++++++
 parquet/src/arrow/mod.rs                           |  1 +
 parquet/src/bloom_filter/mod.rs                    |  7 ++
 parquet/src/column/chunker/cdc.rs                  | 16 +++++
 parquet/src/column/reader/decoder.rs               |  1 +
 parquet/src/column/writer/mod.rs                   |  5 ++
 parquet/src/compression.rs                         |  6 ++
 parquet/src/encodings/decoding.rs                  |  3 +
 parquet/src/encodings/encoding/mod.rs              |  6 ++
 parquet/src/encodings/rle.rs                       |  2 +
 parquet/src/file/metadata/reader.rs                |  1 +
 parquet/src/file/serialized_reader.rs              |  7 ++
 parquet/src/file/writer.rs                         |  4 ++
 parquet/src/record/api.rs                          |  7 ++
 parquet/src/record/reader.rs                       |  2 +
 parquet/src/record/triplet.rs                      |  4 ++
 parquet/src/util/bit_util.rs                       |  1 +
 parquet/src/util/prefix.rs                         |  2 +
 parquet/tests/arrow_reader/bad_data.rs             |  9 ++-
 parquet/tests/arrow_reader/bloom_filter/sync.rs    |  1 +
 parquet/tests/arrow_reader/statistics.rs           | 45 +++++++++++++
 parquet/tests/arrow_writer/layout.rs               |  3 +
 parquet/tests/arrow_writer/mod.rs                  |  2 +
 parquet/tests/ieee754_nan_interop.rs               |  1 +
 30 files changed, 243 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/miri.sh b/.github/workflows/miri.sh
index 73cff87ff7..436992904e 100755
--- a/.github/workflows/miri.sh
+++ b/.github/workflows/miri.sh
@@ -24,6 +24,7 @@ CRATES="
     -p arrow-schema
     -p arrow-select
     -p arrow-string
+    -p parquet
 "
 
 setup_miri() {
diff --git a/.github/workflows/miri.yaml b/.github/workflows/miri.yaml
index c30989c17a..3c3a9d5e21 100644
--- a/.github/workflows/miri.yaml
+++ b/.github/workflows/miri.yaml
@@ -48,6 +48,7 @@ on:
       - arrow-schema/**
       - arrow-select/**
       - arrow-string/**
+      - parquet/**
 
 permissions:
   contents: read
@@ -57,8 +58,9 @@ jobs:
     name: MIRI
     runs-on: ubuntu-latest
     strategy:
+      fail-fast: false
       matrix:
-        partition: [1, 2, 3, 4, 5, 6]
+        partition: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
     steps:
       - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1  # 
v7.0.1
         with:
@@ -76,4 +78,4 @@ jobs:
         env:
           RUST_BACKTRACE: full
           RUST_LOG: "trace"
-        run: bash .github/workflows/miri.sh ${{ matrix.partition }} 6
+        run: bash .github/workflows/miri.sh ${{ matrix.partition }} 12
diff --git a/parquet/src/arrow/arrow_reader/mod.rs 
b/parquet/src/arrow/arrow_reader/mod.rs
index 006c1f452c..ab3e015455 100644
--- a/parquet/src/arrow/arrow_reader/mod.rs
+++ b/parquet/src/arrow/arrow_reader/mod.rs
@@ -2134,6 +2134,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_primitive_single_column_reader_test() {
         run_single_column_reader_tests::<BoolType, _, BoolType>(
             2,
@@ -2176,6 +2177,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_unsigned_primitive_single_column_reader_test() {
         run_single_column_reader_tests::<Int32Type, _, Int32Type>(
             2,
@@ -2499,6 +2501,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_fixed_length_binary_column_reader() {
         run_single_column_reader_tests::<FixedLenByteArrayType, _, 
RandFixedLenGen>(
             20,
@@ -2519,6 +2522,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_interval_day_time_column_reader() {
         run_single_column_reader_tests::<FixedLenByteArrayType, _, 
RandFixedLenGen>(
             12,
@@ -2543,6 +2547,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_int96_single_column_reader_test() {
         let encodings = &[Encoding::PLAIN, Encoding::RLE_DICTIONARY];
 
@@ -2626,6 +2631,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_utf8_single_column_reader_test() {
         fn string_converter<O: OffsetSizeTrait>(vals: &[Option<ByteArray>]) -> 
ArrayRef {
             Arc::new(GenericStringArray::<O>::from_iter(vals.iter().map(|x| {
@@ -2880,6 +2886,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_read_float16_nonzeros_file() {
         use arrow_array::Float16Array;
         let testdata = arrow::util::test_util::parquet_test_data();
@@ -2936,6 +2943,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Zstd calls native C functions unsupported by 
Miri
     fn test_read_float32_float64_byte_stream_split() {
         let path = format!(
             "{}/byte_stream_split.zstd.parquet",
@@ -2965,6 +2973,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_read_extended_byte_stream_split() {
         let path = format!(
             "{}/byte_stream_split_extended.gzip.parquet",
@@ -3769,6 +3778,7 @@ pub(crate) mod tests {
         File::open(path.as_path()).expect("File not found!")
     }
 
+    #[cfg_attr(miri, ignore)] // calls native Zstd code unsupported by Miri
     #[test]
     fn test_read_structs() {
         // This particular test file has columns of struct types where there is
@@ -3822,6 +3832,7 @@ pub(crate) mod tests {
         }
     }
 
+    #[cfg_attr(miri, ignore)] // calls native Zstd code unsupported by Miri
     #[test]
     // same as test_read_structs but constructs projection mask via column 
names
     fn test_read_structs_by_name() {
@@ -4704,6 +4715,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_row_group_exact_multiple() {
         const BATCH_SIZE: usize = REPETITION_LEVELS_BATCH_SIZE;
         test_row_group_batch(8, 8);
@@ -4801,6 +4813,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_scan_row_with_selection() {
         let testdata = arrow::util::test_util::parquet_test_data();
         let path = format!("{testdata}/alltypes_tiny_pages_plain.parquet");
@@ -4874,6 +4887,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_read_with_page_index_enabled() {
         let testdata = arrow::util::test_util::parquet_test_data();
 
@@ -5025,6 +5039,7 @@ pub(crate) mod tests {
     //
     // For more information, check: 
https://github.com/apache/arrow-rs/issues/2988
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_read_lz4_hadoop_fallback() {
         for file in [
             "hadoop_lz4_compressed.parquet",
@@ -5061,6 +5076,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_read_lz4_hadoop_large() {
         let testdata = arrow::util::test_util::parquet_test_data();
         let path = format!("{testdata}/hadoop_lz4_compressed_larger.parquet");
@@ -5302,6 +5318,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_list_selection() {
         let schema = Arc::new(Schema::new(vec![Field::new_list(
             "list",
@@ -5357,6 +5374,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_list_selection_fuzz() {
         let mut rng = rng();
         let schema = Arc::new(Schema::new(vec![Field::new_list(
@@ -5795,6 +5813,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_row_numbers_with_multiple_row_groups() {
         test_row_numbers_with_multiple_row_groups_helper(
             false,
@@ -5821,6 +5840,7 @@ pub(crate) mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_row_numbers_with_multiple_row_groups_and_filter() {
         test_row_numbers_with_multiple_row_groups_helper(
             true,
diff --git a/parquet/src/arrow/arrow_reader/read_plan.rs 
b/parquet/src/arrow/arrow_reader/read_plan.rs
index f5b436ad0a..0c27e61dae 100644
--- a/parquet/src/arrow/arrow_reader/read_plan.rs
+++ b/parquet/src/arrow/arrow_reader/read_plan.rs
@@ -546,6 +546,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn preferred_selection_strategy_mask_matches_selector_backing() {
         use rand::{RngExt, rng};
 
diff --git a/parquet/src/arrow/arrow_reader/selection/algebra.rs 
b/parquet/src/arrow/arrow_reader/selection/algebra.rs
index be8363f8ae..e0fda42b82 100644
--- a/parquet/src/arrow/arrow_reader/selection/algebra.rs
+++ b/parquet/src/arrow/arrow_reader/selection/algebra.rs
@@ -583,6 +583,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_and_fuzz() {
         let mut rand = rng();
         for _ in 0..100 {
@@ -880,6 +881,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_mask_algebra_with_offsets() {
         // Offsets and lengths that are not byte (or word) aligned on either 
side,
         // so the common prefix can start and end mid byte. Covers both the 
equal
@@ -928,6 +930,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_mask_algebra_does_not_retain_backing_buffer() {
         // A short slice of a long mask must not keep the long allocation 
alive,
         // including when the other operand is empty and contributes nothing.
@@ -951,6 +954,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_mask_algebra_fuzz() {
         let mut rng = rng();
         for _ in 0..200 {
diff --git a/parquet/src/arrow/arrow_reader/selection/boolean.rs 
b/parquet/src/arrow/arrow_reader/selection/boolean.rs
index 1196fac219..89a454b9c2 100644
--- a/parquet/src/arrow/arrow_reader/selection/boolean.rs
+++ b/parquet/src/arrow/arrow_reader/selection/boolean.rs
@@ -605,6 +605,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_mask_backing_fuzz_equivalence() {
         let mut rand = rng();
         for _ in 0..100 {
@@ -724,6 +725,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_boolean_mask_from_selectors_fuzz_equivalence() {
         let mut rand = rng();
         for _ in 0..200 {
@@ -777,6 +779,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_trim_mask_fuzz_equivalence() {
         let mut rand = rng();
         for _ in 0..200 {
diff --git a/parquet/src/arrow/arrow_writer/mod.rs 
b/parquet/src/arrow/arrow_writer/mod.rs
index a359314127..ac38a11f10 100644
--- a/parquet/src/arrow/arrow_writer/mod.rs
+++ b/parquet/src/arrow/arrow_writer/mod.rs
@@ -2215,6 +2215,7 @@ mod tests {
     /// no offset index to rebuild). Spans multiple data pages so the
     /// dictionary-first reordering is exercised.
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn dictionary_column_round_trips_with_offset_index_disabled() {
         let schema = Arc::new(Schema::new(vec![Field::new("k", 
DataType::Int32, true)]));
 
@@ -2396,6 +2397,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_non_null() {
         let schema = Schema::new(vec![Field::new("a", DataType::Int32, 
false)]);
         let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
@@ -2406,6 +2408,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_list() {
         // define schema
         let schema = Schema::new(vec![Field::new(
@@ -2441,6 +2444,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_list_non_null() {
         // define schema
         let schema = Schema::new(vec![Field::new(
@@ -2475,6 +2479,7 @@ mod tests {
     }
 
     #[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(
@@ -2499,6 +2504,7 @@ mod tests {
     }
 
     #[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(
@@ -2523,6 +2529,7 @@ mod tests {
     }
 
     #[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(
@@ -2547,6 +2554,7 @@ mod tests {
     }
 
     #[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(
@@ -2571,6 +2579,7 @@ mod tests {
     }
 
     #[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![
@@ -2611,6 +2620,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_binary() {
         let raw_string_values = vec!["foo", "bar", "baz", "quux"];
         let raw_binary_values = [
@@ -2634,6 +2644,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_binary_view() {
         let raw_string_values = vec!["foo", "bar", "large payload over 12 
bytes", "lulu"];
         let raw_binary_values = vec![
@@ -2655,6 +2666,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_binary_view_long_value() {
         // There is special case validation for long values (greater than 128)
         // 128 encodes as 0x80 0x00 0x00 0x00 in little endian, which should
@@ -2729,6 +2741,7 @@ mod tests {
     }
 
     #[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));
@@ -3181,6 +3194,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn arrow_writer_float_nans() {
         let f16_field = Field::new("a", DataType::Float16, false);
         let f32_field = Field::new("b", DataType::Float32, false);
@@ -3515,11 +3529,13 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn all_null_primitive_single_column() {
         let values = Arc::new(Int32Array::from(vec![None; SMALL_SIZE]));
         RoundTripTest::new(values).run();
     }
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn null_single_column() {
         let values = Arc::new(NullArray::new(SMALL_SIZE));
         RoundTripTest::new(values).run();
@@ -3527,6 +3543,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn bool_single_column() {
         required_and_optional::<BooleanArray, _>(
             [true, false].iter().cycle().copied().take(SMALL_SIZE),
@@ -3534,6 +3551,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn bool_large_single_column() {
         let values = Arc::new(
             [None, Some(true), Some(false)]
@@ -3688,51 +3706,61 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn i8_single_column() {
         required_and_optional::<Int8Array, _>(0..SMALL_SIZE as i8);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn i16_single_column() {
         required_and_optional::<Int16Array, _>(0..SMALL_SIZE as i16);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn i32_single_column() {
         required_and_optional::<Int32Array, _>(0..SMALL_SIZE as i32);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn i64_single_column() {
         required_and_optional::<Int64Array, _>(0..SMALL_SIZE as i64);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn u8_single_column() {
         required_and_optional::<UInt8Array, _>(0..SMALL_SIZE as u8);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn u16_single_column() {
         required_and_optional::<UInt16Array, _>(0..SMALL_SIZE as u16);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn u32_single_column() {
         required_and_optional::<UInt32Array, _>(0..SMALL_SIZE as u32);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn u64_single_column() {
         required_and_optional::<UInt64Array, _>(0..SMALL_SIZE as u64);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn f32_single_column() {
         required_and_optional::<Float32Array, _>((0..SMALL_SIZE).map(|i| i as 
f32));
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn f64_single_column() {
         required_and_optional::<Float64Array, _>((0..SMALL_SIZE).map(|i| i as 
f64));
     }
@@ -3742,6 +3770,7 @@ mod tests {
     // RoundTripTest manually instead of calling required_and_optional for 
these tests.
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn timestamp_second_single_column() {
         let raw_values: Vec<_> = (0..SMALL_SIZE as i64).collect();
         let values = Arc::new(TimestampSecondArray::from(raw_values));
@@ -3750,6 +3779,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn timestamp_millisecond_single_column() {
         let raw_values: Vec<_> = (0..SMALL_SIZE as i64).collect();
         let values = Arc::new(TimestampMillisecondArray::from(raw_values));
@@ -3758,6 +3788,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn timestamp_microsecond_single_column() {
         let raw_values: Vec<_> = (0..SMALL_SIZE as i64).collect();
         let values = Arc::new(TimestampMicrosecondArray::from(raw_values));
@@ -3766,6 +3797,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn timestamp_nanosecond_single_column() {
         let raw_values: Vec<_> = (0..SMALL_SIZE as i64).collect();
         let values = Arc::new(TimestampNanosecondArray::from(raw_values));
@@ -3774,11 +3806,13 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn date32_single_column() {
         required_and_optional::<Date32Array, _>(0..SMALL_SIZE as i32);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn date64_single_column() {
         // Date64 must be a multiple of 86400000, see ARROW-10925
         required_and_optional::<Date64Array, _>(
@@ -3787,51 +3821,61 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn time32_second_single_column() {
         required_and_optional::<Time32SecondArray, _>(0..SMALL_SIZE as i32);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn time32_millisecond_single_column() {
         required_and_optional::<Time32MillisecondArray, _>(0..SMALL_SIZE as 
i32);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn time64_microsecond_single_column() {
         required_and_optional::<Time64MicrosecondArray, _>(0..SMALL_SIZE as 
i64);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn time64_nanosecond_single_column() {
         required_and_optional::<Time64NanosecondArray, _>(0..SMALL_SIZE as 
i64);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn duration_second_single_column() {
         required_and_optional::<DurationSecondArray, _>(0..SMALL_SIZE as i64);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn duration_millisecond_single_column() {
         required_and_optional::<DurationMillisecondArray, _>(0..SMALL_SIZE as 
i64);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn duration_microsecond_single_column() {
         required_and_optional::<DurationMicrosecondArray, _>(0..SMALL_SIZE as 
i64);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn duration_nanosecond_single_column() {
         required_and_optional::<DurationNanosecondArray, _>(0..SMALL_SIZE as 
i64);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn interval_year_month_single_column() {
         required_and_optional::<IntervalYearMonthArray, _>(0..SMALL_SIZE as 
i32);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn interval_day_time_single_column() {
         required_and_optional::<IntervalDayTimeArray, _>(vec![
             IntervalDayTime::new(0, 1),
@@ -3855,6 +3899,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn binary_single_column() {
         let one_vec: Vec<u8> = (0..SMALL_SIZE as u8).collect();
         let many_vecs: Vec<_> = std::iter::repeat_n(one_vec, 
SMALL_SIZE).collect();
@@ -3865,6 +3910,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn binary_view_single_column() {
         let one_vec: Vec<u8> = (0..SMALL_SIZE as u8).collect();
         let many_vecs: Vec<_> = std::iter::repeat_n(one_vec, 
SMALL_SIZE).collect();
@@ -3875,6 +3921,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn i32_column_bloom_filter_at_end() {
         let array = Arc::new(Int32Array::from_iter(0..SMALL_SIZE as i32));
         let files = RoundTripTest::new(array)
@@ -3892,6 +3939,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn i32_column_bloom_filter() {
         let array = Arc::new(Int32Array::from_iter(0..SMALL_SIZE as i32));
         let files = RoundTripTest::new(array)
@@ -3912,6 +3960,7 @@ mod tests {
     /// A large NDV means a larger initial filter that gets folded down;
     /// a small NDV means a smaller initial filter.
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn i32_column_bloom_filter_fixed_ndv() {
         let array = Arc::new(Int32Array::from_iter(0..SMALL_SIZE as i32));
 
@@ -3945,6 +3994,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn binary_column_bloom_filter() {
         let one_vec: Vec<u8> = (0..SMALL_SIZE as u8).collect();
         let many_vecs: Vec<_> = std::iter::repeat_n(one_vec, 
SMALL_SIZE).collect();
@@ -3965,6 +4015,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn empty_string_null_column_bloom_filter() {
         let raw_values: Vec<_> = (0..SMALL_SIZE).map(|i| 
i.to_string()).collect();
         let raw_strs = raw_values.iter().map(|s| s.as_str());
@@ -3985,6 +4036,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn large_binary_single_column() {
         let one_vec: Vec<u8> = (0..SMALL_SIZE as u8).collect();
         let many_vecs: Vec<_> = std::iter::repeat_n(one_vec, 
SMALL_SIZE).collect();
@@ -3995,6 +4047,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn fixed_size_binary_single_column() {
         let mut builder = FixedSizeBinaryBuilder::new(4);
         builder.append_value(b"0123").unwrap();
@@ -4007,6 +4060,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn string_single_column() {
         let raw_values: Vec<_> = (0..SMALL_SIZE).map(|i| 
i.to_string()).collect();
         let raw_strs = raw_values.iter().map(|s| s.as_str());
@@ -4015,6 +4069,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn large_string_single_column() {
         let raw_values: Vec<_> = (0..SMALL_SIZE).map(|i| 
i.to_string()).collect();
         let raw_strs = raw_values.iter().map(|s| s.as_str());
@@ -4023,6 +4078,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn string_view_single_column() {
         let raw_values: Vec<_> = (0..SMALL_SIZE).map(|i| 
i.to_string()).collect();
         let raw_strs = raw_values.iter().map(|s| s.as_str());
@@ -4066,6 +4122,7 @@ mod tests {
     }
 
     #[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());
@@ -4089,6 +4146,7 @@ mod tests {
     }
 
     #[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());
@@ -4114,6 +4172,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn list_nested_nulls() {
         use arrow::datatypes::Int32Type;
         let data = vec![
@@ -4133,6 +4192,7 @@ mod tests {
     }
 
     #[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);
@@ -4150,6 +4210,7 @@ mod tests {
     }
 
     #[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));
@@ -4214,6 +4275,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn fallback_flush_data_page() {
         //tests if the Fallback::flush_data_page clears all buffers correctly
         let raw_values: Vec<_> = (0..MEDIUM_SIZE).map(|i| 
i.to_string()).collect();
@@ -4256,6 +4318,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_string_dictionary() {
         // define schema
         #[expect(deprecated)]
@@ -4509,6 +4572,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_primitive_dictionary() {
         // define schema
         #[expect(deprecated)]
@@ -4532,6 +4596,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_decimal32_dictionary() {
         let integers = vec![12345, 56789, 34567];
 
@@ -4553,6 +4618,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_decimal64_dictionary() {
         let integers = vec![12345, 56789, 34567];
 
@@ -4574,6 +4640,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_decimal128_dictionary() {
         let integers = vec![12345, 56789, 34567];
 
@@ -4595,6 +4662,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_decimal256_dictionary() {
         let integers = vec![
             i256::from_i128(12345),
@@ -4620,6 +4688,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn arrow_writer_string_dictionary_unsigned_index() {
         // define schema
         #[expect(deprecated)]
@@ -4641,6 +4710,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn u32_min_max() {
         // check values roundtrip through parquet
         let src = [
@@ -4687,6 +4757,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn u64_min_max() {
         // check values roundtrip through parquet
         let src = [
@@ -4733,6 +4804,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn statistics_null_counts_only_nulls() {
         // check that null-count statistics for "only NULL"-columns are correct
         let values = Arc::new(UInt64Array::from(vec![None, None]));
@@ -4752,6 +4824,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_list_of_struct_roundtrip() {
         // define schema
         let int_field = Field::new("a", DataType::Int32, true);
@@ -5593,6 +5666,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_different_dict_page_size_limit() {
         let array = Arc::new(Int64Array::from_iter(0..1024 * 1024));
         let schema = Arc::new(Schema::new(vec![
@@ -5631,6 +5705,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_arrow_writer_granular_mode_roundtrip() {
         // Granular mode subdivides chunks and writes more pages than the
         // default batched path. Make sure the data we write back is
@@ -5833,6 +5908,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     // A row limit far smaller than the batch splits it many times over; the 
split must not
     // consume stack proportional to the number of row groups.
     fn test_row_group_limit_rows_only_many_splits() {
@@ -6274,6 +6350,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_number_distinct_values_exact_count() {
         // 50 distinct Int32 values repeated across 100k rows, with every 7th 
row null.
         // Nulls must not be counted as a distinct value.
diff --git a/parquet/src/arrow/mod.rs b/parquet/src/arrow/mod.rs
index 9414337739..ff9924ffef 100644
--- a/parquet/src/arrow/mod.rs
+++ b/parquet/src/arrow/mod.rs
@@ -553,6 +553,7 @@ mod test {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_metadata_read_write_roundtrip_page_index() {
         let parquet_bytes = create_parquet_file();
 
diff --git a/parquet/src/bloom_filter/mod.rs b/parquet/src/bloom_filter/mod.rs
index f92a04dd31..5e8273701d 100644
--- a/parquet/src/bloom_filter/mod.rs
+++ b/parquet/src/bloom_filter/mod.rs
@@ -772,6 +772,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_mask_set_quick_check() {
         for i in 0..1_000_000 {
             let result = Block::mask(i);
@@ -780,6 +781,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_block_insert_and_check() {
         for i in 0..1_000_000 {
             let mut block = Block::ZERO;
@@ -789,6 +791,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_sbbf_insert_and_check() {
         let mut sbbf = Sbbf(vec![Block::ZERO; 1_000]);
         for i in 0..1_000_000 {
@@ -1031,6 +1034,7 @@ mod tests {
     /// Combined: every hash sets the *same bits* in the *same destination
     /// block* whether you fold or build fresh → filters are bit-identical.
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_sbbf_folded_equals_fresh() {
         let values = (0..5000).map(|i| 
format!("elem_{i}")).collect::<Vec<_>>();
         let hashes = values
@@ -1128,6 +1132,7 @@ mod tests {
     /// At each intermediate size we build a fresh filter and assert
     /// bit-equality, confirming the lemma composes across folds.
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_multi_step_fold() {
         let values = (0..3000).map(|i| format!("x_{i}")).collect::<Vec<_>>();
 
@@ -1157,6 +1162,7 @@ mod tests {
     ///
     /// compare the final size after folding against the theoretical optimal 
size
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_fold_size_vs_optimal_fixed_size() {
         for (ndv, target_fpp) in [
             (1000, 0.05),
@@ -1191,6 +1197,7 @@ mod tests {
     /// we measure fpp empirically by probing with values that were never 
inserted
     /// and counting how many are incorrectly marked as present
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_folded_fpp_matches_fresh_fpp() {
         let ndv = 2000;
         let num_probes = 50_000;
diff --git a/parquet/src/column/chunker/cdc.rs 
b/parquet/src/column/chunker/cdc.rs
index a0d6899adc..f524250b1b 100644
--- a/parquet/src/column/chunker/cdc.rs
+++ b/parquet/src/column/chunker/cdc.rs
@@ -1390,6 +1390,7 @@ mod arrow_tests {
                 }
 
                 #[test]
+                #[cfg_attr(miri, ignore)] // Takes too long
                 fn delete_once() {
                     let (dtype, nullable, part_length, edit_length) = config();
                     let schema = make_schema(&dtype, nullable);
@@ -1451,6 +1452,7 @@ mod arrow_tests {
                 }
 
                 #[test]
+                #[cfg_attr(miri, ignore)] // Takes too long
                 fn delete_twice() {
                     let (dtype, nullable, part_length, edit_length) = config();
                     let schema = make_schema(&dtype, nullable);
@@ -1514,6 +1516,7 @@ mod arrow_tests {
                 }
 
                 #[test]
+                #[cfg_attr(miri, ignore)] // Takes too long
                 fn insert_once() {
                     let (dtype, nullable, part_length, edit_length) = config();
                     let schema = make_schema(&dtype, nullable);
@@ -1575,6 +1578,7 @@ mod arrow_tests {
                 }
 
                 #[test]
+                #[cfg_attr(miri, ignore)] // Takes too long
                 fn insert_twice() {
                     let (dtype, nullable, part_length, edit_length) = config();
                     let schema = make_schema(&dtype, nullable);
@@ -1638,6 +1642,7 @@ mod arrow_tests {
                 }
 
                 #[test]
+                #[cfg_attr(miri, ignore)] // Takes too long
                 fn update_once() {
                     let (dtype, nullable, part_length, edit_length) = config();
                     let schema = make_schema(&dtype, nullable);
@@ -1693,6 +1698,7 @@ mod arrow_tests {
                 }
 
                 #[test]
+                #[cfg_attr(miri, ignore)] // Takes too long
                 fn update_twice() {
                     let (dtype, nullable, part_length, edit_length) = config();
                     let schema = make_schema(&dtype, nullable);
@@ -1751,6 +1757,7 @@ mod arrow_tests {
                 }
 
                 #[test]
+                #[cfg_attr(miri, ignore)] // Takes too long
                 fn prepend() {
                     let (dtype, nullable, part_length, edit_length) = config();
                     let schema = make_schema(&dtype, nullable);
@@ -1818,6 +1825,7 @@ mod arrow_tests {
                 }
 
                 #[test]
+                #[cfg_attr(miri, ignore)] // Takes too long
                 fn append() {
                     let (dtype, nullable, part_length, edit_length) = config();
                     let schema = make_schema(&dtype, nullable);
@@ -1901,6 +1909,7 @@ mod arrow_tests {
                 }
 
                 #[test]
+                #[cfg_attr(miri, ignore)] // Takes too long
                 fn array_offsets() {
                     let (dtype, nullable, part_length, edit_length) = config();
                     let schema = make_schema(&dtype, nullable);
@@ -1974,6 +1983,7 @@ mod arrow_tests {
         }
 
         #[test]
+        #[cfg_attr(miri, ignore)] // Takes too long
         fn insert_once() {
             let s = schema();
             let part1 = generate_table(&s, PART_LENGTH, 0);
@@ -2036,6 +2046,7 @@ mod arrow_tests {
         }
 
         #[test]
+        #[cfg_attr(miri, ignore)] // Takes too long
         fn delete_once() {
             let s = schema();
             let part1 = generate_table(&s, PART_LENGTH, 0);
@@ -2094,6 +2105,7 @@ mod arrow_tests {
         }
 
         #[test]
+        #[cfg_attr(miri, ignore)] // Takes too long
         fn update_once() {
             let s = schema();
             let part1 = generate_table(&s, PART_LENGTH, 0);
@@ -2153,6 +2165,7 @@ mod arrow_tests {
         }
 
         #[test]
+        #[cfg_attr(miri, ignore)] // Takes too long
         fn append() {
             let s = schema();
             let part1 = generate_table(&s, PART_LENGTH, 0);
@@ -2216,6 +2229,7 @@ mod arrow_tests {
     // --- Direct chunker test (kept from original) ---
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_cdc_array_offsets_direct() {
         use crate::basic::Type as PhysicalType;
         use crate::schema::types::{ColumnDescriptor, ColumnPath, Type};
@@ -2271,6 +2285,7 @@ mod arrow_tests {
     /// Writing nested list data with CDC enabled panicked with an 
out-of-bounds
     /// slice access when null list entries had non-zero child ranges.
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_cdc_list_roundtrip() {
         let schema = Arc::new(Schema::new(vec![
             Field::new(
@@ -2301,6 +2316,7 @@ mod arrow_tests {
 
     /// Test CDC with deeply nested types: List<List<Int32>>, 
List<Struct<List<Int32>>>
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_cdc_deeply_nested_roundtrip() {
         let inner_field = Field::new_list_field(DataType::Int32, true);
         let inner_type = DataType::List(Arc::new(inner_field));
diff --git a/parquet/src/column/reader/decoder.rs 
b/parquet/src/column/reader/decoder.rs
index ee619ddef8..b7b2cae2c1 100644
--- a/parquet/src/column/reader/decoder.rs
+++ b/parquet/src/column/reader/decoder.rs
@@ -514,6 +514,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_skip_rep_levels() {
         for _ in 0..10 {
             let mut rng = rng();
diff --git a/parquet/src/column/writer/mod.rs b/parquet/src/column/writer/mod.rs
index 8b6f33cc35..c0b7ee04ad 100644
--- a/parquet/src/column/writer/mod.rs
+++ b/parquet/src/column/writer/mod.rs
@@ -2850,6 +2850,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_column_writer_small_write_batch_size() {
         for i in &[1usize, 2, 5, 10, 11, 1023] {
             let props = 
WriterProperties::builder().set_write_batch_size(*i).build();
@@ -3726,6 +3727,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_column_writer_check_float16_min_max() {
         let input = [
             -f16::ONE,
@@ -3750,6 +3752,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_column_writer_check_float16_nan_middle() {
         let input = [f16::ONE, f16::NAN, f16::ONE + f16::ONE]
             .into_iter()
@@ -3767,6 +3770,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_float16_statistics_nan_middle() {
         let input = [f16::ONE, f16::NAN, f16::ONE + f16::ONE]
             .into_iter()
@@ -3784,6 +3788,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_float16_statistics_nan_start() {
         let input = [f16::NAN, f16::ONE, f16::ONE + f16::ONE]
             .into_iter()
diff --git a/parquet/src/compression.rs b/parquet/src/compression.rs
index 04f9256b9c..74d740348a 100644
--- a/parquet/src/compression.rs
+++ b/parquet/src/compression.rs
@@ -916,12 +916,14 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_codec_snappy() {
         test_codec_with_size(CodecType::SNAPPY);
         test_codec_without_size(CodecType::SNAPPY);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_codec_gzip() {
         for level in GzipLevel::MINIMUM_LEVEL..=GzipLevel::MAXIMUM_LEVEL {
             let level = GzipLevel::try_new(level).unwrap();
@@ -931,6 +933,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_codec_brotli() {
         for level in BrotliLevel::MINIMUM_LEVEL..=BrotliLevel::MAXIMUM_LEVEL {
             let level = BrotliLevel::try_new(level).unwrap();
@@ -940,11 +943,13 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_codec_lz4() {
         test_codec_with_size(CodecType::LZ4);
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Zstd calls native C functions unsupported by 
Miri
     fn test_codec_zstd() {
         // since ZstdLevel::MINIMUM_LEVEL is a large negative number, we test 
a smaller range
         for level in
@@ -957,6 +962,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_codec_lz4_raw() {
         test_codec_with_size(CodecType::LZ4_RAW);
     }
diff --git a/parquet/src/encodings/decoding.rs 
b/parquet/src/encodings/decoding.rs
index 2b2bae302e..ad88ae3415 100644
--- a/parquet/src/encodings/decoding.rs
+++ b/parquet/src/encodings/decoding.rs
@@ -1989,6 +1989,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_delta_bit_packed_int32_single_value_skip_large() {
         let block_data = vec![3; 10240];
         test_skip::<Int32Type>(block_data.clone(), 
Encoding::DELTA_BINARY_PACKED, 50);
@@ -2002,6 +2003,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_delta_bit_packed_int32_increasing_value_skip_large() {
         let block_data = (0i32..10240).collect::<Vec<i32>>();
         test_skip::<Int32Type>(block_data.clone(), 
Encoding::DELTA_BINARY_PACKED, 50);
@@ -2015,6 +2017,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_delta_bit_packed_int32_stepped_value_skip_large() {
         let block_data = (0i32..10240).map(|i| i / 2).collect::<Vec<i32>>();
         test_skip::<Int32Type>(block_data.clone(), 
Encoding::DELTA_BINARY_PACKED, 50);
diff --git a/parquet/src/encodings/encoding/mod.rs 
b/parquet/src/encodings/encoding/mod.rs
index 6932450bfa..f6235696dc 100644
--- a/parquet/src/encodings/encoding/mod.rs
+++ b/parquet/src/encodings/encoding/mod.rs
@@ -812,6 +812,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_i32() {
         Int32Type::test(Encoding::PLAIN, TEST_SET_SIZE, -1);
         Int32Type::test(Encoding::PLAIN_DICTIONARY, TEST_SET_SIZE, -1);
@@ -820,6 +821,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_i64() {
         Int64Type::test(Encoding::PLAIN, TEST_SET_SIZE, -1);
         Int64Type::test(Encoding::PLAIN_DICTIONARY, TEST_SET_SIZE, -1);
@@ -828,6 +830,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_i96() {
         Int96Type::test(Encoding::PLAIN, TEST_SET_SIZE, -1);
         Int96Type::test(Encoding::PLAIN_DICTIONARY, TEST_SET_SIZE, -1);
@@ -841,6 +844,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_double() {
         DoubleType::test(Encoding::PLAIN, TEST_SET_SIZE, -1);
         DoubleType::test(Encoding::PLAIN_DICTIONARY, TEST_SET_SIZE, -1);
@@ -848,6 +852,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_byte_array() {
         ByteArrayType::test(Encoding::PLAIN, TEST_SET_SIZE, -1);
         ByteArrayType::test(Encoding::PLAIN_DICTIONARY, TEST_SET_SIZE, -1);
@@ -856,6 +861,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_fixed_len_byte_array() {
         FixedLenByteArrayType::test(Encoding::PLAIN, TEST_SET_SIZE, 100);
         FixedLenByteArrayType::test(Encoding::PLAIN_DICTIONARY, TEST_SET_SIZE, 
100);
diff --git a/parquet/src/encodings/rle.rs b/parquet/src/encodings/rle.rs
index 95538dfb41..68de2487fd 100644
--- a/parquet/src/encodings/rle.rs
+++ b/parquet/src/encodings/rle.rs
@@ -979,6 +979,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_values() {
         for width in 1..MAX_WIDTH + 1 {
             test_rle_values(width, 1, -1);
@@ -1179,6 +1180,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_random() {
         let seed_len = 32;
         let niters = 50;
diff --git a/parquet/src/file/metadata/reader.rs 
b/parquet/src/file/metadata/reader.rs
index 73c3be2237..018cf440cd 100644
--- a/parquet/src/file/metadata/reader.rs
+++ b/parquet/src/file/metadata/reader.rs
@@ -875,6 +875,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_try_parse() {
         let file = get_test_file("alltypes_tiny_pages.parquet");
         let len = file.len();
diff --git a/parquet/src/file/serialized_reader.rs 
b/parquet/src/file/serialized_reader.rs
index ed035d66ad..bc525a78ab 100644
--- a/parquet/src/file/serialized_reader.rs
+++ b/parquet/src/file/serialized_reader.rs
@@ -1555,6 +1555,7 @@ mod tests {
         assert_eq!(page_count, 2);
     }
 
+    #[cfg_attr(miri, ignore)] // calls native Zstd code unsupported by Miri
     #[test]
     fn test_file_reader_empty_compressed_datapage_v2() {
         // this file has a compressed datapage that un-compresses to 0 bytes
@@ -2055,6 +2056,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_file_reader_filter_row_groups_and_range() -> Result<()> {
         let test_file = get_test_file("alltypes_tiny_pages.parquet");
         let origin_reader = SerializedFileReader::new(test_file)?;
@@ -2185,6 +2187,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_page_index_reader_all_type() {
         let test_file = get_test_file("alltypes_tiny_pages_plain.parquet");
         let builder = ReadOptionsBuilder::new();
@@ -2496,6 +2499,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_skip_next_page_with_dictionary_page() {
         let test_file = get_test_file("alltypes_tiny_pages.parquet");
         let builder = ReadOptionsBuilder::new();
@@ -2542,6 +2546,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_skip_page_with_offset_index() {
         let test_file = get_test_file("alltypes_tiny_pages_plain.parquet");
         let builder = ReadOptionsBuilder::new();
@@ -2602,6 +2607,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_peek_page_with_dictionary_page() {
         let test_file = get_test_file("alltypes_tiny_pages.parquet");
         let builder = ReadOptionsBuilder::new();
@@ -2754,6 +2760,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_byte_stream_split_extended() {
         let path = format!(
             "{}/byte_stream_split_extended.gzip.parquet",
diff --git a/parquet/src/file/writer.rs b/parquet/src/file/writer.rs
index 6bdc2f885f..62c1157b7f 100644
--- a/parquet/src/file/writer.rs
+++ b/parquet/src/file/writer.rs
@@ -2353,6 +2353,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_32k_rowgroups() {
         let message_type = "
             message test_schema {
@@ -2502,6 +2503,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     #[cfg(feature = "arrow")]
     fn test_byte_stream_split_extended_roundtrip() {
         let path = format!(
@@ -2616,6 +2618,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_rewrite_no_page_indexes() {
         let file = get_test_file("alltypes_tiny_pages.parquet");
         let metadata = ParquetMetaDataReader::new()
@@ -2647,6 +2650,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_rewrite_missing_column_index() {
         // this file has an INT96 column that lacks a column index entry
         let file = get_test_file("alltypes_tiny_pages.parquet");
diff --git a/parquet/src/record/api.rs b/parquet/src/record/api.rs
index 665a54edb1..6f5d072dc0 100644
--- a/parquet/src/record/api.rs
+++ b/parquet/src/record/api.rs
@@ -1360,6 +1360,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_convert_float16_to_string() {
         assert_eq!(format!("{}", Field::Float16(f16::ONE)), "1.0");
         assert_eq!(format!("{}", Field::Float16(f16::PI)), "3.140625");
@@ -1434,6 +1435,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_row_display() {
         // Primitive types
         assert_eq!(format!("{}", Field::Null), "null");
@@ -1557,6 +1559,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_row_primitive_field_fmt() {
         // Primitives types
         let row = Row::new(vec![
@@ -1647,6 +1650,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_row_primitive_accessors() {
         // primitives
         let row = Row::new(vec![
@@ -1756,6 +1760,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_row_primitive_invalid_accessors() {
         // primitives
         let row = Row::new(vec![
@@ -1863,6 +1868,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_list_primitive_accessors() {
         // primitives
         let list = make_list(vec![Field::Bool(false)]);
@@ -2047,6 +2053,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // inline assembly is not supported
     fn test_to_json_value() {
         assert_eq!(Field::Null.to_json_value(), Value::Null);
         assert_eq!(Field::Bool(true).to_json_value(), Value::Bool(true));
diff --git a/parquet/src/record/reader.rs b/parquet/src/record/reader.rs
index 28b93b5d45..2e2ddd4db5 100644
--- a/parquet/src/record/reader.rs
+++ b/parquet/src/record/reader.rs
@@ -932,6 +932,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_file_reader_rows_nonnullable() {
         let rows = test_file_reader_rows("nonnullable.impala.parquet", 
None).unwrap();
         let expected_rows = vec![row![
@@ -977,6 +978,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_file_reader_rows_nullable() {
         let rows = test_file_reader_rows("nullable.impala.parquet", 
None).unwrap();
         let expected_rows = vec![
diff --git a/parquet/src/record/triplet.rs b/parquet/src/record/triplet.rs
index 440e765c20..4c60c571cc 100644
--- a/parquet/src/record/triplet.rs
+++ b/parquet/src/record/triplet.rs
@@ -396,6 +396,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_triplet_required_column() {
         let path = vec!["ID"];
         let values = vec![Field::Long(8)];
@@ -411,6 +412,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_triplet_optional_column() {
         let path = vec!["nested_struct", "A"];
         let values = vec![Field::Int(1), Field::Int(7)];
@@ -426,6 +428,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_triplet_optional_list_column() {
         let path = vec!["a", "list", "element", "list", "element", "list", 
"element"];
         let values = vec![
@@ -457,6 +460,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_triplet_optional_map_column() {
         let path = vec!["a", "key_value", "value", "key_value", "key"];
         let values = vec![
diff --git a/parquet/src/util/bit_util.rs b/parquet/src/util/bit_util.rs
index ca61a885fd..20ce146463 100644
--- a/parquet/src/util/bit_util.rs
+++ b/parquet/src/util/bit_util.rs
@@ -1302,6 +1302,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_get_batch() {
         const SIZE: &[usize] = &[1, 31, 32, 33, 128, 129];
         for s in SIZE {
diff --git a/parquet/src/util/prefix.rs b/parquet/src/util/prefix.rs
index 1e2c743aac..696c12910e 100644
--- a/parquet/src/util/prefix.rs
+++ b/parquet/src/util/prefix.rs
@@ -83,6 +83,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_common_prefix_length_around_block_boundaries() {
         // Mismatches placed on, either side of, and well past the 32-byte
         // block boundary the scan steps in.
@@ -105,6 +106,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // Takes too long
     fn test_common_prefix_length_unequal_lengths() {
         // Result is capped by the shorter value even when the longer one
         // continues to match, across block boundaries.
diff --git a/parquet/tests/arrow_reader/bad_data.rs 
b/parquet/tests/arrow_reader/bad_data.rs
index fb5f42c324..8587d15230 100644
--- a/parquet/tests/arrow_reader/bad_data.rs
+++ b/parquet/tests/arrow_reader/bad_data.rs
@@ -88,6 +88,7 @@ fn test_parquet_1481() {
 }
 
 #[test]
+#[cfg_attr(miri, ignore)] // Takes too long
 fn test_arrow_gh_41321() {
     let err = read_file("ARROW-GH-41321.parquet").unwrap_err();
     assert_eq!(
@@ -108,9 +109,10 @@ fn test_arrow_gh_41317() {
 #[test]
 fn test_arrow_rs_gh_6229_dict_header() {
     let err = read_file("ARROW-RS-GH-6229-DICTHEADER.parquet").unwrap_err();
-    assert_eq!(
-        err.to_string(),
-        "External: Parquet argument error: Parquet error: Integer overflow: 
out of range integral type conversion attempted"
+    let message = err.to_string();
+    assert!(
+        message.starts_with("External: Parquet argument error: Parquet error: 
Integer overflow:"),
+        "unexpected error: {message}"
     );
 }
 
@@ -160,6 +162,7 @@ fn read_file(name: &str) -> Result<usize, ParquetError> {
     Ok(num_rows)
 }
 
+#[cfg_attr(miri, ignore)] // calls native Zstd code unsupported by Miri
 #[test]
 fn non_standard_delta_blocks() {
     let file = Bytes::from_static(include_bytes!("bigdelta.parquet"));
diff --git a/parquet/tests/arrow_reader/bloom_filter/sync.rs 
b/parquet/tests/arrow_reader/bloom_filter/sync.rs
index 90d0cdc509..ef5c6c0892 100644
--- a/parquet/tests/arrow_reader/bloom_filter/sync.rs
+++ b/parquet/tests/arrow_reader/bloom_filter/sync.rs
@@ -24,6 +24,7 @@ use parquet::{
 };
 
 #[test]
+#[cfg_attr(miri, ignore)] // Takes too long
 fn test_get_row_group_column_bloom_filter_with_length() {
     // convert to new parquet file with bloom_filter_length
     let testdata = arrow::util::test_util::parquet_test_data();
diff --git a/parquet/tests/arrow_reader/statistics.rs 
b/parquet/tests/arrow_reader/statistics.rs
index 11d6fac48e..0311428cb7 100644
--- a/parquet/tests/arrow_reader/statistics.rs
+++ b/parquet/tests/arrow_reader/statistics.rs
@@ -373,6 +373,7 @@ impl Test<'_> {
 // Remaining cases
 //   f64::NAN
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_max_and_min_value_truncated() {
     let reader = TestReader {
@@ -416,6 +417,7 @@ async fn test_max_and_min_value_truncated() {
     .run()
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_one_row_group_without_null() {
     let reader = Int64Case {
@@ -446,6 +448,7 @@ async fn test_one_row_group_without_null() {
     .run()
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_one_row_group_with_null_and_negative() {
     let reader = Int64Case {
@@ -476,6 +479,7 @@ async fn test_one_row_group_with_null_and_negative() {
     .run()
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_two_row_group_with_null() {
     let reader = Int64Case {
@@ -506,6 +510,7 @@ async fn test_two_row_group_with_null() {
     .run()
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_two_row_groups_with_all_nulls_in_one() {
     let reader = Int64Case {
@@ -535,6 +540,7 @@ async fn test_two_row_groups_with_all_nulls_in_one() {
     .run()
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_multiple_data_pages_nulls_and_negatives() {
     let reader = Int64Case {
@@ -568,6 +574,7 @@ async fn test_multiple_data_pages_nulls_and_negatives() {
     .run()
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_data_page_stats_with_all_null_page() {
     for data_type in &[
@@ -642,6 +649,7 @@ async fn test_data_page_stats_with_all_null_page() {
 // . Different row group sizes
 
 // Four different integer types
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_int_64() {
     // This creates a parquet files of 4 columns named "i8", "i16", "i32", 
"i64"
@@ -672,6 +680,7 @@ async fn test_int_64() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_int_32() {
     // This creates a parquet files of 4 columns named "i8", "i16", "i32", 
"i64"
@@ -701,6 +710,7 @@ async fn test_int_32() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_int_16() {
     // This creates a parquet files of 4 columns named "i8", "i16", "i32", 
"i64"
@@ -730,6 +740,7 @@ async fn test_int_16() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_int_8() {
     // This creates a parquet files of 4 columns named "i8", "i16", "i32", 
"i64"
@@ -759,6 +770,7 @@ async fn test_int_8() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_float_16() {
     // This creates a parquet files of 1 column named f
@@ -798,6 +810,7 @@ async fn test_float_16() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_float_32() {
     // This creates a parquet files of 1 column named f
@@ -827,6 +840,7 @@ async fn test_float_32() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_float_64() {
     // This creates a parquet files of 1 column named f
@@ -857,6 +871,7 @@ async fn test_float_64() {
 }
 
 // timestamp
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_timestamp() {
     // This creates a parquet files of 9 columns named "nanos", 
"nanos_timezoned", "micros", "micros_timezoned", "millis", "millis_timezoned", 
"seconds", "seconds_timezoned", "names"
@@ -1116,6 +1131,7 @@ async fn test_timestamp() {
 }
 
 // timestamp with different row group sizes
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_timestamp_diff_rg_sizes() {
     // This creates a parquet files of 9 columns named "nanos", 
"nanos_timezoned", "micros", "micros_timezoned", "millis", "millis_timezoned", 
"seconds", "seconds_timezoned", "names"
@@ -1354,6 +1370,7 @@ async fn test_timestamp_diff_rg_sizes() {
 }
 
 // date with different row group sizes
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_dates_32_diff_rg_sizes() {
     // This creates a parquet files of 3 columns named "date32", "date64", 
"names"
@@ -1394,6 +1411,7 @@ async fn test_dates_32_diff_rg_sizes() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_time32_second_diff_rg_sizes() {
     let reader = TestReader {
@@ -1420,6 +1438,7 @@ async fn test_time32_second_diff_rg_sizes() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_time32_millisecond_diff_rg_sizes() {
     let reader = TestReader {
@@ -1450,6 +1469,7 @@ async fn test_time32_millisecond_diff_rg_sizes() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_time64_microsecond_diff_rg_sizes() {
     let reader = TestReader {
@@ -1486,6 +1506,7 @@ async fn test_time64_microsecond_diff_rg_sizes() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_time64_nanosecond_diff_rg_sizes() {
     let reader = TestReader {
@@ -1522,6 +1543,7 @@ async fn test_time64_nanosecond_diff_rg_sizes() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_dates_64_diff_rg_sizes() {
     // The file is created by 4 record batches (each has a null row), each has 
5 rows but then will be split into 2 row groups with size 13, 7
@@ -1552,6 +1574,7 @@ async fn test_dates_64_diff_rg_sizes() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_uint() {
     // This creates a parquet files of 4 columns named "u8", "u16", "u32", 
"u64"
@@ -1625,6 +1648,7 @@ async fn test_uint() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_int32_range() {
     // This creates a parquet file of 1 column "i"
@@ -1651,6 +1675,7 @@ async fn test_int32_range() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_uint32_range() {
     // This creates a parquet file of 1 column "u"
@@ -1677,6 +1702,7 @@ async fn test_uint32_range() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_numeric_limits_unsigned() {
     // file has 7 rows, 2 row groups: one with 5 rows, one with 2 rows.
@@ -1744,6 +1770,7 @@ async fn test_numeric_limits_unsigned() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_numeric_limits_signed() {
     // file has 7 rows, 2 row groups: one with 5 rows, one with 2 rows.
@@ -1811,6 +1838,7 @@ async fn test_numeric_limits_signed() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_numeric_limits_float() {
     // file has 7 rows, 2 row groups: one with 5 rows, one with 2 rows.
@@ -1878,6 +1906,7 @@ async fn test_numeric_limits_float() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_float64() {
     // This creates a parquet file of 1 column "f"
@@ -1905,6 +1934,7 @@ async fn test_float64() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_float16() {
     // This creates a parquet file of 1 column "f"
@@ -1942,6 +1972,7 @@ async fn test_float16() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_decimal32() {
     // This creates a parquet file of 1 column "decimal32_col" with decimal 
data type and precision 9, scale 2
@@ -1975,6 +2006,7 @@ async fn test_decimal32() {
     }
     .run();
 }
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_decimal64() {
     // This creates a parquet file of 1 column "decimal64_col" with decimal 
data type and precision 9, scale 2
@@ -2008,6 +2040,7 @@ async fn test_decimal64() {
     }
     .run();
 }
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_decimal128() {
     // This creates a parquet file of 1 column "decimal128_col" with decimal 
data type and precision 9, scale 2
@@ -2041,6 +2074,7 @@ async fn test_decimal128() {
     }
     .run();
 }
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_decimal_256() {
     // This creates a parquet file of 1 column "decimal256_col" with decimal 
data type and precicion 9, scale 2
@@ -2074,6 +2108,7 @@ async fn test_decimal_256() {
     }
     .run();
 }
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_dictionary() {
     let reader = TestReader {
@@ -2126,6 +2161,7 @@ async fn test_dictionary() {
     .run();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_byte() {
     // This creates a parquet file of 5 columns
@@ -2257,6 +2293,7 @@ async fn test_byte() {
 }
 
 // PeriodsInColumnNames
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_period_in_column_names() {
     // This creates a parquet file of 2 columns "name" and "service.name"
@@ -2308,6 +2345,7 @@ async fn test_period_in_column_names() {
 }
 
 // Boolean
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_boolean() {
     // This creates a parquet files of 1 column named "bool"
@@ -2364,6 +2402,7 @@ async fn test_struct() {
 }
 
 // UTF8
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_utf8() {
     let reader = TestReader {
@@ -2405,6 +2444,7 @@ async fn test_utf8() {
 }
 
 // UTF8View
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_utf8_view() {
     let reader = TestReader {
@@ -2435,6 +2475,7 @@ async fn test_utf8_view() {
 }
 
 // BinaryView
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_binary_view() {
     let reader = TestReader {
@@ -2466,6 +2507,7 @@ async fn test_binary_view() {
 
 ////// Files with missing statistics ///////
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_missing_statistics() {
     let reader = Int64Case {
@@ -2553,6 +2595,7 @@ fn bool_arrow_and_parquet_schema() -> (SchemaRef, 
SchemaDescPtr) {
 
 /////// NEGATIVE TESTS ///////
 // column not found
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_column_not_found() {
     let reader = TestReader {
@@ -2576,6 +2619,7 @@ async fn test_column_not_found() {
     .run_col_not_found();
 }
 
+#[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
 #[tokio::test]
 async fn test_column_non_existent() {
     // Create a schema with an additional column
@@ -2896,6 +2940,7 @@ mod test {
         }
     }
 
+    #[cfg_attr(miri, ignore)] // tempfile::reopen triggers an unsupported 
Miri/rustix fstat path
     #[test]
     fn struct_leaf_statistics_from_column_index() {
         let leaf_field = Arc::new(Field::new("leaf", DataType::Int32, true));
diff --git a/parquet/tests/arrow_writer/layout.rs 
b/parquet/tests/arrow_writer/layout.rs
index 04f0a9cbed..483553e2d8 100644
--- a/parquet/tests/arrow_writer/layout.rs
+++ b/parquet/tests/arrow_writer/layout.rs
@@ -182,6 +182,7 @@ fn assert_layout(file_reader: &Bytes, meta: 
&ParquetMetaData, layout: &Layout) {
 }
 
 #[test]
+#[cfg_attr(miri, ignore)] // Takes too long
 fn test_primitive() {
     let array = Arc::new(Int32Array::from_iter_values(0..2000)) as _;
     let batch = RecordBatch::try_from_iter([("col", array)]).unwrap();
@@ -359,6 +360,7 @@ fn test_primitive() {
 }
 
 #[test]
+#[cfg_attr(miri, ignore)] // Takes too long
 fn test_string() {
     let array = Arc::new(StringArray::from_iter_values(
         (0..2000).map(|x| format!("{x:04}")),
@@ -616,6 +618,7 @@ fn test_per_column_data_page_size_limit() {
 }
 
 #[test]
+#[cfg_attr(miri, ignore)] // Takes too long
 fn test_fixed_size_binary() {
     // FixedSizeBinary values larger than the data page byte limit.
     let value_size = 1024usize;
diff --git a/parquet/tests/arrow_writer/mod.rs 
b/parquet/tests/arrow_writer/mod.rs
index 2ba2aab6a4..80d4d0da56 100644
--- a/parquet/tests/arrow_writer/mod.rs
+++ b/parquet/tests/arrow_writer/mod.rs
@@ -317,6 +317,7 @@ fn write_dict_dataset(options: ArrowWriterOptions) {
 /// fine), but keeping them together also keeps the in-memory/spill comparison 
on
 /// one consistent baseline.
 #[test]
+#[cfg_attr(miri, ignore)] // Takes too long
 fn page_store_bounds_write_memory() {
     let props = single_row_group_props();
 
@@ -522,6 +523,7 @@ fn write_dict_columns(page_store_factory: Option<Arc<dyn 
PageStoreFactory>>, poo
 /// off the heap as its column closes, so at most one is ever resident, keeping
 /// the spilling peak far below the in-memory K × dict_page baseline.
 #[test]
+#[cfg_attr(miri, ignore)] // Takes too long
 fn page_store_spills_dictionary_pages() {
     // Build the distinct-value pool up front so its bytes sit in the baseline
     // and are not charged to either per-run peak below.
diff --git a/parquet/tests/ieee754_nan_interop.rs 
b/parquet/tests/ieee754_nan_interop.rs
index ec8e6548f8..3d99a84133 100644
--- a/parquet/tests/ieee754_nan_interop.rs
+++ b/parquet/tests/ieee754_nan_interop.rs
@@ -254,6 +254,7 @@ fn test_ieee754_interop() {
 // This test replicates the data produced by the parquet-java code that 
generated
 // parquet-testing/data/floating_orders_nan_count.parquet
 #[test]
+#[cfg_attr(miri, ignore)] // inline assembly is not supported
 fn test_ieee754_interop2() {
     // define schema
     let schema = Schema::new(vec![

Reply via email to