• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2009 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_variant.h"
6 #include "testing/gtest/include/gtest/gtest.h"
7 
8 namespace base {
9 namespace win {
10 
11 namespace {
12 
13 static const wchar_t kTestString1[] = L"Used to create BSTRs";
14 static const wchar_t kTestString2[] = L"Also used to create BSTRs";
15 
GiveMeAVariant(VARIANT * ret)16 void GiveMeAVariant(VARIANT* ret) {
17   EXPECT_TRUE(ret != NULL);
18   ret->vt = VT_BSTR;
19   V_BSTR(ret) = ::SysAllocString(kTestString1);
20 }
21 
22 // A dummy IDispatch implementation (if you can call it that).
23 // The class does nothing intelligent really.  Only increments a counter
24 // when AddRef is called and decrements it when Release is called.
25 class FakeComObject : public IDispatch {
26  public:
FakeComObject()27   FakeComObject() : ref_(0) {
28   }
29 
STDMETHOD_(DWORD,AddRef)30   STDMETHOD_(DWORD, AddRef)() {
31     ref_++;
32     return ref_;
33   }
34 
STDMETHOD_(DWORD,Release)35   STDMETHOD_(DWORD, Release)() {
36     ref_--;
37     return ref_;
38   }
39 
STDMETHOD(QueryInterface)40   STDMETHOD(QueryInterface)(REFIID, void**) {
41     return E_NOTIMPL;
42   }
43 
STDMETHOD(GetTypeInfoCount)44   STDMETHOD(GetTypeInfoCount)(UINT*) {
45     return E_NOTIMPL;
46   }
47 
STDMETHOD(GetTypeInfo)48   STDMETHOD(GetTypeInfo)(UINT, LCID, ITypeInfo**) {
49     return E_NOTIMPL;
50   }
51 
STDMETHOD(GetIDsOfNames)52   STDMETHOD(GetIDsOfNames)(REFIID, LPOLESTR*, UINT, LCID, DISPID*) {
53     return E_NOTIMPL;
54   }
55 
STDMETHOD(Invoke)56   STDMETHOD(Invoke)(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*,
57                     EXCEPINFO*, UINT*) {
58     return E_NOTIMPL;
59   }
60 
61   // A way to check the internal reference count of the class.
ref_count() const62   int ref_count() const {
63     return ref_;
64   }
65 
66  protected:
67   int ref_;
68 };
69 
70 }  // namespace
71 
TEST(ScopedVariantTest,ScopedVariant)72 TEST(ScopedVariantTest, ScopedVariant) {
73   ScopedVariant var;
74   EXPECT_TRUE(var.type() == VT_EMPTY);
75   // V_BSTR(&var) = NULL;  <- NOTE: Assignment like that is not supported
76 
77   ScopedVariant var_bstr(L"VT_BSTR");
78   EXPECT_EQ(VT_BSTR, V_VT(&var_bstr));
79   EXPECT_TRUE(V_BSTR(&var_bstr) != NULL);  // can't use EXPECT_NE for BSTR
80   var_bstr.Reset();
81   EXPECT_NE(VT_BSTR, V_VT(&var_bstr));
82   var_bstr.Set(kTestString2);
83   EXPECT_EQ(VT_BSTR, V_VT(&var_bstr));
84 
85   VARIANT tmp = var_bstr.Release();
86   EXPECT_EQ(VT_EMPTY, V_VT(&var_bstr));
87   EXPECT_EQ(VT_BSTR, V_VT(&tmp));
88   EXPECT_EQ(0, lstrcmp(V_BSTR(&tmp), kTestString2));
89 
90   var.Reset(tmp);
91   EXPECT_EQ(VT_BSTR, V_VT(&var));
92   EXPECT_EQ(0, lstrcmpW(V_BSTR(&var), kTestString2));
93 
94   var_bstr.Swap(var);
95   EXPECT_EQ(VT_EMPTY, V_VT(&var));
96   EXPECT_EQ(VT_BSTR, V_VT(&var_bstr));
97   EXPECT_EQ(0, lstrcmpW(V_BSTR(&var_bstr), kTestString2));
98   var_bstr.Reset();
99 
100   // Test the Compare and Copy routines.
101   GiveMeAVariant(var_bstr.Receive());
102   ScopedVariant var_bstr2(V_BSTR(&var_bstr));
103   EXPECT_EQ(0, var_bstr.Compare(var_bstr2));
104   var_bstr2.Reset();
105   EXPECT_NE(0, var_bstr.Compare(var_bstr2));
106   var_bstr2.Reset(var_bstr.Copy());
107   EXPECT_EQ(0, var_bstr.Compare(var_bstr2));
108   var_bstr2.Reset();
109   var_bstr2.Set(V_BSTR(&var_bstr));
110   EXPECT_EQ(0, var_bstr.Compare(var_bstr2));
111   var_bstr2.Reset();
112   var_bstr.Reset();
113 
114   // Test for the SetDate setter.
115   SYSTEMTIME sys_time;
116   ::GetSystemTime(&sys_time);
117   DATE date;
118   ::SystemTimeToVariantTime(&sys_time, &date);
119   var.Reset();
120   var.SetDate(date);
121   EXPECT_EQ(VT_DATE, var.type());
122   EXPECT_EQ(date, V_DATE(&var));
123 
124   // Simple setter tests.  These do not require resetting the variant
125   // after each test since the variant type is not "leakable" (i.e. doesn't
126   // need to be freed explicitly).
127 
128   // We need static cast here since char defaults to int (!?).
129   var.Set(static_cast<int8>('v'));
130   EXPECT_EQ(VT_I1, var.type());
131   EXPECT_EQ('v', V_I1(&var));
132 
133   var.Set(static_cast<short>(123));
134   EXPECT_EQ(VT_I2, var.type());
135   EXPECT_EQ(123, V_I2(&var));
136 
137   var.Set(static_cast<int32>(123));
138   EXPECT_EQ(VT_I4, var.type());
139   EXPECT_EQ(123, V_I4(&var));
140 
141   var.Set(static_cast<int64>(123));
142   EXPECT_EQ(VT_I8, var.type());
143   EXPECT_EQ(123, V_I8(&var));
144 
145   var.Set(static_cast<uint8>(123));
146   EXPECT_EQ(VT_UI1, var.type());
147   EXPECT_EQ(123, V_UI1(&var));
148 
149   var.Set(static_cast<unsigned short>(123));
150   EXPECT_EQ(VT_UI2, var.type());
151   EXPECT_EQ(123, V_UI2(&var));
152 
153   var.Set(static_cast<uint32>(123));
154   EXPECT_EQ(VT_UI4, var.type());
155   EXPECT_EQ(123, V_UI4(&var));
156 
157   var.Set(static_cast<uint64>(123));
158   EXPECT_EQ(VT_UI8, var.type());
159   EXPECT_EQ(123, V_UI8(&var));
160 
161   var.Set(123.123f);
162   EXPECT_EQ(VT_R4, var.type());
163   EXPECT_EQ(123.123f, V_R4(&var));
164 
165   var.Set(static_cast<double>(123.123));
166   EXPECT_EQ(VT_R8, var.type());
167   EXPECT_EQ(123.123, V_R8(&var));
168 
169   var.Set(true);
170   EXPECT_EQ(VT_BOOL, var.type());
171   EXPECT_EQ(VARIANT_TRUE, V_BOOL(&var));
172   var.Set(false);
173   EXPECT_EQ(VT_BOOL, var.type());
174   EXPECT_EQ(VARIANT_FALSE, V_BOOL(&var));
175 
176   // Com interface tests
177 
178   var.Set(static_cast<IDispatch*>(NULL));
179   EXPECT_EQ(VT_DISPATCH, var.type());
180   EXPECT_EQ(NULL, V_DISPATCH(&var));
181   var.Reset();
182 
183   var.Set(static_cast<IUnknown*>(NULL));
184   EXPECT_EQ(VT_UNKNOWN, var.type());
185   EXPECT_EQ(NULL, V_UNKNOWN(&var));
186   var.Reset();
187 
188   FakeComObject faker;
189   EXPECT_EQ(0, faker.ref_count());
190   var.Set(static_cast<IDispatch*>(&faker));
191   EXPECT_EQ(VT_DISPATCH, var.type());
192   EXPECT_EQ(&faker, V_DISPATCH(&var));
193   EXPECT_EQ(1, faker.ref_count());
194   var.Reset();
195   EXPECT_EQ(0, faker.ref_count());
196 
197   var.Set(static_cast<IUnknown*>(&faker));
198   EXPECT_EQ(VT_UNKNOWN, var.type());
199   EXPECT_EQ(&faker, V_UNKNOWN(&var));
200   EXPECT_EQ(1, faker.ref_count());
201   var.Reset();
202   EXPECT_EQ(0, faker.ref_count());
203 
204   {
205     ScopedVariant disp_var(&faker);
206     EXPECT_EQ(VT_DISPATCH, disp_var.type());
207     EXPECT_EQ(&faker, V_DISPATCH(&disp_var));
208     EXPECT_EQ(1, faker.ref_count());
209   }
210   EXPECT_EQ(0, faker.ref_count());
211 
212   {
213     ScopedVariant ref1(&faker);
214     EXPECT_EQ(1, faker.ref_count());
215     ScopedVariant ref2(static_cast<const VARIANT&>(ref1));
216     EXPECT_EQ(2, faker.ref_count());
217     ScopedVariant ref3;
218     ref3 = static_cast<const VARIANT&>(ref2);
219     EXPECT_EQ(3, faker.ref_count());
220   }
221   EXPECT_EQ(0, faker.ref_count());
222 
223   {
224     ScopedVariant unk_var(static_cast<IUnknown*>(&faker));
225     EXPECT_EQ(VT_UNKNOWN, unk_var.type());
226     EXPECT_EQ(&faker, V_UNKNOWN(&unk_var));
227     EXPECT_EQ(1, faker.ref_count());
228   }
229   EXPECT_EQ(0, faker.ref_count());
230 
231   VARIANT raw;
232   raw.vt = VT_UNKNOWN;
233   raw.punkVal = &faker;
234   EXPECT_EQ(0, faker.ref_count());
235   var.Set(raw);
236   EXPECT_EQ(1, faker.ref_count());
237   var.Reset();
238   EXPECT_EQ(0, faker.ref_count());
239 
240   {
241     ScopedVariant number(123);
242     EXPECT_EQ(VT_I4, number.type());
243     EXPECT_EQ(123, V_I4(&number));
244   }
245 
246   // SAFEARRAY tests
247   var.Set(static_cast<SAFEARRAY*>(NULL));
248   EXPECT_EQ(VT_EMPTY, var.type());
249 
250   SAFEARRAY* sa = ::SafeArrayCreateVector(VT_UI1, 0, 100);
251   ASSERT_TRUE(sa != NULL);
252 
253   var.Set(sa);
254 #ifndef OFFICIAL_BUILD
255   EXPECT_TRUE(ScopedVariant::IsLeakableVarType(var.type()));
256 #endif
257   EXPECT_EQ(VT_ARRAY | VT_UI1, var.type());
258   EXPECT_EQ(sa, V_ARRAY(&var));
259   // The array is destroyed in the destructor of var.
260 }
261 
262 }  // namespace win
263 }  // namespace base
264