aboutsummaryrefslogtreecommitdiff
path: root/test/common/ptr.h
blob: 0c871a761d98e39d36ff713063968e337732f61e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include <cxxtest/TestSuite.h>

#include "common/ptr.h"

class PtrTestSuite : public CxxTest::TestSuite {
	public:

	struct A {
		int a;
	};

	struct B : public A {
		int b;
	};

	// A simple class which keeps track of all its instances
	class InstanceCountingClass {
	public:
		static int count;
		InstanceCountingClass() { count++; }
		InstanceCountingClass(const InstanceCountingClass&) { count++; }
		~InstanceCountingClass() { count--; }
	};

	void test_deletion() {
		TS_ASSERT_EQUALS(InstanceCountingClass::count, 0);
		{
			Common::SharedPtr<InstanceCountingClass> p1(new InstanceCountingClass());
			TS_ASSERT_EQUALS(InstanceCountingClass::count, 1);

			Common::ScopedPtr<InstanceCountingClass> p2(new InstanceCountingClass());
			TS_ASSERT_EQUALS(InstanceCountingClass::count, 2);
		}
		TS_ASSERT_EQUALS(InstanceCountingClass::count, 0);
	}

	struct CustomDeleter {
		static bool invoked;
		void operator()(int *object) {
			invoked = true;
			delete object;
		}
	};

	void test_scoped_deleter() {
		CustomDeleter::invoked = false;

		{
			Common::ScopedPtr<int, CustomDeleter> a(new int(0));
			TS_ASSERT(!CustomDeleter::invoked);
		}

		TS_ASSERT(CustomDeleter::invoked);
	}

	void test_disposable_deleter() {
		CustomDeleter::invoked = false;

		{
			Common::DisposablePtr<int, CustomDeleter> a1(new int, DisposeAfterUse::YES);
			TS_ASSERT(!CustomDeleter::invoked);
		}

		TS_ASSERT(CustomDeleter::invoked);
		CustomDeleter::invoked = false;

		int *a = new int;
		{
			Common::DisposablePtr<int, CustomDeleter> a2(a, DisposeAfterUse::NO);
		}

		TS_ASSERT(!CustomDeleter::invoked);
		delete a;
	}

	void test_scoped_deref() {
		A *raw = new A();
		raw->a = 123;
		Common::ScopedPtr<A> a(raw);
		TS_ASSERT_EQUALS(&*a, &*raw);
		TS_ASSERT_EQUALS(a->a, raw->a);
	}

	void test_disposable_deref() {
		A *raw = new A();
		raw->a = 123;
		Common::DisposablePtr<A> a(raw, DisposeAfterUse::YES);
		TS_ASSERT_EQUALS(&*a, &*raw);
		TS_ASSERT_EQUALS(a->a, raw->a);
	}

	void test_assign() {
		Common::SharedPtr<int> p1(new int(1));
		TS_ASSERT(p1.unique());
		TS_ASSERT_EQUALS(*p1, 1);

		{
			Common::SharedPtr<int> p2 = p1;
			TS_ASSERT(!p1.unique());
			TS_ASSERT_EQUALS(p1.refCount(), p2.refCount());
			TS_ASSERT_EQUALS(p1.refCount(), 2);
			TS_ASSERT_EQUALS(p1, p2);
			TS_ASSERT_EQUALS(*p2, 1);
			{
				Common::SharedPtr<int> p3;
				p3 = p2;
				TS_ASSERT_EQUALS(p3, p2);
				TS_ASSERT_EQUALS(p3, p1);
				TS_ASSERT_EQUALS(p1.refCount(), 3);
				TS_ASSERT_EQUALS(*p3, 1);
				*p3 = 0;
				TS_ASSERT_EQUALS(*p3, 0);
			}
			TS_ASSERT_EQUALS(*p2, 0);
			TS_ASSERT_EQUALS(p1.refCount(), 2);
		}

		TS_ASSERT_EQUALS(*p1, 0);
		TS_ASSERT(p1.unique());
	}

	template<class T>
	struct Deleter {
		bool *test;
		void operator()(T *ptr) { *test = true; delete ptr; }
	};

	void test_deleter() {
		Deleter<int> myDeleter;
		myDeleter.test = new bool(false);

		{
			Common::SharedPtr<int> p(new int(1), myDeleter);
		}

		TS_ASSERT_EQUALS(*myDeleter.test, true);
		delete myDeleter.test;
	}

	void test_compare() {
		Common::SharedPtr<int> p1(new int(1));
		Common::SharedPtr<int> p2;

		TS_ASSERT(p1);
		TS_ASSERT(!p2);

		TS_ASSERT(p1 != 0);
		TS_ASSERT(p2 == 0);

		p1.reset();
		TS_ASSERT(!p1);
	}

	void test_cast() {
		Common::SharedPtr<B> b(new B);
		Common::SharedPtr<A> a(b);
		a = b;
	}
};

int PtrTestSuite::InstanceCountingClass::count = 0;
bool PtrTestSuite::CustomDeleter::invoked = false;