Chris@1742: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@1742: Chris@1742: /* Chris@1742: Sonic Visualiser Chris@1742: An audio file viewer and annotation editor. Chris@1742: Centre for Digital Music, Queen Mary, University of London. Chris@1742: Chris@1742: This program is free software; you can redistribute it and/or Chris@1742: modify it under the terms of the GNU General Public License as Chris@1742: published by the Free Software Foundation; either version 2 of the Chris@1742: License, or (at your option) any later version. See the file Chris@1742: COPYING included with this distribution for more information. Chris@1742: */ Chris@1742: Chris@1742: #include "../ById.h" Chris@1742: Chris@1742: #include Chris@1742: #include Chris@1742: Chris@1742: #include Chris@1742: Chris@1742: using namespace std; Chris@1742: Chris@1742: struct WithoutId {}; Chris@1742: Chris@1752: // We'll need to change access levels for getId() and getUntypedId() Chris@1752: // to test the raw calls Chris@1752: Chris@1752: struct A : public WithTypedId { public: using WithTypedId::getId; }; Chris@1742: struct B1 : public A {}; Chris@1742: struct B2 : public A {}; Chris@1742: Chris@1742: struct M {}; Chris@1742: Chris@1742: typedef TypedById AById; Chris@1742: Chris@1752: struct X : virtual public WithId { public: using WithId::getUntypedId; }; Chris@1742: struct Y : public X, public B2, public M {}; Chris@1742: Chris@1742: class TestById : public QObject Chris@1742: { Chris@1742: Q_OBJECT Chris@1742: Chris@1742: private slots: Chris@1742: void ids() { Chris@1742: // Verify that ids are unique across all classes, not just Chris@1742: // within a class. These must be the first two WithId objects Chris@1742: // allocated in the first test in the suite, otherwise they Chris@1742: // could be different even if they were allocated from Chris@1742: // separate pools. Chris@1742: A a; Chris@1742: X x; Chris@1742: if (a.getId().untyped == x.getUntypedId()) { Chris@1756: std::cerr << "ERROR: a and x have the same id: " << a.getId() Chris@1756: << std::endl; Chris@1742: } Chris@1742: QVERIFY(a.getId().untyped != x.getUntypedId()); Chris@1742: Chris@1742: A aa; Chris@1742: QVERIFY(aa.getId().untyped != a.getId().untyped); Chris@1742: QVERIFY(aa.getId().untyped != x.getUntypedId()); Chris@1742: Chris@1742: // Check the actual ids that have been allocated. This is Chris@1742: // supposed to be a hidden implementation detail, but we want Chris@1742: // to make sure the test itself hasn't become broken in terms Chris@1742: // of allocation order (see comment above) Chris@1742: QCOMPARE(a.getId().untyped, 0); Chris@1742: QCOMPARE(x.getUntypedId(), 1); Chris@1742: QCOMPARE(aa.getId().untyped, 2); Chris@1742: Chris@1742: QVERIFY(!a.getId().isNone()); Chris@1742: QVERIFY(A::Id().isNone()); Chris@1742: } Chris@1742: Chris@1742: // NB each test must release all the items it adds to the ById store Chris@1742: Chris@1742: void anyEmpty() { Chris@1742: auto p = AnyById::get(0); Chris@1742: QVERIFY(!p); Chris@1742: } Chris@1742: Chris@1742: void anySimple() { Chris@1742: auto a = std::make_shared(); Chris@1752: int id = AnyById::add(a); Chris@1752: QCOMPARE(id, a->getId().untyped); Chris@1742: Chris@1752: auto aa = AnyById::getAs(id); Chris@1742: QVERIFY(!!aa); Chris@1742: QCOMPARE(aa->getId(), a->getId()); Chris@1742: QCOMPARE(aa.get(), a.get()); // same object, not just same id! Chris@1752: AnyById::release(id); Chris@1742: } Chris@1742: Chris@1742: void typedEmpty() { Chris@1742: auto p = AById::get({}); Chris@1742: QVERIFY(!p); Chris@1742: } Chris@1742: Chris@1742: void typedSimple() { Chris@1742: auto a = std::make_shared(); Chris@1742: AById::add(a); Chris@1742: Chris@1742: auto aa = AById::get(a->getId()); Chris@1742: QVERIFY(!!aa); Chris@1742: QCOMPARE(aa->getId(), a->getId()); Chris@1742: QCOMPARE(aa.get(), a.get()); // same object, not just same id! Chris@1742: AById::release(a); Chris@1742: } Chris@1742: Chris@1752: void typedReleaseById() { Chris@1742: auto a = std::make_shared(); Chris@1752: auto aid = AById::add(a); Chris@1742: Chris@1752: auto aa = AById::get(aid); Chris@1752: QVERIFY(!!aa); Chris@1752: AById::release(aid); Chris@1752: Chris@1752: aa = AById::get(aid); Chris@1752: QVERIFY(!aa); Chris@1752: } Chris@1752: Chris@1752: void typedReleaseByItem() { Chris@1752: auto a = std::make_shared(); Chris@1752: auto aid = AById::add(a); Chris@1752: Chris@1752: auto aa = AById::get(aid); Chris@1742: QVERIFY(!!aa); Chris@1742: AById::release(a); Chris@1742: Chris@1752: aa = AById::get(aid); Chris@1742: QVERIFY(!aa); Chris@1742: } Chris@1742: Chris@1742: void typedDowncast() { Chris@1742: auto a = std::make_shared(); Chris@1742: auto b1 = std::make_shared(); Chris@1742: AById::add(a); Chris@1742: AById::add(b1); Chris@1742: Chris@1742: auto bb1 = AById::getAs(a->getId()); Chris@1742: QVERIFY(!bb1); Chris@1742: Chris@1742: bb1 = AById::getAs(b1->getId()); Chris@1742: QVERIFY(!!bb1); Chris@1742: QCOMPARE(bb1->getId(), b1->getId()); Chris@1742: Chris@1742: auto bb2 = AById::getAs(b1->getId()); Chris@1742: QVERIFY(!bb2); Chris@1742: Chris@1742: AById::release(a); Chris@1742: AById::release(b1); Chris@1742: } Chris@1742: Chris@1742: void typedCrosscast() { Chris@1742: auto y = std::make_shared(); Chris@1742: AById::add(y); Chris@1742: Chris@1742: auto yy = AById::getAs(y->getId()); Chris@1742: QVERIFY(!!yy); Chris@1742: QCOMPARE(yy->getId(), y->getId()); Chris@1742: Chris@1742: yy = AnyById::getAs(y->getId().untyped); Chris@1742: QVERIFY(!!yy); Chris@1742: QCOMPARE(yy->getId(), y->getId()); Chris@1742: Chris@1742: auto xx = AById::getAs(y->getId()); Chris@1742: QVERIFY(!!xx); Chris@1742: QCOMPARE(xx->getUntypedId(), y->getId().untyped); Chris@1742: QCOMPARE(xx.get(), yy.get()); Chris@1742: Chris@1742: xx = AnyById::getAs(y->getId().untyped); Chris@1742: QVERIFY(!!xx); Chris@1742: QCOMPARE(xx->getUntypedId(), y->getId().untyped); Chris@1742: QCOMPARE(xx.get(), yy.get()); Chris@1742: Chris@1742: auto mm = AnyById::getAs(y->getId().untyped); Chris@1742: QVERIFY(!!mm); Chris@1742: QCOMPARE(mm.get(), yy.get()); Chris@1742: Chris@1742: AById::release(y); Chris@1742: } Chris@1742: Chris@1742: void duplicateAdd() { Chris@1742: auto a = std::make_shared(); Chris@1742: AById::add(a); Chris@1742: try { Chris@1742: AById::add(a); Chris@1756: std::cerr << "Failed to catch expected exception in duplicateAdd" Chris@1756: << std::endl; Chris@1742: QVERIFY(false); Chris@1742: } catch (const std::logic_error &) { Chris@1742: } Chris@1742: AById::release(a); Chris@1742: } Chris@1742: Chris@1742: void unknownRelease() { Chris@1742: auto a = std::make_shared(); Chris@1742: auto b1 = std::make_shared(); Chris@1742: AById::add(a); Chris@1742: try { Chris@1742: AById::release(b1); Chris@1756: std::cerr << "Failed to catch expected exception in unknownRelease" Chris@1756: << std::endl; Chris@1742: QVERIFY(false); Chris@1742: } catch (const std::logic_error &) { Chris@1742: } Chris@1742: AById::release(a); Chris@1742: } Chris@1742: }; Chris@1742: