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