annotate base/test/TestById.h @ 1883:e5d0ea9ac8f1

OK I give in, we are going to have to put this in a separate DLL so we can deploy a version on Win7 that doesn't have the WinRT dependency
author Chris Cannam
date Tue, 21 Jul 2020 13:59:14 +0100
parents 043e05c956fb
children
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@1752 26 // We'll need to change access levels for getId() and getUntypedId()
Chris@1752 27 // to test the raw calls
Chris@1752 28
Chris@1752 29 struct A : public WithTypedId<A> { public: using WithTypedId<A>::getId; };
Chris@1742 30 struct B1 : public A {};
Chris@1742 31 struct B2 : public A {};
Chris@1742 32
Chris@1742 33 struct M {};
Chris@1742 34
Chris@1742 35 typedef TypedById<A, A::Id> AById;
Chris@1742 36
Chris@1752 37 struct X : virtual public WithId { public: using WithId::getUntypedId; };
Chris@1742 38 struct Y : public X, public B2, public M {};
Chris@1742 39
Chris@1742 40 class TestById : public QObject
Chris@1742 41 {
Chris@1742 42 Q_OBJECT
Chris@1742 43
Chris@1742 44 private slots:
Chris@1742 45 void ids() {
Chris@1742 46 // Verify that ids are unique across all classes, not just
Chris@1742 47 // within a class. These must be the first two WithId objects
Chris@1742 48 // allocated in the first test in the suite, otherwise they
Chris@1742 49 // could be different even if they were allocated from
Chris@1742 50 // separate pools.
Chris@1742 51 A a;
Chris@1742 52 X x;
Chris@1742 53 if (a.getId().untyped == x.getUntypedId()) {
Chris@1756 54 std::cerr << "ERROR: a and x have the same id: " << a.getId()
Chris@1756 55 << std::endl;
Chris@1742 56 }
Chris@1742 57 QVERIFY(a.getId().untyped != x.getUntypedId());
Chris@1742 58
Chris@1742 59 A aa;
Chris@1742 60 QVERIFY(aa.getId().untyped != a.getId().untyped);
Chris@1742 61 QVERIFY(aa.getId().untyped != x.getUntypedId());
Chris@1742 62
Chris@1742 63 // Check the actual ids that have been allocated. This is
Chris@1742 64 // supposed to be a hidden implementation detail, but we want
Chris@1742 65 // to make sure the test itself hasn't become broken in terms
Chris@1742 66 // of allocation order (see comment above)
Chris@1742 67 QCOMPARE(a.getId().untyped, 0);
Chris@1742 68 QCOMPARE(x.getUntypedId(), 1);
Chris@1742 69 QCOMPARE(aa.getId().untyped, 2);
Chris@1742 70
Chris@1742 71 QVERIFY(!a.getId().isNone());
Chris@1742 72 QVERIFY(A::Id().isNone());
Chris@1742 73 }
Chris@1742 74
Chris@1742 75 // NB each test must release all the items it adds to the ById store
Chris@1742 76
Chris@1742 77 void anyEmpty() {
Chris@1742 78 auto p = AnyById::get(0);
Chris@1742 79 QVERIFY(!p);
Chris@1742 80 }
Chris@1742 81
Chris@1742 82 void anySimple() {
Chris@1742 83 auto a = std::make_shared<A>();
Chris@1752 84 int id = AnyById::add(a);
Chris@1752 85 QCOMPARE(id, a->getId().untyped);
Chris@1742 86
Chris@1752 87 auto aa = AnyById::getAs<A>(id);
Chris@1742 88 QVERIFY(!!aa);
Chris@1742 89 QCOMPARE(aa->getId(), a->getId());
Chris@1742 90 QCOMPARE(aa.get(), a.get()); // same object, not just same id!
Chris@1752 91 AnyById::release(id);
Chris@1742 92 }
Chris@1742 93
Chris@1742 94 void typedEmpty() {
Chris@1742 95 auto p = AById::get({});
Chris@1742 96 QVERIFY(!p);
Chris@1742 97 }
Chris@1742 98
Chris@1742 99 void typedSimple() {
Chris@1742 100 auto a = std::make_shared<A>();
Chris@1742 101 AById::add(a);
Chris@1742 102
Chris@1742 103 auto aa = AById::get(a->getId());
Chris@1742 104 QVERIFY(!!aa);
Chris@1742 105 QCOMPARE(aa->getId(), a->getId());
Chris@1742 106 QCOMPARE(aa.get(), a.get()); // same object, not just same id!
Chris@1742 107 AById::release(a);
Chris@1742 108 }
Chris@1742 109
Chris@1752 110 void typedReleaseById() {
Chris@1742 111 auto a = std::make_shared<A>();
Chris@1752 112 auto aid = AById::add(a);
Chris@1742 113
Chris@1752 114 auto aa = AById::get(aid);
Chris@1752 115 QVERIFY(!!aa);
Chris@1752 116 AById::release(aid);
Chris@1752 117
Chris@1752 118 aa = AById::get(aid);
Chris@1752 119 QVERIFY(!aa);
Chris@1752 120 }
Chris@1752 121
Chris@1752 122 void typedReleaseByItem() {
Chris@1752 123 auto a = std::make_shared<A>();
Chris@1752 124 auto aid = AById::add(a);
Chris@1752 125
Chris@1752 126 auto aa = AById::get(aid);
Chris@1742 127 QVERIFY(!!aa);
Chris@1742 128 AById::release(a);
Chris@1742 129
Chris@1752 130 aa = AById::get(aid);
Chris@1742 131 QVERIFY(!aa);
Chris@1742 132 }
Chris@1742 133
Chris@1742 134 void typedDowncast() {
Chris@1742 135 auto a = std::make_shared<A>();
Chris@1742 136 auto b1 = std::make_shared<B1>();
Chris@1742 137 AById::add(a);
Chris@1742 138 AById::add(b1);
Chris@1742 139
Chris@1742 140 auto bb1 = AById::getAs<B1>(a->getId());
Chris@1742 141 QVERIFY(!bb1);
Chris@1742 142
Chris@1742 143 bb1 = AById::getAs<B1>(b1->getId());
Chris@1742 144 QVERIFY(!!bb1);
Chris@1742 145 QCOMPARE(bb1->getId(), b1->getId());
Chris@1742 146
Chris@1742 147 auto bb2 = AById::getAs<B2>(b1->getId());
Chris@1742 148 QVERIFY(!bb2);
Chris@1742 149
Chris@1742 150 AById::release(a);
Chris@1742 151 AById::release(b1);
Chris@1742 152 }
Chris@1742 153
Chris@1742 154 void typedCrosscast() {
Chris@1742 155 auto y = std::make_shared<Y>();
Chris@1742 156 AById::add(y);
Chris@1742 157
Chris@1742 158 auto yy = AById::getAs<Y>(y->getId());
Chris@1742 159 QVERIFY(!!yy);
Chris@1742 160 QCOMPARE(yy->getId(), y->getId());
Chris@1742 161
Chris@1742 162 yy = AnyById::getAs<Y>(y->getId().untyped);
Chris@1742 163 QVERIFY(!!yy);
Chris@1742 164 QCOMPARE(yy->getId(), y->getId());
Chris@1742 165
Chris@1742 166 auto xx = AById::getAs<X>(y->getId());
Chris@1742 167 QVERIFY(!!xx);
Chris@1742 168 QCOMPARE(xx->getUntypedId(), y->getId().untyped);
Chris@1742 169 QCOMPARE(xx.get(), yy.get());
Chris@1742 170
Chris@1742 171 xx = AnyById::getAs<X>(y->getId().untyped);
Chris@1742 172 QVERIFY(!!xx);
Chris@1742 173 QCOMPARE(xx->getUntypedId(), y->getId().untyped);
Chris@1742 174 QCOMPARE(xx.get(), yy.get());
Chris@1742 175
Chris@1742 176 auto mm = AnyById::getAs<M>(y->getId().untyped);
Chris@1742 177 QVERIFY(!!mm);
Chris@1742 178 QCOMPARE(mm.get(), yy.get());
Chris@1742 179
Chris@1742 180 AById::release(y);
Chris@1742 181 }
Chris@1742 182
Chris@1742 183 void duplicateAdd() {
Chris@1742 184 auto a = std::make_shared<A>();
Chris@1742 185 AById::add(a);
Chris@1742 186 try {
Chris@1742 187 AById::add(a);
Chris@1756 188 std::cerr << "Failed to catch expected exception in duplicateAdd"
Chris@1756 189 << std::endl;
Chris@1742 190 QVERIFY(false);
Chris@1742 191 } catch (const std::logic_error &) {
Chris@1742 192 }
Chris@1742 193 AById::release(a);
Chris@1742 194 }
Chris@1742 195
Chris@1742 196 void unknownRelease() {
Chris@1742 197 auto a = std::make_shared<A>();
Chris@1742 198 auto b1 = std::make_shared<B1>();
Chris@1742 199 AById::add(a);
Chris@1742 200 try {
Chris@1742 201 AById::release(b1);
Chris@1756 202 std::cerr << "Failed to catch expected exception in unknownRelease"
Chris@1756 203 << std::endl;
Chris@1742 204 QVERIFY(false);
Chris@1742 205 } catch (const std::logic_error &) {
Chris@1742 206 }
Chris@1742 207 AById::release(a);
Chris@1742 208 }
Chris@1742 209 };
Chris@1742 210