Skip to content

Commit 023ea7d

Browse files
committed
[roottest] Provide reproducer for #19022
The test is not available on Windows because the dictionary information is not properly loaded in the same way as on other platforms. For now we keep the tests disabled, considering that it won't affect ATLAS.
1 parent 78b218a commit 023ea7d

File tree

5 files changed

+176
-0
lines changed

5 files changed

+176
-0
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#ifndef ATLASLIKEDATAVECTOR
2+
#define ATLASLIKEDATAVECTOR
3+
4+
// Mimicks the DataVector hierarchy as found in athena
5+
6+
#include <RootMetaSelection.h>
7+
8+
#include <cstdint>
9+
#include <string>
10+
#include <vector>
11+
#include <cstddef>
12+
13+
// https://gitlab.cern.ch/atlas/athena/-/blob/26885cbcf82f069cddff6cd30c123572e362d8fa/Control/AthContainers/AthContainers/tools/DVLNoBase.h#L32
14+
namespace DataModel_detail {
15+
struct NoBase {};
16+
} // namespace DataModel_detail
17+
18+
// https://gitlab.cern.ch/atlas/athena/-/blob/26885cbcf82f069cddff6cd30c123572e362d8fa/Control/AthContainers/AthContainers/DataVector.h#L632
19+
template <class T>
20+
struct DataVectorBase {
21+
typedef DataModel_detail::NoBase Base;
22+
};
23+
24+
// https://gitlab.cern.ch/atlas/athena/-/blob/26885cbcf82f069cddff6cd30c123572e362d8fa/Control/AthContainers/AthContainers/DataVector.h#L792
25+
template <class T, class BASE = typename DataVectorBase<T>::Base>
26+
class AtlasLikeDataVector : public BASE {};
27+
28+
namespace SG {
29+
// https://gitlab.cern.ch/atlas/athena/-/blob/26885cbcf82f069cddff6cd30c123572e362d8fa/Control/AthContainers/AthContainers/AuxVectorData.h#L164
30+
class AuxVectorData {
31+
public:
32+
AuxVectorData() = default;
33+
};
34+
// https://gitlab.cern.ch/atlas/athena/-/blob/26885cbcf82f069cddff6cd30c123572e362d8fa/Control/AthContainers/AthContainers/AuxVectorBase.h#L96
35+
class AuxVectorBase : public AuxVectorData {
36+
public:
37+
AuxVectorBase() = default;
38+
};
39+
} // namespace SG
40+
41+
// https://gitlab.cern.ch/atlas/athena/-/blob/26885cbcf82f069cddff6cd30c123572e362d8fa/Control/AthContainers/AthContainers/DataVector.h#L2058
42+
template <class T>
43+
class AtlasLikeDataVector<T, DataModel_detail::NoBase> : public SG::AuxVectorBase {};
44+
45+
namespace ROOT::Meta::Selection {
46+
// https://gitlab.cern.ch/atlas/athena/-/blob/26885cbcf82f069cddff6cd30c123572e362d8fa/Control/AthContainers/AthContainers/DataVector.h#L3422
47+
template <class T, class BASE>
48+
class AtlasLikeDataVector : KeepFirstTemplateArguments<1>, SelectNoInstance {};
49+
} // namespace ROOT::Meta::Selection
50+
51+
struct CustomStruct {
52+
float a{};
53+
std::vector<float> v1{};
54+
std::vector<std::vector<float>> v2{};
55+
std::string s{};
56+
std::byte b{};
57+
};
58+
59+
namespace {
60+
// https://gitlab.cern.ch/atlas/athena/-/blob/26885cbcf82f069cddff6cd30c123572e362d8fa/Control/AthContainers/AthContainers/AthContainersDict.h#L29
61+
struct DUMMY_INSTANTIATION {
62+
AtlasLikeDataVector<CustomStruct, DataModel_detail::NoBase> dummy1;
63+
ROOT::Meta::Selection::AtlasLikeDataVector<CustomStruct, DataModel_detail::NoBase> dummy2;
64+
};
65+
} // namespace
66+
67+
#endif // ATLASLIKEDATAVECTOR
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Reproducer of https://github.com/root-project/root/issues/19022
2+
3+
# TODO: Figure out how to load the dictionary in the writing test on Windows
4+
if(MSVC and not win_broken_tests)
5+
return()
6+
endif()
7+
8+
# Generate the dictionary for the ATLAS-like container class
9+
# Note that we use a selection.xml file, not a LinkDef, as this is what
10+
# is done in Athena as well. Also note that in the selection we have a rule
11+
# that uses a pattern AtlasLikeDataVector<CustomStruct,*> so we don't rely
12+
# on an explicit declaration of the full class template with 2 arguments.
13+
ROOTTEST_GENERATE_DICTIONARY(
14+
AtlasLikeDataVectorDict
15+
${CMAKE_CURRENT_SOURCE_DIR}/AtlasLikeDataVector.hxx
16+
LINKDEF ${CMAKE_CURRENT_SOURCE_DIR}/selection.xml
17+
FIXTURES_SETUP atlas_datavector_dict_setup
18+
)
19+
20+
# Generate a shared library from the dictionary sources
21+
add_library(AtlasLikeDataVector SHARED AtlasLikeDataVectorDict.cxx)
22+
target_link_libraries(AtlasLikeDataVector Core RIO ROOTNTuple)
23+
add_dependencies(AtlasLikeDataVector AtlasLikeDataVectorDict)
24+
25+
# Generate an executable to write an RNTuple with a field of type
26+
# AtlasLikeDataVector<CustomStruct>. Note that we don't link explicitly
27+
# the executable against the shared library, but the information of the
28+
# dictionary should be autoloaded, thus the rule to drop the second template
29+
# argument should kick in when writing the class to disk.
30+
ROOTTEST_GENERATE_EXECUTABLE(
31+
write
32+
write.cxx
33+
LIBRARIES Core RIO ROOTNTuple
34+
FIXTURES_REQUIRED atlas_datavector_dict_setup
35+
FIXTURES_SETUP atlas_datavector_write_setup)
36+
37+
# Generate an executable to read back the RNTuple with a field of type
38+
# AtlasLikeDataVector<CustomStruct>. Note that we don't link explicitly
39+
# the executable against the shared library, but the information of the
40+
# dictionary should be autoloaded, thus the rule to drop the second template
41+
# argument should kick in when reading the field.
42+
ROOTTEST_GENERATE_EXECUTABLE(
43+
read
44+
read.cxx
45+
LIBRARIES Core RIO ROOTNTuple gtest gtest_main
46+
FIXTURES_REQUIRED atlas_datavector_dict_setup
47+
FIXTURES_SETUP atlas_datavector_read_setup)
48+
49+
ROOTTEST_ADD_TEST(write
50+
EXEC ${CMAKE_CURRENT_BINARY_DIR}/write
51+
FIXTURES_REQUIRED atlas_datavector_write_setup
52+
FIXTURES_SETUP atlas_datavector_write_done)
53+
54+
# In the reading test we rely on the templated call that uses the shortened
55+
# class type AtlasLikeDataVector<CustomStruct>, so we need to include the header
56+
ROOTTEST_ADD_TEST(read
57+
EXEC ${CMAKE_CURRENT_BINARY_DIR}/read
58+
COPY_TO_BUILDDIR ${CMAKE_CURRENT_SOURCE_DIR}/AtlasLikeDataVector.hxx
59+
FIXTURES_REQUIRED "atlas_datavector_read_setup;atlas_datavector_write_done")
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include <string>
2+
3+
#include <ROOT/RField.hxx>
4+
#include <ROOT/RNTupleModel.hxx>
5+
#include <ROOT/RNTupleReader.hxx>
6+
7+
#include <gtest/gtest.h>
8+
9+
#include "AtlasLikeDataVector.hxx"
10+
11+
TEST(RNTupleAtlasDataVector, Read)
12+
{
13+
const auto typeNameBefore = ROOT::RField<AtlasLikeDataVector<CustomStruct>>::TypeName();
14+
const std::string expectedBefore{"AtlasLikeDataVector<CustomStruct,DataModel_detail::NoBase>"};
15+
// Make sure no autoloading happened yet
16+
ASSERT_EQ(typeNameBefore, expectedBefore);
17+
18+
auto reader = ROOT::RNTupleReader::Open("ntpl", "test_ntuple_datavector.root");
19+
const auto &entry = reader->GetModel().GetDefaultEntry();
20+
// The following call should not throw an exception
21+
ASSERT_NO_THROW(entry.GetPtr<AtlasLikeDataVector<CustomStruct>>("my_field"));
22+
23+
const auto typeNameAfter = ROOT::RField<AtlasLikeDataVector<CustomStruct>>::TypeName();
24+
const std::string expectedAfter{"AtlasLikeDataVector<CustomStruct>"};
25+
// Make sure autoloading happened and the rule to suppress the second template argument kicked in
26+
ASSERT_EQ(typeNameAfter, expectedAfter);
27+
}
28+
29+
int main(int argc, char **argv)
30+
{
31+
::testing::InitGoogleTest(&argc, argv);
32+
return RUN_ALL_TESTS();
33+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<lcgdict>
2+
<class name="CustomStruct" />
3+
<class name="SG::AuxVectorData" />
4+
<class name="SG::AuxVectorBase" />
5+
<class pattern="AtlasLikeDataVector<CustomStruct,*>" />
6+
</lcgdict>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <ROOT/RField.hxx>
2+
#include <ROOT/RNTupleModel.hxx>
3+
#include <ROOT/RNTupleWriter.hxx>
4+
5+
int main()
6+
{
7+
auto model = ROOT::RNTupleModel::Create();
8+
model->AddField(ROOT::RFieldBase::Create("my_field", "AtlasLikeDataVector<CustomStruct>").Unwrap());
9+
auto writer = ROOT::RNTupleWriter::Recreate(std::move(model), "ntpl", "test_ntuple_datavector.root");
10+
writer->Fill();
11+
}

0 commit comments

Comments
 (0)