1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/win/scoped_comptr.h" 6 7#include <shlobj.h> 8 9#include "base/memory/scoped_ptr.h" 10#include "base/win/scoped_com_initializer.h" 11#include "testing/gtest/include/gtest/gtest.h" 12 13namespace base { 14namespace win { 15 16namespace { 17 18struct Dummy { 19 Dummy() : adds(0), releases(0) { } 20 void AddRef() { ++adds; } 21 void Release() { ++releases; } 22 23 int adds; 24 int releases; 25}; 26 27extern const IID dummy_iid; 28const IID dummy_iid = { 0x12345678u, 0x1234u, 0x5678u, 01, 23, 45, 67, 89, 29 01, 23, 45 }; 30 31} // namespace 32 33TEST(ScopedComPtrTest, ScopedComPtr) { 34 EXPECT_TRUE(memcmp(&ScopedComPtr<IUnknown>::iid(), &IID_IUnknown, 35 sizeof(IID)) == 0); 36 37 base::win::ScopedCOMInitializer com_initializer; 38 EXPECT_TRUE(com_initializer.succeeded()); 39 40 ScopedComPtr<IUnknown> unk; 41 EXPECT_TRUE(SUCCEEDED(unk.CreateInstance(CLSID_ShellLink))); 42 ScopedComPtr<IUnknown> unk2; 43 unk2.Attach(unk.Detach()); 44 EXPECT_TRUE(unk == NULL); 45 EXPECT_TRUE(unk2 != NULL); 46 47 ScopedComPtr<IMalloc> mem_alloc; 48 EXPECT_TRUE(SUCCEEDED(CoGetMalloc(1, mem_alloc.Receive()))); 49 50 ScopedComPtr<IUnknown> qi_test; 51 EXPECT_HRESULT_SUCCEEDED(mem_alloc.QueryInterface(IID_IUnknown, 52 reinterpret_cast<void**>(qi_test.Receive()))); 53 EXPECT_TRUE(qi_test.get() != NULL); 54 qi_test.Release(); 55 56 // test ScopedComPtr& constructor 57 ScopedComPtr<IMalloc> copy1(mem_alloc); 58 EXPECT_TRUE(copy1.IsSameObject(mem_alloc)); 59 EXPECT_FALSE(copy1.IsSameObject(unk2)); // unk2 is valid but different 60 EXPECT_FALSE(copy1.IsSameObject(unk)); // unk is NULL 61 62 IMalloc* naked_copy = copy1.Detach(); 63 copy1 = naked_copy; // Test the =(T*) operator. 64 naked_copy->Release(); 65 66 copy1.Release(); 67 EXPECT_FALSE(copy1.IsSameObject(unk2)); // unk2 is valid, copy1 is not 68 69 // test Interface* constructor 70 ScopedComPtr<IMalloc> copy2(static_cast<IMalloc*>(mem_alloc)); 71 EXPECT_TRUE(copy2.IsSameObject(mem_alloc)); 72 73 EXPECT_TRUE(SUCCEEDED(unk.QueryFrom(mem_alloc))); 74 EXPECT_TRUE(unk != NULL); 75 unk.Release(); 76 EXPECT_TRUE(unk == NULL); 77 EXPECT_TRUE(unk.IsSameObject(copy1)); // both are NULL 78} 79 80TEST(ScopedComPtrTest, ScopedComPtrVector) { 81 // Verify we don't get error C2558. 82 typedef ScopedComPtr<Dummy, &dummy_iid> Ptr; 83 std::vector<Ptr> bleh; 84 85 scoped_ptr<Dummy> p(new Dummy); 86 { 87 Ptr p2(p.get()); 88 EXPECT_EQ(p->adds, 1); 89 EXPECT_EQ(p->releases, 0); 90 Ptr p3 = p2; 91 EXPECT_EQ(p->adds, 2); 92 EXPECT_EQ(p->releases, 0); 93 p3 = p2; 94 EXPECT_EQ(p->adds, 3); 95 EXPECT_EQ(p->releases, 1); 96 // To avoid hitting a reallocation. 97 bleh.reserve(1); 98 bleh.push_back(p2); 99 EXPECT_EQ(p->adds, 4); 100 EXPECT_EQ(p->releases, 1); 101 EXPECT_EQ(bleh[0], p.get()); 102 bleh.pop_back(); 103 EXPECT_EQ(p->adds, 4); 104 EXPECT_EQ(p->releases, 2); 105 } 106 EXPECT_EQ(p->adds, 4); 107 EXPECT_EQ(p->releases, 4); 108} 109 110} // namespace win 111} // namespace base 112