annotate 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
rev   line source
Chris@1742 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1742 2
Chris@1742 3 /*
Chris@1742 4 Sonic Visualiser
Chris@1742 5 An audio file viewer and annotation editor.
Chris@1742 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1742 7
Chris@1742 8 This program is free software; you can redistribute it and/or
Chris@1742 9 modify it under the terms of the GNU General Public License as
Chris@1742 10 published by the Free Software Foundation; either version 2 of the
Chris@1742 11 License, or (at your option) any later version. See the file
Chris@1742 12 COPYING included with this distribution for more information.
Chris@1742 13 */
Chris@1742 14
Chris@1742 15 #include "../ById.h"
Chris@1742 16
Chris@1742 17 #include <QObject>
Chris@1742 18 #include <QtTest>
Chris@1742 19
Chris@1742 20 #include <iostream>
Chris@1742 21
Chris@1742 22 using namespace std;
Chris@1742 23
Chris@1742 24 struct WithoutId {};
Chris@1742 25
Chris@1742 26 struct A : public WithTypedId<A> {};
Chris@1742 27 struct B1 : public A {};
Chris@1742 28 struct B2 : public A {};
Chris@1742 29
Chris@1742 30 struct M {};
Chris@1742 31
Chris@1742 32 typedef TypedById<A, A::Id> AById;
Chris@1742 33
Chris@1742 34 struct X : virtual public WithId {};
Chris@1742 35 struct Y : public X, public B2, public M {};
Chris@1742 36
Chris@1742 37 class TestById : public QObject
Chris@1742 38 {
Chris@1742 39 Q_OBJECT
Chris@1742 40
Chris@1742 41 private slots:
Chris@1742 42 void ids() {
Chris@1742 43 // Verify that ids are unique across all classes, not just
Chris@1742 44 // within a class. These must be the first two WithId objects
Chris@1742 45 // allocated in the first test in the suite, otherwise they
Chris@1742 46 // could be different even if they were allocated from
Chris@1742 47 // separate pools.
Chris@1742 48 A a;
Chris@1742 49 X x;
Chris@1742 50 if (a.getId().untyped == x.getUntypedId()) {
Chris@1742 51 cerr << "ERROR: a and x have the same id: " << a.getId() << endl;
Chris@1742 52 }
Chris@1742 53 QVERIFY(a.getId().untyped != x.getUntypedId());
Chris@1742 54
Chris@1742 55 A aa;
Chris@1742 56 QVERIFY(aa.getId().untyped != a.getId().untyped);
Chris@1742 57 QVERIFY(aa.getId().untyped != x.getUntypedId());
Chris@1742 58
Chris@1742 59 // Check the actual ids that have been allocated. This is
Chris@1742 60 // supposed to be a hidden implementation detail, but we want
Chris@1742 61 // to make sure the test itself hasn't become broken in terms
Chris@1742 62 // of allocation order (see comment above)
Chris@1742 63 QCOMPARE(a.getId().untyped, 0);
Chris@1742 64 QCOMPARE(x.getUntypedId(), 1);
Chris@1742 65 QCOMPARE(aa.getId().untyped, 2);
Chris@1742 66
Chris@1742 67 QVERIFY(!a.getId().isNone());
Chris@1742 68 QVERIFY(A::Id().isNone());
Chris@1742 69 }
Chris@1742 70
Chris@1742 71 // NB each test must release all the items it adds to the ById store
Chris@1742 72
Chris@1742 73 void anyEmpty() {
Chris@1742 74 auto p = AnyById::get(0);
Chris@1742 75 QVERIFY(!p);
Chris@1742 76 }
Chris@1742 77
Chris@1742 78 void anySimple() {
Chris@1742 79 auto a = std::make_shared<A>();
Chris@1742 80 AnyById::add(a->getId().untyped, a);
Chris@1742 81
Chris@1742 82 auto aa = AnyById::getAs<A>(a->getId().untyped);
Chris@1742 83 QVERIFY(!!aa);
Chris@1742 84 QCOMPARE(aa->getId(), a->getId());
Chris@1742 85 QCOMPARE(aa.get(), a.get()); // same object, not just same id!
Chris@1742 86 AnyById::release(a->getId().untyped);
Chris@1742 87 }
Chris@1742 88
Chris@1742 89 void typedEmpty() {
Chris@1742 90 auto p = AById::get({});
Chris@1742 91 QVERIFY(!p);
Chris@1742 92 }
Chris@1742 93
Chris@1742 94 void typedSimple() {
Chris@1742 95 auto a = std::make_shared<A>();
Chris@1742 96 AById::add(a);
Chris@1742 97
Chris@1742 98 auto aa = AById::get(a->getId());
Chris@1742 99 QVERIFY(!!aa);
Chris@1742 100 QCOMPARE(aa->getId(), a->getId());
Chris@1742 101 QCOMPARE(aa.get(), a.get()); // same object, not just same id!
Chris@1742 102 AById::release(a);
Chris@1742 103 }
Chris@1742 104
Chris@1742 105 void typedRelease() {
Chris@1742 106 auto a = std::make_shared<A>();
Chris@1742 107 AById::add(a);
Chris@1742 108
Chris@1742 109 auto aa = AById::get(a->getId());
Chris@1742 110 QVERIFY(!!aa);
Chris@1742 111 AById::release(a);
Chris@1742 112
Chris@1742 113 aa = AById::get(a->getId());
Chris@1742 114 QVERIFY(!aa);
Chris@1742 115 }
Chris@1742 116
Chris@1742 117 void typedDowncast() {
Chris@1742 118 auto a = std::make_shared<A>();
Chris@1742 119 auto b1 = std::make_shared<B1>();
Chris@1742 120 AById::add(a);
Chris@1742 121 AById::add(b1);
Chris@1742 122
Chris@1742 123 auto bb1 = AById::getAs<B1>(a->getId());
Chris@1742 124 QVERIFY(!bb1);
Chris@1742 125
Chris@1742 126 bb1 = AById::getAs<B1>(b1->getId());
Chris@1742 127 QVERIFY(!!bb1);
Chris@1742 128 QCOMPARE(bb1->getId(), b1->getId());
Chris@1742 129
Chris@1742 130 auto bb2 = AById::getAs<B2>(b1->getId());
Chris@1742 131 QVERIFY(!bb2);
Chris@1742 132
Chris@1742 133 AById::release(a);
Chris@1742 134 AById::release(b1);
Chris@1742 135 }
Chris@1742 136
Chris@1742 137 void typedCrosscast() {
Chris@1742 138 auto y = std::make_shared<Y>();
Chris@1742 139 AById::add(y);
Chris@1742 140
Chris@1742 141 auto yy = AById::getAs<Y>(y->getId());
Chris@1742 142 QVERIFY(!!yy);
Chris@1742 143 QCOMPARE(yy->getId(), y->getId());
Chris@1742 144
Chris@1742 145 yy = AnyById::getAs<Y>(y->getId().untyped);
Chris@1742 146 QVERIFY(!!yy);
Chris@1742 147 QCOMPARE(yy->getId(), y->getId());
Chris@1742 148
Chris@1742 149 auto xx = AById::getAs<X>(y->getId());
Chris@1742 150 QVERIFY(!!xx);
Chris@1742 151 QCOMPARE(xx->getUntypedId(), y->getId().untyped);
Chris@1742 152 QCOMPARE(xx.get(), yy.get());
Chris@1742 153
Chris@1742 154 xx = AnyById::getAs<X>(y->getId().untyped);
Chris@1742 155 QVERIFY(!!xx);
Chris@1742 156 QCOMPARE(xx->getUntypedId(), y->getId().untyped);
Chris@1742 157 QCOMPARE(xx.get(), yy.get());
Chris@1742 158
Chris@1742 159 auto mm = AnyById::getAs<M>(y->getId().untyped);
Chris@1742 160 QVERIFY(!!mm);
Chris@1742 161 QCOMPARE(mm.get(), yy.get());
Chris@1742 162
Chris@1742 163 AById::release(y);
Chris@1742 164 }
Chris@1742 165
Chris@1742 166 void duplicateAdd() {
Chris@1742 167 auto a = std::make_shared<A>();
Chris@1742 168 AById::add(a);
Chris@1742 169 try {
Chris@1742 170 AById::add(a);
Chris@1742 171 cerr << "Failed to catch expected exception in duplicateAdd" << endl;
Chris@1742 172 QVERIFY(false);
Chris@1742 173 } catch (const std::logic_error &) {
Chris@1742 174 }
Chris@1742 175 AById::release(a);
Chris@1742 176 }
Chris@1742 177
Chris@1742 178 void unknownRelease() {
Chris@1742 179 auto a = std::make_shared<A>();
Chris@1742 180 auto b1 = std::make_shared<B1>();
Chris@1742 181 AById::add(a);
Chris@1742 182 try {
Chris@1742 183 AById::release(b1);
Chris@1742 184 cerr << "Failed to catch expected exception in unknownRelease" << endl;
Chris@1742 185 QVERIFY(false);
Chris@1742 186 } catch (const std::logic_error &) {
Chris@1742 187 }
Chris@1742 188 AById::release(a);
Chris@1742 189 }
Chris@1742 190 };
Chris@1742 191