Skip to content

Commit ec3bed8

Browse files
jblomerpcanal
authored andcommitted
[io] add unit test infrastructure for streaming large objects
Uses RStreamerField as a test bed for (de-)serializing large objects with TBufferFile.
1 parent d7b37b8 commit ec3bed8

File tree

5 files changed

+95
-0
lines changed

5 files changed

+95
-0
lines changed

tree/ntuple/test/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ ROOT_GENERATE_DICTIONARY(StreamerFieldDict ${CMAKE_CURRENT_SOURCE_DIR}/StreamerF
105105
MODULE rfield_streamer LINKDEF StreamerFieldLinkDef.h OPTIONS -inlineInputHeader
106106
DEPENDENCIES RIO)
107107

108+
ROOT_ADD_GTEST(rfield_streamer_beyond rfield_streamer_beyond.cxx StreamerBeyond.cxx LIBRARIES ROOTNTuple)
109+
ROOT_GENERATE_DICTIONARY(StreamerBeyondDict ${CMAKE_CURRENT_SOURCE_DIR}/StreamerBeyond.hxx
110+
MODULE rfield_streamer_beyond LINKDEF StreamerBeyondLinkDef.h OPTIONS -inlineInputHeader
111+
DEPENDENCIES RIO)
112+
108113
if(MSVC)
109114
set(command ${CMAKE_COMMAND} -E env "ROOTIGNOREPREFIX=1" $<TARGET_FILE:genreflex>)
110115
else()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "StreamerBeyond.hxx"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#ifndef ROOT_RNTuple_Test_StreamerBeyond
2+
#define ROOT_RNTuple_Test_StreamerBeyond
3+
4+
#include <Rtypes.h>
5+
6+
#include <cstdint>
7+
#include <vector>
8+
9+
struct StreamerBeyond {
10+
std::vector<std::int64_t> fOne;
11+
std::vector<std::int64_t> fTwo;
12+
};
13+
14+
#endif
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#ifdef __CLING__
2+
3+
#pragma link C++ options=rntupleStreamerMode(true) struct StreamerBeyond+;
4+
5+
#endif
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include <ROOT/RFieldBase.hxx>
2+
#include <ROOT/RNTupleModel.hxx>
3+
#include <ROOT/RNTupleReader.hxx>
4+
#include <ROOT/RNTupleWriter.hxx>
5+
6+
#include <cstdio>
7+
#include <string>
8+
#include <utility>
9+
10+
#include "StreamerBeyond.hxx"
11+
#include "gtest/gtest.h"
12+
13+
namespace {
14+
15+
class FileRaii {
16+
private:
17+
std::string fPath;
18+
bool fPreserveFile = false;
19+
20+
public:
21+
explicit FileRaii(const std::string &path) : fPath(path) {}
22+
FileRaii(FileRaii &&) = default;
23+
FileRaii(const FileRaii &) = delete;
24+
FileRaii &operator=(FileRaii &&) = default;
25+
FileRaii &operator=(const FileRaii &) = delete;
26+
~FileRaii()
27+
{
28+
if (!fPreserveFile)
29+
std::remove(fPath.c_str());
30+
}
31+
std::string GetPath() const { return fPath; }
32+
33+
// Useful if you want to keep a test file after the test has finished running
34+
// for debugging purposes. Should only be used locally and never pushed.
35+
void PreserveFile() { fPreserveFile = true; }
36+
};
37+
38+
} // anonymous namespace
39+
40+
TEST(RField, StreamerBeyond)
41+
{
42+
FileRaii fileGuard("test_ntuple_rfield_streamer_beyond.root");
43+
44+
{
45+
auto model = ROOT::RNTupleModel::Create();
46+
auto f = ROOT::RFieldBase::Create("f", "StreamerBeyond").Unwrap();
47+
EXPECT_TRUE(dynamic_cast<ROOT::RStreamerField *>(f.get()));
48+
model->AddField(std::move(f));
49+
auto writer = ROOT::RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
50+
51+
auto ptr = writer->GetModel().GetDefaultEntry().GetPtr<StreamerBeyond>("f");
52+
ptr->fOne = std::vector<std::int64_t>(100000000, -1);
53+
ptr->fTwo = std::vector<std::int64_t>(100000000, -2);
54+
55+
writer->Fill();
56+
}
57+
58+
auto reader = ROOT::RNTupleReader::Open("ntpl", fileGuard.GetPath());
59+
ASSERT_EQ(1u, reader->GetNEntries());
60+
StreamerBeyond sb;
61+
auto view = reader->GetView("f", &sb, "StreamerBeyond");
62+
63+
view(0);
64+
65+
auto ptr = view.GetValue().GetPtr<StreamerBeyond>();
66+
EXPECT_EQ(100000000u, ptr->fOne.size());
67+
EXPECT_EQ(-1, ptr->fOne.at(1000));
68+
EXPECT_EQ(100000000u, ptr->fTwo.size());
69+
EXPECT_EQ(-2, ptr->fTwo.at(2000));
70+
}

0 commit comments

Comments
 (0)