| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/win/variant_conversions.h" |
| |
| #include <stdint.h> |
| #include <wrl/client.h> |
| #include <wrl/implements.h> |
| |
| #include <set> |
| #include <utility> |
| |
| #include "base/containers/contains.h" |
| #include "base/win/dispatch_stub.h" |
| #include "base/win/scoped_bstr.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using base::win::internal::VariantConverter; |
| using base::win::test::DispatchStub; |
| |
| namespace base { |
| namespace win { |
| |
| namespace { |
| |
| static constexpr VARTYPE kSupportedVartypes[] = { |
| VT_BOOL, VT_I1, VT_UI1, VT_I2, VT_UI2, VT_I4, VT_UI4, VT_I8, |
| VT_UI8, VT_R4, VT_R8, VT_DATE, VT_BSTR, VT_UNKNOWN, VT_DISPATCH}; |
| |
| template <VARTYPE ElementVartype> |
| static bool TestIsConvertibleTo(const std::set<VARTYPE>& allowed_vartypes) { |
| for (VARTYPE vartype : kSupportedVartypes) { |
| if (VariantConverter<ElementVartype>::IsConvertibleTo(vartype) != |
| base::Contains(allowed_vartypes, vartype)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| template <VARTYPE ElementVartype> |
| static bool TestIsConvertibleFrom(const std::set<VARTYPE>& allowed_vartypes) { |
| for (VARTYPE vartype : kSupportedVartypes) { |
| if (VariantConverter<ElementVartype>::IsConvertibleFrom(vartype) != |
| base::Contains(allowed_vartypes, vartype)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| } // namespace |
| |
| TEST(VariantConverterTest, VariantTypeBool) { |
| VARIANT variant; |
| V_VT(&variant) = VT_BOOL; |
| |
| VariantConverter<VT_BOOL>::RawSet(&variant, VARIANT_TRUE); |
| EXPECT_EQ(V_BOOL(&variant), VARIANT_TRUE); |
| EXPECT_EQ(VariantConverter<VT_BOOL>::RawGet(variant), VARIANT_TRUE); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_BOOL}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_BOOL>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_BOOL>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeI1) { |
| VARIANT variant; |
| V_VT(&variant) = VT_I1; |
| |
| VariantConverter<VT_I1>::RawSet(&variant, 34); |
| EXPECT_EQ(V_I1(&variant), 34); |
| EXPECT_EQ(VariantConverter<VT_I1>::RawGet(variant), 34); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_I1}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_I1>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_I1>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeUI1) { |
| VARIANT variant; |
| V_VT(&variant) = VT_UI1; |
| |
| VariantConverter<VT_UI1>::RawSet(&variant, 34U); |
| EXPECT_EQ(V_UI1(&variant), 34U); |
| EXPECT_EQ(VariantConverter<VT_UI1>::RawGet(variant), 34U); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_UI1}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_UI1>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_UI1>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeI2) { |
| VARIANT variant; |
| V_VT(&variant) = VT_I2; |
| |
| VariantConverter<VT_I2>::RawSet(&variant, 8738); |
| EXPECT_EQ(V_I2(&variant), 8738); |
| EXPECT_EQ(VariantConverter<VT_I2>::RawGet(variant), 8738); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_I2}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_I2>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_I2>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeUI2) { |
| VARIANT variant; |
| V_VT(&variant) = VT_UI2; |
| |
| VariantConverter<VT_UI2>::RawSet(&variant, 8738U); |
| EXPECT_EQ(V_UI2(&variant), 8738U); |
| EXPECT_EQ(VariantConverter<VT_UI2>::RawGet(variant), 8738U); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_UI2}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_UI2>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_UI2>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeI4) { |
| VARIANT variant; |
| V_VT(&variant) = VT_I4; |
| |
| VariantConverter<VT_I4>::RawSet(&variant, 572662306); |
| EXPECT_EQ(V_I4(&variant), 572662306); |
| EXPECT_EQ(VariantConverter<VT_I4>::RawGet(variant), 572662306); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_I4}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_I4>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_I4>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeUI4) { |
| VARIANT variant; |
| V_VT(&variant) = VT_UI4; |
| |
| VariantConverter<VT_UI4>::RawSet(&variant, 572662306U); |
| EXPECT_EQ(V_UI4(&variant), 572662306U); |
| EXPECT_EQ(VariantConverter<VT_UI4>::RawGet(variant), 572662306U); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_UI4}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_UI4>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_UI4>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeI8) { |
| VARIANT variant; |
| V_VT(&variant) = VT_I8; |
| |
| VariantConverter<VT_I8>::RawSet(&variant, 2459565876494606882); |
| EXPECT_EQ(V_I8(&variant), 2459565876494606882); |
| EXPECT_EQ(VariantConverter<VT_I8>::RawGet(variant), 2459565876494606882); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_I8}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_I8>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_I8>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeUI8) { |
| VARIANT variant; |
| V_VT(&variant) = VT_UI8; |
| |
| VariantConverter<VT_UI8>::RawSet(&variant, 2459565876494606882U); |
| EXPECT_EQ(V_UI8(&variant), 2459565876494606882U); |
| EXPECT_EQ(VariantConverter<VT_UI8>::RawGet(variant), 2459565876494606882U); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_UI8}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_UI8>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_UI8>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeR4) { |
| VARIANT variant; |
| V_VT(&variant) = VT_R4; |
| |
| VariantConverter<VT_R4>::RawSet(&variant, 3.14159f); |
| EXPECT_EQ(V_R4(&variant), 3.14159f); |
| EXPECT_EQ(VariantConverter<VT_R4>::RawGet(variant), 3.14159f); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_R4}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_R4>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_R4>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeR8) { |
| VARIANT variant; |
| V_VT(&variant) = VT_R8; |
| |
| VariantConverter<VT_R8>::RawSet(&variant, 3.14159); |
| EXPECT_EQ(V_R8(&variant), 3.14159); |
| EXPECT_EQ(VariantConverter<VT_R8>::RawGet(variant), 3.14159); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_R8}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_R8>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_R8>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeDate) { |
| SYSTEMTIME sys_time; |
| ::GetSystemTime(&sys_time); |
| DATE date; |
| ::SystemTimeToVariantTime(&sys_time, &date); |
| |
| VARIANT variant; |
| V_VT(&variant) = VT_DATE; |
| |
| VariantConverter<VT_DATE>::RawSet(&variant, date); |
| EXPECT_EQ(V_DATE(&variant), date); |
| EXPECT_EQ(VariantConverter<VT_DATE>::RawGet(variant), date); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_DATE}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_DATE>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_DATE>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeBstr) { |
| ScopedBstr scoped_bstr; |
| scoped_bstr.Allocate(L"some text"); |
| |
| VARIANT variant; |
| V_VT(&variant) = VT_BSTR; |
| |
| VariantConverter<VT_BSTR>::RawSet(&variant, scoped_bstr.Get()); |
| EXPECT_EQ(V_BSTR(&variant), scoped_bstr.Get()); |
| EXPECT_EQ(VariantConverter<VT_BSTR>::RawGet(variant), scoped_bstr.Get()); |
| |
| const std::set<VARTYPE> allowed_vartypes = {VT_BSTR}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_BSTR>(allowed_vartypes)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_BSTR>(allowed_vartypes)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeUnknown) { |
| Microsoft::WRL::ComPtr<IUnknown> unknown = |
| Microsoft::WRL::Make<DispatchStub>(); |
| |
| VARIANT variant; |
| V_VT(&variant) = VT_UNKNOWN; |
| |
| VariantConverter<VT_UNKNOWN>::RawSet(&variant, unknown.Get()); |
| EXPECT_EQ(V_UNKNOWN(&variant), unknown.Get()); |
| EXPECT_EQ(VariantConverter<VT_UNKNOWN>::RawGet(variant), unknown.Get()); |
| |
| const std::set<VARTYPE> allow_convertible_to = {VT_UNKNOWN}; |
| const std::set<VARTYPE> allow_convertible_from = {VT_UNKNOWN, VT_DISPATCH}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_UNKNOWN>(allow_convertible_to)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_UNKNOWN>(allow_convertible_from)); |
| } |
| |
| TEST(VariantConverterTest, VariantTypeDispatch) { |
| Microsoft::WRL::ComPtr<IDispatch> dispatch = |
| Microsoft::WRL::Make<DispatchStub>(); |
| |
| VARIANT variant; |
| V_VT(&variant) = VT_DISPATCH; |
| |
| VariantConverter<VT_DISPATCH>::RawSet(&variant, dispatch.Get()); |
| EXPECT_EQ(V_DISPATCH(&variant), dispatch.Get()); |
| EXPECT_EQ(VariantConverter<VT_DISPATCH>::RawGet(variant), dispatch.Get()); |
| |
| const std::set<VARTYPE> allow_convertible_to = {VT_UNKNOWN, VT_DISPATCH}; |
| const std::set<VARTYPE> allow_convertible_from = {VT_DISPATCH}; |
| EXPECT_TRUE(TestIsConvertibleTo<VT_DISPATCH>(allow_convertible_to)); |
| EXPECT_TRUE(TestIsConvertibleFrom<VT_DISPATCH>(allow_convertible_from)); |
| } |
| |
| } // namespace win |
| } // namespace base |