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
|