Project
Loading...
Searching...
No Matches
test_RootTreeReader.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
18#include "Framework/InputSpec.h"
23#include "Headers/DataHeader.h"
24#include "Headers/NameHeader.h"
25#include "../../Core/test/TestClasses.h"
26#include "Framework/Logger.h"
27#include <TSystem.h>
28#include <TTree.h>
29#include <TFile.h>
30#include <vector>
31
32using namespace o2::framework;
33
34#define ASSERT_ERROR(condition) \
35 if ((condition) == false) { \
36 LOG(fatal) << R"(Test condition ")" #condition R"(" failed)"; \
37 }
38
39const int gTreeSize = 10; // elements in the test tree
41{
42 auto initFct = [](InitContext& ic) {
43 // create a test tree in a temporary file
44 std::string fileName = gSystem->TempDirectory();
45 fileName += "/test_RootTreeReader.root";
46
47 {
48 std::unique_ptr<TFile> testFile(TFile::Open(fileName.c_str(), "RECREATE"));
49 std::unique_ptr<TTree> testTree = std::make_unique<TTree>("testtree", "testtree");
50
51 std::vector<o2::test::TriviallyCopyable> msgblarray;
52 std::vector<o2::test::Polymorphic> valarray;
53 auto* branch1 = testTree->Branch("msgblarray", &msgblarray);
54 auto* branch2 = testTree->Branch("dataarray", &valarray);
55
56 for (int entry = 0; entry < gTreeSize; entry++) {
57 msgblarray.clear();
58 valarray.clear();
59 for (int idx = 0; idx < entry + 1; ++idx) {
60 msgblarray.emplace_back((entry * 10) + idx, 0, 0);
61 valarray.emplace_back((entry * 10) + idx);
62 }
63 testTree->Fill();
64 }
65 testTree->Write();
66 testTree->SetDirectory(nullptr);
67 testFile->Close();
68 }
69
70 auto reader = std::make_shared<RootTreeReader>("testtree", // tree name
71 fileName.c_str(), // input file name
72 RootTreeReader::BranchDefinition<std::vector<o2::test::TriviallyCopyable>>{Output{"TST", "ARRAYOFMSGBL", 0}, "msgblarray"},
73 Output{"TST", "ARRAYOFDATA", 0},
74 "dataarray",
76
77 auto processingFct = [reader](ProcessingContext& pc) {
78 if (reader->getCount() >= gTreeSize) {
79 return;
80 }
81 if (reader->getCount() == 0) {
82 // add two additional headers on the stack in the first entry
83 o2::header::NameHeader<16> auxHeader("extended_info");
84 o2::header::DataHeader dummyheader;
85 (++(*reader))(pc, auxHeader, dummyheader);
86 } else {
87 // test signature without headers for the rest of the entries
88 (++(*reader))(pc);
89 }
90 if ((reader->getCount()) >= gTreeSize) {
91 pc.services().get<ControlService>().endOfStream();
92 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
93 }
94 };
95
96 return processingFct;
97 };
98
99 return DataProcessorSpec{"source", // name of the processor
100 {},
101 {OutputSpec{"TST", "ARRAYOFDATA"},
102 OutputSpec{"TST", "ARRAYOFMSGBL"}},
103 AlgorithmSpec(initFct)};
104}
105
107{
108 auto processingFct = [](ProcessingContext& pc) {
109 static int counter = 0;
111 for (auto& input : pc.inputs()) {
112 auto dh = DataRefUtils::getHeader<const DataHeader*>(input);
113 LOG(info) << dh->dataOrigin.str << " " << dh->dataDescription.str << " " << dh->payloadSize;
114 }
115 auto data = pc.inputs().get<std::vector<o2::test::Polymorphic>>("input1");
116 if (counter == 0) {
117 // the first entry comes together with additional headers on the stack, test those ...
118 auto auxHeader = DataRefUtils::getHeader<o2::header::NameHeader<16>*>(pc.inputs().get("input1"));
119 ASSERT_ERROR(auxHeader != nullptr);
120 if (auxHeader != nullptr) {
121 ASSERT_ERROR(std::string("extended_info") == auxHeader->getName());
122 o2::header::hexDump("", auxHeader, auxHeader->headerSize);
123 auto dummyheader = auxHeader->next();
124 ASSERT_ERROR(dummyheader != nullptr && dummyheader->size() == sizeof(o2::header::DataHeader));
125 }
126 }
127
128 LOG(info) << "count: " << counter << " data elements:" << data.size();
129 ASSERT_ERROR(counter + 1 == data.size());
130
131 // retrieving the unserialized message as vector
132 auto msgblvec = pc.inputs().get<std::vector<o2::test::TriviallyCopyable>*>("input2");
133 ASSERT_ERROR(counter + 1 == msgblvec->size());
134
135 // retrieving the unserialized message as span
136 auto msgblspan = pc.inputs().get<gsl::span<o2::test::TriviallyCopyable>>("input2");
137 ASSERT_ERROR(counter + 1 == msgblspan.size());
138
139 for (unsigned int idx = 0; idx < data.size(); idx++) {
140 LOG(info) << data[idx].get();
141 auto expected = 10 * counter + idx;
142 ASSERT_ERROR(data[idx].get() == expected);
143 ASSERT_ERROR(((*msgblvec)[idx] == o2::test::TriviallyCopyable{expected, 0, 0}));
144 ASSERT_ERROR((msgblspan[idx] == o2::test::TriviallyCopyable{expected, 0, 0}));
145 }
146
147 ++counter;
148 };
149
150 return DataProcessorSpec{"sink", // name of the processor
151 {InputSpec{"input1", "TST", "ARRAYOFDATA"},
152 InputSpec{"input2", "TST", "ARRAYOFMSGBL"}},
153 Outputs{},
154 AlgorithmSpec(processingFct)};
155}
156
A generic reader for ROOT TTrees.
GLuint entry
Definition glcorearb.h:5735
GLboolean * data
Definition glcorearb.h:298
GLuint counter
Definition glcorearb.h:3987
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< DataProcessorSpec > WorkflowSpec
std::vector< OutputSpec > Outputs
void hexDump(const char *desc, const void *voidaddr, size_t len, size_t max=0)
helper function to print a hex/ASCII dump of some memory
static const BaseHeader * get(const std::byte *b, size_t=0)
access header in buffer
Definition DataHeader.h:405
the main header struct
Definition DataHeader.h:618
an example data header containing a name of an object as a null terminated char arr....
Definition NameHeader.h:39
std::map< std::string, ID > expected
#define ASSERT_ERROR(condition)
DataProcessorSpec getSinkSpec()
const int gTreeSize
DataProcessorSpec getSourceSpec()
WorkflowSpec defineDataProcessing(ConfigContext const &)
This function hooks up the the workflow specifications into the DPL driver.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"