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