diff options
Diffstat (limited to 'base/scoped_variant_win_unittest.cc')
-rw-r--r-- | base/scoped_variant_win_unittest.cc | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/base/scoped_variant_win_unittest.cc b/base/scoped_variant_win_unittest.cc new file mode 100644 index 0000000..e826edd --- /dev/null +++ b/base/scoped_variant_win_unittest.cc @@ -0,0 +1,215 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/scoped_variant_win.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +static const wchar_t kTestString1[] = L"Used to create BSTRs"; +static const wchar_t kTestString2[] = L"Also used to create BSTRs"; + +void GiveMeAVariant(VARIANT* ret) { + EXPECT_TRUE(ret != NULL); + ret->vt = VT_BSTR; + V_BSTR(ret) = ::SysAllocString(kTestString1); +} + +// A dummy IDispatch implementation (if you can call it that). +// The class does nothing intelligent really. Only increments a counter +// when AddRef is called and decrements it when Release is called. +class FakeComObject : public IDispatch { + public: + FakeComObject() : ref_(0) { + } + + STDMETHOD_(DWORD, AddRef)() { + ref_++; + return ref_; + } + + STDMETHOD_(DWORD, Release)() { + ref_--; + return ref_; + } + + STDMETHOD(QueryInterface)(REFIID, void**) { + return E_NOTIMPL; + } + + STDMETHOD(GetTypeInfoCount)(UINT*) { + return E_NOTIMPL; + } + + STDMETHOD(GetTypeInfo)(UINT, LCID, ITypeInfo**) { + return E_NOTIMPL; + } + + STDMETHOD(GetIDsOfNames)(REFIID, LPOLESTR*, UINT, LCID, DISPID*) { + return E_NOTIMPL; + } + + STDMETHOD(Invoke)(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, + EXCEPINFO*, UINT*) { + return E_NOTIMPL; + } + + // A way to check the internal reference count of the class. + int ref_count() const { + return ref_; + } + + protected: + int ref_; +}; + +} // namespace + +TEST(ScopedVariantTest, ScopedVariant) { + ScopedVariant var; + EXPECT_TRUE(var.type() == VT_EMPTY); + // V_BSTR(&var) = NULL; <- NOTE: Assignment like that is not supported + + ScopedVariant var_bstr(L"VT_BSTR"); + EXPECT_EQ(VT_BSTR, V_VT(&var_bstr)); + EXPECT_TRUE(V_BSTR(&var_bstr) != NULL); // can't use EXPECT_NE for BSTR + var_bstr.Reset(); + EXPECT_NE(VT_BSTR, V_VT(&var_bstr)); + var_bstr.Set(kTestString2); + EXPECT_EQ(VT_BSTR, V_VT(&var_bstr)); + + VARIANT tmp = var_bstr.Release(); + EXPECT_EQ(VT_EMPTY, V_VT(&var_bstr)); + EXPECT_EQ(VT_BSTR, V_VT(&tmp)); + EXPECT_EQ(0, lstrcmp(V_BSTR(&tmp), kTestString2)); + + var.Reset(tmp); + EXPECT_EQ(VT_BSTR, V_VT(&var)); + EXPECT_EQ(0, lstrcmpW(V_BSTR(&var), kTestString2)); + + var_bstr.Swap(var); + EXPECT_EQ(VT_EMPTY, V_VT(&var)); + EXPECT_EQ(VT_BSTR, V_VT(&var_bstr)); + EXPECT_EQ(0, lstrcmpW(V_BSTR(&var_bstr), kTestString2)); + var_bstr.Reset(); + + // Test the Compare and Copy routines. + GiveMeAVariant(var_bstr.Receive()); + ScopedVariant var_bstr2(V_BSTR(&var_bstr)); + EXPECT_EQ(0, var_bstr.Compare(var_bstr2)); + var_bstr2.Reset(); + EXPECT_NE(0, var_bstr.Compare(var_bstr2)); + var_bstr2.Reset(var_bstr.Copy()); + EXPECT_EQ(0, var_bstr.Compare(var_bstr2)); + var_bstr2.Reset(); + var_bstr2.Set(V_BSTR(&var_bstr)); + EXPECT_EQ(0, var_bstr.Compare(var_bstr2)); + var_bstr2.Reset(); + var_bstr.Reset(); + + // Test for the SetDate setter. + SYSTEMTIME sys_time; + ::GetSystemTime(&sys_time); + DATE date; + ::SystemTimeToVariantTime(&sys_time, &date); + var.Reset(); + var.SetDate(date); + EXPECT_EQ(VT_DATE, var.type()); + EXPECT_EQ(date, V_DATE(&var)); + + // Simple setter tests. These do not require resetting the variant + // after each test since the variant type is not "leakable" (i.e. doesn't + // need to be freed explicitly). + + // We need static cast here since char defaults to int (!?). + var.Set(static_cast<int8>('v')); + EXPECT_EQ(VT_I1, var.type()); + EXPECT_EQ('v', V_I1(&var)); + + var.Set(static_cast<short>(123)); + EXPECT_EQ(VT_I2, var.type()); + EXPECT_EQ(123, V_I2(&var)); + + var.Set(static_cast<int32>(123)); + EXPECT_EQ(VT_I4, var.type()); + EXPECT_EQ(123, V_I4(&var)); + + var.Set(static_cast<int64>(123)); + EXPECT_EQ(VT_I8, var.type()); + EXPECT_EQ(123, V_I8(&var)); + + var.Set(static_cast<uint8>(123)); + EXPECT_EQ(VT_UI1, var.type()); + EXPECT_EQ(123, V_UI1(&var)); + + var.Set(static_cast<unsigned short>(123)); + EXPECT_EQ(VT_UI2, var.type()); + EXPECT_EQ(123, V_UI2(&var)); + + var.Set(static_cast<uint32>(123)); + EXPECT_EQ(VT_UI4, var.type()); + EXPECT_EQ(123, V_UI4(&var)); + + var.Set(static_cast<uint64>(123)); + EXPECT_EQ(VT_UI8, var.type()); + EXPECT_EQ(123, V_UI8(&var)); + + var.Set(123.123f); + EXPECT_EQ(VT_R4, var.type()); + EXPECT_EQ(123.123f, V_R4(&var)); + + var.Set(static_cast<double>(123.123)); + EXPECT_EQ(VT_R8, var.type()); + EXPECT_EQ(123.123, V_R8(&var)); + + var.Set(true); + EXPECT_EQ(VT_BOOL, var.type()); + EXPECT_EQ(VARIANT_TRUE, V_BOOL(&var)); + var.Set(false); + EXPECT_EQ(VT_BOOL, var.type()); + EXPECT_EQ(VARIANT_FALSE, V_BOOL(&var)); + + // Com interface tests + + var.Set(static_cast<IDispatch*>(NULL)); + EXPECT_EQ(VT_DISPATCH, var.type()); + EXPECT_EQ(NULL, V_DISPATCH(&var)); + var.Reset(); + + var.Set(static_cast<IUnknown*>(NULL)); + EXPECT_EQ(VT_UNKNOWN, var.type()); + EXPECT_EQ(NULL, V_UNKNOWN(&var)); + var.Reset(); + + FakeComObject faker; + EXPECT_EQ(0, faker.ref_count()); + var.Set(static_cast<IDispatch*>(&faker)); + EXPECT_EQ(VT_DISPATCH, var.type()); + EXPECT_EQ(&faker, V_DISPATCH(&var)); + EXPECT_EQ(1, faker.ref_count()); + var.Reset(); + EXPECT_EQ(0, faker.ref_count()); + + var.Set(static_cast<IUnknown*>(&faker)); + EXPECT_EQ(VT_UNKNOWN, var.type()); + EXPECT_EQ(&faker, V_UNKNOWN(&var)); + EXPECT_EQ(1, faker.ref_count()); + var.Reset(); + EXPECT_EQ(0, faker.ref_count()); + + // SAFEARRAY tests + var.Set(static_cast<SAFEARRAY*>(NULL)); + EXPECT_EQ(VT_EMPTY, var.type()); + + SAFEARRAY* sa = ::SafeArrayCreateVector(VT_UI1, 0, 100); + ASSERT_TRUE(sa != NULL); + + var.Set(sa); +#ifndef OFFICIAL_BUILD + EXPECT_TRUE(ScopedVariant::IsLeakableVarType(var.type())); +#endif + EXPECT_EQ(VT_ARRAY | VT_UI1, var.type()); + EXPECT_EQ(sa, V_ARRAY(&var)); + // The array is destroyed in the destructor of var. +} |