Merge lp:~michihenning/unity/phablet-unity-api-merge-tests into lp:unity/phablet

Proposed by Michi Henning
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
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.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
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?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
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?

Revision history for this message
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.)

Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

Yes, we can fix those issues later if they turn up.

review: Approve
Revision history for this message
Albert Astals Cid (aacid) wrote :

Doesn't merge with master cleanly

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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+}

Subscribers

People subscribed via source and target branches