Merge lp:~michihenning/unity/phablet-unity-api-merge-tests into lp:unity/phablet
- phablet-unity-api-merge-tests
- Merge into phablet
Status: | Merged |
---|---|
Approved by: | MichaĆ Sawicz |
Approved revision: | no longer in the source branch. |
Merged at revision: | 568 |
Proposed branch: | lp:~michihenning/unity/phablet-unity-api-merge-tests |
Merge into: | lp:unity/phablet |
Prerequisite: | lp:~michihenning/unity/phablet-unity-api-merge-1 |
Diff against target: |
2045 lines (+1893/-2) 22 files modified
CMakeLists.txt (+1/-1) debian/control (+3/-0) include/unity/api/Version.h.cmake (+3/-1) tests/CMakeLists.txt (+1/-0) tests/gtest/CMakeLists.txt (+36/-0) tests/gtest/libgtest/CMakeLists.txt (+31/-0) tests/gtest/unity/CMakeLists.txt (+26/-0) tests/gtest/unity/Exceptions_test.cpp (+536/-0) tests/gtest/unity/api/CMakeLists.txt (+19/-0) tests/gtest/unity/api/Version/CMakeLists.txt (+22/-0) tests/gtest/unity/api/Version/Version_test.cpp (+31/-0) tests/gtest/unity/scopes/CMakeLists.txt (+18/-0) tests/gtest/unity/util/CMakeLists.txt (+22/-0) tests/gtest/unity/util/Daemon/CMakeLists.txt (+22/-0) tests/gtest/unity/util/Daemon/Daemon_test.cpp (+353/-0) tests/gtest/unity/util/Daemon/daemon-tester.py (+58/-0) tests/gtest/unity/util/DefinesPtrs/CMakeLists.txt (+22/-0) tests/gtest/unity/util/DefinesPtrs/DefinesPtrs_test.cpp (+45/-0) tests/gtest/unity/util/FileIO/CMakeLists.txt (+22/-0) tests/gtest/unity/util/FileIO/FileIO_test.cpp (+71/-0) tests/gtest/unity/util/ResourcePtr/CMakeLists.txt (+22/-0) tests/gtest/unity/util/ResourcePtr/ResourcePtr_test.cpp (+529/-0) |
To merge this branch: | bzr merge lp:~michihenning/unity/phablet-unity-api-merge-tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Albert Astals Cid (community) | Needs Fixing | ||
Jussi Pakkanen (community) | Approve | ||
Pete Woods | Pending | ||
Review via email: mp+157326@code.launchpad.net |
Commit message
Added unit tests for the newly-added C++ files.
Description of the change
This MR adds unit tests for the newly-added C++ files.
PS Jenkins bot (ps-jenkins) wrote : | # |
Michi Henning (michihenning) wrote : | # |
OK, the failure is caused by the dependency on libgtest-dev. gtest needs pthreads, but it seems that this isn't installed automatically.
My problem is that I don't know how to correctly tell the debian packaging to pull in pthreads. libpthread is part of libc6, but lib6 comes in various versions for different architectures and debug/non-debug.
Can anyone tell me what the magic incantation is for the debian control file?
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:545
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:546
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Jussi Pakkanen (jpakkane) wrote : | # |
Overall looks quite nice but checking nested exceptions with the text they produce seems really evil. I would imagine that the text they produce is not guaranteed to be ABI stable plus it may change from compiler to compiler and libc to libc. It might even change when the locale is different.
It would be better if the exception hierarchy could be tested programmatically. Does C++ provide the tools to do that properly?
Michi Henning (michihenning) wrote : | # |
I'm not aware of a better way of doing this.
For unity::Exception and its derived exceptions, all of the text that is tested for is actually produced by the application that throws the exception. The only bits of text that come from the Exception implementation itself are the "Exception #n:" and "Exception history:" labels. Right now, these are hard-wired into the implementation, so they can't change even if the locale changes.
For the FileIO exceptions, I add the output from strerror() to the exception string, so that string can change if the locale changes. The easiest thing would probably be to set the LOCALE to "C" at the start of the test. Yes, it's possible for a different libc to use slightly different strings but, in practice, I don't think that's a problem. (It would be easier to adjust the tests if/when that happens than trying to come up with machinery now to deal with this, just in case we encounter a problem that, in fact, we may never encounter.)
Note that I don't want to just drop those tests because, without them, we have no guarantee that the strings are actually correct. (For example, I sometimes find myself catching typos I made in a string when I'm writing the tests.)
Jussi Pakkanen (jpakkane) wrote : | # |
Yes, we can fix those issues later if they turn up.
Albert Astals Cid (aacid) wrote : | # |
Doesn't merge with master cleanly
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:547
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:547
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:548
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:548
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:549
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:550
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:550
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2013-04-09 22:08:51 +0000 |
3 | +++ CMakeLists.txt 2013-04-10 02:45:26 +0000 |
4 | @@ -5,7 +5,7 @@ |
5 | set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "" FORCE) |
6 | endif() |
7 | |
8 | -project(qml-phone-shell CXX) |
9 | +project(qml-phone-shell C CXX) |
10 | |
11 | set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) |
12 | |
13 | |
14 | === modified file 'debian/control' |
15 | --- debian/control 2013-04-10 00:06:16 +0000 |
16 | +++ debian/control 2013-04-10 02:45:26 +0000 |
17 | @@ -24,6 +24,9 @@ |
18 | demo-assets, |
19 | libboost1.49-dev (>= 1.49), |
20 | libboost-regex1.49-dev (>= 1.49), |
21 | + libboost-regex1.49-dev (>= 1.49), |
22 | + libgtest-dev, |
23 | + libc6-dev, |
24 | Standards-Version: 3.9.3 |
25 | Vcs-Bzr: lp:unity/phablet |
26 | |
27 | |
28 | === modified file 'include/unity/api/Version.h.cmake' |
29 | --- include/unity/api/Version.h.cmake 2013-04-04 03:45:01 +0000 |
30 | +++ include/unity/api/Version.h.cmake 2013-04-10 02:45:26 +0000 |
31 | @@ -23,6 +23,8 @@ |
32 | #ifndef UNITY_API_VERSION_H |
33 | #define UNITY_API_VERSION_H |
34 | |
35 | +#include <unity/config.h> |
36 | + |
37 | #define UNITY_API_VERSION_MAJOR @UNITY_API_MAJOR@ |
38 | #define UNITY_API_VERSION_MINOR @UNITY_API_MINOR@ |
39 | #define UNITY_API_VERSION_MICRO @UNITY_API_MICRO@ |
40 | @@ -55,7 +57,7 @@ |
41 | // Version could be a namespace instead of a class, but that requires a lower-case name, |
42 | // which is inconsistent with the remainder of the API. |
43 | |
44 | -class Version |
45 | +class UNITY_API Version |
46 | { |
47 | public: |
48 | /** |
49 | |
50 | === modified file 'tests/CMakeLists.txt' |
51 | --- tests/CMakeLists.txt 2013-04-09 09:44:51 +0000 |
52 | +++ tests/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
53 | @@ -68,5 +68,6 @@ |
54 | |
55 | add_custom_target(alltests) |
56 | |
57 | +add_subdirectory(gtest) |
58 | add_subdirectory(unittests) |
59 | add_subdirectory(qmluitests) |
60 | |
61 | === added directory 'tests/gtest' |
62 | === added file 'tests/gtest/CMakeLists.txt' |
63 | --- tests/gtest/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
64 | +++ tests/gtest/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
65 | @@ -0,0 +1,36 @@ |
66 | +# |
67 | +# Copyright (C) 2013 Canonical Ltd |
68 | +# |
69 | +# This program is free software: you can redistribute it and/or modify |
70 | +# it under the terms of the GNU General Public License version 3 as |
71 | +# published by the Free Software Foundation. |
72 | +# |
73 | +# This program is distributed in the hope that it will be useful, |
74 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
75 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
76 | +# GNU General Public License for more details. |
77 | +# |
78 | +# You should have received a copy of the GNU General Public License |
79 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
80 | +# |
81 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
82 | +# |
83 | + |
84 | +find_package(Threads REQUIRED) |
85 | +set(TESTLIBDIR ${CMAKE_BINARY_DIR}/test/gtest/libgtest/build) |
86 | +set(LIBGTEST gtest) |
87 | +set(TESTLIBS ${LIBGTEST} ${CMAKE_THREAD_LIBS_INIT}) |
88 | + |
89 | +add_subdirectory(libgtest) |
90 | +add_subdirectory(unity) |
91 | + |
92 | +set(TEST_SRC |
93 | +) |
94 | + |
95 | +foreach(src ${TEST_SRC}) |
96 | + get_filename_component(name ${src} NAME_WE) |
97 | + add_executable(${name} ${src}) |
98 | + target_link_libraries(${name} ${LIBS} ${TESTLIBS}) |
99 | + string(REPLACE "_test" "" test_name ${name}) |
100 | + add_test(${test_name} ${name}) |
101 | +endforeach(src) |
102 | |
103 | === added directory 'tests/gtest/libgtest' |
104 | === added file 'tests/gtest/libgtest/CMakeLists.txt' |
105 | --- tests/gtest/libgtest/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
106 | +++ tests/gtest/libgtest/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
107 | @@ -0,0 +1,31 @@ |
108 | +# |
109 | +# Copyright (C) 2013 Canonical Ltd |
110 | +# |
111 | +# This program is free software: you can redistribute it and/or modify |
112 | +# it under the terms of the GNU General Public License version 3 as |
113 | +# published by the Free Software Foundation. |
114 | +# |
115 | +# This program is distributed in the hope that it will be useful, |
116 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
117 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
118 | +# GNU General Public License for more details. |
119 | +# |
120 | +# You should have received a copy of the GNU General Public License |
121 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
122 | +# |
123 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
124 | +# |
125 | + |
126 | +if (NOT DEFINED GTEST_ROOT) |
127 | + set(GTEST_ROOT /usr/src/gtest) |
128 | +endif() |
129 | + |
130 | +set(GTEST_SRC_DIR "${GTEST_ROOT}/src") |
131 | +set(GTEST_INCLUDE_DIR ${GTEST_ROOT}) |
132 | + |
133 | +add_library(gtest STATIC |
134 | +${GTEST_SRC_DIR}/gtest-all.cc |
135 | +${GTEST_SRC_DIR}/gtest_main.cc |
136 | +) |
137 | + |
138 | +set_target_properties(gtest PROPERTIES INCLUDE_DIRECTORIES ${GTEST_INCLUDE_DIR}) |
139 | |
140 | === added directory 'tests/gtest/unity' |
141 | === added file 'tests/gtest/unity/CMakeLists.txt' |
142 | --- tests/gtest/unity/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
143 | +++ tests/gtest/unity/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
144 | @@ -0,0 +1,26 @@ |
145 | +# |
146 | +# Copyright (C) 2013 Canonical Ltd |
147 | +# |
148 | +# This program is free software: you can redistribute it and/or modify |
149 | +# it under the terms of the GNU General Public License version 3 as |
150 | +# published by the Free Software Foundation. |
151 | +# |
152 | +# This program is distributed in the hope that it will be useful, |
153 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
154 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
155 | +# GNU General Public License for more details. |
156 | +# |
157 | +# You should have received a copy of the GNU General Public License |
158 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
159 | +# |
160 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
161 | +# |
162 | + |
163 | +add_subdirectory(api) |
164 | +add_subdirectory(scopes) |
165 | +add_subdirectory(util) |
166 | + |
167 | +add_executable(Exceptions_test Exceptions_test.cpp) |
168 | +target_link_libraries(Exceptions_test ${LIBS} ${TESTLIBS}) |
169 | + |
170 | +add_test(Exceptions Exceptions_test) |
171 | |
172 | === added file 'tests/gtest/unity/Exceptions_test.cpp' |
173 | --- tests/gtest/unity/Exceptions_test.cpp 1970-01-01 00:00:00 +0000 |
174 | +++ tests/gtest/unity/Exceptions_test.cpp 2013-04-10 02:45:26 +0000 |
175 | @@ -0,0 +1,536 @@ |
176 | +/* |
177 | + * Copyright (C) 2013 Canonical Ltd |
178 | + * |
179 | + * This program is free software: you can redistribute it and/or modify |
180 | + * it under the terms of the GNU General Public License version 3 as |
181 | + * published by the Free Software Foundation. |
182 | + * |
183 | + * This program is distributed in the hope that it will be useful, |
184 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
185 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
186 | + * GNU General Public License for more details. |
187 | + * |
188 | + * You should have received a copy of the GNU General Public License |
189 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
190 | + * |
191 | + * Authored by: Michi Henning <michi.henning@canonical.com> |
192 | + */ |
193 | + |
194 | +#include <unity/UnityExceptions.h> |
195 | +#include <unity/internal/UnityExceptionsImpl.h> |
196 | + |
197 | +#include <gtest/gtest.h> |
198 | + |
199 | +using namespace std; |
200 | +using namespace unity; |
201 | + |
202 | +// |
203 | +// Check Exception base class functionality (copy, assignment, accessor methods, etc.) |
204 | +// |
205 | + |
206 | +TEST(Exception, basic) |
207 | +{ |
208 | + SyscallException e("Hello", 0); |
209 | + EXPECT_EQ("Hello (errno = 0)", e.reason()); |
210 | + EXPECT_STREQ("unity::SyscallException", e.what()); |
211 | + |
212 | + SyscallException e2(e); |
213 | + EXPECT_EQ(e2.reason(), e.reason()); |
214 | + EXPECT_STREQ(e2.what(), e.what()); |
215 | + |
216 | + SyscallException e3("blah", 0); |
217 | + e2 = e3; |
218 | + EXPECT_EQ(e2.reason(), e3.reason()); |
219 | + EXPECT_STREQ(e2.what(), e.what()); |
220 | + |
221 | + EXPECT_EQ("unity::SyscallException: blah (errno = 0)", e3.to_string()); |
222 | + EXPECT_EQ("unity::SyscallException: blah (errno = 0)", e3.to_string(0, " ")); |
223 | + EXPECT_EQ(" unity::SyscallException: blah (errno = 0)", e3.to_string(1, " ")); |
224 | + EXPECT_EQ(" unity::SyscallException: blah (errno = 0)", e3.to_string(2, " ")); |
225 | +} |
226 | + |
227 | +TEST(Exception, empty_reason) |
228 | +{ |
229 | + { |
230 | + InvalidArgumentException e(""); |
231 | + EXPECT_EQ("", e.reason()); |
232 | + EXPECT_STREQ("unity::InvalidArgumentException", e.what()); |
233 | + } |
234 | + |
235 | + { |
236 | + SyscallException e("", 0); |
237 | + EXPECT_EQ("(errno = 0)", e.reason()); |
238 | + EXPECT_STREQ("unity::SyscallException", e.what()); |
239 | + } |
240 | +} |
241 | + |
242 | +// |
243 | +// A few helper functions so we can test that the nesting works correctly. |
244 | +// |
245 | + |
246 | +void a() |
247 | +{ |
248 | + throw bad_alloc(); |
249 | +} |
250 | + |
251 | +void b() |
252 | +{ |
253 | + try |
254 | + { |
255 | + a(); |
256 | + } |
257 | + catch (...) |
258 | + { |
259 | + throw InvalidArgumentException("a() threw"); |
260 | + } |
261 | +} |
262 | + |
263 | +void c() |
264 | +{ |
265 | + try |
266 | + { |
267 | + b(); |
268 | + } |
269 | + catch (nested_exception const&) |
270 | + { |
271 | + throw InvalidArgumentException("b() threw"); |
272 | + } |
273 | +} |
274 | + |
275 | +class E : public std::exception, public nested_exception |
276 | +{ |
277 | +public: |
278 | + virtual char const* what() const noexcept |
279 | + { |
280 | + return "E"; |
281 | + } |
282 | + E() = default; |
283 | + ~E() noexcept {} |
284 | +}; |
285 | + |
286 | +void throw_E() |
287 | +{ |
288 | + try |
289 | + { |
290 | + c(); |
291 | + } |
292 | + catch (...) |
293 | + { |
294 | + throw E(); |
295 | + } |
296 | +} |
297 | + |
298 | +void d() |
299 | +{ |
300 | + try |
301 | + { |
302 | + throw_E(); |
303 | + } |
304 | + catch (...) |
305 | + { |
306 | + throw InvalidArgumentException("throw_E() threw"); |
307 | + } |
308 | +} |
309 | + |
310 | +struct N : public nested_exception |
311 | +{ |
312 | +}; |
313 | + |
314 | +void throw_N() |
315 | +{ |
316 | + try |
317 | + { |
318 | + b(); |
319 | + } |
320 | + catch (...) |
321 | + { |
322 | + throw N(); |
323 | + } |
324 | +} |
325 | + |
326 | +void f() |
327 | +{ |
328 | + try |
329 | + { |
330 | + throw_N(); |
331 | + } |
332 | + catch (...) |
333 | + { |
334 | + throw InvalidArgumentException("throw_N() threw"); |
335 | + } |
336 | +} |
337 | + |
338 | +void throw_unknown() |
339 | +{ |
340 | + throw 42; |
341 | +} |
342 | + |
343 | +void g() |
344 | +{ |
345 | + try |
346 | + { |
347 | + throw_unknown(); |
348 | + } |
349 | + catch (...) |
350 | + { |
351 | + throw InvalidArgumentException("throw_unknown threw"); |
352 | + } |
353 | +} |
354 | + |
355 | +TEST(Exception, nesting) |
356 | +{ |
357 | + // Check basic chaining works and terminates correctly on a std::exception. |
358 | + |
359 | + try |
360 | + { |
361 | + c(); |
362 | + } |
363 | + catch (Exception const& e) |
364 | + { |
365 | + EXPECT_EQ("unity::InvalidArgumentException: b() threw:\n" |
366 | + " unity::InvalidArgumentException: a() threw:\n" |
367 | + " std::bad_alloc", e.to_string()); |
368 | + } |
369 | + |
370 | + // Check that we follow the chain for exceptions we don't know, but that derive |
371 | + // from both std::exception and std::nested_exception. |
372 | + |
373 | + try |
374 | + { |
375 | + d(); |
376 | + } |
377 | + catch (Exception const& e) |
378 | + { |
379 | + EXPECT_EQ("unity::InvalidArgumentException: throw_E() threw:\n" |
380 | + " E (derived from std::exception and std::nested_exception):\n" |
381 | + " unity::InvalidArgumentException: b() threw:\n" |
382 | + " unity::InvalidArgumentException: a() threw:\n" |
383 | + " std::bad_alloc", e.to_string()); |
384 | + } |
385 | + |
386 | + // Check that we follow the chain for exceptions that are derived from std::nested_exception |
387 | + // but not std::exception. |
388 | + |
389 | + try |
390 | + { |
391 | + f(); |
392 | + } |
393 | + catch (unity::Exception const& e) |
394 | + { |
395 | + EXPECT_EQ("unity::InvalidArgumentException: throw_N() threw:\n" |
396 | + " std::nested_exception:\n" |
397 | + " unity::InvalidArgumentException: a() threw:\n" |
398 | + " std::bad_alloc", e.to_string()); |
399 | + } |
400 | + |
401 | + // Check that we are correctly dealing with unknown exceptions |
402 | + |
403 | + try |
404 | + { |
405 | + g(); |
406 | + } |
407 | + catch (unity::Exception const& e) |
408 | + { |
409 | + EXPECT_EQ("unity::InvalidArgumentException: throw_unknown threw:\n" |
410 | + " unknown exception", e.to_string()); |
411 | + } |
412 | +} |
413 | + |
414 | +// |
415 | +// Test the history chaining. |
416 | +// |
417 | + |
418 | +TEST(Exception, history) |
419 | +{ |
420 | + // Check that remember() and get_earlier() return the correct exception. |
421 | + |
422 | + { |
423 | + InvalidArgumentException e(""); |
424 | + EXPECT_EQ(nullptr, e.get_earlier()); |
425 | + exception_ptr ep = make_exception_ptr(e); |
426 | + |
427 | + InvalidArgumentException e2(""); |
428 | + exception_ptr ep2 = e2.remember(ep); |
429 | + EXPECT_EQ(e2.get_earlier(), ep); |
430 | + } |
431 | + |
432 | + { |
433 | + InvalidArgumentException e(""); |
434 | + exception_ptr ep = make_exception_ptr(e); |
435 | + |
436 | + InvalidArgumentException e2(""); |
437 | + exception_ptr ep2 = e2.remember(ep); |
438 | + EXPECT_EQ(e2.get_earlier(), ep); |
439 | + } |
440 | + |
441 | + |
442 | + // Check that we are following the history chain. |
443 | + |
444 | + { |
445 | + exception_ptr ep; |
446 | + try |
447 | + { |
448 | + throw InvalidArgumentException("Step 1"); |
449 | + } |
450 | + catch (Exception& e) |
451 | + { |
452 | + ep = e.remember(ep); |
453 | + } |
454 | + InvalidArgumentException e2("Step 2"); |
455 | + ep = e2.remember(ep); |
456 | + |
457 | + try |
458 | + { |
459 | + ShutdownException e("Finalization problem"); |
460 | + e.remember(ep); |
461 | + throw e; |
462 | + } |
463 | + catch (Exception const& e) |
464 | + { |
465 | + string reason = e.to_string(); |
466 | + EXPECT_EQ("unity::ShutdownException: Finalization problem\n" |
467 | + " Exception history:\n" |
468 | + " Exception #1:\n" |
469 | + " unity::InvalidArgumentException: Step 1\n" |
470 | + " Exception #2:\n" |
471 | + " unity::InvalidArgumentException: Step 2", e.to_string()); |
472 | + } |
473 | + } |
474 | + |
475 | + |
476 | + // Same test, but this time with nested exceptions in the history. |
477 | + |
478 | + { |
479 | + exception_ptr ep; |
480 | + try |
481 | + { |
482 | + c(); |
483 | + } |
484 | + catch (Exception& e) |
485 | + { |
486 | + ep = e.remember(ep); |
487 | + } |
488 | + try |
489 | + { |
490 | + f(); |
491 | + } |
492 | + catch (Exception &e) |
493 | + { |
494 | + ep = e.remember(ep); |
495 | + } |
496 | + |
497 | + try |
498 | + { |
499 | + ShutdownException e("Finalization problem"); |
500 | + e.remember(ep); |
501 | + throw e; |
502 | + } |
503 | + catch (Exception const& e) |
504 | + { |
505 | + string reason = e.to_string(); |
506 | + EXPECT_EQ("unity::ShutdownException: Finalization problem\n" |
507 | + " Exception history:\n" |
508 | + " Exception #1:\n" |
509 | + " unity::InvalidArgumentException: b() threw:\n" |
510 | + " unity::InvalidArgumentException: a() threw:\n" |
511 | + " std::bad_alloc\n" |
512 | + " Exception #2:\n" |
513 | + " unity::InvalidArgumentException: throw_N() threw:\n" |
514 | + " std::nested_exception:\n" |
515 | + " unity::InvalidArgumentException: a() threw:\n" |
516 | + " std::bad_alloc", e.to_string()); |
517 | + } |
518 | + } |
519 | + |
520 | + // Same test, but this time with history in a nested exception. |
521 | + |
522 | + { |
523 | + exception_ptr ep; |
524 | + try |
525 | + { |
526 | + c(); |
527 | + } |
528 | + catch (Exception& e) |
529 | + { |
530 | + ep = e.remember(ep); |
531 | + } |
532 | + try |
533 | + { |
534 | + f(); |
535 | + } |
536 | + catch (Exception &e) |
537 | + { |
538 | + ep = e.remember(ep); |
539 | + } |
540 | + |
541 | + try |
542 | + { |
543 | + try |
544 | + { |
545 | + ShutdownException e("Finalization problem"); |
546 | + e.remember(ep); |
547 | + throw e; |
548 | + } |
549 | + catch (Exception &e) |
550 | + { |
551 | + throw ShutdownException("Cannot finalize"); |
552 | + } |
553 | + } |
554 | + catch (Exception const& e) |
555 | + { |
556 | + EXPECT_EQ("unity::ShutdownException: Cannot finalize:\n" |
557 | + " unity::ShutdownException: Finalization problem\n" |
558 | + " Exception history:\n" |
559 | + " Exception #1:\n" |
560 | + " unity::InvalidArgumentException: b() threw:\n" |
561 | + " unity::InvalidArgumentException: a() threw:\n" |
562 | + " std::bad_alloc\n" |
563 | + " Exception #2:\n" |
564 | + " unity::InvalidArgumentException: throw_N() threw:\n" |
565 | + " std::nested_exception:\n" |
566 | + " unity::InvalidArgumentException: a() threw:\n" |
567 | + " std::bad_alloc", e.to_string()); |
568 | + } |
569 | + } |
570 | +} |
571 | + |
572 | +// |
573 | +// Tests for the state of concrete derived exceptions follow. |
574 | +// |
575 | + |
576 | +TEST(SyscallException, state) |
577 | +{ |
578 | + // Check that we correctly mention the error code. |
579 | + |
580 | + { |
581 | + SyscallException e("without error", 0); |
582 | + EXPECT_EQ("unity::SyscallException: without error (errno = 0)", e.to_string()); |
583 | + SyscallException e2("blah", 0); |
584 | + e2 = e; |
585 | + EXPECT_EQ(e.reason(), e2.reason()); |
586 | + } |
587 | + |
588 | + { |
589 | + SyscallException e("with error code", 42); |
590 | + EXPECT_EQ("unity::SyscallException: with error code (errno = 42)", e.to_string()); |
591 | + EXPECT_EQ(e.error(), 42); |
592 | + EXPECT_THROW(rethrow_exception(e.self()), SyscallException); |
593 | + } |
594 | + |
595 | + { |
596 | + SyscallException e("with errno", EPERM); |
597 | + EXPECT_EQ("unity::SyscallException: with errno (errno = 1)", e.to_string()); |
598 | + EXPECT_EQ(e.error(), EPERM); |
599 | + EXPECT_THROW(rethrow_exception(e.self()), SyscallException); |
600 | + } |
601 | +} |
602 | + |
603 | +TEST(InvalidArgumentException, state) |
604 | +{ |
605 | + { |
606 | + InvalidArgumentException e("bad arg"); |
607 | + EXPECT_STREQ("unity::InvalidArgumentException", e.what()); |
608 | + EXPECT_THROW(rethrow_exception(e.self()), InvalidArgumentException); |
609 | + InvalidArgumentException e2("blah"); |
610 | + e2 = e; |
611 | + EXPECT_EQ(e.reason(), e2.reason()); |
612 | + } |
613 | +} |
614 | + |
615 | +TEST(LogicException, state) |
616 | +{ |
617 | + { |
618 | + LogicException e("You shouldn't have done that!"); |
619 | + EXPECT_STREQ("unity::LogicException", e.what()); |
620 | + EXPECT_THROW(rethrow_exception(e.self()), LogicException); |
621 | + LogicException e2("blah"); |
622 | + e2 = e; |
623 | + EXPECT_EQ(e.reason(), e2.reason()); |
624 | + } |
625 | +} |
626 | + |
627 | +TEST(ShutdownException, state) |
628 | +{ |
629 | + { |
630 | + ShutdownException e("Need some kicks"); |
631 | + EXPECT_STREQ("unity::ShutdownException", e.what()); |
632 | + EXPECT_THROW(rethrow_exception(e.self()), ShutdownException); |
633 | + ShutdownException e2("blah"); |
634 | + e2 = e; |
635 | + EXPECT_EQ(e.reason(), e2.reason()); |
636 | + } |
637 | +} |
638 | + |
639 | +TEST(FileException, state) |
640 | +{ |
641 | + { |
642 | + FileException e("File error", 0); |
643 | + EXPECT_EQ("File error", e.reason()); |
644 | + EXPECT_STREQ("unity::FileException", e.what()); |
645 | + EXPECT_EQ(0, e.error()); |
646 | + EXPECT_THROW(rethrow_exception(e.self()), FileException); |
647 | + FileException e2("blah", 0); |
648 | + e2 = e; |
649 | + EXPECT_EQ(e.reason(), e2.reason()); |
650 | + EXPECT_EQ(e.error(), e2.error()); |
651 | + } |
652 | + |
653 | + { |
654 | + FileException e("File error", 42); |
655 | + EXPECT_EQ("File error (errno = 42)", e.reason()); |
656 | + EXPECT_STREQ("unity::FileException", e.what()); |
657 | + EXPECT_EQ(42, e.error()); |
658 | + EXPECT_THROW(rethrow_exception(e.self()), FileException); |
659 | + FileException e2("blah", 0); |
660 | + e2 = e; |
661 | + EXPECT_EQ(e.reason(), e2.reason()); |
662 | + EXPECT_EQ(e.error(), e2.error()); |
663 | + } |
664 | +} |
665 | + |
666 | +TEST(ResourceException, state) |
667 | +{ |
668 | + { |
669 | + ResourceException e("Need some kicks"); |
670 | + EXPECT_STREQ("unity::ResourceException", e.what()); |
671 | + EXPECT_THROW(rethrow_exception(e.self()), ResourceException); |
672 | + ResourceException e2("blah"); |
673 | + e2 = e; |
674 | + EXPECT_EQ(e.reason(), e2.reason()); |
675 | + } |
676 | +} |
677 | + |
678 | +// Dynamic allocation to get around bogus function coverage reports by gcov. |
679 | + |
680 | +TEST(Exceptions, dynamic) |
681 | +{ |
682 | + { |
683 | + SyscallException* ep = new SyscallException("Hello", 0); |
684 | + delete ep; |
685 | + } |
686 | + |
687 | + { |
688 | + InvalidArgumentException* ep = new InvalidArgumentException("Hello"); |
689 | + delete ep; |
690 | + } |
691 | + |
692 | + { |
693 | + LogicException* ep = new LogicException("Hello"); |
694 | + delete ep; |
695 | + } |
696 | + |
697 | + { |
698 | + ShutdownException* ep = new ShutdownException("Hello"); |
699 | + delete ep; |
700 | + } |
701 | + |
702 | + { |
703 | + FileException* ep = new FileException("Hello", 0); |
704 | + delete ep; |
705 | + } |
706 | + |
707 | + { |
708 | + ResourceException* ep = new ResourceException("Hello"); |
709 | + delete ep; |
710 | + } |
711 | +} |
712 | |
713 | === added directory 'tests/gtest/unity/api' |
714 | === added file 'tests/gtest/unity/api/CMakeLists.txt' |
715 | --- tests/gtest/unity/api/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
716 | +++ tests/gtest/unity/api/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
717 | @@ -0,0 +1,19 @@ |
718 | +# |
719 | +# Copyright (C) 2013 Canonical Ltd |
720 | +# |
721 | +# This program is free software: you can redistribute it and/or modify |
722 | +# it under the terms of the GNU General Public License version 3 as |
723 | +# published by the Free Software Foundation. |
724 | +# |
725 | +# This program is distributed in the hope that it will be useful, |
726 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
727 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
728 | +# GNU General Public License for more details. |
729 | +# |
730 | +# You should have received a copy of the GNU General Public License |
731 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
732 | +# |
733 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
734 | +# |
735 | + |
736 | +add_subdirectory(Version) |
737 | |
738 | === added directory 'tests/gtest/unity/api/Version' |
739 | === added file 'tests/gtest/unity/api/Version/CMakeLists.txt' |
740 | --- tests/gtest/unity/api/Version/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
741 | +++ tests/gtest/unity/api/Version/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
742 | @@ -0,0 +1,22 @@ |
743 | +# |
744 | +# Copyright (C) 2013 Canonical Ltd |
745 | +# |
746 | +# This program is free software: you can redistribute it and/or modify |
747 | +# it under the terms of the GNU General Public License version 3 as |
748 | +# published by the Free Software Foundation. |
749 | +# |
750 | +# This program is distributed in the hope that it will be useful, |
751 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
752 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
753 | +# GNU General Public License for more details. |
754 | +# |
755 | +# You should have received a copy of the GNU General Public License |
756 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
757 | +# |
758 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
759 | +# |
760 | + |
761 | +add_executable(Version_test Version_test.cpp) |
762 | +target_link_libraries(Version_test ${LIBS} ${TESTLIBS}) |
763 | + |
764 | +add_test(Version Version_test) |
765 | |
766 | === added file 'tests/gtest/unity/api/Version/Version_test.cpp' |
767 | --- tests/gtest/unity/api/Version/Version_test.cpp 1970-01-01 00:00:00 +0000 |
768 | +++ tests/gtest/unity/api/Version/Version_test.cpp 2013-04-10 02:45:26 +0000 |
769 | @@ -0,0 +1,31 @@ |
770 | +/* |
771 | + * Copyright (C) 2013 Canonical Ltd |
772 | + * |
773 | + * This program is free software: you can redistribute it and/or modify |
774 | + * it under the terms of the GNU General Public License version 3 as |
775 | + * published by the Free Software Foundation. |
776 | + * |
777 | + * This program is distributed in the hope that it will be useful, |
778 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
779 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
780 | + * GNU General Public License for more details. |
781 | + * |
782 | + * You should have received a copy of the GNU General Public License |
783 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
784 | + * |
785 | + * Authored by: Michi Henning <michi.henning@canonical.com> |
786 | + */ |
787 | + |
788 | +#include <unity/api/Version.h> |
789 | + |
790 | +#include <gtest/gtest.h> |
791 | + |
792 | +using namespace unity::api; |
793 | + |
794 | +TEST(Version, basic) |
795 | +{ |
796 | + EXPECT_EQ(Version::major_version(), UNITY_API_VERSION_MAJOR); |
797 | + EXPECT_EQ(Version::minor_version(), UNITY_API_VERSION_MINOR); |
798 | + EXPECT_EQ(Version::micro_version(), UNITY_API_VERSION_MICRO); |
799 | + EXPECT_STREQ(Version::str(), UNITY_API_VERSION_STRING); |
800 | +} |
801 | |
802 | === added directory 'tests/gtest/unity/scopes' |
803 | === added file 'tests/gtest/unity/scopes/CMakeLists.txt' |
804 | --- tests/gtest/unity/scopes/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
805 | +++ tests/gtest/unity/scopes/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
806 | @@ -0,0 +1,18 @@ |
807 | +# |
808 | +# Copyright (C) 2013 Canonical Ltd |
809 | +# |
810 | +# This program is free software: you can redistribute it and/or modify |
811 | +# it under the terms of the GNU General Public License version 3 as |
812 | +# published by the Free Software Foundation. |
813 | +# |
814 | +# This program is distributed in the hope that it will be useful, |
815 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
816 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
817 | +# GNU General Public License for more details. |
818 | +# |
819 | +# You should have received a copy of the GNU General Public License |
820 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
821 | +# |
822 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
823 | +# |
824 | + |
825 | |
826 | === added directory 'tests/gtest/unity/util' |
827 | === added file 'tests/gtest/unity/util/CMakeLists.txt' |
828 | --- tests/gtest/unity/util/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
829 | +++ tests/gtest/unity/util/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
830 | @@ -0,0 +1,22 @@ |
831 | +# |
832 | +# Copyright (C) 2013 Canonical Ltd |
833 | +# |
834 | +# This program is free software: you can redistribute it and/or modify |
835 | +# it under the terms of the GNU General Public License version 3 as |
836 | +# published by the Free Software Foundation. |
837 | +# |
838 | +# This program is distributed in the hope that it will be useful, |
839 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
840 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
841 | +# GNU General Public License for more details. |
842 | +# |
843 | +# You should have received a copy of the GNU General Public License |
844 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
845 | +# |
846 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
847 | +# |
848 | + |
849 | +add_subdirectory(Daemon) |
850 | +add_subdirectory(DefinesPtrs) |
851 | +add_subdirectory(FileIO) |
852 | +add_subdirectory(ResourcePtr) |
853 | |
854 | === added directory 'tests/gtest/unity/util/Daemon' |
855 | === added file 'tests/gtest/unity/util/Daemon/CMakeLists.txt' |
856 | --- tests/gtest/unity/util/Daemon/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
857 | +++ tests/gtest/unity/util/Daemon/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
858 | @@ -0,0 +1,22 @@ |
859 | +# |
860 | +# Copyright (C) 2013 Canonical Ltd |
861 | +# |
862 | +# This program is free software: you can redistribute it and/or modify |
863 | +# it under the terms of the GNU General Public License version 3 as |
864 | +# published by the Free Software Foundation. |
865 | +# |
866 | +# This program is distributed in the hope that it will be useful, |
867 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
868 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
869 | +# GNU General Public License for more details. |
870 | +# |
871 | +# You should have received a copy of the GNU General Public License |
872 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
873 | +# |
874 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
875 | +# |
876 | + |
877 | +add_executable(Daemon_test Daemon_test.cpp) |
878 | +target_link_libraries(Daemon_test ${LIBS} ${TESTLIBS}) |
879 | + |
880 | +add_test(Daemon ${CMAKE_CURRENT_SOURCE_DIR}/daemon-tester.py ${CMAKE_CURRENT_BINARY_DIR}/Daemon_test) |
881 | |
882 | === added file 'tests/gtest/unity/util/Daemon/Daemon_test.cpp' |
883 | --- tests/gtest/unity/util/Daemon/Daemon_test.cpp 1970-01-01 00:00:00 +0000 |
884 | +++ tests/gtest/unity/util/Daemon/Daemon_test.cpp 2013-04-10 02:45:26 +0000 |
885 | @@ -0,0 +1,353 @@ |
886 | +/* |
887 | + * Copyright (C) 2013 Canonical Ltd |
888 | + * |
889 | + * This program is free software: you can redistribute it and/or modify |
890 | + * it under the terms of the GNU General Public License version 3 as |
891 | + * published by the Free Software Foundation. |
892 | + * |
893 | + * This program is distributed in the hope that it will be useful, |
894 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
895 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
896 | + * GNU General Public License for more details. |
897 | + * |
898 | + * You should have received a copy of the GNU General Public License |
899 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
900 | + * |
901 | + * Authored by: Michi Henning <michi.henning@canonical.com> |
902 | + */ |
903 | + |
904 | +#include <unity/util/Daemon.h> |
905 | +#include <unity/UnityExceptions.h> |
906 | + |
907 | +#include <fcntl.h> |
908 | +#include <sys/param.h> |
909 | +#include <gtest/gtest.h> |
910 | + |
911 | +using namespace std; |
912 | +using namespace unity; |
913 | +using namespace unity::util; |
914 | + |
915 | +// |
916 | +// The daemonize_me() method forks and lets the parent exit with zero exit status. In addition, it connects |
917 | +// the standard file descriptors to /dev/null. This means we cannot use gtest EXPECT macros to test because, |
918 | +// as far as gtest is concerned, everything worked just fine. |
919 | +// |
920 | +// To deal with this, we create a file Daemon_test.out in the directory the test runs in. If the file is |
921 | +// empty after the test, we know that the test succeeded. Otherwise, it contains any failure messages |
922 | +// that were detected. |
923 | +// |
924 | + |
925 | +char const* error_file = "Daemon_test.out"; |
926 | + |
927 | +int |
928 | +clear_error_file() |
929 | +{ |
930 | + mode_t old_umask = umask(0); // Make sure we have mode rw-rw-rw for the file, otherwise different |
931 | + // people running the test can have problems. |
932 | + int fd = open(error_file, O_CREAT | O_TRUNC | O_WRONLY, 0666); |
933 | + umask(old_umask); |
934 | + close(fd); |
935 | + return fd; |
936 | +} |
937 | + |
938 | +// Write the supplied message into the error file, preceded by file name and line number. |
939 | +// We open and close the file for each new line because daemonize_me() may close file descriptors, |
940 | +// so we cannot keep the error file open while the various tests are running. We use a raw write() system |
941 | +// call to write the messages, so there are no buffering issues, even if we crash unexpectedly. |
942 | + |
943 | +void |
944 | +error(string const& file, int line, string const& msg) |
945 | +{ |
946 | + int fd = open(error_file, O_APPEND | O_WRONLY); |
947 | + if (fd == -1) |
948 | + { |
949 | + // Little we can do here, seeing that we are a daemon. |
950 | + abort(); |
951 | + } |
952 | + ostringstream s; |
953 | + s << file << ":" << line; |
954 | + if (!msg.empty()) |
955 | + { |
956 | + s << ": " << msg; |
957 | + } |
958 | + s << endl; |
959 | + string l = s.str(); |
960 | + int bytes __attribute__((unused)) |
961 | + = write(fd, l.c_str(), l.size()); // Need to use return value to stop warning from gcc. |
962 | + close(fd); |
963 | +} |
964 | + |
965 | +// Check that the standard three file descriptors are connected to /dev/null. |
966 | + |
967 | +void |
968 | +check_std_descriptors() |
969 | +{ |
970 | + struct stat null_st; |
971 | + if (stat("/dev/null", &null_st) == -1) |
972 | + { |
973 | + error(__FILE__, __LINE__, "stat() failed"); |
974 | + } |
975 | + |
976 | + struct stat st; |
977 | + |
978 | + if (fstat(0, &st) == -1) |
979 | + { |
980 | + error(__FILE__, __LINE__, "fstat() failed"); |
981 | + } |
982 | + if (st.st_dev != null_st.st_dev || st.st_ino != null_st.st_ino) |
983 | + { |
984 | + error(__FILE__, __LINE__, "stdin not opened to /dev/null"); |
985 | + } |
986 | + |
987 | + if (fstat(1, &st) == -1) |
988 | + { |
989 | + error(__FILE__, __LINE__, "fstat() failed"); |
990 | + } |
991 | + if (st.st_dev != null_st.st_dev || st.st_ino != null_st.st_ino) |
992 | + { |
993 | + error(__FILE__, __LINE__, "stdout not opened to /dev/null"); |
994 | + } |
995 | + |
996 | + if (fstat(2, &st) == -1) |
997 | + { |
998 | + error(__FILE__, __LINE__, "fstat() failed"); |
999 | + } |
1000 | + if (st.st_dev != null_st.st_dev || st.st_ino != null_st.st_ino) |
1001 | + { |
1002 | + error(__FILE__, __LINE__, "stderr not opened to /dev/null"); |
1003 | + } |
1004 | +} |
1005 | + |
1006 | +// Check if fd is a descriptor for an open file. |
1007 | + |
1008 | +bool |
1009 | +is_open(int fd) |
1010 | +{ |
1011 | + struct stat st; |
1012 | + return fstat(fd, &st) != -1; |
1013 | +} |
1014 | + |
1015 | +string |
1016 | +get_cwd() |
1017 | +{ |
1018 | + char* wd = get_current_dir_name(); |
1019 | + if (wd == nullptr) |
1020 | + { |
1021 | + abort(); |
1022 | + } |
1023 | + string dir = wd; |
1024 | + free(wd); |
1025 | + return dir; |
1026 | +} |
1027 | + |
1028 | +TEST(Daemon, basic) |
1029 | +{ |
1030 | + // Clear the error file. We do this only once, for this first test, so we start out with an empty file. |
1031 | + // Any test failures reported hereafter append to the file. |
1032 | + |
1033 | + if (clear_error_file() == -1) |
1034 | + { |
1035 | + cerr << "Daemon_test.cpp: cannot clear error file" << endl; |
1036 | + abort(); |
1037 | + } |
1038 | + |
1039 | + Daemon::UPtr d = Daemon::create(); |
1040 | + |
1041 | + int pid = getpid(); |
1042 | + |
1043 | + // Open a file so we can check that the file is still open after daemonizing. |
1044 | + |
1045 | + int fd = open(".", O_RDONLY); |
1046 | + if (fd == -1) |
1047 | + { |
1048 | + abort(); |
1049 | + } |
1050 | + |
1051 | + d->daemonize_me(); |
1052 | + EXPECT_TRUE(pid != getpid()); // We really did fork... |
1053 | + |
1054 | + check_std_descriptors(); |
1055 | + |
1056 | + if (!is_open(fd)) |
1057 | + { |
1058 | + error(__FILE__, __LINE__, "test file closed, should be open"); |
1059 | + } |
1060 | + |
1061 | + // Daemonize again, asking for open files to be closed. The file we opened earlier should be closed. |
1062 | + |
1063 | + d->close_fds(); |
1064 | + d->daemonize_me(); |
1065 | + check_std_descriptors(); |
1066 | + |
1067 | + if (is_open(fd)) |
1068 | + { |
1069 | + error(__FILE__, __LINE__, "test file open, should be closed"); |
1070 | + } |
1071 | +} |
1072 | + |
1073 | +// Dummy signal handler |
1074 | + |
1075 | +void |
1076 | +usr2_handler(int) |
1077 | +{ |
1078 | +} |
1079 | + |
1080 | +TEST(Daemon, signals) |
1081 | +{ |
1082 | + // Check that signal mask is changed or left alone as appropriate. |
1083 | + |
1084 | + Daemon::UPtr d = Daemon::create(); |
1085 | + |
1086 | + // Set SIGUSR1 to be ignored and set SIGUSR2 to be caught. |
1087 | + |
1088 | + struct sigaction usr1_action; |
1089 | + memset(&usr1_action, 0, sizeof(usr1_action)); // To stop valgrind complaints |
1090 | + usr1_action.sa_handler = SIG_IGN; |
1091 | + if (sigaction(SIGUSR1, &usr1_action, nullptr) == -1) |
1092 | + { |
1093 | + error(__FILE__, __LINE__, "cannot ignore SIGUSR1"); |
1094 | + abort(); |
1095 | + } |
1096 | + |
1097 | + struct sigaction usr2_action; |
1098 | + memset(&usr2_action, 0, sizeof(usr1_action)); // To stop valgrind complaints |
1099 | + usr2_action.sa_handler = usr2_handler; |
1100 | + if (sigaction(SIGUSR2, &usr2_action, nullptr) == -1) |
1101 | + { |
1102 | + error(__FILE__, __LINE__, "cannot catch SIGUSR2"); |
1103 | + abort(); |
1104 | + } |
1105 | + |
1106 | + d->daemonize_me(); |
1107 | + |
1108 | + struct sigaction prev_action; |
1109 | + |
1110 | + if (sigaction(SIGUSR1, &usr1_action, &prev_action) == -1) |
1111 | + { |
1112 | + error(__FILE__, __LINE__, "cannot restore SIGUSR1"); |
1113 | + abort(); |
1114 | + } |
1115 | + if (prev_action.sa_handler != usr1_action.sa_handler) |
1116 | + { |
1117 | + error(__FILE__, __LINE__, "SIGUSR1 should have been left alone, but wasn't"); |
1118 | + } |
1119 | + |
1120 | + if (sigaction(SIGUSR2, &usr2_action, &prev_action) == -1) |
1121 | + { |
1122 | + error(__FILE__, __LINE__, "cannot restore SIGUSR2"); |
1123 | + abort(); |
1124 | + } |
1125 | + if (prev_action.sa_handler != usr2_action.sa_handler) |
1126 | + { |
1127 | + error(__FILE__, __LINE__, "SIGUSR2 should have been left alone, but wasn't"); |
1128 | + } |
1129 | + |
1130 | + // Daemonize again, resetting signals, so we can check that they are at the defaults. |
1131 | + |
1132 | + d->reset_signals(); |
1133 | + d->daemonize_me(); |
1134 | + |
1135 | + if (sigaction(SIGUSR1, &usr1_action, &prev_action) == -1) |
1136 | + { |
1137 | + error(__FILE__, __LINE__, "cannot set SIGUSR1"); |
1138 | + abort(); |
1139 | + } |
1140 | + if (prev_action.sa_handler != SIG_DFL) |
1141 | + { |
1142 | + error(__FILE__, __LINE__, "SIGUSR1 should have been reset, but wasn't"); |
1143 | + } |
1144 | + |
1145 | + if (sigaction(SIGUSR2, &usr2_action, &prev_action) == -1) |
1146 | + { |
1147 | + error(__FILE__, __LINE__, "cannot set SIGUSR2"); |
1148 | + abort(); |
1149 | + } |
1150 | + if (prev_action.sa_handler != SIG_DFL) |
1151 | + { |
1152 | + error(__FILE__, __LINE__, "SIGUSR2 should have been reset, but wasn't"); |
1153 | + } |
1154 | +} |
1155 | + |
1156 | +TEST(Daemon, umask) |
1157 | +{ |
1158 | + // Check that umask is changed or left alone as appropriate. |
1159 | + |
1160 | + Daemon::UPtr d = Daemon::create(); |
1161 | + |
1162 | + umask(027); |
1163 | + d->daemonize_me(); |
1164 | + mode_t new_umask = umask(022); |
1165 | + if (new_umask != 027) |
1166 | + { |
1167 | + error(__FILE__, __LINE__, "umask was changed, but should not have been"); |
1168 | + } |
1169 | + |
1170 | + // Daemonize again, changing umask, so we can check that the umask was indeed changed. |
1171 | + |
1172 | + d->set_umask(0); |
1173 | + d->daemonize_me(); |
1174 | + new_umask = umask(027); |
1175 | + if (new_umask != 0) |
1176 | + { |
1177 | + error(__FILE__, __LINE__, "umask was not changed, but should have been"); |
1178 | + } |
1179 | +} |
1180 | + |
1181 | +TEST(Daemon, dir) |
1182 | +{ |
1183 | + // Check that working directory is changed or left alone as appropriate. |
1184 | + |
1185 | + Daemon::UPtr d = Daemon::create(); |
1186 | + |
1187 | + string old_wd = get_cwd(); |
1188 | + d->daemonize_me(); |
1189 | + string new_wd = get_cwd(); |
1190 | + if (new_wd != old_wd) |
1191 | + { |
1192 | + error(__FILE__, __LINE__, "working dir was changed, but should not have been"); |
1193 | + } |
1194 | + |
1195 | + // Daemonize again, changing directory, so we can check that the directory was indeed changed. |
1196 | + |
1197 | + d->set_working_directory("/"); |
1198 | + d->daemonize_me(); |
1199 | + new_wd = get_cwd(); |
1200 | + |
1201 | + if (new_wd != "/") |
1202 | + { |
1203 | + error(__FILE__, __LINE__, "working dir was not changed, but should have been"); |
1204 | + } |
1205 | + |
1206 | + // Check that errors in setting working directory are correctly diagnosed. |
1207 | + |
1208 | + d->set_working_directory("/no_such_directory"); |
1209 | + try |
1210 | + { |
1211 | + d->daemonize_me(); |
1212 | + error(__FILE__, __LINE__, "daemonize_me() should have thrown, but didn't"); |
1213 | + |
1214 | + FAIL(); |
1215 | + } |
1216 | + catch (SyscallException const& e) |
1217 | + { |
1218 | + if (e.to_string() != "unity::SyscallException: chdir(\"/no_such_directory\") failed (errno = 2)") |
1219 | + { |
1220 | + error(__FILE__, __LINE__, "wrong message for SyscallException"); |
1221 | + } |
1222 | + } |
1223 | +} |
1224 | + |
1225 | +TEST(Daemon, tty) |
1226 | +{ |
1227 | + // Check that the process cannot re-acquire a control terminal |
1228 | + |
1229 | + Daemon::UPtr d = Daemon::create(); |
1230 | + |
1231 | + d->daemonize_me(); |
1232 | + |
1233 | + int fd = open("/dev/tty", O_RDWR); |
1234 | + if (fd != -1) |
1235 | + { |
1236 | + error(__FILE__, __LINE__, "re-acquired control terminal but should not have been able to"); |
1237 | + } |
1238 | +} |
1239 | |
1240 | === added file 'tests/gtest/unity/util/Daemon/daemon-tester.py' |
1241 | --- tests/gtest/unity/util/Daemon/daemon-tester.py 1970-01-01 00:00:00 +0000 |
1242 | +++ tests/gtest/unity/util/Daemon/daemon-tester.py 2013-04-10 02:45:26 +0000 |
1243 | @@ -0,0 +1,58 @@ |
1244 | +#! /usr/bin/env python |
1245 | + |
1246 | +# |
1247 | +# Copyright (C) 2013 Canonical Ltd |
1248 | +# |
1249 | +# This program is free software: you can redistribute it and/or modify |
1250 | +# it under the terms of the GNU General Public License version 3 as |
1251 | +# published by the Free Software Foundation. |
1252 | +# |
1253 | +# This program is distributed in the hope that it will be useful, |
1254 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1255 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1256 | +# GNU General Public License for more details. |
1257 | +# |
1258 | +# You should have received a copy of the GNU General Public License |
1259 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1260 | +# |
1261 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
1262 | +# |
1263 | + |
1264 | +# |
1265 | +# Little test driver program to execute the Daemon_test binary, wait a little, and check |
1266 | +# whether the test reported any errors. If the file /tmp/Daemon_test.out has non-zero size, |
1267 | +# the test run produced errors. |
1268 | +# |
1269 | + |
1270 | +import argparse |
1271 | +import os |
1272 | +import sys |
1273 | +import subprocess |
1274 | +import time |
1275 | + |
1276 | +def run_daemon(path): |
1277 | + status = subprocess.call(path) |
1278 | + if status != 0: |
1279 | + exit("cannot run " + path) |
1280 | + time.sleep(1) # Give process time to complete |
1281 | + |
1282 | +# |
1283 | +# Main program. |
1284 | +# |
1285 | + |
1286 | +parser = argparse.ArgumentParser(description = 'Test driver for Daemon_test') |
1287 | +parser.add_argument('Daemon_test', nargs = 1, help = 'Full path to Daemon_test executable') |
1288 | + |
1289 | +args = parser.parse_args() |
1290 | +progname = parser.prog |
1291 | + |
1292 | +daemon = args.Daemon_test[0] |
1293 | +run_daemon(daemon) |
1294 | + |
1295 | +size = os.stat("Daemon_test.out").st_size |
1296 | +if size == 0: |
1297 | + exit(0) |
1298 | + |
1299 | +with open("Daemon_test.out", 'r') as file: |
1300 | + sys.stderr.write(file.read()) |
1301 | + exit(1) |
1302 | |
1303 | === added directory 'tests/gtest/unity/util/DefinesPtrs' |
1304 | === added file 'tests/gtest/unity/util/DefinesPtrs/CMakeLists.txt' |
1305 | --- tests/gtest/unity/util/DefinesPtrs/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1306 | +++ tests/gtest/unity/util/DefinesPtrs/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
1307 | @@ -0,0 +1,22 @@ |
1308 | +# |
1309 | +# Copyright (C) 2013 Canonical Ltd |
1310 | +# |
1311 | +# This program is free software: you can redistribute it and/or modify |
1312 | +# it under the terms of the GNU General Public License version 3 as |
1313 | +# published by the Free Software Foundation. |
1314 | +# |
1315 | +# This program is distributed in the hope that it will be useful, |
1316 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1317 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1318 | +# GNU General Public License for more details. |
1319 | +# |
1320 | +# You should have received a copy of the GNU General Public License |
1321 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1322 | +# |
1323 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
1324 | +# |
1325 | + |
1326 | +add_executable(DefinesPtrs_test DefinesPtrs_test.cpp) |
1327 | +target_link_libraries(DefinesPtrs_test ${LIBS} ${TESTLIBS}) |
1328 | + |
1329 | +add_test(DefinesPtrs DefinesPtrs_test) |
1330 | |
1331 | === added file 'tests/gtest/unity/util/DefinesPtrs/DefinesPtrs_test.cpp' |
1332 | --- tests/gtest/unity/util/DefinesPtrs/DefinesPtrs_test.cpp 1970-01-01 00:00:00 +0000 |
1333 | +++ tests/gtest/unity/util/DefinesPtrs/DefinesPtrs_test.cpp 2013-04-10 02:45:26 +0000 |
1334 | @@ -0,0 +1,45 @@ |
1335 | +/* |
1336 | + * Copyright (C) 2013 Canonical Ltd |
1337 | + * |
1338 | + * This program is free software: you can redistribute it and/or modify |
1339 | + * it under the terms of the GNU General Public License version 3 as |
1340 | + * published by the Free Software Foundation. |
1341 | + * |
1342 | + * This program is distributed in the hope that it will be useful, |
1343 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1344 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1345 | + * GNU General Public License for more details. |
1346 | + * |
1347 | + * You should have received a copy of the GNU General Public License |
1348 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1349 | + * |
1350 | + * Authored by: Michi Henning <michi.henning@canonical.com> |
1351 | + */ |
1352 | + |
1353 | +#include <unity/util/DefinesPtrs.h> |
1354 | +#include <unity/util/NonCopyable.h> |
1355 | + |
1356 | +#include <gtest/gtest.h> |
1357 | + |
1358 | +using namespace unity::util; |
1359 | + |
1360 | +class MyClass : public DefinesPtrs<MyClass>, private NonCopyable |
1361 | +{ |
1362 | +public: |
1363 | + static SPtr create() |
1364 | + { |
1365 | + return SPtr(new MyClass); |
1366 | + } |
1367 | + |
1368 | +private: |
1369 | + MyClass() |
1370 | + { |
1371 | + } |
1372 | +}; |
1373 | + |
1374 | +TEST(DefinesPtrs, basic) |
1375 | +{ |
1376 | + // No real test here. This is just so we get function coverage for the coverage tests. |
1377 | + |
1378 | + MyClass::SPtr p = MyClass::create(); |
1379 | +} |
1380 | |
1381 | === added directory 'tests/gtest/unity/util/FileIO' |
1382 | === added file 'tests/gtest/unity/util/FileIO/CMakeLists.txt' |
1383 | --- tests/gtest/unity/util/FileIO/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1384 | +++ tests/gtest/unity/util/FileIO/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
1385 | @@ -0,0 +1,22 @@ |
1386 | +# |
1387 | +# Copyright (C) 2013 Canonical Ltd |
1388 | +# |
1389 | +# This program is free software: you can redistribute it and/or modify |
1390 | +# it under the terms of the GNU General Public License version 3 as |
1391 | +# published by the Free Software Foundation. |
1392 | +# |
1393 | +# This program is distributed in the hope that it will be useful, |
1394 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1395 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1396 | +# GNU General Public License for more details. |
1397 | +# |
1398 | +# You should have received a copy of the GNU General Public License |
1399 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1400 | +# |
1401 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
1402 | +# |
1403 | + |
1404 | +add_executable(FileIO_test FileIO_test.cpp) |
1405 | +target_link_libraries(FileIO_test ${LIBS} ${TESTLIBS}) |
1406 | + |
1407 | +add_test(FileIO FileIO_test) |
1408 | |
1409 | === added file 'tests/gtest/unity/util/FileIO/FileIO_test.cpp' |
1410 | --- tests/gtest/unity/util/FileIO/FileIO_test.cpp 1970-01-01 00:00:00 +0000 |
1411 | +++ tests/gtest/unity/util/FileIO/FileIO_test.cpp 2013-04-10 02:45:26 +0000 |
1412 | @@ -0,0 +1,71 @@ |
1413 | +/* |
1414 | + * Copyright (C) 2013 Canonical Ltd |
1415 | + * |
1416 | + * This program is free software: you can redistribute it and/or modify |
1417 | + * it under the terms of the GNU General Public License version 3 as |
1418 | + * published by the Free Software Foundation. |
1419 | + * |
1420 | + * This program is distributed in the hope that it will be useful, |
1421 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1422 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1423 | + * GNU General Public License for more details. |
1424 | + * |
1425 | + * You should have received a copy of the GNU General Public License |
1426 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1427 | + * |
1428 | + * Authored by: Michi Henning <michi.henning@canonical.com> |
1429 | + */ |
1430 | + |
1431 | +#include <unity/UnityExceptions.h> |
1432 | +#include <unity/util/FileIO.h> |
1433 | + |
1434 | +#include <gtest/gtest.h> |
1435 | + |
1436 | +#include <fstream> |
1437 | + |
1438 | +using namespace std; |
1439 | +using namespace unity; |
1440 | +using namespace unity::util; |
1441 | + |
1442 | +TEST(FileIO, basic) |
1443 | +{ |
1444 | + int i __attribute__((unused)) |
1445 | + = system("rm -f testfile; echo \"some chars\" >testfile"); |
1446 | + |
1447 | + string s = read_text_file("testfile"); |
1448 | + EXPECT_EQ("some chars\n", s); |
1449 | + |
1450 | + vector<uint8_t> v = read_binary_file("testfile"); |
1451 | + string contents("some chars\n"); |
1452 | + EXPECT_EQ(vector<uint8_t>(contents.begin(), contents.end()), v); |
1453 | + |
1454 | + system("rm -fr empty; >empty"); |
1455 | + s = read_text_file("empty"); |
1456 | + EXPECT_TRUE(s.empty()); |
1457 | +} |
1458 | + |
1459 | +TEST(FileIO, exceptions) |
1460 | +{ |
1461 | + try |
1462 | + { |
1463 | + read_text_file("no_such_file"); |
1464 | + FAIL(); |
1465 | + } |
1466 | + catch (FileException const& e) |
1467 | + { |
1468 | + EXPECT_EQ("unity::FileException: cannot open \"no_such_file\": No such file or directory (errno = 2)", |
1469 | + e.to_string()); |
1470 | + } |
1471 | + |
1472 | + try |
1473 | + { |
1474 | + int i __attribute__((unused)) |
1475 | + = system("rm -fr testdir; mkdir testdir"); |
1476 | + read_text_file("testdir"); |
1477 | + FAIL(); |
1478 | + } |
1479 | + catch (FileException const& e) |
1480 | + { |
1481 | + EXPECT_EQ("unity::FileException: \"testdir\" is not a regular file", e.to_string()); |
1482 | + } |
1483 | +} |
1484 | |
1485 | === added directory 'tests/gtest/unity/util/ResourcePtr' |
1486 | === added file 'tests/gtest/unity/util/ResourcePtr/CMakeLists.txt' |
1487 | --- tests/gtest/unity/util/ResourcePtr/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1488 | +++ tests/gtest/unity/util/ResourcePtr/CMakeLists.txt 2013-04-10 02:45:26 +0000 |
1489 | @@ -0,0 +1,22 @@ |
1490 | +# |
1491 | +# Copyright (C) 2013 Canonical Ltd |
1492 | +# |
1493 | +# This program is free software: you can redistribute it and/or modify |
1494 | +# it under the terms of the GNU General Public License version 3 as |
1495 | +# published by the Free Software Foundation. |
1496 | +# |
1497 | +# This program is distributed in the hope that it will be useful, |
1498 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1499 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1500 | +# GNU General Public License for more details. |
1501 | +# |
1502 | +# You should have received a copy of the GNU General Public License |
1503 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1504 | +# |
1505 | +# Authored by: Michi Henning <michi.henning@canonical.com> |
1506 | +# |
1507 | + |
1508 | +add_executable(ResourcePtr_test ResourcePtr_test.cpp) |
1509 | +target_link_libraries(ResourcePtr_test ${LIBS} ${TESTLIBS}) |
1510 | + |
1511 | +add_test(ResourcePtr ResourcePtr_test) |
1512 | |
1513 | === added file 'tests/gtest/unity/util/ResourcePtr/ResourcePtr_test.cpp' |
1514 | --- tests/gtest/unity/util/ResourcePtr/ResourcePtr_test.cpp 1970-01-01 00:00:00 +0000 |
1515 | +++ tests/gtest/unity/util/ResourcePtr/ResourcePtr_test.cpp 2013-04-10 02:45:26 +0000 |
1516 | @@ -0,0 +1,529 @@ |
1517 | +/* |
1518 | + * Copyright (C) 2013 Canonical Ltd |
1519 | + * |
1520 | + * This program is free software: you can redistribute it and/or modify |
1521 | + * it under the terms of the GNU General Public License version 3 as |
1522 | + * published by the Free Software Foundation. |
1523 | + * |
1524 | + * This program is distributed in the hope that it will be useful, |
1525 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1526 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1527 | + * GNU General Public License for more details. |
1528 | + * |
1529 | + * You should have received a copy of the GNU General Public License |
1530 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1531 | + * |
1532 | + * Authored by: Michi Henning <michi.henning@canonical.com> |
1533 | + */ |
1534 | + |
1535 | +#include <gtest/gtest.h> |
1536 | +#include <unity/UnityExceptions.h> |
1537 | +#include <unity/util/ResourcePtr.h> |
1538 | + |
1539 | +#include <set> |
1540 | + |
1541 | +using namespace std; |
1542 | +using namespace unity; |
1543 | +using namespace unity::util; |
1544 | + |
1545 | +namespace |
1546 | +{ |
1547 | + |
1548 | +std::set<int*> allocated; // Tracks allocated resources |
1549 | + |
1550 | +} |
1551 | + |
1552 | +// |
1553 | +// Fake allocation and deallocation functions. |
1554 | +// |
1555 | + |
1556 | +int* alloc_int(int p) |
1557 | +{ |
1558 | + int* pointer = reinterpret_cast<int*>(p); |
1559 | + allocated.insert(pointer); |
1560 | + return pointer; |
1561 | +} |
1562 | + |
1563 | +int dealloc_int(int* i) |
1564 | +{ |
1565 | + auto it = allocated.find(i); |
1566 | + EXPECT_NE(it, allocated.end()); |
1567 | + allocated.erase(it); |
1568 | + return 0; |
1569 | +} |
1570 | + |
1571 | +// |
1572 | +// Check that allocator and deallocator are called with the correct argument |
1573 | +// and that get() returns the correct value. |
1574 | +// |
1575 | + |
1576 | +TEST(ResourcePtr, basic) |
1577 | +{ |
1578 | + { |
1579 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(dealloc_int); |
1580 | + EXPECT_FALSE(rp.has_resource()); |
1581 | + } |
1582 | + |
1583 | + { |
1584 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(alloc_int(99), dealloc_int); |
1585 | + EXPECT_EQ(allocated.size(), 1); |
1586 | + EXPECT_NE(allocated.find(rp.get()), allocated.end()); |
1587 | + EXPECT_TRUE(rp.has_resource()); |
1588 | + } |
1589 | + EXPECT_TRUE(allocated.empty()); |
1590 | +} |
1591 | + |
1592 | +// |
1593 | +// A deallocator that expects two arguments. We use std::bind to call it as if it expected only one. |
1594 | +// |
1595 | + |
1596 | +int dealloc_string_int(string const& s, int* i) |
1597 | +{ |
1598 | + EXPECT_EQ(s, "Hello"); |
1599 | + dealloc_int(i); |
1600 | + return 0; |
1601 | +} |
1602 | + |
1603 | +// |
1604 | +// Check that calling with bind works as expected. |
1605 | +// |
1606 | + |
1607 | +TEST(ResourcePtr, bind) |
1608 | +{ |
1609 | + { |
1610 | + auto call_dealloc = std::bind(&dealloc_string_int, "Hello", std::placeholders::_1); |
1611 | + ResourcePtr<int*, decltype(call_dealloc)> rp(alloc_int(42), call_dealloc); |
1612 | + EXPECT_EQ(allocated.size(), 1); |
1613 | + EXPECT_NE(allocated.find(rp.get()), allocated.end()); |
1614 | + } |
1615 | + EXPECT_TRUE(allocated.empty()); |
1616 | +} |
1617 | + |
1618 | +// |
1619 | +// Check that reset assigns the new pointer value. |
1620 | +// |
1621 | + |
1622 | +TEST(ResourcePtr, reset) |
1623 | +{ |
1624 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(alloc_int(77), dealloc_int); |
1625 | + EXPECT_EQ(allocated.size(), 1); |
1626 | + EXPECT_NE(allocated.find(rp.get()), allocated.end()); |
1627 | + |
1628 | + rp.reset(alloc_int(33)); |
1629 | + EXPECT_EQ(allocated.size(), 1); |
1630 | + EXPECT_EQ(allocated.find((int*)77), allocated.end()); |
1631 | + EXPECT_NE(allocated.find((int*)33), allocated.end()); |
1632 | + |
1633 | + rp.reset(alloc_int(10)); |
1634 | + rp.reset(alloc_int(20)); // Will deallocate the previous resource, so this will not cause a leak. |
1635 | +} |
1636 | + |
1637 | +// |
1638 | +// Check that dealloc deallocates and can be called multiple times without ill effects. |
1639 | +// |
1640 | + |
1641 | +TEST(ResourcePtr, dealloc) |
1642 | +{ |
1643 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(dealloc_int); |
1644 | + |
1645 | + rp.reset(alloc_int(77)); |
1646 | + EXPECT_EQ(allocated.size(), 1); |
1647 | + EXPECT_NE(allocated.find(rp.get()), allocated.end()); |
1648 | + |
1649 | + rp.dealloc(); |
1650 | + EXPECT_EQ(allocated.size(), 0); |
1651 | + EXPECT_FALSE(rp.has_resource()); |
1652 | + |
1653 | + rp.dealloc(); |
1654 | + EXPECT_EQ(allocated.size(), 0); |
1655 | + EXPECT_FALSE(rp.has_resource()); |
1656 | + |
1657 | + rp.reset(alloc_int(33)); |
1658 | + EXPECT_EQ(allocated.size(), 1); |
1659 | + EXPECT_NE(allocated.find((int*)33), allocated.end()); |
1660 | + EXPECT_TRUE(rp.has_resource()); |
1661 | + |
1662 | + rp.dealloc(); |
1663 | + EXPECT_EQ(allocated.size(), 0); |
1664 | + EXPECT_FALSE(rp.has_resource()); |
1665 | + |
1666 | + rp.dealloc(); |
1667 | + EXPECT_EQ(allocated.size(), 0); |
1668 | + EXPECT_FALSE(rp.has_resource()); |
1669 | +} |
1670 | + |
1671 | +int dealloc_throw(int* i) |
1672 | +{ |
1673 | + auto it = allocated.find(i); |
1674 | + EXPECT_NE(it, allocated.end()); |
1675 | + allocated.erase(it); |
1676 | + throw 99; |
1677 | +} |
1678 | + |
1679 | +// |
1680 | +// Test that things work correctly if the deleter throws. |
1681 | +// |
1682 | + |
1683 | +TEST(ResourcePtr, dealloc_throw) |
1684 | +{ |
1685 | + { |
1686 | + ResourcePtr<int*, decltype(&dealloc_throw)> rp(dealloc_throw); |
1687 | + rp.reset(alloc_int(77)); |
1688 | + |
1689 | + try |
1690 | + { |
1691 | + rp.dealloc(); |
1692 | + } |
1693 | + catch (int i) |
1694 | + { |
1695 | + EXPECT_EQ(99, i); |
1696 | + EXPECT_FALSE(rp.has_resource()); |
1697 | + } |
1698 | + } |
1699 | + |
1700 | + { |
1701 | + // Same test again, but this time by causing the deallocation via reset(). |
1702 | + ResourcePtr<int*, decltype(&dealloc_throw)> rp(dealloc_throw); |
1703 | + rp.reset(alloc_int(77)); |
1704 | + |
1705 | + try |
1706 | + { |
1707 | + rp.reset(alloc_int(66)); |
1708 | + } |
1709 | + catch (int i) |
1710 | + { |
1711 | + EXPECT_EQ(99, i); |
1712 | + EXPECT_TRUE(rp.has_resource()); // True because rp now owns the new resource |
1713 | + } |
1714 | + } |
1715 | + |
1716 | + { |
1717 | + // Same test again, but this time by letting the destructor do |
1718 | + // the deallocation. |
1719 | + try |
1720 | + { |
1721 | + ResourcePtr<int*, decltype(&dealloc_throw)> rp(dealloc_throw); |
1722 | + rp.reset(alloc_int(77)); |
1723 | + } |
1724 | + catch (...) |
1725 | + { |
1726 | + FAIL(); |
1727 | + } |
1728 | + } |
1729 | +} |
1730 | + |
1731 | +// |
1732 | +// get() without a resource throws. |
1733 | +// |
1734 | + |
1735 | +TEST(ResourcePtr, get_throw) |
1736 | +{ |
1737 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(dealloc_int); |
1738 | + |
1739 | + try |
1740 | + { |
1741 | + rp.get(); |
1742 | + FAIL(); |
1743 | + } |
1744 | + catch (std::logic_error const& e) |
1745 | + { |
1746 | + EXPECT_STREQ("get() called on ResourcePtr without resource", e.what()); |
1747 | + } |
1748 | + |
1749 | + rp.reset(alloc_int(99)); |
1750 | + rp.dealloc(); |
1751 | + |
1752 | + try |
1753 | + { |
1754 | + rp.get(); |
1755 | + FAIL(); |
1756 | + } |
1757 | + catch (std::logic_error const& e) |
1758 | + { |
1759 | + EXPECT_STREQ("get() called on ResourcePtr without resource", e.what()); |
1760 | + } |
1761 | +} |
1762 | + |
1763 | +// |
1764 | +// Check that release() releases the resource and throws if there is no resource to release. |
1765 | +// |
1766 | + |
1767 | +TEST(ResourcePtr, release) |
1768 | +{ |
1769 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(dealloc_int); |
1770 | + |
1771 | + rp.reset(alloc_int(99)); |
1772 | + EXPECT_TRUE(rp.has_resource()); |
1773 | + rp.release(); |
1774 | + EXPECT_FALSE(rp.has_resource()); |
1775 | + |
1776 | + try |
1777 | + { |
1778 | + rp.release(); |
1779 | + FAIL(); |
1780 | + } |
1781 | + catch (std::logic_error const& e) |
1782 | + { |
1783 | + EXPECT_STREQ("release() called on ResourcePtr without resource", e.what()); |
1784 | + } |
1785 | +} |
1786 | + |
1787 | +// |
1788 | +// operator bool() |
1789 | +// |
1790 | + |
1791 | +TEST(ResourcePtr, operator_bool) |
1792 | +{ |
1793 | + { |
1794 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(dealloc_int); |
1795 | + if (rp) |
1796 | + { |
1797 | + FAIL(); |
1798 | + } |
1799 | + } |
1800 | + |
1801 | + { |
1802 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(alloc_int(99), dealloc_int); |
1803 | + if (!rp) |
1804 | + { |
1805 | + FAIL(); |
1806 | + } |
1807 | + } |
1808 | +} |
1809 | + |
1810 | +// |
1811 | +// get_deleter() (two versions) |
1812 | +// |
1813 | + |
1814 | +TEST(ResourcePtr, get_deleter) |
1815 | +{ |
1816 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(dealloc_int); |
1817 | + EXPECT_EQ(rp.get_deleter(), &dealloc_int); |
1818 | + |
1819 | + const ResourcePtr<int*, decltype(&dealloc_int)> rp_const(dealloc_int); |
1820 | + EXPECT_EQ(rp_const.get_deleter(), &dealloc_int); |
1821 | +} |
1822 | + |
1823 | +class Comparable |
1824 | +{ |
1825 | +public: |
1826 | + Comparable() |
1827 | + : i_(0) |
1828 | + { |
1829 | + } |
1830 | + |
1831 | + Comparable(int i) |
1832 | + : i_(i) |
1833 | + { |
1834 | + } |
1835 | + |
1836 | + bool operator<(Comparable const& rhs) const |
1837 | + { |
1838 | + return i_ < rhs.i_; |
1839 | + } |
1840 | + |
1841 | + bool operator==(Comparable const& rhs) const |
1842 | + { |
1843 | + return i_ == rhs.i_; |
1844 | + } |
1845 | + |
1846 | + int get() const |
1847 | + { |
1848 | + return i_; |
1849 | + } |
1850 | + |
1851 | +private: |
1852 | + int i_; |
1853 | +}; |
1854 | + |
1855 | +void no_op(Comparable) {} // Dummy deallocation function |
1856 | + |
1857 | +ResourcePtr<Comparable, decltype(&no_op)> |
1858 | +make_comparable(int i) |
1859 | +{ |
1860 | + return ResourcePtr<Comparable, decltype(&no_op)>(Comparable(i), no_op); |
1861 | +} |
1862 | + |
1863 | +// |
1864 | +// Check move constructor and move assignment operator |
1865 | +// |
1866 | + |
1867 | +TEST(ResourcePtr, move) |
1868 | +{ |
1869 | + { |
1870 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(dealloc_int); |
1871 | + ResourcePtr<int*, decltype(&dealloc_int)> rp2(std::move(rp)); |
1872 | + |
1873 | + EXPECT_FALSE(rp.has_resource()); |
1874 | + EXPECT_FALSE(rp2.has_resource()); |
1875 | + } |
1876 | + |
1877 | + { |
1878 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(dealloc_int); |
1879 | + rp.reset(alloc_int(99)); |
1880 | + ResourcePtr<int*, decltype(&dealloc_int)> rp2(std::move(rp)); |
1881 | + |
1882 | + EXPECT_FALSE(rp.has_resource()); |
1883 | + EXPECT_TRUE(rp2.has_resource()); |
1884 | + EXPECT_EQ(allocated.size(), 1); |
1885 | + EXPECT_NE(allocated.find((int*)99), allocated.end()); |
1886 | + } |
1887 | + |
1888 | + { |
1889 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(dealloc_int); |
1890 | + |
1891 | + rp = std::move(ResourcePtr<int*, decltype(&dealloc_int)>(dealloc_int)); |
1892 | + |
1893 | + EXPECT_FALSE(rp.has_resource()); |
1894 | + } |
1895 | + |
1896 | + { |
1897 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(dealloc_int); |
1898 | + rp.reset(alloc_int(99)); |
1899 | + EXPECT_TRUE(rp.has_resource()); |
1900 | + |
1901 | + rp = std::move(ResourcePtr<int*, decltype(&dealloc_int)>(dealloc_int)); |
1902 | + |
1903 | + EXPECT_FALSE(rp.has_resource()); |
1904 | + EXPECT_TRUE(allocated.empty()); |
1905 | + } |
1906 | + |
1907 | + { |
1908 | + ResourcePtr<int*, decltype(&dealloc_int)> rp(dealloc_int); |
1909 | + rp.reset(alloc_int(99)); |
1910 | + |
1911 | + rp = std::move(ResourcePtr<int*, decltype(&dealloc_int)>(alloc_int(42), dealloc_int)); |
1912 | + |
1913 | + EXPECT_TRUE(rp.has_resource()); |
1914 | + EXPECT_EQ(allocated.size(), 1); |
1915 | + EXPECT_NE(allocated.find((int*)42), allocated.end()); |
1916 | + } |
1917 | + |
1918 | + { |
1919 | + ResourcePtr<Comparable, decltype(&no_op)> r(make_comparable(53)); |
1920 | + EXPECT_EQ(53, r.get().get()); |
1921 | + } |
1922 | + |
1923 | + { |
1924 | + ResourcePtr<Comparable, decltype(&no_op)> r(no_op); |
1925 | + r = make_comparable(44); |
1926 | + |
1927 | + EXPECT_EQ(44, r.get().get()); |
1928 | + } |
1929 | +} |
1930 | + |
1931 | +TEST(ResourcePtr, comparisons) |
1932 | +{ |
1933 | + { |
1934 | + ResourcePtr<Comparable, decltype(&no_op)> zero(Comparable(0), no_op); |
1935 | + ResourcePtr<Comparable, decltype(&no_op)> one(Comparable(1), no_op); |
1936 | + ResourcePtr<Comparable, decltype(&no_op)> no_init(no_op); |
1937 | + |
1938 | + EXPECT_TRUE(no_init == no_init); |
1939 | + EXPECT_FALSE(zero == no_init); |
1940 | + EXPECT_FALSE(no_init == zero); |
1941 | + |
1942 | + EXPECT_FALSE(zero == one); |
1943 | + EXPECT_TRUE(zero == zero); |
1944 | + |
1945 | + EXPECT_TRUE(zero != one); |
1946 | + |
1947 | + EXPECT_TRUE(no_init < zero); |
1948 | + EXPECT_FALSE(no_init < no_init); |
1949 | + EXPECT_FALSE(zero < no_init); |
1950 | + |
1951 | + EXPECT_TRUE(zero < one); |
1952 | + EXPECT_FALSE(one < zero); |
1953 | + EXPECT_FALSE(zero < zero); |
1954 | + |
1955 | + EXPECT_TRUE(zero <= one); |
1956 | + EXPECT_TRUE(one <= one); |
1957 | + EXPECT_FALSE(one <= zero); |
1958 | + |
1959 | + EXPECT_TRUE(one > zero); |
1960 | + EXPECT_FALSE(zero > one); |
1961 | + EXPECT_FALSE(one > one); |
1962 | + |
1963 | + EXPECT_TRUE(one >= zero); |
1964 | + EXPECT_TRUE(one >= one); |
1965 | + EXPECT_FALSE(zero >= one); |
1966 | + } |
1967 | +} |
1968 | + |
1969 | +TEST(ResourcePtr, swap) |
1970 | +{ |
1971 | + { |
1972 | + ResourcePtr<Comparable, decltype(&no_op)> zero(Comparable(0), no_op); |
1973 | + ResourcePtr<Comparable, decltype(&no_op)> one(Comparable(1), no_op); |
1974 | + ResourcePtr<Comparable, decltype(&no_op)> no_init(no_op); |
1975 | + |
1976 | + // Member swap |
1977 | + zero.swap(one); |
1978 | + EXPECT_EQ(zero.get(), 1); |
1979 | + EXPECT_EQ(one.get(), 0); |
1980 | + |
1981 | + // Non-member swap |
1982 | + unity::util::swap(one, no_init); |
1983 | + EXPECT_TRUE(no_init.has_resource()); |
1984 | + EXPECT_FALSE(one.has_resource()); |
1985 | + |
1986 | + // Self-swap |
1987 | + zero.swap(zero); |
1988 | + EXPECT_EQ(zero.get(), 1); |
1989 | + } |
1990 | +} |
1991 | + |
1992 | +TEST(ResourcePtr, std_specializations) |
1993 | +{ |
1994 | + ResourcePtr<Comparable, decltype(&no_op)> nr1(no_op); |
1995 | + ResourcePtr<Comparable, decltype(&no_op)> nr2(no_op); |
1996 | + ResourcePtr<Comparable, decltype(&no_op)> zero(Comparable(0), no_op); |
1997 | + ResourcePtr<Comparable, decltype(&no_op)> one(Comparable(1), no_op); |
1998 | + |
1999 | + std::equal_to<ResourcePtr<Comparable, decltype(&no_op)>> equal; |
2000 | + std::not_equal_to<ResourcePtr<Comparable, decltype(&no_op)>> not_equal; |
2001 | + std::less<ResourcePtr<Comparable, decltype(&no_op)>> less; |
2002 | + std::less_equal<ResourcePtr<Comparable, decltype(&no_op)>> less_equal; |
2003 | + std::greater<ResourcePtr<Comparable, decltype(&no_op)>> greater; |
2004 | + std::greater_equal<ResourcePtr<Comparable, decltype(&no_op)>> greater_equal; |
2005 | + |
2006 | + EXPECT_TRUE(equal.operator()(nr1, nr2)); |
2007 | + EXPECT_FALSE(equal.operator()(nr1, one)); |
2008 | + EXPECT_FALSE(equal.operator()(one, nr1)); |
2009 | + EXPECT_TRUE(equal.operator()(one, one)); |
2010 | + EXPECT_FALSE(equal.operator()(zero, one)); |
2011 | + |
2012 | + EXPECT_FALSE(not_equal.operator()(nr1, nr2)); |
2013 | + EXPECT_TRUE(not_equal.operator()(nr1, one)); |
2014 | + EXPECT_TRUE(not_equal.operator()(one, nr1)); |
2015 | + EXPECT_FALSE(not_equal.operator()(one, one)); |
2016 | + EXPECT_TRUE(not_equal.operator()(zero, one)); |
2017 | + |
2018 | + EXPECT_FALSE(less.operator()(nr1, nr2)); |
2019 | + EXPECT_TRUE(less.operator()(nr1, one)); |
2020 | + EXPECT_FALSE(less.operator()(one, nr1)); |
2021 | + EXPECT_FALSE(less.operator()(one, one)); |
2022 | + EXPECT_TRUE(less.operator()(zero, one)); |
2023 | + EXPECT_FALSE(less.operator()(one, zero)); |
2024 | + |
2025 | + EXPECT_TRUE(less_equal.operator()(nr1, nr2)); |
2026 | + EXPECT_TRUE(less_equal.operator()(nr1, one)); |
2027 | + EXPECT_FALSE(less_equal.operator()(one, nr1)); |
2028 | + EXPECT_TRUE(less_equal.operator()(one, one)); |
2029 | + EXPECT_TRUE(less_equal.operator()(zero, one)); |
2030 | + EXPECT_FALSE(less_equal.operator()(one, zero)); |
2031 | + |
2032 | + EXPECT_FALSE(greater.operator()(nr1, nr2)); |
2033 | + EXPECT_FALSE(greater.operator()(nr1, one)); |
2034 | + EXPECT_TRUE(greater.operator()(one, nr1)); |
2035 | + EXPECT_FALSE(greater.operator()(one, one)); |
2036 | + EXPECT_FALSE(greater.operator()(zero, one)); |
2037 | + EXPECT_TRUE(greater.operator()(one, zero)); |
2038 | + |
2039 | + EXPECT_TRUE(greater_equal.operator()(nr1, nr2)); |
2040 | + EXPECT_FALSE(greater_equal.operator()(nr1, one)); |
2041 | + EXPECT_TRUE(greater_equal.operator()(one, nr1)); |
2042 | + EXPECT_TRUE(greater_equal.operator()(one, one)); |
2043 | + EXPECT_FALSE(greater_equal.operator()(zero, one)); |
2044 | + EXPECT_TRUE(greater_equal.operator()(one, zero)); |
2045 | +} |
FAILED: Continuous integration, rev:544 jenkins. qa.ubuntu. com/job/ unity-phablet- ci/281/ jenkins. qa.ubuntu. com/job/ unity-phablet- quantal- armhf-ci/ 282/console jenkins. qa.ubuntu. com/job/ unity-phablet- quantal- i386-ci/ 281/console jenkins. qa.ubuntu. com/job/ unity-phablet- raring- armhf-ci/ 157/console jenkins. qa.ubuntu. com/job/ unity-phablet- raring- i386-ci/ 157/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ unity-phablet- ci/281/ rebuild
http://