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