1 // Copyright 2011 The Chromium Authors
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 <stdint.h>
6 #include <wrl/client.h>
7 #include <wrl/implements.h>
8
9 #include <utility>
10
11 #include "base/win/dispatch_stub.h"
12 #include "base/win/scoped_variant.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 using base::win::test::DispatchStub;
16
17 namespace base {
18 namespace win {
19
20 namespace {
21
22 constexpr wchar_t kTestString[] = L"Test string for BSTRs.";
23
InitializeVariantWithBstr(VARIANT * var)24 void InitializeVariantWithBstr(VARIANT* var) {
25 if (!var) {
26 ADD_FAILURE() << "|var| cannot be null.";
27 return;
28 }
29
30 var->vt = VT_BSTR;
31 V_BSTR(var) = ::SysAllocString(kTestString);
32 }
33
ExpectRefCount(ULONG expected_refcount,IUnknown * object)34 void ExpectRefCount(ULONG expected_refcount, IUnknown* object) {
35 // In general, code should not check the values of AddRef() and Release().
36 // However, tests need to validate that ScopedVariant safely owns a COM object
37 // so they are checked for this unit test.
38 EXPECT_EQ(expected_refcount + 1, object->AddRef());
39 EXPECT_EQ(expected_refcount, object->Release());
40 }
41
ExpectVariantType(VARENUM var_type,const ScopedVariant & var)42 void ExpectVariantType(VARENUM var_type, const ScopedVariant& var) {
43 EXPECT_EQ(var_type, var.type());
44 EXPECT_EQ(var_type, V_VT(var.ptr()));
45 }
46
47 } // namespace
48
TEST(ScopedVariantTest,Empty)49 TEST(ScopedVariantTest, Empty) {
50 ScopedVariant var;
51 ExpectVariantType(VT_EMPTY, var);
52 }
53
TEST(ScopedVariantTest,ConstructBstr)54 TEST(ScopedVariantTest, ConstructBstr) {
55 ScopedVariant var(kTestString);
56 ExpectVariantType(VT_BSTR, var);
57 EXPECT_STREQ(kTestString, V_BSTR(var.ptr()));
58 }
59
TEST(ScopedVariantTest,SetBstr)60 TEST(ScopedVariantTest, SetBstr) {
61 ScopedVariant var;
62 var.Set(kTestString);
63 ExpectVariantType(VT_BSTR, var);
64 EXPECT_STREQ(kTestString, V_BSTR(var.ptr()));
65 }
66
TEST(ScopedVariantTest,ReleaseBstr)67 TEST(ScopedVariantTest, ReleaseBstr) {
68 ScopedVariant var;
69 var.Set(kTestString);
70 VARIANT released_variant = var.Release();
71 ExpectVariantType(VT_EMPTY, var);
72 EXPECT_EQ(VT_BSTR, V_VT(&released_variant));
73 EXPECT_STREQ(kTestString, V_BSTR(&released_variant));
74 ::VariantClear(&released_variant);
75 }
76
TEST(ScopedVariantTest,ResetToEmptyBstr)77 TEST(ScopedVariantTest, ResetToEmptyBstr) {
78 ScopedVariant var(kTestString);
79 ExpectVariantType(VT_BSTR, var);
80 var.Reset();
81 ExpectVariantType(VT_EMPTY, var);
82 }
83
TEST(ScopedVariantTest,TakeOwnershipBstr)84 TEST(ScopedVariantTest, TakeOwnershipBstr) {
85 VARIANT bstr_variant;
86 bstr_variant.vt = VT_BSTR;
87 bstr_variant.bstrVal = ::SysAllocString(kTestString);
88
89 ScopedVariant var;
90 var.Reset(bstr_variant);
91 ExpectVariantType(VT_BSTR, var);
92 EXPECT_EQ(bstr_variant.bstrVal, V_BSTR(var.ptr()));
93 }
94
TEST(ScopedVariantTest,SwapBstr)95 TEST(ScopedVariantTest, SwapBstr) {
96 ScopedVariant from(kTestString);
97 ScopedVariant to;
98 to.Swap(from);
99 ExpectVariantType(VT_EMPTY, from);
100 ExpectVariantType(VT_BSTR, to);
101 EXPECT_STREQ(kTestString, V_BSTR(to.ptr()));
102 }
103
TEST(ScopedVariantTest,CompareBstr)104 TEST(ScopedVariantTest, CompareBstr) {
105 ScopedVariant var_bstr1;
106 InitializeVariantWithBstr(var_bstr1.Receive());
107 ScopedVariant var_bstr2(V_BSTR(var_bstr1.ptr()));
108 EXPECT_EQ(0, var_bstr1.Compare(var_bstr2));
109
110 var_bstr2.Reset();
111 EXPECT_NE(0, var_bstr1.Compare(var_bstr2));
112 }
113
TEST(ScopedVariantTest,ReceiveAndCopyBstr)114 TEST(ScopedVariantTest, ReceiveAndCopyBstr) {
115 ScopedVariant var_bstr1;
116 InitializeVariantWithBstr(var_bstr1.Receive());
117 ScopedVariant var_bstr2;
118 var_bstr2.Reset(var_bstr1.Copy());
119 EXPECT_EQ(0, var_bstr1.Compare(var_bstr2));
120 }
121
TEST(ScopedVariantTest,SetBstrFromBstrVariant)122 TEST(ScopedVariantTest, SetBstrFromBstrVariant) {
123 ScopedVariant var_bstr1;
124 InitializeVariantWithBstr(var_bstr1.Receive());
125 ScopedVariant var_bstr2;
126 var_bstr2.Set(V_BSTR(var_bstr1.ptr()));
127 EXPECT_EQ(0, var_bstr1.Compare(var_bstr2));
128 }
129
TEST(ScopedVariantTest,SetDate)130 TEST(ScopedVariantTest, SetDate) {
131 ScopedVariant var;
132 SYSTEMTIME sys_time;
133 ::GetSystemTime(&sys_time);
134 DATE date;
135 ::SystemTimeToVariantTime(&sys_time, &date);
136 var.SetDate(date);
137 ExpectVariantType(VT_DATE, var);
138 EXPECT_EQ(date, V_DATE(var.ptr()));
139 }
140
TEST(ScopedVariantTest,SetSigned1Byte)141 TEST(ScopedVariantTest, SetSigned1Byte) {
142 ScopedVariant var;
143 var.Set(static_cast<int8_t>('v'));
144 ExpectVariantType(VT_I1, var);
145 EXPECT_EQ('v', V_I1(var.ptr()));
146 }
147
TEST(ScopedVariantTest,SetSigned2Byte)148 TEST(ScopedVariantTest, SetSigned2Byte) {
149 ScopedVariant var;
150 var.Set(static_cast<int16_t>(123));
151 ExpectVariantType(VT_I2, var);
152 EXPECT_EQ(123, V_I2(var.ptr()));
153 }
154
TEST(ScopedVariantTest,SetSigned4Byte)155 TEST(ScopedVariantTest, SetSigned4Byte) {
156 ScopedVariant var;
157 var.Set(123);
158 ExpectVariantType(VT_I4, var);
159 EXPECT_EQ(123, V_I4(var.ptr()));
160 }
161
TEST(ScopedVariantTest,SetSigned8Byte)162 TEST(ScopedVariantTest, SetSigned8Byte) {
163 ScopedVariant var;
164 var.Set(static_cast<int64_t>(123));
165 ExpectVariantType(VT_I8, var);
166 EXPECT_EQ(123, V_I8(var.ptr()));
167 }
168
TEST(ScopedVariantTest,SetUnsigned1Byte)169 TEST(ScopedVariantTest, SetUnsigned1Byte) {
170 ScopedVariant var;
171 var.Set(static_cast<uint8_t>(123));
172 ExpectVariantType(VT_UI1, var);
173 EXPECT_EQ(123u, V_UI1(var.ptr()));
174 }
175
TEST(ScopedVariantTest,SetUnsigned2Byte)176 TEST(ScopedVariantTest, SetUnsigned2Byte) {
177 ScopedVariant var;
178 var.Set(static_cast<uint16_t>(123));
179 ExpectVariantType(VT_UI2, var);
180 EXPECT_EQ(123u, V_UI2(var.ptr()));
181 }
182
TEST(ScopedVariantTest,SetUnsigned4Byte)183 TEST(ScopedVariantTest, SetUnsigned4Byte) {
184 ScopedVariant var;
185 var.Set(static_cast<uint32_t>(123));
186 ExpectVariantType(VT_UI4, var);
187 EXPECT_EQ(123u, V_UI4(var.ptr()));
188 }
189
TEST(ScopedVariantTest,SetUnsigned8Byte)190 TEST(ScopedVariantTest, SetUnsigned8Byte) {
191 ScopedVariant var;
192 var.Set(static_cast<uint64_t>(123));
193 ExpectVariantType(VT_UI8, var);
194 EXPECT_EQ(123u, V_UI8(var.ptr()));
195 }
196
TEST(ScopedVariantTest,SetReal4Byte)197 TEST(ScopedVariantTest, SetReal4Byte) {
198 ScopedVariant var;
199 var.Set(123.123f);
200 ExpectVariantType(VT_R4, var);
201 EXPECT_EQ(123.123f, V_R4(var.ptr()));
202 }
203
TEST(ScopedVariantTest,SetReal8Byte)204 TEST(ScopedVariantTest, SetReal8Byte) {
205 ScopedVariant var;
206 var.Set(static_cast<double>(123.123));
207 ExpectVariantType(VT_R8, var);
208 EXPECT_EQ(123.123, V_R8(var.ptr()));
209 }
210
TEST(ScopedVariantTest,SetBooleanTrue)211 TEST(ScopedVariantTest, SetBooleanTrue) {
212 ScopedVariant var;
213 var.Set(true);
214 ExpectVariantType(VT_BOOL, var);
215 EXPECT_EQ(VARIANT_TRUE, V_BOOL(var.ptr()));
216 }
217
TEST(ScopedVariantTest,SetBooleanFalse)218 TEST(ScopedVariantTest, SetBooleanFalse) {
219 ScopedVariant var;
220 var.Set(false);
221 ExpectVariantType(VT_BOOL, var);
222 EXPECT_EQ(VARIANT_FALSE, V_BOOL(var.ptr()));
223 }
224
TEST(ScopedVariantTest,SetComIDispatch)225 TEST(ScopedVariantTest, SetComIDispatch) {
226 ScopedVariant var;
227 Microsoft::WRL::ComPtr<IDispatch> dispatch_stub =
228 Microsoft::WRL::Make<DispatchStub>();
229 ExpectRefCount(1U, dispatch_stub.Get());
230 var.Set(dispatch_stub.Get());
231 ExpectVariantType(VT_DISPATCH, var);
232 EXPECT_EQ(dispatch_stub.Get(), V_DISPATCH(var.ptr()));
233 ExpectRefCount(2U, dispatch_stub.Get());
234 var.Reset();
235 ExpectRefCount(1U, dispatch_stub.Get());
236 }
237
TEST(ScopedVariantTest,SetComNullIDispatch)238 TEST(ScopedVariantTest, SetComNullIDispatch) {
239 ScopedVariant var;
240 var.Set(static_cast<IDispatch*>(nullptr));
241 ExpectVariantType(VT_DISPATCH, var);
242 EXPECT_EQ(nullptr, V_DISPATCH(var.ptr()));
243 }
244
TEST(ScopedVariantTest,SetComIUnknown)245 TEST(ScopedVariantTest, SetComIUnknown) {
246 ScopedVariant var;
247 Microsoft::WRL::ComPtr<IUnknown> unknown_stub =
248 Microsoft::WRL::Make<DispatchStub>();
249 ExpectRefCount(1U, unknown_stub.Get());
250 var.Set(unknown_stub.Get());
251 ExpectVariantType(VT_UNKNOWN, var);
252 EXPECT_EQ(unknown_stub.Get(), V_UNKNOWN(var.ptr()));
253 ExpectRefCount(2U, unknown_stub.Get());
254 var.Reset();
255 ExpectRefCount(1U, unknown_stub.Get());
256 }
257
TEST(ScopedVariantTest,SetComNullIUnknown)258 TEST(ScopedVariantTest, SetComNullIUnknown) {
259 ScopedVariant var;
260 var.Set(static_cast<IUnknown*>(nullptr));
261 ExpectVariantType(VT_UNKNOWN, var);
262 EXPECT_EQ(nullptr, V_UNKNOWN(var.ptr()));
263 }
264
TEST(ScopedVariant,ScopedComIDispatchConstructor)265 TEST(ScopedVariant, ScopedComIDispatchConstructor) {
266 Microsoft::WRL::ComPtr<IDispatch> dispatch_stub =
267 Microsoft::WRL::Make<DispatchStub>();
268 {
269 ScopedVariant var(dispatch_stub.Get());
270 ExpectVariantType(VT_DISPATCH, var);
271 EXPECT_EQ(dispatch_stub.Get(), V_DISPATCH(var.ptr()));
272 ExpectRefCount(2U, dispatch_stub.Get());
273 }
274 ExpectRefCount(1U, dispatch_stub.Get());
275 }
276
TEST(ScopedVariant,ScopedComIDispatchMove)277 TEST(ScopedVariant, ScopedComIDispatchMove) {
278 Microsoft::WRL::ComPtr<IDispatch> dispatch_stub =
279 Microsoft::WRL::Make<DispatchStub>();
280 {
281 ScopedVariant var1(dispatch_stub.Get());
282 ExpectRefCount(2U, dispatch_stub.Get());
283 ScopedVariant var2(std::move(var1));
284 ExpectRefCount(2U, dispatch_stub.Get());
285 ScopedVariant var3;
286 var3 = std::move(var2);
287 ExpectRefCount(2U, dispatch_stub.Get());
288 }
289 ExpectRefCount(1U, dispatch_stub.Get());
290 }
291
TEST(ScopedVariant,ScopedComIDispatchCopy)292 TEST(ScopedVariant, ScopedComIDispatchCopy) {
293 Microsoft::WRL::ComPtr<IDispatch> dispatch_stub =
294 Microsoft::WRL::Make<DispatchStub>();
295 {
296 ScopedVariant var1(dispatch_stub.Get());
297 ExpectRefCount(2U, dispatch_stub.Get());
298 ScopedVariant var2(static_cast<const VARIANT&>(var1));
299 ExpectRefCount(3U, dispatch_stub.Get());
300 ScopedVariant var3;
301 var3 = static_cast<const VARIANT&>(var2);
302 ExpectRefCount(4U, dispatch_stub.Get());
303 }
304 ExpectRefCount(1U, dispatch_stub.Get());
305 }
306
TEST(ScopedVariant,ScopedComIUnknownConstructor)307 TEST(ScopedVariant, ScopedComIUnknownConstructor) {
308 Microsoft::WRL::ComPtr<IUnknown> unknown_stub =
309 Microsoft::WRL::Make<DispatchStub>();
310 {
311 ScopedVariant unk_var(unknown_stub.Get());
312 ExpectVariantType(VT_UNKNOWN, unk_var);
313 EXPECT_EQ(unknown_stub.Get(), V_UNKNOWN(unk_var.ptr()));
314 ExpectRefCount(2U, unknown_stub.Get());
315 }
316 ExpectRefCount(1U, unknown_stub.Get());
317 }
318
TEST(ScopedVariant,ScopedComIUnknownWithRawVariant)319 TEST(ScopedVariant, ScopedComIUnknownWithRawVariant) {
320 ScopedVariant var;
321 Microsoft::WRL::ComPtr<IUnknown> unknown_stub =
322 Microsoft::WRL::Make<DispatchStub>();
323 VARIANT raw;
324 raw.vt = VT_UNKNOWN;
325 raw.punkVal = unknown_stub.Get();
326 ExpectRefCount(1U, unknown_stub.Get());
327 var.Set(raw);
328 ExpectRefCount(2U, unknown_stub.Get());
329 var.Reset();
330 ExpectRefCount(1U, unknown_stub.Get());
331 }
332
TEST(ScopedVariant,SetSafeArray)333 TEST(ScopedVariant, SetSafeArray) {
334 SAFEARRAY* sa = ::SafeArrayCreateVector(VT_UI1, 0, 100);
335 ASSERT_TRUE(sa);
336
337 ScopedVariant var;
338 var.Set(sa);
339 EXPECT_TRUE(ScopedVariant::IsLeakableVarType(var.type()));
340 ExpectVariantType(static_cast<VARENUM>(VT_ARRAY | VT_UI1), var);
341 EXPECT_EQ(sa, V_ARRAY(var.ptr()));
342 // The array is destroyed in the destructor of var.
343 sa = nullptr;
344 }
345
TEST(ScopedVariant,SetNullSafeArray)346 TEST(ScopedVariant, SetNullSafeArray) {
347 ScopedVariant var;
348 var.Set(static_cast<SAFEARRAY*>(nullptr));
349 ExpectVariantType(VT_EMPTY, var);
350 }
351
352 } // namespace win
353 } // namespace base
354