ATLAS Offline Software
Loading...
Searching...
No Matches
test-hdf5-merge.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "HDF5Utils/Merger.h"
6#include "H5Cpp.h"
7
8#include <algorithm>
9#include <iostream>
10#include <sstream>
11#include <string>
12#include <vector>
13
14namespace {
15 // Create a group chain (e.g. "a/b/c") under the file's root and write a
16 // chunked, extensible 1D int dataset at the end of it.
17 void writeNestedDataset(
18 H5::H5File& file,
19 const std::string& groupChain,
20 const std::string& dsName,
21 int firstValue,
22 hsize_t nRows)
23 {
24 H5::Group cur = file.openGroup("/");
25 std::istringstream chain(groupChain);
26 std::string part;
27 while (std::getline(chain, part, '/'))
28 cur = cur.createGroup(part);
29
30 hsize_t dims[1] = {nRows};
31 hsize_t maxDims[1] = {H5S_UNLIMITED};
32 H5::DataSpace space(1, dims, maxDims);
33 H5::DSetCreatPropList props;
34 hsize_t chunk[1] = {std::max<hsize_t>(nRows, 1)};
35 props.setChunk(1, chunk);
36 H5::DataSet ds = cur.createDataSet(
37 dsName, H5::PredType::NATIVE_INT, space, props);
38
39 std::vector<int> data(nRows);
40 for (hsize_t i = 0; i < nRows; ++i) data.at(i) = firstValue + int(i);
41 ds.write(data.data(), H5::PredType::NATIVE_INT);
42 }
43
44 hsize_t readExtent(H5::H5File& file, const std::string& dsPath)
45 {
46 H5::DataSet ds = file.openDataSet(dsPath);
47 hsize_t dims[1];
48 ds.getSpace().getSimpleExtentDims(dims);
49 return dims[0];
50 }
51}
52
53// Regression test for a bug where merging a source group into a target that
54// doesn't yet have a matching child group would merge that child twice: once
55// while creating it, once more right after. Every dataset under a
56// newly-created group ended up with its rows duplicated.
57int main() {
58 const std::string groupChain = "a/b/c";
59 const std::string dsPath = "/a/b/c/dataset";
60 const hsize_t rows = 5;
61
62 {
63 H5::H5File src("merge_test_src1.h5", H5F_ACC_TRUNC);
64 writeNestedDataset(src, groupChain, "dataset", 0, rows);
65 }
66 {
67 H5::H5File src("merge_test_src2.h5", H5F_ACC_TRUNC);
68 writeNestedDataset(src, groupChain, "dataset", 100, rows);
69 }
70
71 H5::H5File target("merge_test_out.h5", H5F_ACC_TRUNC);
72 H5Utils::Merger merger;
73
74 // Merging into a target with none of "a/b/c" yet: this is the path that
75 // recursively creates new groups, and used to trigger the double merge.
76 {
77 H5::H5File src1("merge_test_src1.h5", H5F_ACC_RDONLY);
78 merger.merge(target, src1);
79 }
80 hsize_t afterFirst = readExtent(target, dsPath);
81 if (afterFirst != rows) {
82 std::cerr << "FAIL: merging into a brand-new nested group produced "
83 << afterFirst << " rows, expected " << rows
84 << " (double-merge bug?)" << std::endl;
85 return 1;
86 }
87
88 // Merging a second source into the now-existing "a/b/c" group: this is
89 // the ordinary "found" path and should still merge exactly once.
90 {
91 H5::H5File src2("merge_test_src2.h5", H5F_ACC_RDONLY);
92 merger.merge(target, src2);
93 }
94 hsize_t afterSecond = readExtent(target, dsPath);
95 if (afterSecond != 2 * rows) {
96 std::cerr << "FAIL: merging into an existing nested group produced "
97 << afterSecond << " rows, expected " << 2 * rows << std::endl;
98 return 1;
99 }
100
101 std::cout << "test-hdf5-merge: OK" << std::endl;
102 return 0;
103}
void merge(H5::Group &target, const H5::Group &source)
Merge a source group into a target group.
Definition Merger.cxx:29
unsigned int constexpr nRows
Definition RPDUtils.h:24
int main()
TFile * file