File indexing completed on 2024-04-06 12:03:57
0001 #include "DataFormats/Common/interface/OwnVector.h"
0002 #include "DataFormats/Common/interface/PtrVector.h"
0003 #include "DataFormats/Common/interface/RefVector.h"
0004 #include "DataFormats/Common/interface/TestHandle.h"
0005 #include "FWCore/Utilities/interface/Exception.h"
0006
0007 #include "cppunit/extensions/HelperMacros.h"
0008
0009 #include "boost/lambda/bind.hpp"
0010 #include "boost/lambda/lambda.hpp"
0011
0012 #include <algorithm>
0013 #include <cmath>
0014 #include <iomanip>
0015 #include <iostream>
0016 #include <iterator>
0017 #include <memory>
0018
0019 #include "DataFormats/Common/interface/MultiAssociation.h"
0020
0021 namespace {
0022 struct DummyBase {
0023 virtual ~DummyBase() {}
0024 virtual int id() const { return 0; }
0025 virtual DummyBase* clone() const { return new DummyBase(*this); }
0026 void const* addr() const { return this; }
0027 };
0028 struct DummyDer1 : public DummyBase {
0029 virtual int id() const { return 1; }
0030 virtual DummyDer1* clone() const { return new DummyDer1(*this); }
0031 };
0032 struct DummyDer2 : public DummyBase {
0033 virtual int id() const { return 2; }
0034 virtual DummyDer2* clone() const { return new DummyDer2(*this); }
0035 };
0036 }
0037
0038 using namespace edm;
0039
0040 class testMultiAssociation : public CppUnit::TestFixture {
0041 CPPUNIT_TEST_SUITE(testMultiAssociation);
0042 CPPUNIT_TEST(checkAll);
0043 CPPUNIT_TEST(checkVals);
0044 CPPUNIT_TEST(checkTwoFillers);
0045 CPPUNIT_TEST(checkUnsortedKeys);
0046 CPPUNIT_TEST(checkBadFill);
0047 CPPUNIT_TEST(checkBadRead);
0048 CPPUNIT_TEST(checkWithPtr);
0049 CPPUNIT_TEST(checkWithOwn);
0050 CPPUNIT_TEST(checkWritableMap);
0051 CPPUNIT_TEST_SUITE_END();
0052 typedef std::vector<double> CVal;
0053 typedef std::vector<int> CKey1;
0054 typedef std::vector<float> CKey2;
0055 typedef std::vector<DummyDer1> CObj;
0056 typedef Ptr<DummyBase> PObj;
0057 typedef PtrVector<DummyBase> PObjs;
0058 typedef OwnVector<DummyBase> OObj;
0059 typedef MultiAssociation<RefVector<CVal> > MultiRef;
0060 typedef MultiAssociation<CVal> MultiVal;
0061 typedef MultiAssociation<PObjs> MultiPtr;
0062 typedef MultiAssociation<OObj> MultiOwn;
0063
0064
0065
0066
0067 public:
0068 testMultiAssociation();
0069 void setUp() {}
0070 void tearDown() {}
0071 void checkAll();
0072 void checkVals();
0073 void checkTwoFillers();
0074 void checkUnsortedKeys();
0075 void checkBadFill();
0076 void checkBadRead();
0077 template <typename Map>
0078 bool tryTwoFillers(bool lazy);
0079 template <typename Map>
0080 bool tryUnsortedKeys(bool lazy);
0081 bool tryBadFill(int i);
0082 bool tryBadRead(int i);
0083 void checkWithPtr();
0084 void checkWithOwn();
0085 void checkWritableMap();
0086 void test(MultiRef const&);
0087 void test(MultiVal const&);
0088 void test2(MultiRef const&);
0089 #ifdef private
0090 void dump(MultiRef::Indices const&);
0091 template <typename T>
0092 void dump(RefVector<T> const&);
0093 template <typename T>
0094 void dump(std::vector<T> const&);
0095 void dump(MultiRef const&, char const* when);
0096 void dump(MultiVal const&, char const* when);
0097 #else
0098 template <typename T>
0099 void dump(RefVector<T> const&) {}
0100 template <typename T>
0101 void dump(std::vector<T> const&) {}
0102 void dump(MultiRef const&, char const* ) {}
0103 void dump(MultiVal const&, char const* ) {}
0104 #endif
0105 CVal k;
0106 CKey1 v1;
0107 CKey2 v2;
0108 CObj der1s;
0109 PObjs ptrs;
0110 OObj bases;
0111 edm::TestHandle<CVal> handleV;
0112 edm::TestHandle<CKey1> handleK1;
0113 edm::TestHandle<CKey2> handleK2;
0114 std::vector<int> w1, w2;
0115
0116 template <typename Key, typename UnaryFunc, typename BinaryFunc>
0117 void fastFillRefs(edm::TestHandle<Key> const& handle, MultiRef& map, UnaryFunc const& u, BinaryFunc const& f) {
0118 MultiRef::FastFiller filler = map.fastFiller(handle);
0119 for (typename Key::const_iterator it = handle->begin(), ed = handle->end(); it != ed; ++it) {
0120 if (!u(*it))
0121 continue;
0122 RefVector<CVal> vals;
0123 for (std::vector<double>::const_iterator it2 = k.begin(), ed2 = k.end(); it2 != ed2; ++it2) {
0124 if (f(*it, *it2)) {
0125 vals.push_back(Ref<CVal>(handleV, it2 - k.begin()));
0126 }
0127 }
0128 filler.setValues(Ref<Key>(handle, it - handle->begin()), vals);
0129 }
0130 }
0131
0132 template <typename Key, typename UnaryFunc, typename BinaryFunc>
0133 void lazyFillRefs(
0134 edm::TestHandle<Key> const& handle, MultiRef& map, UnaryFunc const& u, BinaryFunc const& f, bool swap) {
0135 MultiRef::LazyFiller filler = map.lazyFiller(handle, true);
0136 for (typename Key::const_iterator it = handle->begin(), ed = handle->end(); it != ed; ++it) {
0137 if (!u(*it))
0138 continue;
0139 RefVector<CVal> vals;
0140 for (std::vector<double>::const_iterator it2 = k.begin(), ed2 = k.end(); it2 != ed2; ++it2) {
0141 if (f(*it, *it2)) {
0142 vals.push_back(Ref<CVal>(handleV, it2 - k.begin()));
0143 }
0144 }
0145 if (swap) {
0146 filler.swapValues(Ref<Key>(handle, it - handle->begin()), vals);
0147 } else {
0148 filler.setValues(Ref<Key>(handle, it - handle->begin()), vals);
0149 }
0150 }
0151 }
0152
0153 template <typename Key, typename UnaryFunc, typename BinaryFunc>
0154 void fastFillVals(edm::TestHandle<Key> const& handle, MultiVal& map, UnaryFunc const& u, BinaryFunc const& f) {
0155 MultiVal::FastFiller filler = map.fastFiller(handle);
0156 for (typename Key::const_iterator it = handle->begin(), ed = handle->end(); it != ed; ++it) {
0157 if (!u(*it))
0158 continue;
0159 CVal vals;
0160 for (std::vector<double>::const_iterator it2 = k.begin(), ed2 = k.end(); it2 != ed2; ++it2) {
0161 if (f(*it, *it2)) {
0162 vals.push_back(*it2);
0163 }
0164 }
0165 filler.setValues(Ref<Key>(handle, it - handle->begin()), vals);
0166 }
0167 }
0168
0169 template <typename Key, typename UnaryFunc, typename BinaryFunc>
0170 void lazyFillVals(
0171 edm::TestHandle<Key> const& handle, MultiVal& map, UnaryFunc const& u, BinaryFunc const& f, bool swap) {
0172 MultiVal::LazyFiller filler = map.lazyFiller(handle, true);
0173 for (typename Key::const_iterator it = handle->begin(), ed = handle->end(); it != ed; ++it) {
0174 if (!u(*it))
0175 continue;
0176 CVal vals;
0177 for (std::vector<double>::const_iterator it2 = k.begin(), ed2 = k.end(); it2 != ed2; ++it2) {
0178 if (f(*it, *it2)) {
0179 vals.push_back(*it2);
0180 }
0181 }
0182 if (swap) {
0183 filler.swapValues(Ref<Key>(handle, it - handle->begin()), vals);
0184 } else {
0185 filler.setValues(Ref<Key>(handle, it - handle->begin()), vals);
0186 }
0187 }
0188 }
0189
0190
0191 };
0192
0193 CPPUNIT_TEST_SUITE_REGISTRATION(testMultiAssociation);
0194
0195 testMultiAssociation::testMultiAssociation() {
0196 k.push_back(1.1);
0197 k.push_back(2.2);
0198 k.push_back(3.3);
0199 k.push_back(4.4);
0200 ProductID const pidV(1);
0201 handleV = edm::TestHandle<CVal>(&k, pidV);
0202
0203 v1.push_back(1);
0204 v1.push_back(2);
0205 v1.push_back(3);
0206 v1.push_back(4);
0207 ProductID const pidK1(2);
0208 handleK1 = edm::TestHandle<CKey1>(&v1, pidK1);
0209
0210 v2.push_back(1.);
0211 v2.push_back(2.);
0212 v2.push_back(3.);
0213 v2.push_back(4.);
0214 v2.push_back(5.);
0215 ProductID const pidK2(3);
0216 handleK2 = edm::TestHandle<CKey2>(&v2, pidK2);
0217
0218 for (size_t j = 0; j < 10; ++j)
0219 der1s.push_back(DummyDer1());
0220 for (size_t j = 0; j < 10; ++j) {
0221 if (j % 3 == 0)
0222 bases.push_back(std::make_unique<DummyBase>());
0223 if (j % 3 == 1)
0224 bases.push_back(std::make_unique<DummyDer1>());
0225 if (j % 3 == 2)
0226 bases.push_back(std::make_unique<DummyDer2>());
0227 CPPUNIT_ASSERT(bases[j].id() == int(j % 3));
0228 }
0229 edm::TestHandle<CObj> handleObj(&der1s, ProductID(10));
0230 for (size_t j = 0; j < 7; ++j) {
0231 size_t k = (j * 37) % 10;
0232 ptrs.push_back(PObj(handleObj, k));
0233 CPPUNIT_ASSERT(ptrs[j]->id() == 1);
0234 CPPUNIT_ASSERT(ptrs[j]->addr() == &der1s[k]);
0235 }
0236 }
0237
0238 void testMultiAssociation::checkAll() {
0239 using boost::lambda::_1;
0240 using boost::lambda::_2;
0241 {
0242 MultiRef try1;
0243 dump(try1, "empty");
0244 fastFillRefs(handleK1, try1, _1 > 0, _1 > _2);
0245 dump(try1, "fill 1");
0246 fastFillRefs(handleK2, try1, _1 > 0, _1 > _2);
0247 dump(try1, "fill 2");
0248 test(try1);
0249 }
0250 {
0251 MultiRef try2;
0252 fastFillRefs(
0253 handleK1, try2, _1 > 0, (_1 < _2) && (2 * bind(floor, _1 / 2) != _1));
0254 fastFillRefs(
0255 handleK2, try2, _1 > 0, (_1 < _2) && (2 * bind(floor, _1 / 2) != _1));
0256 dump(try2, "fill 2");
0257 test2(try2);
0258 }
0259 {
0260 MultiRef try2;
0261 fastFillRefs(handleK1,
0262 try2,
0263 (2 * bind(floor, _1 / 2) != _1),
0264 (_1 < _2) && (2 * bind(floor, _1 / 2) != _1));
0265 fastFillRefs(handleK2,
0266 try2,
0267 (2 * bind(floor, _1 / 2) != _1),
0268 (_1 < _2) && (2 * bind(floor, _1 / 2) != _1));
0269 dump(try2, "fill 2");
0270 test2(try2);
0271 }
0272 {
0273 MultiRef try3;
0274 fastFillRefs(handleK1, try3, _1 < 0, (_1 > _2));
0275 fastFillRefs(handleK2, try3, _1 > 0, (_1 > _2));
0276 dump(try3, "no first");
0277 }
0278 {
0279 MultiRef try3;
0280 fastFillRefs(handleK1, try3, _1 > 0, (_1 > _2));
0281 fastFillRefs(handleK2, try3, _1 < 0, (_1 > _2));
0282 dump(try3, "no second");
0283 }
0284 {
0285 MultiRef try3;
0286 fastFillRefs(handleK1, try3, _1 < 0, (_1 > _2));
0287 fastFillRefs(handleK2, try3, _1 < 0, (_1 > _2));
0288 dump(try3, "neither");
0289 }
0290 {
0291 MultiRef try1;
0292 lazyFillRefs(handleK1, try1, _1 > 0, _1 > _2, false);
0293 lazyFillRefs(handleK2, try1, _1 > 0, _1 > _2, false);
0294 dump(try1, "fill 2");
0295 test(try1);
0296 }
0297 {
0298 MultiRef try2;
0299 lazyFillRefs(handleK1,
0300 try2,
0301 (2 * bind(floor, _1 / 2) != _1),
0302 (_1 < _2) && (2 * bind(floor, _1 / 2) != _1),
0303 false);
0304 lazyFillRefs(handleK2,
0305 try2,
0306 (2 * bind(floor, _1 / 2) != _1),
0307 (_1 < _2) && (2 * bind(floor, _1 / 2) != _1),
0308 false);
0309 dump(try2, "fill 2");
0310 test2(try2);
0311 }
0312 {
0313 MultiRef try1;
0314 lazyFillRefs(handleK1, try1, _1 > 0, _1 > _2, true);
0315 lazyFillRefs(handleK2, try1, _1 > 0, _1 > _2, true);
0316 dump(try1, "fill 2");
0317 test(try1);
0318 }
0319 {
0320 MultiRef try2;
0321 lazyFillRefs(handleK1,
0322 try2,
0323 (2 * bind(floor, _1 / 2) != _1),
0324 (_1 < _2) && (2 * bind(floor, _1 / 2) != _1),
0325 true);
0326 lazyFillRefs(handleK2,
0327 try2,
0328 (2 * bind(floor, _1 / 2) != _1),
0329 (_1 < _2) && (2 * bind(floor, _1 / 2) != _1),
0330 true);
0331 dump(try2, "fill 2");
0332 test2(try2);
0333 }
0334 }
0335
0336 void testMultiAssociation::checkVals() {
0337 using boost::lambda::_1;
0338 using boost::lambda::_2;
0339 {
0340 MultiVal try1;
0341 dump(try1, "empty");
0342 fastFillVals(handleK1, try1, _1 > 0, _1 > _2);
0343 dump(try1, "fill 1");
0344 fastFillVals(handleK2, try1, _1 > 0, _1 > _2);
0345 dump(try1, "fill 2");
0346 test(try1);
0347 }
0348 {
0349 MultiVal try1;
0350 lazyFillVals(handleK1, try1, _1 > 0, _1 > _2, false);
0351 lazyFillVals(handleK2, try1, _1 > 0, _1 > _2, false);
0352 dump(try1, "fill 2");
0353 test(try1);
0354 }
0355 {
0356 MultiVal try1;
0357 lazyFillVals(handleK1, try1, _1 > 0, _1 > _2, true);
0358 lazyFillVals(handleK2, try1, _1 > 0, _1 > _2, true);
0359 dump(try1, "fill 2");
0360 test(try1);
0361 }
0362 }
0363
0364 #ifdef private
0365 void testMultiAssociation::dump(MultiRef::Indices const& indices) {
0366 using namespace std;
0367 cerr << " Dumping Index map at " << &indices << endl;
0368 cerr << " id_offsets_ (size = " << indices.id_offsets_.size() << ")" << endl;
0369 for (size_t i = 0; i < indices.id_offsets_.size(); ++i) {
0370 cerr << " [" << setw(3) << i << "]: (" << setw(3) << indices.id_offsets_[i].first << ", " << setw(3)
0371 << indices.id_offsets_[i].second << ")" << endl;
0372 }
0373 cerr << " ref_offsets_ (size = " << indices.ref_offsets_.size() << ")" << endl;
0374 for (size_t i = 0; i < indices.ref_offsets_.size(); ++i) {
0375 cerr << " [" << setw(3) << i << "]: " << setw(4) << indices.ref_offsets_[i] << ")" << endl;
0376 }
0377 cerr << " isFilling_: " << indices.isFilling_ << endl;
0378 }
0379 template <typename T>
0380 void testMultiAssociation::dump(edm::RefVector<T> const& data) {
0381 using namespace std;
0382 cerr << " Dumping " << typeid(data).name() << " at " << &data << endl;
0383 cerr << " ID: " << data.id() << endl;
0384 cerr << " Values (size = " << data.size() << ")" << endl;
0385 for (size_t i = 0; i < data.size(); ++i) {
0386 cerr << " [" << setw(3) << i << "]: key = " << setw(4) << data[i].key();
0387 if (data[i].isNull())
0388 cerr << ", NULL" << endl;
0389 else
0390 cerr << ", value = " << *data[i] << endl;
0391 }
0392 }
0393 template <typename T>
0394 void testMultiAssociation::dump(std::vector<T> const& data) {
0395 using namespace std;
0396 cerr << " Dumping " << typeid(data).name() << " at " << &data << endl;
0397 cerr << " Values (size = " << data.size() << ")" << endl;
0398 for (size_t i = 0; i < data.size(); ++i) {
0399 cerr << " [" << setw(3) << i << "]: key = " << setw(4) << data[i] << endl;
0400 }
0401 }
0402
0403 void testMultiAssociation::dump(MultiRef const& assoc, char const* what) {
0404 using namespace std;
0405 cerr << "\nDumping MultiRef at " << &assoc << " for " << what << endl;
0406 dump(assoc.indices_);
0407 dump(assoc.data_);
0408 cerr << endl;
0409 }
0410 void testMultiAssociation::dump(MultiVal const& assoc, char const* what) {
0411 using namespace std;
0412 cerr << "\nDumping MultiVal at " << &assoc << " for " << what << endl;
0413 dump(assoc.indices_);
0414 dump(assoc.data_);
0415 cerr << endl;
0416 }
0417
0418 #endif
0419
0420 void testMultiAssociation::test(MultiRef const& assoc) {
0421
0422 CPPUNIT_ASSERT(!assoc.contains(ProductID(1)));
0423 CPPUNIT_ASSERT(assoc.contains(ProductID(2)));
0424 CPPUNIT_ASSERT(assoc.contains(ProductID(3)));
0425 CPPUNIT_ASSERT(!assoc.contains(ProductID(4)));
0426
0427
0428 MultiRef::const_range br1, br2, br3, br4;
0429 br1 = assoc[edm::Ref<CKey1>(handleK1, 0)];
0430 br2 = assoc[edm::Ref<CKey1>(handleK1, 1)];
0431 br3 = assoc[edm::Ref<CKey1>(handleK1, 2)];
0432 br4 = assoc[edm::Ref<CKey1>(handleK1, 3)];
0433 CPPUNIT_ASSERT(br1.size() == 0);
0434 CPPUNIT_ASSERT(br2.size() == 1);
0435 CPPUNIT_ASSERT(br3.size() == 2);
0436 CPPUNIT_ASSERT(br4.size() == 3);
0437 CPPUNIT_ASSERT(br2.begin()->id() == ProductID(1));
0438 CPPUNIT_ASSERT(br2.begin()->key() == 0);
0439 CPPUNIT_ASSERT(**br2.begin() == k.front());
0440 CPPUNIT_ASSERT(*br2.front() == k.front());
0441 CPPUNIT_ASSERT(*br2[0] == k[0]);
0442 CPPUNIT_ASSERT(br4.back().id() == ProductID(1));
0443 CPPUNIT_ASSERT(br4.back().key() == 2);
0444 CPPUNIT_ASSERT(br4[2].key() == 2);
0445
0446
0447
0448 br1 = assoc[edm::Ref<CKey1>(handleK1, 0)];
0449 CPPUNIT_ASSERT(br1.end() == br1.begin());
0450 br2 = assoc[edm::Ref<CKey1>(handleK1, 1)];
0451 CPPUNIT_ASSERT(br2.end() == br2.begin() + 1);
0452 CPPUNIT_ASSERT(br2.begin() == br1.end());
0453 br3 = assoc[edm::Ref<CKey1>(handleK1, 2)];
0454 CPPUNIT_ASSERT(br3.end() == br3.begin() + 2);
0455 CPPUNIT_ASSERT(br3.begin() == br2.end());
0456
0457 br1 = assoc[edm::Ref<CKey1>(handleK1, 3)];
0458 br2 = assoc[edm::Ref<CKey2>(handleK2, 0)];
0459 br3 = assoc[edm::Ref<CKey2>(handleK2, 1)];
0460 CPPUNIT_ASSERT(br1.end() == br1.begin() + 3);
0461 CPPUNIT_ASSERT(br1.end() == br2.begin() + 0);
0462 CPPUNIT_ASSERT(br2.end() == br2.begin() + 0);
0463 CPPUNIT_ASSERT(br2.end() == br3.begin() + 0);
0464 CPPUNIT_ASSERT(br3.end() == br3.begin() + 1);
0465
0466
0467 edm::RefVector<CVal> r1, r2, r3, r4, r5;
0468 r1 = assoc.getValues(edm::Ref<CKey1>(handleK1, 0));
0469 r2 = assoc.getValues(edm::Ref<CKey1>(handleK1, 1));
0470 r3 = assoc.getValues(edm::Ref<CKey1>(handleK1, 2));
0471 r4 = assoc.getValues(edm::Ref<CKey1>(handleK1, 3));
0472 CPPUNIT_ASSERT(r1.size() == 0);
0473 CPPUNIT_ASSERT(r2.size() == 1);
0474 CPPUNIT_ASSERT(r3.size() == 2);
0475 CPPUNIT_ASSERT(r4.size() == 3);
0476 CPPUNIT_ASSERT(r2.begin()->id() == ProductID(1));
0477 CPPUNIT_ASSERT(r2.begin()->key() == 0);
0478 CPPUNIT_ASSERT(**r2.begin() == k.front());
0479 CPPUNIT_ASSERT(**r2.begin() == k.front());
0480 CPPUNIT_ASSERT((r4.end() - 1)->id() == ProductID(1));
0481 CPPUNIT_ASSERT((r4.end() - 1)->key() == 2);
0482 }
0483
0484 void testMultiAssociation::test2(MultiRef const& assoc) {
0485
0486 CPPUNIT_ASSERT(!assoc.contains(ProductID(1)));
0487 CPPUNIT_ASSERT(assoc.contains(ProductID(2)));
0488 CPPUNIT_ASSERT(assoc.contains(ProductID(3)));
0489 CPPUNIT_ASSERT(!assoc.contains(ProductID(4)));
0490
0491
0492 MultiRef::const_range br1, br2, br3, br4;
0493 br1 = assoc[edm::Ref<CKey1>(handleK1, 0)];
0494 CPPUNIT_ASSERT(br1.end() == br1.begin() + 4);
0495 br2 = assoc[edm::Ref<CKey1>(handleK1, 1)];
0496 CPPUNIT_ASSERT(br2.end() == br2.begin() + 0);
0497 CPPUNIT_ASSERT(br2.begin() == br1.end());
0498 br3 = assoc[edm::Ref<CKey1>(handleK1, 2)];
0499 CPPUNIT_ASSERT(br3.end() == br3.begin() + 2);
0500 CPPUNIT_ASSERT(br3.begin() == br2.end());
0501
0502 br1 = assoc[edm::Ref<CKey1>(handleK1, 3)];
0503 br2 = assoc[edm::Ref<CKey2>(handleK2, 0)];
0504 br3 = assoc[edm::Ref<CKey2>(handleK2, 1)];
0505 CPPUNIT_ASSERT(br1.end() == br1.begin() + 0);
0506 CPPUNIT_ASSERT(br1.end() == br2.begin() + 0);
0507 CPPUNIT_ASSERT(br2.end() == br2.begin() + 4);
0508 CPPUNIT_ASSERT(br2.end() == br3.begin() + 0);
0509 CPPUNIT_ASSERT(br3.end() == br3.begin() + 0);
0510 }
0511
0512 void testMultiAssociation::test(MultiVal const& assoc) {
0513 #if 1
0514
0515 MultiVal::const_range r1, r2, r3, r4, r5;
0516 r1 = assoc[edm::Ref<CKey1>(handleK1, 0)];
0517 r2 = assoc[edm::Ref<CKey1>(handleK1, 1)];
0518 r3 = assoc[edm::Ref<CKey1>(handleK1, 2)];
0519 r4 = assoc[edm::Ref<CKey1>(handleK1, 3)];
0520 #else
0521
0522 CVal r1, r2, r3, r4, r5;
0523 r1 = assoc.getValues(edm::Ref<CKey1>(handleK1, 0));
0524 r2 = assoc.getValues(edm::Ref<CKey1>(handleK1, 1));
0525 r3 = assoc.getValues(edm::Ref<CKey1>(handleK1, 2));
0526 r4 = assoc.getValues(edm::Ref<CKey1>(handleK1, 3));
0527 #endif
0528 CPPUNIT_ASSERT(r1.size() == 0);
0529 CPPUNIT_ASSERT(r2.size() == 1);
0530 CPPUNIT_ASSERT(r3.size() == 2);
0531 CPPUNIT_ASSERT(r4.size() == 3);
0532 CPPUNIT_ASSERT(r2[0] == k[0]);
0533 CPPUNIT_ASSERT(r3[0] == k[0]);
0534 CPPUNIT_ASSERT(r3[1] == k[1]);
0535 CPPUNIT_ASSERT(r4[0] == k[0]);
0536 CPPUNIT_ASSERT(r4[1] == k[1]);
0537 CPPUNIT_ASSERT(r4[2] == k[2]);
0538 }
0539
0540 template <typename Map>
0541 bool testMultiAssociation::tryTwoFillers(bool lazyfiller) {
0542 Map map;
0543 if (lazyfiller) {
0544 typename Map::LazyFiller filler1(map, handleK1, true);
0545 typename Map::LazyFiller filler2(map, handleK2, true);
0546 } else {
0547 typename Map::FastFiller filler1(map, handleK1);
0548 typename Map::FastFiller filler2(map, handleK2);
0549 }
0550 return true;
0551 }
0552 void testMultiAssociation::checkTwoFillers() {
0553 CPPUNIT_ASSERT(tryTwoFillers<MultiRef>(true));
0554 CPPUNIT_ASSERT_THROW(tryTwoFillers<MultiRef>(false), cms::Exception);
0555 CPPUNIT_ASSERT(tryTwoFillers<MultiVal>(true));
0556 CPPUNIT_ASSERT_THROW(tryTwoFillers<MultiVal>(false), cms::Exception);
0557 }
0558 template <typename Map>
0559 bool testMultiAssociation::tryUnsortedKeys(bool lazy) {
0560 Map map;
0561 typename Map::Collection coll1, coll2;
0562 if (lazy) {
0563 typename Map::LazyFiller filler(map, handleK1, true);
0564 filler.setValues(Ref<CKey1>(handleK1, 1), coll1);
0565 filler.setValues(Ref<CKey1>(handleK1, 0), coll2);
0566 } else {
0567 typename Map::FastFiller filler(map, handleK1);
0568 filler.setValues(Ref<CKey1>(handleK1, 1), coll1);
0569 filler.setValues(Ref<CKey1>(handleK1, 0), coll2);
0570 }
0571 return true;
0572 }
0573 void testMultiAssociation::checkUnsortedKeys() {
0574 CPPUNIT_ASSERT(tryUnsortedKeys<MultiRef>(true));
0575 CPPUNIT_ASSERT_THROW(tryUnsortedKeys<MultiRef>(false), cms::Exception);
0576 CPPUNIT_ASSERT(tryUnsortedKeys<MultiVal>(true));
0577 CPPUNIT_ASSERT_THROW(tryUnsortedKeys<MultiVal>(false), cms::Exception);
0578 }
0579
0580
0581 bool testMultiAssociation::tryBadFill(int i) {
0582 MultiRef m;
0583 MultiRef::Collection coll1;
0584 coll1.push_back(Ref<CVal>(handleV, 1));
0585 switch (i) {
0586 case 0: {
0587 MultiRef::FastFiller filler = m.fastFiller(handleK1);
0588 filler.setValues(Ref<CKey1>(handleK1, 0), coll1);
0589 }; break;
0590 case 1: {
0591 MultiRef::FastFiller filler = m.fastFiller(handleK1);
0592 filler.setValues(Ref<CKey2>(handleK2, 0), coll1);
0593 }; break;
0594 case 2: {
0595 {
0596 MultiRef::FastFiller filler = m.fastFiller(handleK1);
0597 }
0598 { MultiRef::FastFiller filler = m.fastFiller(handleK2); }
0599 }; break;
0600 case 3: {
0601 {
0602 MultiRef::FastFiller filler = m.fastFiller(handleK1);
0603 }
0604 { MultiRef::FastFiller filler = m.fastFiller(handleK1); }
0605 }; break;
0606 case 4: {
0607 {
0608 MultiRef::LazyFiller filler = m.lazyFiller(handleK1);
0609 }
0610 { MultiRef::LazyFiller filler = m.lazyFiller(handleK1); }
0611 }; break;
0612 case 5: {
0613 {
0614 MultiRef::LazyFiller filler = m.lazyFiller(handleK1, true);
0615 }
0616 { MultiRef::LazyFiller filler = m.lazyFiller(handleK1, true); }
0617 }; break;
0618 case 6: {
0619 MultiRef::LazyFiller filler = m.lazyFiller(handleK1, true);
0620 CPPUNIT_ASSERT(m.empty());
0621 filler.fill();
0622 CPPUNIT_ASSERT(!m.empty());
0623 filler.fill();
0624 }; break;
0625 case 8: {
0626 {
0627 MultiRef::LazyFiller filler = m.lazyFiller(handleK1, false);
0628 }
0629 CPPUNIT_ASSERT(m.empty());
0630 } break;
0631 case 9: {
0632 MultiRef::FastFiller filler = m.fastFiller(handleK1);
0633 filler.setValues(Ref<CKey1>(handleK1, handleK1->size() + 5, false), coll1);
0634 } break;
0635 case 10: {
0636 MultiRef::LazyFiller filler = m.lazyFiller(handleK1, false);
0637 MultiRef::LazyFiller filler2 = filler;
0638 filler2.setValues(Ref<CKey1>(handleK1, 0), coll1);
0639 filler2.fill();
0640 } break;
0641 case 11: {
0642 MultiRef::LazyFiller filler = m.lazyFiller(handleK1, true);
0643 MultiRef::LazyFiller filler2 = filler;
0644 } break;
0645 case 12: {
0646 MultiRef::FastFiller filler = m.fastFiller(handleK1);
0647 MultiRef::FastFiller filler2 = filler;
0648 } break;
0649 default:
0650 if (i % 2 == 1)
0651 throw cms::Exception("Programmed failure");
0652 break;
0653 }
0654 return true;
0655 }
0656 void testMultiAssociation::checkBadFill() {
0657 for (int i = 0; i < 100; ++i) {
0658 if (i % 2 == 0)
0659 CPPUNIT_ASSERT(tryBadFill(i));
0660 else
0661 CPPUNIT_ASSERT_THROW(tryBadFill(i), cms::Exception);
0662 }
0663 }
0664
0665 bool testMultiAssociation::tryBadRead(int i) {
0666 using boost::lambda::_1;
0667 using boost::lambda::_2;
0668 MultiRef m;
0669 fastFillRefs(handleK1, m, _1 > 0, _1 > _2);
0670 fastFillRefs(handleK2, m, _1 > 0, _1 > _2);
0671 switch (i) {
0672 case 0:
0673 m[Ref<CKey1>(handleK1, 0, false)];
0674 break;
0675 case 1:
0676 m[Ref<CVal>(handleV, 0, false)];
0677 break;
0678 case 3:
0679
0680 m[Ref<CKey2>(handleK2, 5, false)];
0681 break;
0682 case 5:
0683
0684
0685 m[Ref<CKey1>(handleK1, 5, false)];
0686 break;
0687 default:
0688 if (i % 2 == 1)
0689 throw cms::Exception("Programmed failure");
0690 break;
0691 }
0692 return true;
0693 }
0694 void testMultiAssociation::checkWritableMap() {
0695 using boost::lambda::_1;
0696 using boost::lambda::_2;
0697 MultiVal tryRW;
0698 fastFillVals(handleK1, tryRW, _1 > 0, _1 > _2);
0699 fastFillVals(handleK2, tryRW, _1 > 0, _1 > _2);
0700 test(tryRW);
0701
0702 MultiVal::range r1, r1bis;
0703 r1 = tryRW[edm::Ref<CKey1>(handleK1, 1)];
0704 CPPUNIT_ASSERT(r1[0] == k[0]);
0705 r1[0] = k[1];
0706
0707 CPPUNIT_ASSERT(r1[0] == k[1]);
0708
0709 r1bis = tryRW[edm::Ref<CKey1>(handleK1, 1)];
0710 CPPUNIT_ASSERT(r1bis[0] == k[1]);
0711 }
0712
0713 void testMultiAssociation::checkBadRead() {
0714 for (int i = 0; i < 100; ++i) {
0715 if (i % 2 == 0)
0716 CPPUNIT_ASSERT(tryBadRead(i));
0717 else
0718 CPPUNIT_ASSERT_THROW(tryBadRead(i), cms::Exception);
0719 }
0720 }
0721
0722 void testMultiAssociation::checkWithPtr() {
0723 MultiPtr map;
0724 {
0725 MultiPtr::FastFiller filler = map.fastFiller(handleK1);
0726 edm::TestHandle<CObj> handleObj(&der1s, ProductID(10));
0727 for (size_t i = 0; i < handleK1->size(); ++i) {
0728 PObjs vals;
0729 for (size_t j = 0; j < ((i + 2) % 3); ++j) {
0730 vals.push_back(PObj(handleObj, (3 * i + 4 * j) % 10));
0731 }
0732 if (!vals.empty())
0733 filler.setValues(Ref<CKey1>(handleK1, i), vals);
0734 }
0735 }
0736 {
0737 for (size_t i = 0; i < handleK1->size(); ++i) {
0738 MultiPtr::const_range r = map[Ref<CKey1>(handleK1, i)];
0739 CPPUNIT_ASSERT(static_cast<size_t>(r.size()) == ((i + 2) % 3));
0740 for (size_t j = 0; j < ((i + 2) % 3); ++j) {
0741 CPPUNIT_ASSERT(r[j].key() == (3 * i + 4 * j) % 10);
0742 CPPUNIT_ASSERT(r[j]->addr() == &der1s[(3 * i + 4 * j) % 10]);
0743
0744
0745 }
0746 }
0747 }
0748 }
0749 void testMultiAssociation::checkWithOwn() {
0750 MultiOwn map;
0751 {
0752 MultiOwn::FastFiller filler = map.fastFiller(handleK1);
0753 for (size_t i = 0; i < handleK1->size(); ++i) {
0754 OObj vals;
0755 for (size_t j = 0; j < ((i + 2) % 3); ++j) {
0756 vals.push_back(bases[(i + j) % 3].clone());
0757 }
0758 if (!vals.empty())
0759 filler.setValues(Ref<CKey1>(handleK1, i), vals);
0760 }
0761 }
0762 {
0763 for (size_t i = 0; i < handleK1->size(); ++i) {
0764 MultiOwn::const_range r = map[Ref<CKey1>(handleK1, i)];
0765 CPPUNIT_ASSERT(static_cast<size_t>(r.size()) == ((i + 2) % 3));
0766 for (size_t j = 0; j < ((i + 2) % 3); ++j) {
0767 CPPUNIT_ASSERT((r.begin() + j)->id() == bases[(i + j) % 3].id());
0768 }
0769 }
0770 }
0771 }