Mercurial > hg > svcore
diff base/test/TestById.h @ 1742:52705a328b34 by-id
Rejig ById so as to put everything in a single pool, so that at the core you can go from numeric id (untyped) to anything the object can be dynamic_cast to. Useful for building other abstractions like PlayParameter-type registrations that don't know about e.g. Models. Probably some more tweaking needed. Also add tests
author | Chris Cannam |
---|---|
date | Fri, 28 Jun 2019 17:36:30 +0100 |
parents | |
children | 6d09d68165a4 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/base/test/TestById.h Fri Jun 28 17:36:30 2019 +0100 @@ -0,0 +1,191 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "../ById.h" + +#include <QObject> +#include <QtTest> + +#include <iostream> + +using namespace std; + +struct WithoutId {}; + +struct A : public WithTypedId<A> {}; +struct B1 : public A {}; +struct B2 : public A {}; + +struct M {}; + +typedef TypedById<A, A::Id> AById; + +struct X : virtual public WithId {}; +struct Y : public X, public B2, public M {}; + +class TestById : public QObject +{ + Q_OBJECT + +private slots: + void ids() { + // Verify that ids are unique across all classes, not just + // within a class. These must be the first two WithId objects + // allocated in the first test in the suite, otherwise they + // could be different even if they were allocated from + // separate pools. + A a; + X x; + if (a.getId().untyped == x.getUntypedId()) { + cerr << "ERROR: a and x have the same id: " << a.getId() << endl; + } + QVERIFY(a.getId().untyped != x.getUntypedId()); + + A aa; + QVERIFY(aa.getId().untyped != a.getId().untyped); + QVERIFY(aa.getId().untyped != x.getUntypedId()); + + // Check the actual ids that have been allocated. This is + // supposed to be a hidden implementation detail, but we want + // to make sure the test itself hasn't become broken in terms + // of allocation order (see comment above) + QCOMPARE(a.getId().untyped, 0); + QCOMPARE(x.getUntypedId(), 1); + QCOMPARE(aa.getId().untyped, 2); + + QVERIFY(!a.getId().isNone()); + QVERIFY(A::Id().isNone()); + } + + // NB each test must release all the items it adds to the ById store + + void anyEmpty() { + auto p = AnyById::get(0); + QVERIFY(!p); + } + + void anySimple() { + auto a = std::make_shared<A>(); + AnyById::add(a->getId().untyped, a); + + auto aa = AnyById::getAs<A>(a->getId().untyped); + QVERIFY(!!aa); + QCOMPARE(aa->getId(), a->getId()); + QCOMPARE(aa.get(), a.get()); // same object, not just same id! + AnyById::release(a->getId().untyped); + } + + void typedEmpty() { + auto p = AById::get({}); + QVERIFY(!p); + } + + void typedSimple() { + auto a = std::make_shared<A>(); + AById::add(a); + + auto aa = AById::get(a->getId()); + QVERIFY(!!aa); + QCOMPARE(aa->getId(), a->getId()); + QCOMPARE(aa.get(), a.get()); // same object, not just same id! + AById::release(a); + } + + void typedRelease() { + auto a = std::make_shared<A>(); + AById::add(a); + + auto aa = AById::get(a->getId()); + QVERIFY(!!aa); + AById::release(a); + + aa = AById::get(a->getId()); + QVERIFY(!aa); + } + + void typedDowncast() { + auto a = std::make_shared<A>(); + auto b1 = std::make_shared<B1>(); + AById::add(a); + AById::add(b1); + + auto bb1 = AById::getAs<B1>(a->getId()); + QVERIFY(!bb1); + + bb1 = AById::getAs<B1>(b1->getId()); + QVERIFY(!!bb1); + QCOMPARE(bb1->getId(), b1->getId()); + + auto bb2 = AById::getAs<B2>(b1->getId()); + QVERIFY(!bb2); + + AById::release(a); + AById::release(b1); + } + + void typedCrosscast() { + auto y = std::make_shared<Y>(); + AById::add(y); + + auto yy = AById::getAs<Y>(y->getId()); + QVERIFY(!!yy); + QCOMPARE(yy->getId(), y->getId()); + + yy = AnyById::getAs<Y>(y->getId().untyped); + QVERIFY(!!yy); + QCOMPARE(yy->getId(), y->getId()); + + auto xx = AById::getAs<X>(y->getId()); + QVERIFY(!!xx); + QCOMPARE(xx->getUntypedId(), y->getId().untyped); + QCOMPARE(xx.get(), yy.get()); + + xx = AnyById::getAs<X>(y->getId().untyped); + QVERIFY(!!xx); + QCOMPARE(xx->getUntypedId(), y->getId().untyped); + QCOMPARE(xx.get(), yy.get()); + + auto mm = AnyById::getAs<M>(y->getId().untyped); + QVERIFY(!!mm); + QCOMPARE(mm.get(), yy.get()); + + AById::release(y); + } + + void duplicateAdd() { + auto a = std::make_shared<A>(); + AById::add(a); + try { + AById::add(a); + cerr << "Failed to catch expected exception in duplicateAdd" << endl; + QVERIFY(false); + } catch (const std::logic_error &) { + } + AById::release(a); + } + + void unknownRelease() { + auto a = std::make_shared<A>(); + auto b1 = std::make_shared<B1>(); + AById::add(a); + try { + AById::release(b1); + cerr << "Failed to catch expected exception in unknownRelease" << endl; + QVERIFY(false); + } catch (const std::logic_error &) { + } + AById::release(a); + } +}; +