15 #include <fmt/format.h>
17 #include <gsl/pointers>
24 auto getTypeName( std::string_view dependency ) {
25 auto unknownClassPos = dependency.find(
"UNKNOWN_CLASS:" );
26 return ( unknownClassPos != std::string::npos )
28 :
std::string( dependency );
32 auto getNameFromLoc( std::string_view loc ) {
33 auto lastSlashPos = loc.find_last_of(
'/' );
34 return std::string{ lastSlashPos != loc.npos ? loc.
substr( lastSlashPos + 1 ) : loc };
51 ,
m_filename( this,
"TreeFilename",
"generic_ntuple_writer_tree.root",
52 "Filename where the NTuple writer alg writes the ttree." ) {}
58 if ( extraInputs.empty() ) {
60 "No extra inputs locations specified. Please define extra inputs for the NTuple writer.",
name(),
64 auto tempFile = std::make_unique<TFile>(
m_filename.
value().c_str(),
"RECREATE" );
65 if ( !tempFile || tempFile->IsZombie() ) {
71 m_tree = std::make_unique<TTree>(
"GenericWriterTree",
"Tree of GenericWriter Algorithm" ).release();
73 throw GaudiException(
"Failed to create TTree. Ensure sufficient resources and permissions.",
name(),
82 "Failed to retrieve the event service. Ensure the Event Service is properly configured and available.",
100 if ( sc.isFailure() ) {
103 "Failed to retrieve object for location '{}'. Ensure the location is correct and the object exists.",
104 wrapper.getLocation() ),
108 wrapper.setBranchData( pObj );
119 if (
m_tree->Write() <= 0 ) {
123 info() <<
"TTree written to ROOT file. File closed." <<
endmsg;
131 for (
const auto& dep : extraInputs ) {
132 auto typeName = getTypeName( dep.className() );
133 auto branchName = getNameFromLoc( dep.key() );
163 # define BOOST_TEST_MODULE test_GenericNTupleWriter
164 # include <boost/test/unit_test.hpp>
182 return dummyServices;
185 virtual bool existsService( std::string_view )
const override {
return false; }
192 virtual unsigned long addRef()
override {
return 0; }
194 virtual unsigned long release()
override {
return 0; }
202 virtual unsigned long refCount()
const override {
return 1; }
206 BOOST_AUTO_TEST_CASE( testGetTypeName ) {
208 BOOST_CHECK_EQUAL( getTypeName(
"MyClass" ),
"MyClass" );
209 BOOST_CHECK_EQUAL( getTypeName(
"std::vector<double>" ),
"std::vector<double>" );
210 BOOST_CHECK_EQUAL( getTypeName(
"UNKNOWN_CLASS:MyCustomClass" ),
"MyCustomClass" );
213 BOOST_AUTO_TEST_CASE( testGetNameFromLoc ) {
215 BOOST_CHECK_EQUAL( getNameFromLoc(
"/Event/MyAlg/MyData" ),
"MyData" );
216 BOOST_CHECK_EQUAL( getNameFromLoc(
"MyAlg/MyData" ),
"MyData" );
217 BOOST_CHECK_EQUAL( getNameFromLoc(
"MyData" ),
"MyData" );
218 BOOST_CHECK_EQUAL( getNameFromLoc(
"" ),
"" );
222 BOOST_AUTO_TEST_CASE( testInit ) {
223 MockISvcLocator mockLocator;
227 BOOST_CHECK_EQUAL(
writer.name(),
"test_writer" );
231 BOOST_AUTO_TEST_CASE( testCreateBranches_EmptyDeps ) {
232 MockISvcLocator mockLocator;
237 return e.message() ==
"No extra inputs locations specified. Please define extra inputs for the NTuple writer.";
242 BOOST_AUTO_TEST_CASE( testCreateBranches_InvalidType ) {
243 MockISvcLocator mockLocator;
244 auto tree = std::make_unique<TTree>(
"testTree",
"test tree" );
246 writer.setTree( tree.get() );
252 return e.message() ==
"Cannot create branch loc for unknown class: InvalidType. Provide a dictionary please.";
257 BOOST_AUTO_TEST_CASE( testCreateBranches_BasicTypes ) {
258 MockISvcLocator mockLocator;
259 auto tree = std::make_unique<TTree>(
"testTree",
"test tree" );
261 writer.setTree( tree.get() );
263 DataObjIDColl dependencies{ {
"int",
"loc1" }, {
"double",
"loc2" }, {
"std::string",
"loc3" } };
265 writer.createBranches( dependencies );
268 BOOST_CHECK_EQUAL(
writer.getBranchWrappersSize(), expectedTypes.size() );
269 BOOST_CHECK( expectedTypes ==
writer.getBranchesClassNames() );
273 BOOST_AUTO_TEST_CASE( testCreateBranches_ROOTKnownTypes ) {
274 MockISvcLocator mockLocator;
275 auto tree = std::make_unique<TTree>(
"testTree",
"test tree" );
277 writer.setTree( tree.get() );
279 DataObjIDColl dependencies{ {
"std::vector<double>",
"vectorDoubleLoc" }, {
"TH1D",
"hist1DLoc" } };
281 writer.createBranches( dependencies );
284 BOOST_CHECK_EQUAL(
writer.getBranchWrappersSize(), expectedTypes.size() );
285 BOOST_CHECK( expectedTypes ==
writer.getBranchesClassNames() );
289 BOOST_AUTO_TEST_CASE( testFileOpenException ) {
290 MockISvcLocator mockLocator;
294 BOOST_CHECK(
writer.setProperty(
"ExtraInputs", dependencies ).isSuccess() );
295 BOOST_CHECK(
writer.setProperty(
"TreeFilename",
"/invalid/path/to/file.root" ).isSuccess() );
297 return e.message() ==
"Failed to open file '/invalid/path/to/file.root'. Check file path and permissions.";