From 6b95847de10e7864b2019f7af216db2d162906c1 Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Thu, 15 Jan 2026 16:31:31 +0100 Subject: [PATCH 1/2] Add tests for structure of RNTuple ... with clusters and cluster groups. Closes #29 --- structure/README.md | 7 ++++++ structure/cluster_groups/README.md | 3 +++ structure/cluster_groups/read.C | 6 +++++ structure/cluster_groups/write.C | 37 ++++++++++++++++++++++++++++++ structure/clusters/README.md | 3 +++ structure/clusters/read.C | 6 +++++ structure/clusters/write.C | 29 +++++++++++++++++++++++ structure/read_structure.hxx | 36 +++++++++++++++++++++++++++++ 8 files changed, 127 insertions(+) create mode 100644 structure/README.md create mode 100644 structure/cluster_groups/README.md create mode 100644 structure/cluster_groups/read.C create mode 100644 structure/cluster_groups/write.C create mode 100644 structure/clusters/README.md create mode 100644 structure/clusters/read.C create mode 100644 structure/clusters/write.C create mode 100644 structure/read_structure.hxx diff --git a/structure/README.md b/structure/README.md new file mode 100644 index 0000000..95b266d --- /dev/null +++ b/structure/README.md @@ -0,0 +1,7 @@ +# Structure + +For the RNTuple Validation Suite, we assume that the structure is orthogonal to the supported types and serialized data. +Therefore all tests in this category write a single `Int32` field with type `std::int32_t` the entries have ascending values. + + * [`clusters`](clusters): multiple clusters + * [`cluster_groups`](cluster_groups): multiple cluster groups diff --git a/structure/cluster_groups/README.md b/structure/cluster_groups/README.md new file mode 100644 index 0000000..df91ddd --- /dev/null +++ b/structure/cluster_groups/README.md @@ -0,0 +1,3 @@ +# Cluster Groups + +Two cluster groups with two clusters each and a total of four entries. diff --git a/structure/cluster_groups/read.C b/structure/cluster_groups/read.C new file mode 100644 index 0000000..4dc3fb3 --- /dev/null +++ b/structure/cluster_groups/read.C @@ -0,0 +1,6 @@ +#include "../read_structure.hxx" + +void read(std::string_view input = "structure.cluster_groups.root", + std::string_view output = "structure.cluster_groups.json") { + read_structure(input, output); +} diff --git a/structure/cluster_groups/write.C b/structure/cluster_groups/write.C new file mode 100644 index 0000000..a066b5d --- /dev/null +++ b/structure/cluster_groups/write.C @@ -0,0 +1,37 @@ +#include +#include +#include + +using ROOT::Experimental::RNTupleModel; +using ROOT::Experimental::RNTupleWriteOptions; +using ROOT::Experimental::RNTupleWriter; + +#include +#include + +void write(std::string_view filename = "structure.cluster_groups.root") { + auto model = RNTupleModel::Create(); + + auto Int32 = model->MakeField("Int32"); + + RNTupleWriteOptions options; + options.SetCompression(0); + auto writer = + RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options); + + *Int32 = 1; + writer->Fill(); + writer->CommitCluster(); + + *Int32 = 2; + writer->Fill(); + writer->CommitCluster(/*commitClusterGroup=*/true); + + *Int32 = 3; + writer->Fill(); + writer->CommitCluster(); + + *Int32 = 4; + writer->Fill(); + writer->CommitCluster(/*commitClusterGroup=*/true); +} diff --git a/structure/clusters/README.md b/structure/clusters/README.md new file mode 100644 index 0000000..a5f19cb --- /dev/null +++ b/structure/clusters/README.md @@ -0,0 +1,3 @@ +# Clusters + +Two clusters with one entry each. diff --git a/structure/clusters/read.C b/structure/clusters/read.C new file mode 100644 index 0000000..6eb7ed0 --- /dev/null +++ b/structure/clusters/read.C @@ -0,0 +1,6 @@ +#include "../read_structure.hxx" + +void read(std::string_view input = "structure.clusters.root", + std::string_view output = "structure.clusters.json") { + read_structure(input, output); +} diff --git a/structure/clusters/write.C b/structure/clusters/write.C new file mode 100644 index 0000000..ddaa34c --- /dev/null +++ b/structure/clusters/write.C @@ -0,0 +1,29 @@ +#include +#include +#include + +using ROOT::Experimental::RNTupleModel; +using ROOT::Experimental::RNTupleWriteOptions; +using ROOT::Experimental::RNTupleWriter; + +#include +#include + +void write(std::string_view filename = "structure.clusters.root") { + auto model = RNTupleModel::Create(); + + auto Int32 = model->MakeField("Int32"); + + RNTupleWriteOptions options; + options.SetCompression(0); + auto writer = + RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options); + + *Int32 = 1; + writer->Fill(); + writer->CommitCluster(); + + *Int32 = 2; + writer->Fill(); + writer->CommitCluster(); +} diff --git a/structure/read_structure.hxx b/structure/read_structure.hxx new file mode 100644 index 0000000..ce521cf --- /dev/null +++ b/structure/read_structure.hxx @@ -0,0 +1,36 @@ +#include +#include + +using ROOT::Experimental::RNTupleReader; + +#include +#include +#include +#include +#include + +void read_structure(std::string_view input, std::string_view output) { + std::ofstream os(std::string{output}); + os << "[\n"; + + auto reader = RNTupleReader::Open("ntpl", input); + auto Int32 = + reader->GetModel().GetDefaultEntry().GetPtr("Int32"); + bool first = true; + for (auto index : *reader) { + reader->LoadEntry(index); + + if (first) { + first = false; + } else { + os << ",\n"; + } + os << " {\n"; + os << " \"Int32\": " << *Int32 << "\n"; + os << " }"; + // Newline is intentionally missing, may need to print a comma before the + // next entry. + } + os << "\n"; + os << "]\n"; +} From 857bc87359da0cc20b33d6fceedd9de1f924ab75 Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Thu, 15 Jan 2026 16:40:22 +0100 Subject: [PATCH 2/2] Add test for empty RNTuple Closes #33 --- structure/README.md | 1 + structure/empty/README.md | 3 +++ structure/empty/read.C | 6 ++++++ structure/empty/write.C | 24 ++++++++++++++++++++++++ structure/read_structure.hxx | 4 +++- 5 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 structure/empty/README.md create mode 100644 structure/empty/read.C create mode 100644 structure/empty/write.C diff --git a/structure/README.md b/structure/README.md index 95b266d..e106f36 100644 --- a/structure/README.md +++ b/structure/README.md @@ -5,3 +5,4 @@ Therefore all tests in this category write a single `Int32` field with type `std * [`clusters`](clusters): multiple clusters * [`cluster_groups`](cluster_groups): multiple cluster groups + * [`empty`](empty): empty RNTuple without entries diff --git a/structure/empty/README.md b/structure/empty/README.md new file mode 100644 index 0000000..d852dac --- /dev/null +++ b/structure/empty/README.md @@ -0,0 +1,3 @@ +# Empty RNTuple + +An RNTuple with a field, but no entry. diff --git a/structure/empty/read.C b/structure/empty/read.C new file mode 100644 index 0000000..a3a3889 --- /dev/null +++ b/structure/empty/read.C @@ -0,0 +1,6 @@ +#include "../read_structure.hxx" + +void read(std::string_view input = "structure.empty.root", + std::string_view output = "structure.empty.json") { + read_structure(input, output); +} diff --git a/structure/empty/write.C b/structure/empty/write.C new file mode 100644 index 0000000..055d33c --- /dev/null +++ b/structure/empty/write.C @@ -0,0 +1,24 @@ +#include +#include +#include + +using ROOT::Experimental::RNTupleModel; +using ROOT::Experimental::RNTupleWriteOptions; +using ROOT::Experimental::RNTupleWriter; + +#include +#include + +void write(std::string_view filename = "structure.empty.root") { + auto model = RNTupleModel::Create(); + + auto Int32 = model->MakeField("Int32"); + + RNTupleWriteOptions options; + options.SetCompression(0); + auto writer = + RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options); + + // Destruct the writer / commit the dataset without filling an entry. + writer.reset(); +} diff --git a/structure/read_structure.hxx b/structure/read_structure.hxx index ce521cf..5bf7091 100644 --- a/structure/read_structure.hxx +++ b/structure/read_structure.hxx @@ -31,6 +31,8 @@ void read_structure(std::string_view input, std::string_view output) { // Newline is intentionally missing, may need to print a comma before the // next entry. } - os << "\n"; + if (!first) { + os << "\n"; + } os << "]\n"; }