blob: 5d215931e302ddd4a1cf1123de346112df54221d [file] [log] [blame]
initial.commitd7cae122008-07-26 21:49:381// Copyright 2008, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14// * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30#include "testing/gtest/include/gtest/gtest.h"
31#include "base/singleton_dll_unittest.h"
32#include "base/file_util.h"
33#include "base/path_service.h"
34
35class SingletonTest : public testing::Test {
36 public:
37 SingletonTest() {
38 }
39
40 virtual void SetUp() {
41 module_ = NULL;
42 non_leak_called_ = false;
43 leaky_called_ = false;
44 }
45
46 virtual void TearDown() {
47 ASSERT_FALSE(module_);
48 }
49
50 static bool IsTestCaseDisabled() {
51 // Check if the dll exists beside the executable.
52 std::wstring path;
53 PathService::Get(base::DIR_EXE, &path);
54 file_util::AppendToPath(&path, kLibrary);
55 return !file_util::PathExists(path);
56 }
57
58 protected:
59 void LoadLibrary() {
60 ASSERT_FALSE(module_);
61 module_ = ::LoadLibrary(kLibrary);
62 ASSERT_TRUE(module_ != NULL);
63 }
64
65 void FreeLibrary() {
66 ASSERT_TRUE(module_ != NULL);
67 ASSERT_TRUE(::FreeLibrary(module_));
68 module_ = NULL;
69 }
70
71 template<typename T>
72 void GetProc(const char* function_name, T* function) {
73 ASSERT_TRUE(module_ != NULL);
74 *function = reinterpret_cast<T>(GetProcAddress(module_, function_name));
75 ASSERT_TRUE(*function);
76 }
77
78 void VerifiesCallbacks() {
79 EXPECT_TRUE(non_leak_called_);
80 EXPECT_FALSE(leaky_called_);
81 non_leak_called_ = false;
82 leaky_called_ = false;
83 }
84
85 void VerifiesCallbacksNotCalled() {
86 EXPECT_FALSE(non_leak_called_);
87 EXPECT_FALSE(leaky_called_);
88 non_leak_called_ = false;
89 leaky_called_ = false;
90 }
91
92 static void WINAPI CallbackNoLeak() {
93 non_leak_called_ = true;
94 }
95
96 static void WINAPI CallbackLeak() {
97 leaky_called_ = true;
98 }
99
100 private:
101 static const wchar_t* const kLibrary;
102 HMODULE module_;
103 static bool non_leak_called_;
104 static bool leaky_called_;
105};
106
107bool SingletonTest::non_leak_called_ = false;
108bool SingletonTest::leaky_called_ = false;
109
110const wchar_t* const SingletonTest::kLibrary = L"singleton_dll_unittest.dll";
111
112TEST_F(SingletonTest, Basic) {
113 if (IsTestCaseDisabled())
114 return;
115
116 int* singleton_int_1;
117 int* singleton_int_2;
118 int* singleton_int_3;
119 int* singleton_int_4;
120 int* singleton_int_5;
121 CallBackFunc* leaky_singleton;
122
123 LoadLibrary();
124 {
125 SingletonIntFunc sut1;
126 SingletonIntFunc sut2;
127 SingletonIntFunc sut3;
128 SingletonIntFunc sut4;
129 SingletonIntFunc sut5;
130 {
131 GetProc("SingletonInt1", &sut1);
132 singleton_int_1 = sut1();
133 }
134 // Ensure POD type initialization.
135 EXPECT_EQ(*singleton_int_1, 0);
136 *singleton_int_1 = 1;
137
138 EXPECT_EQ(singleton_int_1, sut1());
139 EXPECT_EQ(*singleton_int_1, 1);
140
141 {
142 GetProc("SingletonInt2", &sut2);
143 singleton_int_2 = sut2();
144 }
145 // Same instance that 1.
146 EXPECT_EQ(*singleton_int_2, 1);
147 EXPECT_EQ(singleton_int_1, singleton_int_2);
148
149 {
150 GetProc("SingletonInt3", &sut3);
151 singleton_int_3 = sut3();
152 }
153 // Different instance than 1 and 2.
154 EXPECT_EQ(*singleton_int_3, 0);
155 EXPECT_NE(singleton_int_1, singleton_int_3);
156 *singleton_int_3 = 3;
157 EXPECT_EQ(*singleton_int_1, 1);
158 EXPECT_EQ(*singleton_int_2, 1);
159
160 {
161 GetProc("SingletonInt4", &sut4);
162 singleton_int_4 = sut4();
163 }
164 // Use a lock for creation. Not really tested at length.
165 EXPECT_EQ(*singleton_int_4, 0);
166 *singleton_int_4 = 4;
167 EXPECT_NE(singleton_int_1, singleton_int_4);
168 EXPECT_NE(singleton_int_3, singleton_int_4);
169
170 {
171 GetProc("SingletonInt5", &sut5);
172 singleton_int_5 = sut5();
173 }
174 // Is default initialized to 5.
175 EXPECT_EQ(*singleton_int_5, 5);
176 EXPECT_NE(singleton_int_1, singleton_int_5);
177 EXPECT_NE(singleton_int_3, singleton_int_5);
178 EXPECT_NE(singleton_int_4, singleton_int_5);
179#ifdef _DEBUG
180 // In release, the optimizer may make both exports use exactly the same
181 // code.
182 EXPECT_NE(sut1, sut2);
183#endif
184 EXPECT_NE(sut2, sut3);
185 EXPECT_NE(sut3, sut4);
186 EXPECT_NE(sut4, sut5);
187
188 LeakySingletonFunc noleak;
189 GetProc("SingletonNoLeak", &noleak);
190 noleak(&CallbackNoLeak);
191 LeakySingletonFunc leak;
192 GetProc("SingletonLeak", &leak);
193 leak(&CallbackLeak);
194 GetLeakySingletonFunc get_leaky;
195 GetProc("GetLeakySingleton", &get_leaky);
196 leaky_singleton = get_leaky();
197 EXPECT_TRUE(leaky_singleton);
198 }
199 FreeLibrary();
200
201 // Verify that only the expected callback has been called.
202 VerifiesCallbacks();
203 // Delete the leaky singleton. It is interesting to note that Purify does
204 // *not* detect the leak when this call is commented out. :(
205 EXPECT_TRUE(CustomAllocTrait<CallBackFunc>::Delete(leaky_singleton));
206
207 LoadLibrary();
208 {
209 // Verifiy that the variables were reset.
210 {
211 SingletonIntFunc sut1;
212 GetProc("SingletonInt1", &sut1);
213 singleton_int_1 = sut1();
214 EXPECT_EQ(*singleton_int_1, 0);
215 }
216 {
217 SingletonIntFunc sut5;
218 GetProc("SingletonInt5", &sut5);
219 singleton_int_5 = sut5();
220 EXPECT_EQ(*singleton_int_5, 5);
221 }
222 }
223 // The leaky singleton shouldn't leak since SingletonLeak has not been called.
224 FreeLibrary();
225
226 VerifiesCallbacksNotCalled();
227}