| Index: base/scoped_ptr_cotask_unittest.cc
|
| diff --git a/base/scoped_ptr_cotask_unittest.cc b/base/scoped_ptr_cotask_unittest.cc
|
| deleted file mode 100644
|
| index 8b22d2c5fba669a6ddcbd9f387e67bc5b5a65e1a..0000000000000000000000000000000000000000
|
| --- a/base/scoped_ptr_cotask_unittest.cc
|
| +++ /dev/null
|
| @@ -1,308 +0,0 @@
|
| -// Copyright 2007-2009 Google Inc.
|
| -//
|
| -// Licensed under the Apache License, Version 2.0 (the "License");
|
| -// you may not use this file except in compliance with the License.
|
| -// You may obtain a copy of the License at
|
| -//
|
| -// http://www.apache.org/licenses/LICENSE-2.0
|
| -//
|
| -// Unless required by applicable law or agreed to in writing, software
|
| -// distributed under the License is distributed on an "AS IS" BASIS,
|
| -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -// See the License for the specific language governing permissions and
|
| -// limitations under the License.
|
| -// ========================================================================
|
| -
|
| -#include <vector>
|
| -#include "omaha/base/debug.h"
|
| -#include "omaha/base/scoped_ptr_cotask.h"
|
| -#include "omaha/testing/unit_test.h"
|
| -
|
| -// TestMallocSpy monitors CoTaskMemAlloc/Free, and records statistics about
|
| -// them.
|
| -
|
| -class TestMallocSpy : public IMallocSpy {
|
| - public:
|
| - struct Alloc {
|
| - size_t size;
|
| - void* ptr;
|
| - bool freed;
|
| - };
|
| -
|
| - TestMallocSpy() : ref_(1) {}
|
| -
|
| - virtual ~TestMallocSpy() {}
|
| -
|
| - size_t NumAllocs() const { return allocs_.size(); }
|
| -
|
| - const Alloc* GetAlloc(size_t i) const {
|
| - if (i >= allocs_.size())
|
| - return NULL;
|
| - return &allocs_[i];
|
| - }
|
| -
|
| - size_t NumFrees() const { return frees_.size(); }
|
| -
|
| - const Alloc* GetFree(size_t i) const {
|
| - if (i >= frees_.size())
|
| - return NULL;
|
| - ASSERT1(frees_[i] < allocs_.size());
|
| - return &allocs_[frees_[i]];
|
| - }
|
| -
|
| - // IUnknown methods
|
| - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv) {
|
| - if (NULL == ppv) {
|
| - return E_POINTER;
|
| - }
|
| - if (::IsEqualIID(__uuidof(IUnknown), riid) ||
|
| - ::IsEqualIID(__uuidof(IMallocSpy), riid)) {
|
| - AddRef();
|
| - *ppv = static_cast<IUnknown*>(this);
|
| - return S_OK;
|
| - }
|
| - *ppv = NULL;
|
| - return E_NOINTERFACE;
|
| - }
|
| - virtual ULONG STDMETHODCALLTYPE AddRef() {
|
| - return ++ref_;
|
| - }
|
| - virtual ULONG STDMETHODCALLTYPE Release() {
|
| - ULONG r = --ref_;
|
| - if (0 == r) {
|
| - delete this;
|
| - }
|
| - return r;
|
| - }
|
| -
|
| - // IMallocSpy methods
|
| - virtual SIZE_T STDMETHODCALLTYPE PreAlloc(SIZE_T request_size) {
|
| - Alloc a = { request_size, NULL, false };
|
| - allocs_.push_back(a);
|
| - return request_size;
|
| - }
|
| - virtual void* STDMETHODCALLTYPE PostAlloc(void* actual) {
|
| - ASSERT1(!allocs_.empty());
|
| - ASSERT1(NULL == allocs_.back().ptr);
|
| - allocs_.back().ptr = actual;
|
| - return actual;
|
| - }
|
| - virtual void* STDMETHODCALLTYPE PreFree(void* request, BOOL spyed) {
|
| - if (spyed) {
|
| - bool found = false;
|
| - for (size_t i = 0; i < allocs_.size(); ++i) {
|
| - if ((allocs_[i].ptr == request) && !allocs_[i].freed) {
|
| - allocs_[i].freed = true;
|
| - frees_.push_back(i);
|
| - found = true;
|
| - break;
|
| - }
|
| - }
|
| - ASSERT1(found);
|
| - }
|
| - return request;
|
| - }
|
| - virtual void STDMETHODCALLTYPE PostFree(BOOL) {}
|
| - virtual SIZE_T STDMETHODCALLTYPE PreRealloc(void*,
|
| - SIZE_T request_size,
|
| - void**,
|
| - BOOL) {
|
| - return request_size;
|
| - }
|
| - virtual void* STDMETHODCALLTYPE PostRealloc(void* actual, BOOL) {
|
| - return actual;
|
| - }
|
| - virtual void* STDMETHODCALLTYPE PreGetSize(void* request, BOOL) {
|
| - return request;
|
| - }
|
| - virtual SIZE_T STDMETHODCALLTYPE PostGetSize(SIZE_T actual_size, BOOL) {
|
| - return actual_size;
|
| - }
|
| - virtual void* STDMETHODCALLTYPE PreDidAlloc(void* request, BOOL) {
|
| - return request;
|
| - }
|
| - virtual int STDMETHODCALLTYPE PostDidAlloc(void*, BOOL, int fActual) {
|
| - return fActual;
|
| - }
|
| - virtual void STDMETHODCALLTYPE PreHeapMinimize() {}
|
| - virtual void STDMETHODCALLTYPE PostHeapMinimize() {}
|
| -
|
| - private:
|
| - ULONG ref_;
|
| - std::vector<Alloc> allocs_;
|
| - std::vector<size_t> frees_;
|
| -};
|
| -
|
| -// MallocTest runs tests with a TestMallocSpy installed.
|
| -
|
| -class MallocTest : public testing::Test {
|
| - public:
|
| - virtual void SetUp() {
|
| - spy_.Attach(new TestMallocSpy);
|
| - ASSERT_SUCCEEDED(::CoRegisterMallocSpy(spy_.p));
|
| - EXPECT_EQ(0, spy()->NumAllocs());
|
| - }
|
| - virtual void TearDown() {
|
| - EXPECT_EQ(spy()->NumAllocs(), spy()->NumFrees());
|
| - ASSERT_SUCCEEDED(::CoRevokeMallocSpy());
|
| - }
|
| - TestMallocSpy* spy() { return spy_.p; }
|
| -
|
| - private:
|
| - CComPtr<TestMallocSpy> spy_;
|
| -};
|
| -
|
| -TEST_F(MallocTest, StrDupCoTask) {
|
| - const char kNarrowString[] = "Hello";
|
| - const size_t kNarrowLen = strlen(kNarrowString);
|
| - const wchar_t kWideString[] = L"World";
|
| - const size_t kWideLen = wcslen(kWideString);
|
| -
|
| - // Test StrDupCoTask with narrow strings.
|
| - char* narrow_copy = StrDupCoTask(kNarrowString, kNarrowLen);
|
| -
|
| - ASSERT_EQ(1, spy()->NumAllocs());
|
| - EXPECT_EQ(0, spy()->NumFrees());
|
| - EXPECT_EQ((kNarrowLen + 1) * sizeof(char), spy()->GetAlloc(0)->size);
|
| - EXPECT_EQ(narrow_copy, spy()->GetAlloc(0)->ptr);
|
| - EXPECT_FALSE(spy()->GetAlloc(0)->freed);
|
| -
|
| - ::CoTaskMemFree(narrow_copy);
|
| -
|
| - ASSERT_EQ(1, spy()->NumFrees());
|
| - EXPECT_EQ(spy()->GetAlloc(0), spy()->GetFree(0));
|
| - EXPECT_EQ(narrow_copy, spy()->GetFree(0)->ptr);
|
| - EXPECT_TRUE(spy()->GetFree(0)->freed);
|
| -
|
| - // Test StrDupCoTask with wide strings.
|
| - wchar_t* wide_copy = StrDupCoTask(kWideString, kWideLen);
|
| -
|
| - ASSERT_EQ(2, spy()->NumAllocs());
|
| - EXPECT_EQ(1, spy()->NumFrees());
|
| - EXPECT_EQ((kWideLen + 1) * sizeof(wchar_t), spy()->GetAlloc(1)->size);
|
| - EXPECT_EQ(wide_copy, spy()->GetAlloc(1)->ptr);
|
| - EXPECT_FALSE(spy()->GetAlloc(1)->freed);
|
| -
|
| - ::CoTaskMemFree(wide_copy);
|
| -
|
| - ASSERT_EQ(2, spy()->NumFrees());
|
| - EXPECT_EQ(spy()->GetAlloc(1), spy()->GetFree(1));
|
| - EXPECT_EQ(wide_copy, spy()->GetFree(1)->ptr);
|
| - EXPECT_TRUE(spy()->GetFree(1)->freed);
|
| -}
|
| -
|
| -TEST_F(MallocTest, scoped_ptr_cotask) {
|
| - scoped_ptr_cotask<wchar_t>* string_ptr;
|
| -
|
| - // Creating an empty ptr does no additional allocations.
|
| - string_ptr = new scoped_ptr_cotask<wchar_t>;
|
| - ASSERT_EQ(0, spy()->NumAllocs());
|
| - EXPECT_EQ(0, spy()->NumFrees());
|
| -
|
| - // Assigning a string does not additional allocations.
|
| - string_ptr->reset(StrDupCoTask(L"hi", 2));
|
| - ASSERT_EQ(1, spy()->NumAllocs());
|
| - EXPECT_EQ(0, spy()->NumFrees());
|
| - EXPECT_EQ(3 * sizeof(wchar_t), spy()->GetAlloc(0)->size);
|
| - EXPECT_FALSE(spy()->GetAlloc(0)->freed);
|
| -
|
| - EXPECT_EQ(0, memcmp(string_ptr->get(), L"hi", 3 * sizeof(wchar_t)));
|
| -
|
| - // Replacing the string frees the old memory.
|
| - string_ptr->reset(StrDupCoTask(L"there", 5));
|
| - ASSERT_EQ(2, spy()->NumAllocs());
|
| - EXPECT_EQ(1, spy()->NumFrees());
|
| - EXPECT_EQ(6 * sizeof(wchar_t), spy()->GetAlloc(1)->size);
|
| - EXPECT_TRUE(spy()->GetAlloc(0)->freed);
|
| - EXPECT_FALSE(spy()->GetAlloc(1)->freed);
|
| -
|
| - // Deleting the string frees the memory.
|
| - delete string_ptr;
|
| - ASSERT_EQ(2, spy()->NumAllocs());
|
| - EXPECT_EQ(2, spy()->NumFrees());
|
| - EXPECT_TRUE(spy()->GetAlloc(1)->freed);
|
| -}
|
| -
|
| -TEST_F(MallocTest, scoped_array_cotask) {
|
| - const size_t kSize = 5;
|
| - scoped_array_cotask<wchar_t*>* string_array;
|
| -
|
| - // Allocate an array of 5 empty elements.
|
| - string_array = new scoped_array_cotask<wchar_t*>(kSize);
|
| - ASSERT_EQ(kSize, string_array->size());
|
| - ASSERT_EQ(1, spy()->NumAllocs());
|
| - EXPECT_EQ(0, spy()->NumFrees());
|
| - EXPECT_EQ(kSize * sizeof(wchar_t*), spy()->GetAlloc(0)->size);
|
| -
|
| - // Populate array elements.
|
| - for (size_t i = 0; i < kSize; ++i) {
|
| - EXPECT_TRUE(NULL == (*string_array)[i]);
|
| - (*string_array)[i] = StrDupCoTask(L"hi", 2);
|
| - }
|
| - EXPECT_EQ(1 + kSize, spy()->NumAllocs());
|
| - EXPECT_EQ(0, spy()->NumFrees());
|
| -
|
| - // Get is idempotent.
|
| - wchar_t** ptr = string_array->get();
|
| - EXPECT_EQ(ptr, string_array->get());
|
| - EXPECT_EQ(ptr, spy()->GetAlloc(0)->ptr);
|
| - EXPECT_EQ(0, spy()->NumFrees());
|
| -
|
| - // Release is not idempotent, but does not free memory.
|
| - ptr = string_array->release();
|
| - EXPECT_TRUE(NULL == string_array->release());
|
| - EXPECT_EQ(ptr, spy()->GetAlloc(0)->ptr);
|
| - EXPECT_EQ(0, spy()->NumFrees());
|
| -
|
| - // Deleting a released array does not free memory.
|
| - delete string_array;
|
| - EXPECT_EQ(0, spy()->NumFrees());
|
| -
|
| - // Constructing an array from existing memory, does not cause allocations.
|
| - string_array = new scoped_array_cotask<wchar_t*>(kSize, ptr);
|
| - EXPECT_EQ(1 + kSize, spy()->NumAllocs());
|
| - EXPECT_EQ(0, spy()->NumFrees());
|
| -
|
| - // Deleting an array frees all elements and the array.
|
| - delete string_array;
|
| - ASSERT_EQ(1 + kSize, spy()->NumAllocs());
|
| - EXPECT_EQ(1 + kSize, spy()->NumFrees());
|
| - for (size_t i = 0; i < spy()->NumAllocs(); ++i) {
|
| - EXPECT_TRUE(spy()->GetAlloc(i)->freed);
|
| - }
|
| -}
|
| -
|
| -TEST_F(MallocTest, scoped_array_cotask_reset) {
|
| - // This test exposes a former bug, where reset did not reallocate a new
|
| - // array after being released.
|
| -
|
| - // Allocate an empty array.
|
| - const size_t kSize = 5;
|
| - scoped_array_cotask<int*>* array = new scoped_array_cotask<int*>(kSize);
|
| - ASSERT_EQ(1, spy()->NumAllocs());
|
| -
|
| - // Release the array, to verify it was allocated.
|
| - int** first_raw_array = array->release();
|
| - EXPECT_TRUE(NULL != first_raw_array);
|
| - EXPECT_FALSE(spy()->GetAlloc(0)->freed);
|
| -
|
| - // Allocate another empty array.
|
| - array->reset(kSize);
|
| - ASSERT_EQ(2, spy()->NumAllocs());
|
| -
|
| - // Release the second array, to verify it was allocated.
|
| - int** second_raw_array = array->release();
|
| - EXPECT_TRUE(NULL != second_raw_array);
|
| - EXPECT_FALSE(spy()->GetAlloc(1)->freed);
|
| -
|
| - // Use the scoped_array_cotask object to dispose of the allocated arrays.
|
| - array->reset(kSize, first_raw_array);
|
| - array->reset(kSize, second_raw_array);
|
| - delete array;
|
| -
|
| - // Check the final conditions.
|
| - ASSERT_EQ(2, spy()->NumAllocs());
|
| - for (size_t i = 0; i < spy()->NumAllocs(); ++i) {
|
| - EXPECT_TRUE(spy()->GetAlloc(i)->freed);
|
| - }
|
| -}
|
|
|