File indexing completed on 2025-06-17 01:30:10
0001 #include <algorithm>
0002 #include <cassert>
0003 #include <iterator>
0004 #include <ostream>
0005 #include <stdexcept>
0006 #include <vector>
0007
0008 #include <catch.hpp>
0009
0010 #include "DataFormats/Common/interface/DetSetVector.h"
0011 #include "DataFormats/Common/interface/Ref.h"
0012 #include "DataFormats/Common/interface/TestHandle.h"
0013 #include "DataFormats/Provenance/interface/ProductID.h"
0014
0015 using namespace edm;
0016
0017
0018
0019
0020
0021 struct Empty {};
0022
0023 template <typename BASE>
0024 class ValueWithKeyT : public BASE {
0025 public:
0026
0027 ValueWithKeyT() : d_(0.0) {}
0028
0029
0030 ~ValueWithKeyT() = default;
0031
0032
0033
0034 double sort_key() const { return d_; }
0035
0036
0037 bool operator<(ValueWithKeyT const& other) const { return sort_key() < other.sort_key(); }
0038
0039
0040
0041
0042
0043
0044 explicit ValueWithKeyT(double d) : d_(d) {}
0045
0046
0047
0048 double val() const { return d_; }
0049
0050 private:
0051 double d_;
0052 };
0053
0054 typedef edm::DoNotSortUponInsertion DNS;
0055
0056 template <>
0057 double ValueWithKeyT<DNS>::sort_key() const {
0058 throw std::logic_error("You can't sort me!");
0059 }
0060
0061 typedef ValueWithKeyT<Empty> Value;
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 template <typename BASE>
0076 std::ostream& operator<<(std::ostream& os, ValueWithKeyT<BASE> const& v) {
0077 os << " val: " << v.val();
0078 return os;
0079 }
0080
0081 typedef edm::DetSetVector<Value> coll_type;
0082 typedef coll_type::detset detset;
0083
0084 void check_outer_collection_order(coll_type const& c) {
0085 if (c.size() < 2)
0086 return;
0087 coll_type::const_iterator i = c.begin();
0088 coll_type::const_iterator e = c.end();
0089
0090 coll_type::const_iterator prev(i);
0091 ++i;
0092 for (; i != e; ++i, ++prev) {
0093
0094
0095 REQUIRE(prev->id < i->id);
0096 }
0097 }
0098
0099 void check_inner_collection_order(detset const& d) {
0100 if (d.data.size() < 2)
0101 return;
0102 detset::const_iterator i = d.data.begin();
0103 detset::const_iterator e = d.data.end();
0104
0105 detset::const_iterator prev(i);
0106 ++i;
0107 for (; i != e; ++i, ++prev) {
0108
0109
0110
0111
0112
0113 REQUIRE(!(*i < *prev));
0114 }
0115 }
0116
0117 void printDetSet(detset const& ds, std::ostream& os) {
0118 os << "size: " << ds.data.size() << '\n' << "values: ";
0119 std::copy(ds.data.begin(), ds.data.end(), std::ostream_iterator<detset::value_type>(os, " "));
0120 }
0121
0122 void sanity_check(coll_type const& c) {
0123 check_outer_collection_order(c);
0124 for (coll_type::const_iterator i = c.begin(), e = c.end(); i != e; ++i) {
0125
0126
0127 check_inner_collection_order(*i);
0128 }
0129 }
0130
0131 void check_ids(coll_type const& c) {
0132
0133 std::vector<det_id_type> all_ids;
0134 for (coll_type::const_iterator i = c.begin(), e = c.end(); i != e; ++i) {
0135 all_ids.push_back(i->id);
0136 }
0137 REQUIRE(c.size() == all_ids.size());
0138
0139 std::vector<det_id_type> nice_ids;
0140 c.getIds(nice_ids);
0141 REQUIRE(all_ids == nice_ids);
0142 }
0143
0144 namespace {
0145 template <typename T>
0146 struct DSVGetter : edm::EDProductGetter {
0147 DSVGetter() : edm::EDProductGetter(), prod_(nullptr) {}
0148 WrapperBase const* getIt(ProductID const&) const override { return prod_; }
0149
0150 std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> getThinnedProduct(ProductID const&,
0151 unsigned int) const override {
0152 return std::nullopt;
0153 }
0154
0155 void getThinnedProducts(ProductID const& pid,
0156 std::vector<WrapperBase const*>& wrappers,
0157 std::vector<unsigned int>& keys) const override {}
0158
0159 edm::OptionalThinnedKey getThinnedKeyFrom(ProductID const&, unsigned int, ProductID const&) const override {
0160 return std::monostate{};
0161 }
0162
0163 unsigned int transitionIndex_() const override { return 0U; }
0164
0165 edm::Wrapper<T> const* prod_;
0166 };
0167 }
0168
0169 TEST_CASE("test DetSetVector with sort_key", "[DetSetVector]") {
0170 SECTION("detsetTest") {
0171
0172 detset d;
0173 Value v1(1.1);
0174 Value v2(2.2);
0175 d.id = edm::det_id_type(3);
0176 d.data.push_back(v1);
0177 d.data.push_back(v2);
0178 edm::detail::sort_by_key(d.data.begin(), d.data.end(), [](const Value& v) { return v.sort_key(); });
0179 check_inner_collection_order(d);
0180
0181 }
0182
0183 SECTION("refTest") {
0184 coll_type c;
0185 detset d3;
0186 Value v1(1.1);
0187 Value v2(2.2);
0188 d3.id = edm::det_id_type(3);
0189 d3.data.push_back(v1);
0190 d3.data.push_back(v2);
0191 c.insert(d3);
0192 detset d1;
0193 Value v1a(4.1);
0194 Value v2a(3.2);
0195 d1.id = edm::det_id_type(1);
0196 d1.data.push_back(v1a);
0197 d1.data.push_back(v2a);
0198 c.insert(d1);
0199 c.post_insert();
0200
0201 auto pC = std::make_unique<coll_type>(c);
0202 edm::Wrapper<coll_type> wrapper(std::move(pC));
0203 DSVGetter<coll_type> theGetter;
0204 theGetter.prod_ = &wrapper;
0205
0206 typedef edm::Ref<coll_type, detset> RefDetSet;
0207 typedef edm::Ref<coll_type, Value> RefDet;
0208
0209 {
0210 RefDetSet refSet(edm::ProductID(1, 1), 0, &theGetter);
0211 REQUIRE((!(d1 < *refSet) && !(*refSet < d1)));
0212 }
0213 {
0214 RefDetSet refSet(edm::ProductID(1, 1), 1, &theGetter);
0215 REQUIRE((!(d3 < *refSet) && !(*refSet < d3)));
0216 }
0217 {
0218 RefDet refDet(edm::ProductID(1, 1), RefDet::key_type(3, 0), &theGetter);
0219 REQUIRE((!(v1 < *refDet) && !(*refDet < v1)));
0220 }
0221
0222 {
0223 TestHandle<coll_type> pc2(&c, ProductID(1, 1));
0224 RefDet refDet = makeRefToDetSetVector(pc2, det_id_type(3), c[3].data.begin());
0225 REQUIRE((!(v1 < *refDet) && !(*refDet < v1)));
0226 }
0227
0228 using namespace Catch::Matchers;
0229 SECTION("bad detid") {
0230 TestHandle<coll_type> pc2(&c, ProductID(1, 1));
0231 REQUIRE_THROWS_MATCHES(
0232 makeRefToDetSetVector(pc2, det_id_type(12), c[3].data.begin()),
0233 edm::Exception,
0234 Predicate<edm::Exception>(
0235 [](auto const& iExcept) { return iExcept.categoryCode() == edm::errors::InvalidReference; },
0236 "Exception has wrong category"));
0237 }
0238
0239 SECTION("bad iterator") {
0240 TestHandle<coll_type> pc2(&c, ProductID(1, 1));
0241 REQUIRE_THROWS_MATCHES(
0242 makeRefToDetSetVector(pc2, det_id_type(1), c[3].data.begin()),
0243 edm::Exception,
0244 Predicate<edm::Exception>([](auto const& x) { return x.categoryCode() == edm::errors::InvalidReference; },
0245 "Exception has wrong category"));
0246 }
0247 }
0248
0249 SECTION("work") {
0250 coll_type c1;
0251 c1.post_insert();
0252 sanity_check(c1);
0253 REQUIRE(c1.size() == 0);
0254 REQUIRE(c1.empty());
0255
0256 coll_type c2(c1);
0257 REQUIRE(c2.size() == c1.size());
0258 sanity_check(c2);
0259 coll_type c;
0260 sanity_check(c);
0261 {
0262 detset d;
0263 Value v1(1.1);
0264 Value v2(2.2);
0265 d.id = edm::det_id_type(3);
0266 d.data.push_back(v1);
0267 d.data.push_back(v2);
0268 c.insert(d);
0269 c.post_insert();
0270 }
0271 sanity_check(c);
0272 REQUIRE(c.size() == 1);
0273 {
0274 detset d;
0275 Value v1(4.1);
0276 Value v2(3.2);
0277 d.id = edm::det_id_type(1);
0278 d.data.push_back(v1);
0279 d.data.push_back(v2);
0280 c.insert(d);
0281 c.post_insert();
0282 }
0283 sanity_check(c);
0284 REQUIRE(c.size() == 2);
0285
0286 {
0287 detset d;
0288 Value v1(1.1);
0289 Value v2(1.2);
0290 Value v3(2.2);
0291 d.id = edm::det_id_type(10);
0292 d.data.push_back(v3);
0293 d.data.push_back(v2);
0294 d.data.push_back(v1);
0295 c.insert(d);
0296 c.post_insert();
0297 }
0298 sanity_check(c);
0299 REQUIRE(c.size() == 3);
0300
0301 coll_type another;
0302 c.swap(another);
0303 REQUIRE(c.empty());
0304 REQUIRE(another.size() == 3);
0305 sanity_check(c);
0306 sanity_check(another);
0307
0308 c.swap(another);
0309 REQUIRE(c.size() == 3);
0310
0311 {
0312
0313 coll_type::iterator i = c.find(edm::det_id_type(11));
0314 REQUIRE(i == c.end());
0315
0316 coll_type::const_iterator ci = static_cast<coll_type const&>(c).find(edm::det_id_type(11));
0317 REQUIRE(ci == c.end());
0318 }
0319 {
0320
0321 coll_type::iterator i = c.find(edm::det_id_type(10));
0322 REQUIRE(i != c.end());
0323 REQUIRE(i->id == 10);
0324 REQUIRE(i->data.size() == 3);
0325 }
0326 using namespace Catch::Matchers;
0327 {
0328
0329 SECTION("op[] should throw") {
0330 REQUIRE_THROWS_MATCHES(
0331 c[edm::det_id_type(100)],
0332 edm::Exception,
0333 Predicate<edm::Exception>([](auto const& x) { return x.categoryCode() == edm::errors::InvalidReference; },
0334 "Exception has wrong category"));
0335 }
0336 }
0337
0338 {
0339
0340 SECTION("coll_type op[] should throw") {
0341 REQUIRE_THROWS_MATCHES(
0342 static_cast<coll_type const&>(c)[edm::det_id_type(100)],
0343 edm::Exception,
0344 Predicate<edm::Exception>([](auto const& x) { return x.categoryCode() == edm::errors::InvalidReference; },
0345 "Exception has wrong category"));
0346 }
0347 }
0348 {
0349
0350 coll_type const& rc = c;
0351 coll_type::const_reference r = rc[3];
0352 REQUIRE(r.id == edm::det_id_type(3));
0353 REQUIRE(r.data.size() == 2);
0354
0355 coll_type::reference r2 = c[3];
0356 REQUIRE(r2.id == edm::det_id_type(3));
0357 REQUIRE(r2.data.size() == 2);
0358 }
0359
0360 {
0361
0362
0363 coll_type::size_type oldsize = c.size();
0364 coll_type::reference r = c.find_or_insert(edm::det_id_type(17));
0365 coll_type::size_type newsize = c.size();
0366 REQUIRE(newsize > oldsize);
0367 REQUIRE(newsize == (oldsize + 1));
0368 REQUIRE(r.id == edm::det_id_type(17));
0369 REQUIRE(r.data.size() == 0);
0370 r.data.push_back(Value(10.1));
0371 r.data.push_back(Value(9.1));
0372 r.data.push_back(Value(4.0));
0373 r.data.push_back(Value(4.0));
0374 c.post_insert();
0375 sanity_check(c);
0376 }
0377 {
0378
0379 unsigned int const numDetSets = 20;
0380 unsigned int const detSetSize = 14;
0381 std::vector<detset> v;
0382 for (unsigned int i = 0; i < numDetSets; ++i) {
0383 detset d(i);
0384 for (unsigned int j = 0; j < detSetSize; ++j) {
0385 d.data.push_back(Value(100 * i + 1.0 / j));
0386 }
0387 v.push_back(d);
0388 }
0389 REQUIRE(v.size() == numDetSets);
0390 coll_type c3(v);
0391 c3.post_insert();
0392 REQUIRE(v.size() == 0);
0393 REQUIRE(c3.size() == numDetSets);
0394 sanity_check(c3);
0395
0396 coll_type c4;
0397 c4 = c3;
0398 REQUIRE(c4.size() == numDetSets);
0399 sanity_check(c3);
0400 sanity_check(c4);
0401
0402 check_ids(c3);
0403 }
0404 }
0405 }