Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: base/scoped_ptr_cotask_unittest.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/scoped_ptr_cotask.h ('k') | base/security/aes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2007-2009 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15
16 #include <vector>
17 #include "omaha/base/debug.h"
18 #include "omaha/base/scoped_ptr_cotask.h"
19 #include "omaha/testing/unit_test.h"
20
21 // TestMallocSpy monitors CoTaskMemAlloc/Free, and records statistics about
22 // them.
23
24 class TestMallocSpy : public IMallocSpy {
25 public:
26 struct Alloc {
27 size_t size;
28 void* ptr;
29 bool freed;
30 };
31
32 TestMallocSpy() : ref_(1) {}
33
34 virtual ~TestMallocSpy() {}
35
36 size_t NumAllocs() const { return allocs_.size(); }
37
38 const Alloc* GetAlloc(size_t i) const {
39 if (i >= allocs_.size())
40 return NULL;
41 return &allocs_[i];
42 }
43
44 size_t NumFrees() const { return frees_.size(); }
45
46 const Alloc* GetFree(size_t i) const {
47 if (i >= frees_.size())
48 return NULL;
49 ASSERT1(frees_[i] < allocs_.size());
50 return &allocs_[frees_[i]];
51 }
52
53 // IUnknown methods
54 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv) {
55 if (NULL == ppv) {
56 return E_POINTER;
57 }
58 if (::IsEqualIID(__uuidof(IUnknown), riid) ||
59 ::IsEqualIID(__uuidof(IMallocSpy), riid)) {
60 AddRef();
61 *ppv = static_cast<IUnknown*>(this);
62 return S_OK;
63 }
64 *ppv = NULL;
65 return E_NOINTERFACE;
66 }
67 virtual ULONG STDMETHODCALLTYPE AddRef() {
68 return ++ref_;
69 }
70 virtual ULONG STDMETHODCALLTYPE Release() {
71 ULONG r = --ref_;
72 if (0 == r) {
73 delete this;
74 }
75 return r;
76 }
77
78 // IMallocSpy methods
79 virtual SIZE_T STDMETHODCALLTYPE PreAlloc(SIZE_T request_size) {
80 Alloc a = { request_size, NULL, false };
81 allocs_.push_back(a);
82 return request_size;
83 }
84 virtual void* STDMETHODCALLTYPE PostAlloc(void* actual) {
85 ASSERT1(!allocs_.empty());
86 ASSERT1(NULL == allocs_.back().ptr);
87 allocs_.back().ptr = actual;
88 return actual;
89 }
90 virtual void* STDMETHODCALLTYPE PreFree(void* request, BOOL spyed) {
91 if (spyed) {
92 bool found = false;
93 for (size_t i = 0; i < allocs_.size(); ++i) {
94 if ((allocs_[i].ptr == request) && !allocs_[i].freed) {
95 allocs_[i].freed = true;
96 frees_.push_back(i);
97 found = true;
98 break;
99 }
100 }
101 ASSERT1(found);
102 }
103 return request;
104 }
105 virtual void STDMETHODCALLTYPE PostFree(BOOL) {}
106 virtual SIZE_T STDMETHODCALLTYPE PreRealloc(void*,
107 SIZE_T request_size,
108 void**,
109 BOOL) {
110 return request_size;
111 }
112 virtual void* STDMETHODCALLTYPE PostRealloc(void* actual, BOOL) {
113 return actual;
114 }
115 virtual void* STDMETHODCALLTYPE PreGetSize(void* request, BOOL) {
116 return request;
117 }
118 virtual SIZE_T STDMETHODCALLTYPE PostGetSize(SIZE_T actual_size, BOOL) {
119 return actual_size;
120 }
121 virtual void* STDMETHODCALLTYPE PreDidAlloc(void* request, BOOL) {
122 return request;
123 }
124 virtual int STDMETHODCALLTYPE PostDidAlloc(void*, BOOL, int fActual) {
125 return fActual;
126 }
127 virtual void STDMETHODCALLTYPE PreHeapMinimize() {}
128 virtual void STDMETHODCALLTYPE PostHeapMinimize() {}
129
130 private:
131 ULONG ref_;
132 std::vector<Alloc> allocs_;
133 std::vector<size_t> frees_;
134 };
135
136 // MallocTest runs tests with a TestMallocSpy installed.
137
138 class MallocTest : public testing::Test {
139 public:
140 virtual void SetUp() {
141 spy_.Attach(new TestMallocSpy);
142 ASSERT_SUCCEEDED(::CoRegisterMallocSpy(spy_.p));
143 EXPECT_EQ(0, spy()->NumAllocs());
144 }
145 virtual void TearDown() {
146 EXPECT_EQ(spy()->NumAllocs(), spy()->NumFrees());
147 ASSERT_SUCCEEDED(::CoRevokeMallocSpy());
148 }
149 TestMallocSpy* spy() { return spy_.p; }
150
151 private:
152 CComPtr<TestMallocSpy> spy_;
153 };
154
155 TEST_F(MallocTest, StrDupCoTask) {
156 const char kNarrowString[] = "Hello";
157 const size_t kNarrowLen = strlen(kNarrowString);
158 const wchar_t kWideString[] = L"World";
159 const size_t kWideLen = wcslen(kWideString);
160
161 // Test StrDupCoTask with narrow strings.
162 char* narrow_copy = StrDupCoTask(kNarrowString, kNarrowLen);
163
164 ASSERT_EQ(1, spy()->NumAllocs());
165 EXPECT_EQ(0, spy()->NumFrees());
166 EXPECT_EQ((kNarrowLen + 1) * sizeof(char), spy()->GetAlloc(0)->size);
167 EXPECT_EQ(narrow_copy, spy()->GetAlloc(0)->ptr);
168 EXPECT_FALSE(spy()->GetAlloc(0)->freed);
169
170 ::CoTaskMemFree(narrow_copy);
171
172 ASSERT_EQ(1, spy()->NumFrees());
173 EXPECT_EQ(spy()->GetAlloc(0), spy()->GetFree(0));
174 EXPECT_EQ(narrow_copy, spy()->GetFree(0)->ptr);
175 EXPECT_TRUE(spy()->GetFree(0)->freed);
176
177 // Test StrDupCoTask with wide strings.
178 wchar_t* wide_copy = StrDupCoTask(kWideString, kWideLen);
179
180 ASSERT_EQ(2, spy()->NumAllocs());
181 EXPECT_EQ(1, spy()->NumFrees());
182 EXPECT_EQ((kWideLen + 1) * sizeof(wchar_t), spy()->GetAlloc(1)->size);
183 EXPECT_EQ(wide_copy, spy()->GetAlloc(1)->ptr);
184 EXPECT_FALSE(spy()->GetAlloc(1)->freed);
185
186 ::CoTaskMemFree(wide_copy);
187
188 ASSERT_EQ(2, spy()->NumFrees());
189 EXPECT_EQ(spy()->GetAlloc(1), spy()->GetFree(1));
190 EXPECT_EQ(wide_copy, spy()->GetFree(1)->ptr);
191 EXPECT_TRUE(spy()->GetFree(1)->freed);
192 }
193
194 TEST_F(MallocTest, scoped_ptr_cotask) {
195 scoped_ptr_cotask<wchar_t>* string_ptr;
196
197 // Creating an empty ptr does no additional allocations.
198 string_ptr = new scoped_ptr_cotask<wchar_t>;
199 ASSERT_EQ(0, spy()->NumAllocs());
200 EXPECT_EQ(0, spy()->NumFrees());
201
202 // Assigning a string does not additional allocations.
203 string_ptr->reset(StrDupCoTask(L"hi", 2));
204 ASSERT_EQ(1, spy()->NumAllocs());
205 EXPECT_EQ(0, spy()->NumFrees());
206 EXPECT_EQ(3 * sizeof(wchar_t), spy()->GetAlloc(0)->size);
207 EXPECT_FALSE(spy()->GetAlloc(0)->freed);
208
209 EXPECT_EQ(0, memcmp(string_ptr->get(), L"hi", 3 * sizeof(wchar_t)));
210
211 // Replacing the string frees the old memory.
212 string_ptr->reset(StrDupCoTask(L"there", 5));
213 ASSERT_EQ(2, spy()->NumAllocs());
214 EXPECT_EQ(1, spy()->NumFrees());
215 EXPECT_EQ(6 * sizeof(wchar_t), spy()->GetAlloc(1)->size);
216 EXPECT_TRUE(spy()->GetAlloc(0)->freed);
217 EXPECT_FALSE(spy()->GetAlloc(1)->freed);
218
219 // Deleting the string frees the memory.
220 delete string_ptr;
221 ASSERT_EQ(2, spy()->NumAllocs());
222 EXPECT_EQ(2, spy()->NumFrees());
223 EXPECT_TRUE(spy()->GetAlloc(1)->freed);
224 }
225
226 TEST_F(MallocTest, scoped_array_cotask) {
227 const size_t kSize = 5;
228 scoped_array_cotask<wchar_t*>* string_array;
229
230 // Allocate an array of 5 empty elements.
231 string_array = new scoped_array_cotask<wchar_t*>(kSize);
232 ASSERT_EQ(kSize, string_array->size());
233 ASSERT_EQ(1, spy()->NumAllocs());
234 EXPECT_EQ(0, spy()->NumFrees());
235 EXPECT_EQ(kSize * sizeof(wchar_t*), spy()->GetAlloc(0)->size);
236
237 // Populate array elements.
238 for (size_t i = 0; i < kSize; ++i) {
239 EXPECT_TRUE(NULL == (*string_array)[i]);
240 (*string_array)[i] = StrDupCoTask(L"hi", 2);
241 }
242 EXPECT_EQ(1 + kSize, spy()->NumAllocs());
243 EXPECT_EQ(0, spy()->NumFrees());
244
245 // Get is idempotent.
246 wchar_t** ptr = string_array->get();
247 EXPECT_EQ(ptr, string_array->get());
248 EXPECT_EQ(ptr, spy()->GetAlloc(0)->ptr);
249 EXPECT_EQ(0, spy()->NumFrees());
250
251 // Release is not idempotent, but does not free memory.
252 ptr = string_array->release();
253 EXPECT_TRUE(NULL == string_array->release());
254 EXPECT_EQ(ptr, spy()->GetAlloc(0)->ptr);
255 EXPECT_EQ(0, spy()->NumFrees());
256
257 // Deleting a released array does not free memory.
258 delete string_array;
259 EXPECT_EQ(0, spy()->NumFrees());
260
261 // Constructing an array from existing memory, does not cause allocations.
262 string_array = new scoped_array_cotask<wchar_t*>(kSize, ptr);
263 EXPECT_EQ(1 + kSize, spy()->NumAllocs());
264 EXPECT_EQ(0, spy()->NumFrees());
265
266 // Deleting an array frees all elements and the array.
267 delete string_array;
268 ASSERT_EQ(1 + kSize, spy()->NumAllocs());
269 EXPECT_EQ(1 + kSize, spy()->NumFrees());
270 for (size_t i = 0; i < spy()->NumAllocs(); ++i) {
271 EXPECT_TRUE(spy()->GetAlloc(i)->freed);
272 }
273 }
274
275 TEST_F(MallocTest, scoped_array_cotask_reset) {
276 // This test exposes a former bug, where reset did not reallocate a new
277 // array after being released.
278
279 // Allocate an empty array.
280 const size_t kSize = 5;
281 scoped_array_cotask<int*>* array = new scoped_array_cotask<int*>(kSize);
282 ASSERT_EQ(1, spy()->NumAllocs());
283
284 // Release the array, to verify it was allocated.
285 int** first_raw_array = array->release();
286 EXPECT_TRUE(NULL != first_raw_array);
287 EXPECT_FALSE(spy()->GetAlloc(0)->freed);
288
289 // Allocate another empty array.
290 array->reset(kSize);
291 ASSERT_EQ(2, spy()->NumAllocs());
292
293 // Release the second array, to verify it was allocated.
294 int** second_raw_array = array->release();
295 EXPECT_TRUE(NULL != second_raw_array);
296 EXPECT_FALSE(spy()->GetAlloc(1)->freed);
297
298 // Use the scoped_array_cotask object to dispose of the allocated arrays.
299 array->reset(kSize, first_raw_array);
300 array->reset(kSize, second_raw_array);
301 delete array;
302
303 // Check the final conditions.
304 ASSERT_EQ(2, spy()->NumAllocs());
305 for (size_t i = 0; i < spy()->NumAllocs(); ++i) {
306 EXPECT_TRUE(spy()->GetAlloc(i)->freed);
307 }
308 }
OLDNEW
« no previous file with comments | « base/scoped_ptr_cotask.h ('k') | base/security/aes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698