Skip to content

Encapsulate parquet round trip test logic in struct - #10545

Merged
alamb merged 3 commits into
apache:mainfrom
alamb:alamb/encapsulate_round_trp
Aug 6, 2026
Merged

Encapsulate parquet round trip test logic in struct#10545
alamb merged 3 commits into
apache:mainfrom
alamb:alamb/encapsulate_round_trp

Conversation

@alamb

@alamb alamb commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

I am trying to understand the depth of our round trip tests (there are over 4000
lines of tests in the arrow writer module). After some study it appears there
are tests to round trip both single columns and record batches, which share some
non trivial amount of logic.

It also makes it hard to evaluate coverage because there are several similar but not quite the same free functions and it is unclear hwo they are related to each other
and what some of the parameters mean (like the argument to roundtrip_one_column)

I think making it easier to find and evaluate test coverage will make it easier to
maintain and extend this crate in the future.

What changes are included in this PR?

  1. Move round trip logic into methods on RoundTripTest rather than free functions

Are these changes tested?

Only tests

Are there any user-facing changes?

No

@github-actions github-actions Bot added the parquet Changes to the parquet crate label Aug 4, 2026

one_column_roundtrip(Arc::clone(&string_view_values), false);
one_column_roundtrip(Arc::clone(&binary_view_values), false);
RoundTripTest::new(Arc::clone(&string_view_values))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is much easier to understand now -- the nullable_flag is now self documenting

/// Round trip testing fixture:
///
/// Tests based on this fixture write data to parquet and then read it back.
struct RoundTripTest {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed and moved a few parameters to fields

builder = builder.set_bloom_filter_max_ndv(ndv);
}
let props = builder.build();
/// Run the test specified by the options, returning the encoded Parquet bytes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Viewing this diff without whitespace makes this change clearer I think: https://github.com/apache/arrow-rs/pull/10545/changes?w=1

The method is indented but the only new code is this

            let schema = schema.unwrap_or_else(|| {
                let data_type = values.data_type().clone();
                Arc::new(Schema::new(vec![Field::new("col", data_type, nullable)]))
            });

…r_ndv

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@alamb alamb changed the title Encapsulate round trip logic in struct Encapsulate parquet round trip test logic in struct Aug 4, 2026

@etseidl etseidl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@sdf-jkl sdf-jkl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alamb A few suggestions, but nothing serious.

  • drop the nullability flag and go back to generating the default schema in new()
  • make with_nullable always set nullability to false. Change the name to with_non_nullable_schema and reuse the existing schema instead of generating a new one.

Comment on lines +3217 to +3220
fn with_nullable(mut self, nullable: bool) -> Self {
self.nullable = nullable;
self
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If schema nullability is the default and with_nullable(true) is never used, can simplify to -

Suggested change
fn with_nullable(mut self, nullable: bool) -> Self {
self.nullable = nullable;
self
}
fn with_non_nullable_schema(mut self) -> Self {
self.nullable = false;
self
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or if we keep behavior where new() generates a schema, we can go back to using an existing one -

Suggested change
fn with_nullable(mut self, nullable: bool) -> Self {
self.nullable = nullable;
self
}
fn with_non_nullable_schema(mut self) -> Self {
let field =
self.schema.field(0).clone().with_nullable(false);
self.schema = Arc::new(Schema::new_with_metadata(
vec![field],
self.schema.metadata().clone(),
));
self
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I guess it also follows the Field::with_nullable(bool) API

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, if you don't mind I am going to keep following the Field::with_nullable API

I have big hopes to unify these round trip tests with the ones that use record batches as well. We'll see if that is reasonable or not

@alamb
alamb merged commit 88b7d5a into apache:main Aug 6, 2026
18 checks passed
@alamb

alamb commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

Thank you for the reviews @etseidl and @sdf-jkl -- I will keep working on these tests

@Jefffrey Jefffrey added the development-process Related to development process of arrow-rs label Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

development-process Related to development process of arrow-rs parquet Changes to the parquet crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants