1/*-------------------------------------------------------------------------
2 * drawElements C++ Base Library
3 * -----------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Unique pointer.
22 *//*--------------------------------------------------------------------*/
23
24#include "deUniquePtr.hpp"
25
26#include <exception>
27
28namespace de
29{
30
31namespace
32{
33
34class Object
35{
36public:
37	Object (bool& exists)
38		: m_exists(exists)
39	{
40		m_exists = true;
41	}
42
43	~Object (void)
44	{
45		m_exists = false;
46	}
47
48private:
49	bool& m_exists;
50};
51
52struct CustomDeleter
53{
54	CustomDeleter (bool* called) : m_called(called) {}
55
56	void operator() (Object* ptr)
57	{
58		DE_TEST_ASSERT(!*m_called);
59		delete ptr;
60		*m_called = true;
61	}
62
63	bool* m_called;
64};
65
66MovePtr<Object> createObject (bool& exists)
67{
68	UniquePtr<Object> objectPtr(new Object(exists));
69	return objectPtr.move();
70}
71
72} // anonymous
73
74void UniquePtr_selfTest (void)
75{
76	// Basic test.
77	{
78		bool exists = false;
79		{
80			UniquePtr<Object> ptr(new Object(exists));
81			DE_TEST_ASSERT(exists);
82			DE_TEST_ASSERT(ptr.get() != DE_NULL);
83		}
84		DE_TEST_ASSERT(!exists);
85	}
86
87	// Exception test.
88	{
89		bool exists = false;
90		try
91		{
92			UniquePtr<Object> ptr(new Object(exists));
93			DE_TEST_ASSERT(exists);
94			DE_TEST_ASSERT(ptr.get() != DE_NULL);
95			throw std::exception();
96		}
97		catch (const std::exception&)
98		{
99			DE_TEST_ASSERT(!exists);
100		}
101		DE_TEST_ASSERT(!exists);
102	}
103
104	// Expression test.
105	{
106		bool exists = false;
107		bool test	= (UniquePtr<Object>(new Object(exists))).get() != DE_NULL && exists;
108		DE_TEST_ASSERT(!exists);
109		DE_TEST_ASSERT(test);
110	}
111
112	// Custom deleter.
113	{
114		bool exists = false;
115		bool deleterCalled = false;
116		{
117			UniquePtr<Object, CustomDeleter> ptr(new Object(exists), CustomDeleter(&deleterCalled));
118			DE_TEST_ASSERT(exists);
119			DE_TEST_ASSERT(!deleterCalled);
120			DE_TEST_ASSERT(ptr.get() != DE_NULL);
121		}
122		DE_TEST_ASSERT(!exists);
123		DE_TEST_ASSERT(deleterCalled);
124	}
125
126	// MovePtr -> MovePtr moving
127	{
128		bool exists = false;
129		MovePtr<Object> ptr(new Object(exists));
130		DE_TEST_ASSERT(exists);
131		{
132			MovePtr<Object> ptr2 = ptr;
133			DE_TEST_ASSERT(exists);
134			// Ownership moved to ptr2, should be deleted when ptr2 goes out of scope.
135		}
136		DE_TEST_ASSERT(!exists);
137	}
138
139	// UniquePtr -> MovePtr moving
140	{
141		bool exists = false;
142		UniquePtr<Object> ptr(new Object(exists));
143		DE_TEST_ASSERT(exists);
144		{
145			MovePtr<Object> ptr2 = ptr.move();
146			DE_TEST_ASSERT(exists);
147			// Ownership moved to ptr2, should be deleted when ptr2 goes out of scope.
148		}
149		DE_TEST_ASSERT(!exists);
150	}
151
152	// MovePtr -> UniquePtr moving
153	{
154		bool exists = false;
155		{
156			UniquePtr<Object> ptr(createObject(exists));
157			DE_TEST_ASSERT(exists);
158		}
159		DE_TEST_ASSERT(!exists);
160	}
161
162	// MovePtr assignment
163	{
164		bool exists1 = false;
165		bool exists2 = false;
166		MovePtr<Object> ptr1(new Object(exists1));
167		MovePtr<Object> ptr2(new Object(exists2));
168		ptr1 = ptr2;
169		DE_TEST_ASSERT(!exists1);
170		DE_TEST_ASSERT(exists2);
171	}
172
173	// MovePtr stealing
174	{
175		bool exists = false;
176		Object* raw = DE_NULL;
177		{
178			MovePtr<Object> ptr1(new Object(exists));
179			raw = ptr1.release();
180			DE_TEST_ASSERT(raw != DE_NULL);
181			DE_TEST_ASSERT(ptr1.get() == DE_NULL);
182			DE_TEST_ASSERT(exists);
183		}
184		DE_TEST_ASSERT(exists);
185		delete raw;
186		DE_TEST_ASSERT(!exists);
187	}
188
189	// Null MovePtr and assigning to it.
190	{
191		bool exists = false;
192		{
193			MovePtr<Object> ptr1;
194			DE_TEST_ASSERT(ptr1.get() == DE_NULL);
195			MovePtr<Object> ptr2(new Object(exists));
196			ptr1 = ptr2;
197			DE_TEST_ASSERT(exists);
198			DE_TEST_ASSERT(ptr1.get() != DE_NULL);
199			DE_TEST_ASSERT(ptr2.get() == DE_NULL);
200		}
201		DE_TEST_ASSERT(!exists);
202	}
203
204#if 0
205	// UniquePtr assignment or copy construction should not compile. This
206	// piece of code is intentionally commented out. To manually test that
207	// copying a UniquePtr is statically forbidden, uncomment and try to
208	// compile.
209	{
210		bool exists = false;
211		UniquePtr<Object> ptr(new Object(exists));
212		{
213			UniquePtr<Object> ptr2(ptr);
214			DE_TEST_ASSERT(exists);
215		}
216		DE_TEST_ASSERT(!exists);
217	}
218#endif
219}
220
221} // de
222