Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: test/plugin/DetachedInitializationTest.cpp

Issue 29332660: Issue #3391 - Add detached initialization class
Patch Set: address comments Created Jan. 29, 2016, 3:37 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 Eyeo GmbH
4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <exception>
19 #include <gtest/gtest.h>
20 #include "../../src/plugin/DetachedInitialization.h"
21
22 // Initializer that does nothing
23 void NullFunction()
24 {}
25
26 // Initializer that always throws
27 const std::string failMessage = "initializer failed on purpose";
28 void FailFunction()
29 {
30 throw std::runtime_error(failMessage);
31 }
32
33 /*
34 * The destructor has to be able to block to wait for the initializer
35 * This test ensures that it doesn't block unnecessarily.
36 */
37 TEST(DetachedInitializer, DestructorDoesNotBlockAfterNoActivity)
38 {
39 DetachedInitializer<NullFunction> x;
40 }
41
42 TEST(DetachedInitializer, NullInstance)
43 {
44 ASSERT_NO_THROW(
45 {
46 DetachedInitializer<NullFunction> x;
47 x.SpawnInitializer();
48 x.EnsureInitialized();
49 }
50 );
51 }
52
53 /*
54 * This test illustrates a defect in Google Test.
55 * This test fails with a message that the test threw an exception.
56 * The exception message is the one thrown by FailFunction.
57 * It does not fail, importantly, because SpawnInitializer() throws.
58 * This can be verified in the debugger.
59 *
60 * It's disabled in the present code base so it doesn't break the unit test.
61 * Check this test again when we upgrade past GTest 1.60 and the VS 2012 toolset .
62 */
63 TEST(DetachedInitializer, DISABLED_EnsureInitializedThrowingGtestDefectIllustrat ion)
64 {
65 DetachedInitializer<FailFunction> x;
66 bool threw = false;
67 try
68 {
69 x.SpawnInitializer();
70 }
71 catch (...)
72 {
73 threw = true;
74 FAIL() << "SpawnInitializer() threw";
75 }
76 ASSERT_FALSE(threw);
77 }
78
79 /*
80 * This test fails because of a defect in Google Test.
81 * It's disabled at present, but should be enabled when the previous test is wor king.
82 */
83 TEST(DetachedInitializer, DISABLED_EnsureInitializedThrowing)
84 {
85 DetachedInitializer<FailFunction> x;
86 try
87 {
88 x.SpawnInitializer();
89 }
90 catch (...)
91 {
92 FAIL() << "SpawnInitializer() threw";
93 return;
94 }
95 try
96 {
97 x.EnsureInitialized();
98 FAIL() << "EnsureInitialized() did not throw";
99 }
100 catch (std::runtime_error& e)
101 {
102 ASSERT_EQ(failMessage, e.what());
103 }
104 }
105
106 /*
107 * Resetable version of DetachedInitializer
108 */
109 template<void(&F)()>
110 class DidReset
111 : public DetachedInitializer<F>
112 {
113 public:
114 void Reset()
115 {
116 isInitializationComplete.store(false, std::memory_order_relaxed);
117 hasInitializerStarted.store(false, std::memory_order_relaxed);
118 initializerException = nullptr;
119 // Lock and unlock the mutex to clear any previous state
120 // It will also detect a locked mutex left over from a previous test.
121 mutex.lock();
122 mutex.unlock();
123 }
124 };
125
126 /*
127 * Uses designated implementation pattern of DetachedInitializer
128 */
129 struct DeferredIncrementingInitializer
130 {
131 static int initializedCount;
132
133 static void Incrementer()
134 {
135 ++initializedCount;
136 }
137
138 typedef DidReset<Incrementer> InitializerType;
139 static InitializerType di;
140
141 public:
142 DeferredIncrementingInitializer()
143 {
144 di.SpawnInitializer();
145 }
146
147 static void ResetClass()
148 {
149 initializedCount = 0;
150 di.Reset();
151 }
152
153 static int GetInitializerCount ()
154 {
155 di.EnsureInitialized();
156 return initializedCount;
157 }
158 };
159 DeferredIncrementingInitializer::InitializerType DeferredIncrementingInitializer ::di;
160 int DeferredIncrementingInitializer::initializedCount = 0;
161
162 TEST(DetachedInitializer, Single)
163 {
164 DeferredIncrementingInitializer::ResetClass();
165 DeferredIncrementingInitializer x;
166 ASSERT_EQ(1, DeferredIncrementingInitializer::GetInitializerCount());
167 }
168
169 TEST(DetachedInitializer, Two)
170 {
171 DeferredIncrementingInitializer::ResetClass();
172 DeferredIncrementingInitializer x;
173 DeferredIncrementingInitializer y;
174 ASSERT_EQ(1, DeferredIncrementingInitializer::GetInitializerCount());
175 }
176
177 /*
178 * This test implicitly calls EnsureInitialized before the second call to SpawnI nitializer.
179 */
180 TEST(DetachedInitializer, TwoInterleaved)
181 {
182 DeferredIncrementingInitializer::ResetClass();
183 DeferredIncrementingInitializer x;
184 EXPECT_EQ(1, DeferredIncrementingInitializer::GetInitializerCount());
185 DeferredIncrementingInitializer y;
186 ASSERT_EQ(1, DeferredIncrementingInitializer::GetInitializerCount());
187 }
188
189 TEST(DetachedInitializer, Many)
190 {
191 DeferredIncrementingInitializer::ResetClass();
192 const int many = 1000000;
193 for (int j = 0; j < many;++j)
194 {
195 DeferredIncrementingInitializer x;
196 }
197 ASSERT_EQ(1, DeferredIncrementingInitializer::GetInitializerCount());
198 }
OLDNEW
« src/plugin/DetachedInitialization.h ('K') | « src/plugin/DetachedInitialization.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld