/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
DataFormats/Common/test/testMultiAssociation.cc
795 строк
26 KB
Chris Jones
Moved tests in DataFormats/Common to catch2
31 мар 2026, 17:34
31 мар 2026, 17:34
46bb420
Код
Авторство
О чём код?
#include "DataFormats/Common/interface/OwnVector.h" #include "DataFormats/Common/interface/PtrVector.h" #include "DataFormats/Common/interface/RefVector.h" #include "DataFormats/Common/interface/TestHandle.h" #include "FWCore/Utilities/interface/Exception.h" #include <catch2/catch_all.hpp> #include "boost/lambda/bind.hpp" #include "boost/lambda/lambda.hpp" #include <algorithm> #include <cmath> #include <iomanip> #include <iostream> #include <iterator> #include <memory> #include "DataFormats/Common/interface/MultiAssociation.h" namespace { struct DummyBase { virtual ~DummyBase() {} virtual int id() const { return 0; } virtual DummyBase* clone() const { return new DummyBase(*this); } void const* addr() const { return this; } }; struct DummyDer1 : public DummyBase { virtual int id() const { return 1; } virtual DummyDer1* clone() const { return new DummyDer1(*this); } }; struct DummyDer2 : public DummyBase { virtual int id() const { return 2; } virtual DummyDer2* clone() const { return new DummyDer2(*this); } }; } // namespace using namespace edm; typedef std::vector<double> CVal; // Values typedef std::vector<int> CKey1; // Keys 1 typedef std::vector<float> CKey2; // Keys 2 typedef std::vector<DummyDer1> CObj; typedef Ptr<DummyBase> PObj; typedef PtrVector<DummyBase> PObjs; typedef OwnVector<DummyBase> OObj; typedef MultiAssociation<RefVector<CVal> > MultiRef; typedef MultiAssociation<CVal> MultiVal; typedef MultiAssociation<PObjs> MultiPtr; typedef MultiAssociation<OObj> MultiOwn; namespace { /** * Map to each key, all values that are greater than key * Try both with MultiAssociation<RefVector<double>> and MultiAssociation<vector<double> > */ struct TestData { CVal k; CKey1 v1; CKey2 v2; CObj der1s; PObjs ptrs; OObj bases; edm::TestHandle<CVal> handleV; edm::TestHandle<CKey1> handleK1; edm::TestHandle<CKey2> handleK2; std::vector<int> w1, w2; void initialize(); void checkAll(); void checkVals(); void checkTwoFillers(); void checkUnsortedKeys(); void checkBadFill(); void checkBadRead(); template <typename Map> bool tryTwoFillers(bool lazy); template <typename Map> bool tryUnsortedKeys(bool lazy); bool tryBadFill(int i); bool tryBadRead(int i); void checkWithPtr(); void checkWithOwn(); void checkWritableMap(); void test(MultiRef const&); void test(MultiVal const&); void test2(MultiRef const&); #ifdef private void dump(MultiRef::Indices const&); template <typename T> void dump(RefVector<T> const&); template <typename T> void dump(std::vector<T> const&); void dump(MultiRef const&, char const* when); void dump(MultiVal const&, char const* when); #else template <typename T> void dump(RefVector<T> const&) {} template <typename T> void dump(std::vector<T> const&) {} void dump(MultiRef const&, char const* /*when*/) {} void dump(MultiVal const&, char const* /*when*/) {} #endif template <typename Key, typename UnaryFunc, typename BinaryFunc> void fastFillRefs(edm::TestHandle<Key> const& handle, MultiRef& map, UnaryFunc const& u, BinaryFunc const& f) { MultiRef::FastFiller filler = map.fastFiller(handle); for (typename Key::const_iterator it = handle->begin(), ed = handle->end(); it != ed; ++it) { if (!u(*it)) continue; RefVector<CVal> vals; for (std::vector<double>::const_iterator it2 = k.begin(), ed2 = k.end(); it2 != ed2; ++it2) { if (f(*it, *it2)) { vals.push_back(Ref<CVal>(handleV, it2 - k.begin())); } } filler.setValues(Ref<Key>(handle, it - handle->begin()), vals); } } template <typename Key, typename UnaryFunc, typename BinaryFunc> void lazyFillRefs( edm::TestHandle<Key> const& handle, MultiRef& map, UnaryFunc const& u, BinaryFunc const& f, bool swap) { MultiRef::LazyFiller filler = map.lazyFiller(handle, true); for (typename Key::const_iterator it = handle->begin(), ed = handle->end(); it != ed; ++it) { if (!u(*it)) continue; RefVector<CVal> vals; for (std::vector<double>::const_iterator it2 = k.begin(), ed2 = k.end(); it2 != ed2; ++it2) { if (f(*it, *it2)) { vals.push_back(Ref<CVal>(handleV, it2 - k.begin())); } } if (swap) { filler.swapValues(Ref<Key>(handle, it - handle->begin()), vals); } else { filler.setValues(Ref<Key>(handle, it - handle->begin()), vals); } } } template <typename Key, typename UnaryFunc, typename BinaryFunc> void fastFillVals(edm::TestHandle<Key> const& handle, MultiVal& map, UnaryFunc const& u, BinaryFunc const& f) { MultiVal::FastFiller filler = map.fastFiller(handle); for (typename Key::const_iterator it = handle->begin(), ed = handle->end(); it != ed; ++it) { if (!u(*it)) continue; CVal vals; for (std::vector<double>::const_iterator it2 = k.begin(), ed2 = k.end(); it2 != ed2; ++it2) { if (f(*it, *it2)) { vals.push_back(*it2); } } filler.setValues(Ref<Key>(handle, it - handle->begin()), vals); } } template <typename Key, typename UnaryFunc, typename BinaryFunc> void lazyFillVals( edm::TestHandle<Key> const& handle, MultiVal& map, UnaryFunc const& u, BinaryFunc const& f, bool swap) { MultiVal::LazyFiller filler = map.lazyFiller(handle, true); for (typename Key::const_iterator it = handle->begin(), ed = handle->end(); it != ed; ++it) { if (!u(*it)) continue; CVal vals; for (std::vector<double>::const_iterator it2 = k.begin(), ed2 = k.end(); it2 != ed2; ++it2) { if (f(*it, *it2)) { vals.push_back(*it2); } } if (swap) { filler.swapValues(Ref<Key>(handle, it - handle->begin()), vals); } else { filler.setValues(Ref<Key>(handle, it - handle->begin()), vals); } } } //template<typename Map, typename Filler> tryUnsortedKeys() ; }; void TestData::initialize() { k.push_back(1.1); k.push_back(2.2); k.push_back(3.3); k.push_back(4.4); ProductID const pidV(1); handleV = edm::TestHandle<CVal>(&k, pidV); v1.push_back(1); v1.push_back(2); v1.push_back(3); v1.push_back(4); ProductID const pidK1(2); handleK1 = edm::TestHandle<CKey1>(&v1, pidK1); v2.push_back(1.); v2.push_back(2.); v2.push_back(3.); v2.push_back(4.); v2.push_back(5.); ProductID const pidK2(3); handleK2 = edm::TestHandle<CKey2>(&v2, pidK2); for (size_t j = 0; j < 10; ++j) der1s.push_back(DummyDer1()); for (size_t j = 0; j < 10; ++j) { if (j % 3 == 0) bases.push_back(std::make_unique<DummyBase>()); if (j % 3 == 1) bases.push_back(std::make_unique<DummyDer1>()); if (j % 3 == 2) bases.push_back(std::make_unique<DummyDer2>()); REQUIRE(bases[j].id() == int(j % 3)); } edm::TestHandle<CObj> handleObj(&der1s, ProductID(10)); for (size_t j = 0; j < 7; ++j) { size_t k = (j * 37) % 10; ptrs.push_back(PObj(handleObj, k)); REQUIRE(ptrs[j]->id() == 1); REQUIRE(ptrs[j]->addr() == &der1s[k]); } } } // namespace TEST_CASE("MultiAssociation", "[MultiAssociation]") { TestData data; data.initialize(); SECTION("checkAll") { data.checkAll(); } SECTION("checkVals") { data.checkVals(); } SECTION("checkTwoFillers") { data.checkTwoFillers(); } SECTION("checkUnsortedKeys") { data.checkUnsortedKeys(); } SECTION("checkBadFill") { data.checkBadFill(); } SECTION("checkBadRead") { data.checkBadRead(); } SECTION("checkWithPtr") { data.checkWithPtr(); } SECTION("checkWithOwn") { data.checkWithOwn(); } SECTION("checkWritableMap") { data.checkWritableMap(); } } namespace { void TestData::checkAll() { using boost::lambda::_1; using boost::lambda::_2; { MultiRef try1; dump(try1, "empty"); fastFillRefs(handleK1, try1, _1 > 0, _1 > _2); dump(try1, "fill 1"); fastFillRefs(handleK2, try1, _1 > 0, _1 > _2); dump(try1, "fill 2"); test(try1); } { MultiRef try2; fastFillRefs( handleK1, try2, _1 > 0, (_1 < _2) && (2 * bind(floor, _1 / 2) != _1)); // fill all, but leave empty the odds fastFillRefs( handleK2, try2, _1 > 0, (_1 < _2) && (2 * bind(floor, _1 / 2) != _1)); // fill all, but leave empty the odds dump(try2, "fill 2"); test2(try2); } { MultiRef try2; fastFillRefs(handleK1, try2, (2 * bind(floor, _1 / 2) != _1), (_1 < _2) && (2 * bind(floor, _1 / 2) != _1)); // don't fill the odds fastFillRefs(handleK2, try2, (2 * bind(floor, _1 / 2) != _1), (_1 < _2) && (2 * bind(floor, _1 / 2) != _1)); // don't fill the odds dump(try2, "fill 2"); test2(try2); } { MultiRef try3; fastFillRefs(handleK1, try3, _1 < 0, (_1 > _2)); // don't fill any of the first fastFillRefs(handleK2, try3, _1 > 0, (_1 > _2)); // dump(try3, "no first"); } { MultiRef try3; fastFillRefs(handleK1, try3, _1 > 0, (_1 > _2)); // fastFillRefs(handleK2, try3, _1 < 0, (_1 > _2)); // don't fill the second dump(try3, "no second"); } { MultiRef try3; fastFillRefs(handleK1, try3, _1 < 0, (_1 > _2)); // don't fill any of the first fastFillRefs(handleK2, try3, _1 < 0, (_1 > _2)); // nor the second dump(try3, "neither"); } { MultiRef try1; lazyFillRefs(handleK1, try1, _1 > 0, _1 > _2, false); lazyFillRefs(handleK2, try1, _1 > 0, _1 > _2, false); dump(try1, "fill 2"); test(try1); } { MultiRef try2; lazyFillRefs(handleK1, try2, (2 * bind(floor, _1 / 2) != _1), (_1 < _2) && (2 * bind(floor, _1 / 2) != _1), false); // don't fill the odds lazyFillRefs(handleK2, try2, (2 * bind(floor, _1 / 2) != _1), (_1 < _2) && (2 * bind(floor, _1 / 2) != _1), false); // don't fill the odds dump(try2, "fill 2"); test2(try2); } { MultiRef try1; lazyFillRefs(handleK1, try1, _1 > 0, _1 > _2, true); lazyFillRefs(handleK2, try1, _1 > 0, _1 > _2, true); dump(try1, "fill 2"); test(try1); } { MultiRef try2; lazyFillRefs(handleK1, try2, (2 * bind(floor, _1 / 2) != _1), (_1 < _2) && (2 * bind(floor, _1 / 2) != _1), true); // don't fill the odds lazyFillRefs(handleK2, try2, (2 * bind(floor, _1 / 2) != _1), (_1 < _2) && (2 * bind(floor, _1 / 2) != _1), true); // don't fill the odds dump(try2, "fill 2"); test2(try2); } } void TestData::checkVals() { using boost::lambda::_1; using boost::lambda::_2; { MultiVal try1; dump(try1, "empty"); fastFillVals(handleK1, try1, _1 > 0, _1 > _2); dump(try1, "fill 1"); fastFillVals(handleK2, try1, _1 > 0, _1 > _2); dump(try1, "fill 2"); test(try1); } { MultiVal try1; lazyFillVals(handleK1, try1, _1 > 0, _1 > _2, false); lazyFillVals(handleK2, try1, _1 > 0, _1 > _2, false); dump(try1, "fill 2"); test(try1); } { MultiVal try1; lazyFillVals(handleK1, try1, _1 > 0, _1 > _2, true); lazyFillVals(handleK2, try1, _1 > 0, _1 > _2, true); dump(try1, "fill 2"); test(try1); } } #ifdef private void TestData::dump(MultiRef::Indices const& indices) { using namespace std; cerr << " Dumping Index map at " << &indices << endl; cerr << " id_offsets_ (size = " << indices.id_offsets_.size() << ")" << endl; for (size_t i = 0; i < indices.id_offsets_.size(); ++i) { cerr << " [" << setw(3) << i << "]: (" << setw(3) << indices.id_offsets_[i].first << ", " << setw(3) << indices.id_offsets_[i].second << ")" << endl; } cerr << " ref_offsets_ (size = " << indices.ref_offsets_.size() << ")" << endl; for (size_t i = 0; i < indices.ref_offsets_.size(); ++i) { cerr << " [" << setw(3) << i << "]: " << setw(4) << indices.ref_offsets_[i] << ")" << endl; } cerr << " isFilling_: " << indices.isFilling_ << endl; } template <typename T> void TestData::dump(RefVector<T> const& data) { using namespace std; cerr << " Dumping " << typeid(data).name() << " at " << &data << endl; cerr << " ID: " << data.id() << endl; cerr << " Values (size = " << data.size() << ")" << endl; for (size_t i = 0; i < data.size(); ++i) { cerr << " [" << setw(3) << i << "]: key = " << setw(4) << data[i].key(); if (data[i].isNull()) cerr << ", NULL" << endl; else cerr << ", value = " << *data[i] << endl; } } template <typename T> void TestData::dump(std::vector<T> const& data) { using namespace std; cerr << " Dumping " << typeid(data).name() << " at " << &data << endl; cerr << " Values (size = " << data.size() << ")" << endl; for (size_t i = 0; i < data.size(); ++i) { cerr << " [" << setw(3) << i << "]: key = " << setw(4) << data[i] << endl; } } void TestData::dump(MultiRef const& assoc, char const* what) { using namespace std; cerr << "\nDumping MultiRef at " << &assoc << " for " << what << endl; dump(assoc.indices_); dump(assoc.data_); cerr << endl; } void TestData::dump(MultiVal const& assoc, char const* what) { using namespace std; cerr << "\nDumping MultiVal at " << &assoc << " for " << what << endl; dump(assoc.indices_); dump(assoc.data_); cerr << endl; } #endif void TestData::test(MultiRef const& assoc) { // TEST contains REQUIRE(!assoc.contains(ProductID(1))); REQUIRE(assoc.contains(ProductID(2))); REQUIRE(assoc.contains(ProductID(3))); REQUIRE(!assoc.contains(ProductID(4))); // TEST const_range access MultiRef::const_range br1, br2, br3, br4; br1 = assoc[edm::Ref<CKey1>(handleK1, 0)]; br2 = assoc[edm::Ref<CKey1>(handleK1, 1)]; br3 = assoc[edm::Ref<CKey1>(handleK1, 2)]; br4 = assoc[edm::Ref<CKey1>(handleK1, 3)]; REQUIRE(br1.size() == 0); REQUIRE(br2.size() == 1); REQUIRE(br3.size() == 2); REQUIRE(br4.size() == 3); REQUIRE(br2.begin()->id() == ProductID(1)); REQUIRE(br2.begin()->key() == 0); REQUIRE(**br2.begin() == k.front()); REQUIRE(*br2.front() == k.front()); REQUIRE(*br2[0] == k[0]); REQUIRE(br4.back().id() == ProductID(1)); REQUIRE(br4.back().key() == 2); REQUIRE(br4[2].key() == 2); // TEST const_ranges // Check that ranges are consecutive br1 = assoc[edm::Ref<CKey1>(handleK1, 0)]; REQUIRE(br1.end() == br1.begin()); br2 = assoc[edm::Ref<CKey1>(handleK1, 1)]; REQUIRE(br2.end() == br2.begin() + 1); REQUIRE(br2.begin() == br1.end()); br3 = assoc[edm::Ref<CKey1>(handleK1, 2)]; REQUIRE(br3.end() == br3.begin() + 2); REQUIRE(br3.begin() == br2.end()); // Check that ranges are consecutive across collections br1 = assoc[edm::Ref<CKey1>(handleK1, 3)]; br2 = assoc[edm::Ref<CKey2>(handleK2, 0)]; br3 = assoc[edm::Ref<CKey2>(handleK2, 1)]; REQUIRE(br1.end() == br1.begin() + 3); REQUIRE(br1.end() == br2.begin() + 0); REQUIRE(br2.end() == br2.begin() + 0); REQUIRE(br2.end() == br3.begin() + 0); REQUIRE(br3.end() == br3.begin() + 1); // TEST RefVector access edm::RefVector<CVal> r1, r2, r3, r4, r5; r1 = assoc.getValues(edm::Ref<CKey1>(handleK1, 0)); r2 = assoc.getValues(edm::Ref<CKey1>(handleK1, 1)); r3 = assoc.getValues(edm::Ref<CKey1>(handleK1, 2)); r4 = assoc.getValues(edm::Ref<CKey1>(handleK1, 3)); REQUIRE(r1.size() == 0); REQUIRE(r2.size() == 1); REQUIRE(r3.size() == 2); REQUIRE(r4.size() == 3); REQUIRE(r2.begin()->id() == ProductID(1)); REQUIRE(r2.begin()->key() == 0); REQUIRE(**r2.begin() == k.front()); REQUIRE(**r2.begin() == k.front()); REQUIRE((r4.end() - 1)->id() == ProductID(1)); REQUIRE((r4.end() - 1)->key() == 2); } void TestData::test2(MultiRef const& assoc) { // TEST contains REQUIRE(!assoc.contains(ProductID(1))); REQUIRE(assoc.contains(ProductID(2))); REQUIRE(assoc.contains(ProductID(3))); REQUIRE(!assoc.contains(ProductID(4))); // TEST const_range access MultiRef::const_range br1, br2, br3, br4; br1 = assoc[edm::Ref<CKey1>(handleK1, 0)]; REQUIRE(br1.end() == br1.begin() + 4); br2 = assoc[edm::Ref<CKey1>(handleK1, 1)]; REQUIRE(br2.end() == br2.begin() + 0); REQUIRE(br2.begin() == br1.end()); br3 = assoc[edm::Ref<CKey1>(handleK1, 2)]; REQUIRE(br3.end() == br3.begin() + 2); REQUIRE(br3.begin() == br2.end()); // Check that ranges are consecutive across collections br1 = assoc[edm::Ref<CKey1>(handleK1, 3)]; br2 = assoc[edm::Ref<CKey2>(handleK2, 0)]; br3 = assoc[edm::Ref<CKey2>(handleK2, 1)]; REQUIRE(br1.end() == br1.begin() + 0); REQUIRE(br1.end() == br2.begin() + 0); REQUIRE(br2.end() == br2.begin() + 4); REQUIRE(br2.end() == br3.begin() + 0); REQUIRE(br3.end() == br3.begin() + 0); } void TestData::test(MultiVal const& assoc) { #if 1 // TEST Vector access MultiVal::const_range r1, r2, r3, r4, r5; r1 = assoc[edm::Ref<CKey1>(handleK1, 0)]; r2 = assoc[edm::Ref<CKey1>(handleK1, 1)]; r3 = assoc[edm::Ref<CKey1>(handleK1, 2)]; r4 = assoc[edm::Ref<CKey1>(handleK1, 3)]; #else // TEST Vector access CVal r1, r2, r3, r4, r5; r1 = assoc.getValues(edm::Ref<CKey1>(handleK1, 0)); r2 = assoc.getValues(edm::Ref<CKey1>(handleK1, 1)); r3 = assoc.getValues(edm::Ref<CKey1>(handleK1, 2)); r4 = assoc.getValues(edm::Ref<CKey1>(handleK1, 3)); #endif REQUIRE(r1.size() == 0); REQUIRE(r2.size() == 1); REQUIRE(r3.size() == 2); REQUIRE(r4.size() == 3); REQUIRE(r2[0] == k[0]); REQUIRE(r3[0] == k[0]); REQUIRE(r3[1] == k[1]); REQUIRE(r4[0] == k[0]); REQUIRE(r4[1] == k[1]); REQUIRE(r4[2] == k[2]); } template <typename Map> bool TestData::tryTwoFillers(bool lazyfiller) { Map map; if (lazyfiller) { typename Map::LazyFiller filler1(map, handleK1, true); typename Map::LazyFiller filler2(map, handleK2, true); } else { typename Map::FastFiller filler1(map, handleK1); typename Map::FastFiller filler2(map, handleK2); } return true; } void TestData::checkTwoFillers() { REQUIRE(tryTwoFillers<MultiRef>(true)); REQUIRE_THROWS_AS(tryTwoFillers<MultiRef>(false), cms::Exception); REQUIRE(tryTwoFillers<MultiVal>(true)); REQUIRE_THROWS_AS(tryTwoFillers<MultiVal>(false), cms::Exception); } template <typename Map> bool TestData::tryUnsortedKeys(bool lazy) { Map map; typename Map::Collection coll1, coll2; if (lazy) { typename Map::LazyFiller filler(map, handleK1, true); filler.setValues(Ref<CKey1>(handleK1, 1), coll1); filler.setValues(Ref<CKey1>(handleK1, 0), coll2); } else { typename Map::FastFiller filler(map, handleK1); filler.setValues(Ref<CKey1>(handleK1, 1), coll1); filler.setValues(Ref<CKey1>(handleK1, 0), coll2); } return true; } void TestData::checkUnsortedKeys() { REQUIRE(tryUnsortedKeys<MultiRef>(true)); REQUIRE_THROWS_AS(tryUnsortedKeys<MultiRef>(false), cms::Exception); REQUIRE(tryUnsortedKeys<MultiVal>(true)); REQUIRE_THROWS_AS(tryUnsortedKeys<MultiVal>(false), cms::Exception); } // i = even: succeed; i = odd: fail bool TestData::tryBadFill(int i) { MultiRef m; MultiRef::Collection coll1; coll1.push_back(Ref<CVal>(handleV, 1)); switch (i) { case 0: { // fill with right prod. id MultiRef::FastFiller filler = m.fastFiller(handleK1); filler.setValues(Ref<CKey1>(handleK1, 0), coll1); }; break; case 1: { // fill with wrong prod. id MultiRef::FastFiller filler = m.fastFiller(handleK1); filler.setValues(Ref<CKey2>(handleK2, 0), coll1); }; break; case 2: { // fill again with different id { MultiRef::FastFiller filler = m.fastFiller(handleK1); } { MultiRef::FastFiller filler = m.fastFiller(handleK2); } }; break; case 3: { // fill again with the same id { MultiRef::FastFiller filler = m.fastFiller(handleK1); } { MultiRef::FastFiller filler = m.fastFiller(handleK1); } }; break; case 4: { // Check lazyFiller doesn't fill if not requested { MultiRef::LazyFiller filler = m.lazyFiller(handleK1); } { MultiRef::LazyFiller filler = m.lazyFiller(handleK1); } }; break; case 5: { // Check lazyFiller can't fill twice the same key if requested { MultiRef::LazyFiller filler = m.lazyFiller(handleK1, true); } { MultiRef::LazyFiller filler = m.lazyFiller(handleK1, true); } }; break; case 6: { // Check lazyFiller doesn't fill twice by mistake MultiRef::LazyFiller filler = m.lazyFiller(handleK1, true); REQUIRE(m.empty()); filler.fill(); REQUIRE(!m.empty()); filler.fill(); }; break; case 8: { // Check lazyFiller doesn't fill if not requested { MultiRef::LazyFiller filler = m.lazyFiller(handleK1, false); } REQUIRE(m.empty()); } break; case 9: { // Check index out of bounds MultiRef::FastFiller filler = m.fastFiller(handleK1); filler.setValues(Ref<CKey1>(handleK1, handleK1->size() + 5, false), coll1); } break; case 10: { // Can copy a LazyFiller, if I don't fill twice MultiRef::LazyFiller filler = m.lazyFiller(handleK1, false); MultiRef::LazyFiller filler2 = filler; filler2.setValues(Ref<CKey1>(handleK1, 0), coll1); filler2.fill(); } break; case 11: { // Can copy a LazyFiller, but crash if I fill twice MultiRef::LazyFiller filler = m.lazyFiller(handleK1, true); MultiRef::LazyFiller filler2 = filler; } break; case 12: { // Can copy a FastFiller MultiRef::FastFiller filler = m.fastFiller(handleK1); MultiRef::FastFiller filler2 = filler; } break; default: if (i % 2 == 1) throw cms::Exception("Programmed failure"); break; } return true; } void TestData::checkBadFill() { for (int i = 0; i < 100; ++i) { if (i % 2 == 0) REQUIRE(tryBadFill(i)); else REQUIRE_THROWS_AS(tryBadFill(i), cms::Exception); } } bool TestData::tryBadRead(int i) { using boost::lambda::_1; using boost::lambda::_2; MultiRef m; fastFillRefs(handleK1, m, _1 > 0, _1 > _2); fastFillRefs(handleK2, m, _1 > 0, _1 > _2); switch (i) { case 0: // good id and key m[Ref<CKey1>(handleK1, 0, false)]; break; case 1: // wrong id m[Ref<CVal>(handleV, 0, false)]; break; case 3: // wrong id & key, and outside bounds // this does crash m[Ref<CKey2>(handleK2, 5, false)]; break; case 5: // wrong id & key, but still within bounds // we check explicitly for this in Indexconst_rangeAssociation::get, even if it costs // extra time m[Ref<CKey1>(handleK1, 5, false)]; break; default: if (i % 2 == 1) throw cms::Exception("Programmed failure"); break; } return true; } void TestData::checkWritableMap() { using boost::lambda::_1; using boost::lambda::_2; MultiVal tryRW; fastFillVals(handleK1, tryRW, _1 > 0, _1 > _2); fastFillVals(handleK2, tryRW, _1 > 0, _1 > _2); test(tryRW); MultiVal::range r1, r1bis; r1 = tryRW[edm::Ref<CKey1>(handleK1, 1)]; REQUIRE(r1[0] == k[0]); r1[0] = k[1]; // check that we modified the range REQUIRE(r1[0] == k[1]); // check that even the real thing got modified r1bis = tryRW[edm::Ref<CKey1>(handleK1, 1)]; REQUIRE(r1bis[0] == k[1]); } void TestData::checkBadRead() { for (int i = 0; i < 100; ++i) { if (i % 2 == 0) REQUIRE(tryBadRead(i)); else REQUIRE_THROWS_AS(tryBadRead(i), cms::Exception); } } void TestData::checkWithPtr() { MultiPtr map; { // Fill the map MultiPtr::FastFiller filler = map.fastFiller(handleK1); edm::TestHandle<CObj> handleObj(&der1s, ProductID(10)); for (size_t i = 0; i < handleK1->size(); ++i) { PObjs vals; for (size_t j = 0; j < ((i + 2) % 3); ++j) { vals.push_back(PObj(handleObj, (3 * i + 4 * j) % 10)); } if (!vals.empty()) filler.setValues(Ref<CKey1>(handleK1, i), vals); } } { // Read the map for (size_t i = 0; i < handleK1->size(); ++i) { MultiPtr::const_range r = map[Ref<CKey1>(handleK1, i)]; REQUIRE(static_cast<size_t>(r.size()) == ((i + 2) % 3)); for (size_t j = 0; j < ((i + 2) % 3); ++j) { REQUIRE(r[j].key() == (3 * i + 4 * j) % 10); REQUIRE(r[j]->addr() == &der1s[(3 * i + 4 * j) % 10]); //REQUIRE( (r.begin()+j)->key() == (3*i+4*j)%10 ); //REQUIRE( (*(r.begin()+j))->addr() == &der1s[(3*i+4*j)%10]); } } } } void TestData::checkWithOwn() { MultiOwn map; { // Fill the map MultiOwn::FastFiller filler = map.fastFiller(handleK1); for (size_t i = 0; i < handleK1->size(); ++i) { OObj vals; for (size_t j = 0; j < ((i + 2) % 3); ++j) { vals.push_back(bases[(i + j) % 3].clone()); } if (!vals.empty()) filler.setValues(Ref<CKey1>(handleK1, i), vals); } } { // Read the map for (size_t i = 0; i < handleK1->size(); ++i) { MultiOwn::const_range r = map[Ref<CKey1>(handleK1, i)]; REQUIRE(static_cast<size_t>(r.size()) == ((i + 2) % 3)); for (size_t j = 0; j < ((i + 2) % 3); ++j) { REQUIRE((r.begin() + j)->id() == bases[(i + j) % 3].id()); } } } } } // namespace