File indexing completed on 2025-01-18 09:13:11
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Geometry/GeometryHierarchyMap.hpp"
0012 #include "Acts/Geometry/GeometryIdentifier.hpp"
0013 #include "Acts/Plugins/Json/GeometryHierarchyMapJsonConverter.hpp"
0014 #include "Acts/Tests/CommonHelpers/DataDirectory.hpp"
0015
0016 #include <algorithm>
0017 #include <fstream>
0018 #include <initializer_list>
0019 #include <stdexcept>
0020 #include <string>
0021 #include <vector>
0022
0023 #include <nlohmann/json.hpp>
0024
0025 namespace {
0026
0027 using Acts::GeometryIdentifier;
0028 using nlohmann::json;
0029
0030
0031 GeometryIdentifier makeId(int volume = 0, int layer = 0, int sensitive = 0) {
0032 return GeometryIdentifier().setVolume(volume).setLayer(layer).setSensitive(
0033 sensitive);
0034 }
0035
0036
0037
0038 struct Thing {
0039 double x = 1.0;
0040 int y = 23;
0041
0042 friend constexpr bool operator==(const Thing& lhs, const Thing& rhs) {
0043 return (lhs.x == rhs.x) && (lhs.y == rhs.y);
0044 }
0045 };
0046
0047
0048
0049
0050 void to_json(json& j, const Thing& t) {
0051 j = json{{"x", t.x}, {"y", t.y}};
0052 }
0053
0054 void from_json(const json& j, Thing& t) {
0055 j.at("x").get_to(t.x);
0056 j.at("y").get_to(t.y);
0057 }
0058
0059 std::ostream& operator<<(std::ostream& os, const Thing& t) {
0060 os << nlohmann::json(t);
0061 return os;
0062 }
0063
0064 class ThingDecorator {
0065 public:
0066 void decorate(const Thing* a_thing, nlohmann::json& a_json) const {
0067 if (a_thing != nullptr) {
0068 a_json["product"] = a_thing->x * a_thing->y;
0069 }
0070 }
0071 };
0072
0073 using Container = Acts::GeometryHierarchyMap<Thing>;
0074 using Converter =
0075 Acts::GeometryHierarchyMapJsonConverter<Thing, ThingDecorator>;
0076
0077 }
0078
0079 template <>
0080 void Acts::decorateJson<Thing>(const ThingDecorator* decorator,
0081 const Thing& src, nlohmann::json& dest) {
0082 if (decorator != nullptr) {
0083 decorator->decorate(&src, dest);
0084 }
0085 }
0086
0087 BOOST_TEST_DONT_PRINT_LOG_VALUE(json::iterator)
0088 BOOST_TEST_DONT_PRINT_LOG_VALUE(Container::Iterator)
0089
0090 BOOST_AUTO_TEST_SUITE(GeometryHierarchyMapJsonConverter)
0091
0092 BOOST_AUTO_TEST_CASE(ToJson) {
0093 ThingDecorator decorator;
0094 Container c = {
0095 {makeId(1), {2.0, -3}},
0096 {makeId(2, 3), {-4.5, 5}},
0097 {makeId(4, 5, 6), {7.25, -8}},
0098 };
0099 json j = Converter("thing").toJson(c, &decorator);
0100
0101 BOOST_CHECK(j.is_object());
0102
0103 auto header = j.find("acts-geometry-hierarchy-map");
0104 BOOST_CHECK_NE(header, j.end());
0105 BOOST_CHECK(header->is_object());
0106 BOOST_CHECK(header->at("format-version").is_number_integer());
0107 BOOST_CHECK_EQUAL(header->at("format-version").get<int>(), 0);
0108 BOOST_CHECK(header->at("value-identifier").is_string());
0109 BOOST_CHECK_EQUAL(header->at("value-identifier").get<std::string>(), "thing");
0110
0111 auto entries = j.find("entries");
0112 BOOST_CHECK_NE(entries, j.end());
0113 BOOST_CHECK(entries->is_array());
0114 BOOST_CHECK_EQUAL(entries->size(), 3u);
0115 }
0116
0117 BOOST_AUTO_TEST_CASE(FromJson) {
0118 json j = {
0119 {
0120 "acts-geometry-hierarchy-map",
0121 {
0122 {"format-version", 0},
0123 {"value-identifier", "thing"},
0124 },
0125 },
0126 {
0127 "entries",
0128 {
0129 {
0130 {"volume", 2},
0131 {"layer", 3},
0132 {"value", {{"x", 4.0}, {"y", 4}}},
0133 },
0134 {
0135 {"volume", 5},
0136 {"layer", 6},
0137 {"sensitive", 7},
0138 {"value", {{"x", 3.0}, {"y", 3}}},
0139 },
0140 },
0141 },
0142 };
0143 Container c = Converter("thing").fromJson(j);
0144
0145 BOOST_CHECK(!c.empty());
0146 BOOST_CHECK_EQUAL(c.size(), 2);
0147 {
0148 auto it = c.find(makeId(2, 3));
0149 BOOST_CHECK_NE(it, c.end());
0150 BOOST_CHECK_EQUAL(it->x, 4.0);
0151 BOOST_CHECK_EQUAL(it->y, 4);
0152 }
0153 {
0154 auto it = c.find(makeId(5, 6, 7));
0155 BOOST_CHECK_NE(it, c.end());
0156 BOOST_CHECK_EQUAL(it->x, 3.0);
0157 BOOST_CHECK_EQUAL(it->y, 3);
0158 }
0159 }
0160
0161 BOOST_AUTO_TEST_CASE(FromJsonMissingHeader) {
0162 json j = {
0163 {"entries", {}},
0164 };
0165 BOOST_CHECK_THROW(Converter("an-identifier").fromJson(j),
0166 std::invalid_argument);
0167 }
0168
0169 BOOST_AUTO_TEST_CASE(FromJsonInvalidFormatVersion) {
0170 json j = {
0171 {
0172 "acts-geometry-hierarchy-map",
0173 {
0174 {"format-version", -1},
0175 {"value-identifier", "an-identifier"},
0176 },
0177 },
0178 {"entries", {}},
0179 };
0180 BOOST_CHECK_THROW(Converter("an-identifier").fromJson(j),
0181 std::invalid_argument);
0182 }
0183
0184 BOOST_AUTO_TEST_CASE(FromJsonInvalidValueIdentifier) {
0185 json j = {
0186 {
0187 "acts-geometry-hierarchy-map",
0188 {
0189 {"format-version", 0},
0190 {"value-identifier", "an-identifier"},
0191 },
0192 },
0193 {"entries", {}},
0194 };
0195 BOOST_CHECK_THROW(Converter("not-the-identifier").fromJson(j),
0196 std::invalid_argument);
0197 }
0198
0199 BOOST_AUTO_TEST_CASE(FromJsonMissingEntries) {
0200 json j = {
0201 {
0202 "acts-geometry-hierarchy-map",
0203 {
0204 {"format-version", 0},
0205 {"value-identifier", "an-identifier"},
0206 },
0207 },
0208 };
0209 BOOST_CHECK_THROW(Converter("an-identifier").fromJson(j),
0210 std::invalid_argument);
0211 }
0212
0213 BOOST_AUTO_TEST_CASE(Roundtrip) {
0214 ThingDecorator decorator;
0215 Container c0 = {
0216 {makeId(1), {2.0, -3}},
0217 {makeId(2, 3), {-4.5, 5}},
0218 {makeId(4, 5, 6), {7.25, -8}},
0219 };
0220 auto j = Converter("the-identifier").toJson(c0, &decorator);
0221 auto c1 = Converter("the-identifier").fromJson(j);
0222
0223 BOOST_CHECK_EQUAL(c0.size(), c1.size());
0224 for (auto i = std::min(c0.size(), c1.size()); 0 < i--;) {
0225 BOOST_CHECK_EQUAL(c0.idAt(i), c1.idAt(i));
0226 BOOST_CHECK_EQUAL(c0.valueAt(i), c1.valueAt(i));
0227 }
0228 }
0229
0230 BOOST_AUTO_TEST_CASE(FromFile) {
0231
0232 auto path = Acts::Test::getDataPath("geometry-hierarchy-map.json");
0233 auto file = std::ifstream(path, std::ifstream::in | std::ifstream::binary);
0234 BOOST_CHECK(file.good());
0235 json j;
0236 file >> j;
0237 BOOST_CHECK(file.good());
0238
0239 Container c = Converter("thing").fromJson(j);
0240
0241 BOOST_CHECK(!c.empty());
0242 BOOST_CHECK_EQUAL(c.size(), 4);
0243 BOOST_CHECK_NE(c.find(makeId()), c.end());
0244 BOOST_CHECK_NE(c.find(makeId(1, 2)), c.end());
0245 BOOST_CHECK_NE(c.find(makeId(3)), c.end());
0246 BOOST_CHECK_NE(c.find(makeId(3, 4)), c.end());
0247 }
0248
0249 BOOST_AUTO_TEST_SUITE_END()