chromium/base/win/variant_vector_unittest.cc

// 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_vector.h"

#include <stddef.h>
#include <windows.foundation.h>
#include <wrl/client.h>

#include <optional>

#include "base/test/gtest_util.h"
#include "base/win/dispatch_stub.h"
#include "base/win/scoped_safearray.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::win::test::DispatchStub;

namespace base {
namespace win {

TEST(VariantVectorTest, InitiallyEmpty) {
  VariantVector vector;
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_TRUE(vector.Empty());
}

TEST(VariantVectorTest, MoveConstructor) {
  VariantVector vector1;
  Microsoft::WRL::ComPtr<IDispatch> dispatch =
      Microsoft::WRL::Make<DispatchStub>();
  vector1.Insert<VT_DISPATCH>(dispatch.Get());
  EXPECT_EQ(vector1.Type(), VT_DISPATCH);
  EXPECT_EQ(vector1.Size(), 1U);

  VariantVector vector2(std::move(vector1));
  EXPECT_EQ(vector1.Type(), VT_EMPTY);
  EXPECT_EQ(vector1.Size(), 0U);
  EXPECT_EQ(vector2.Type(), VT_DISPATCH);
  EXPECT_EQ(vector2.Size(), 1U);
  // |dispatch| should have been transferred to |vector2|.
  EXPECT_EQ(dispatch.Reset(), 1U);
}

TEST(VariantVectorTest, MoveAssignOperator) {
  VariantVector vector1, vector2;
  Microsoft::WRL::ComPtr<IDispatch> dispatch1 =
      Microsoft::WRL::Make<DispatchStub>();
  Microsoft::WRL::ComPtr<IDispatch> dispatch2 =
      Microsoft::WRL::Make<DispatchStub>();
  vector1.Insert<VT_DISPATCH>(dispatch1.Get());
  vector2.Insert<VT_UNKNOWN>(dispatch2.Get());
  EXPECT_EQ(vector1.Type(), VT_DISPATCH);
  EXPECT_EQ(vector1.Size(), 1U);
  EXPECT_EQ(vector2.Type(), VT_UNKNOWN);
  EXPECT_EQ(vector2.Size(), 1U);
  vector1 = std::move(vector2);
  EXPECT_EQ(vector1.Type(), VT_UNKNOWN);
  EXPECT_EQ(vector1.Size(), 1U);
  EXPECT_EQ(vector2.Type(), VT_EMPTY);
  EXPECT_EQ(vector2.Size(), 0U);
  // |dispatch1| should have been released during the move.
  EXPECT_EQ(dispatch1.Reset(), 0U);
  // |dispatch2| should have been transferred to |vector1|.
  EXPECT_EQ(dispatch2.Reset(), 1U);

  // Indirectly move |vector1| into itself.
  VariantVector& reference_to_vector1 = vector1;
  EXPECT_DCHECK_DEATH(vector1 = std::move(reference_to_vector1));
}

TEST(VariantVectorTest, Insert) {
  VariantVector vector;
  vector.Insert<VT_I4>(123);
  EXPECT_EQ(vector.Type(), VT_I4);
  // The first insert sets the type to VT_I4, and attempting to insert
  // unrelated types will silently fail in release builds but DCHECKs
  // in debug builds.
  EXPECT_DCHECK_DEATH(vector.Insert<VT_UI4>(1U));
  EXPECT_DCHECK_DEATH(vector.Insert<VT_R8>(100.0));
  EXPECT_EQ(vector.Type(), VT_I4);
  EXPECT_EQ(vector.Size(), 1U);
  EXPECT_FALSE(vector.Empty());
}

TEST(VariantVectorTest, InsertCanUpcastDispatchToUnknown) {
  Microsoft::WRL::ComPtr<IDispatch> dispatch =
      Microsoft::WRL::Make<DispatchStub>();
  Microsoft::WRL::ComPtr<IDispatch> unknown;
  dispatch.CopyTo(&unknown);

  VariantVector vector;
  vector.Insert<VT_UNKNOWN>(unknown.Get());
  vector.Insert<VT_UNKNOWN>(dispatch.Get());
  vector.Insert<VT_DISPATCH>(dispatch.Get());
  EXPECT_EQ(vector.Type(), VT_UNKNOWN);
  EXPECT_EQ(vector.Size(), 3U);
}

TEST(VariantVectorTest, InsertCannotDowncastUnknownToDispatch) {
  Microsoft::WRL::ComPtr<IDispatch> dispatch =
      Microsoft::WRL::Make<DispatchStub>();
  Microsoft::WRL::ComPtr<IDispatch> unknown;
  dispatch.CopyTo(&unknown);

  VariantVector vector;
  vector.Insert<VT_DISPATCH>(dispatch.Get());
  // The first insert sets the type to VT_DISPATCH, and attempting to
  // explicitly insert VT_UNKNOWN will silently fail in release builds
  // but DCHECKs in debug builds.
  EXPECT_DCHECK_DEATH(vector.Insert<VT_UNKNOWN>(unknown.Get()));
  EXPECT_DCHECK_DEATH(vector.Insert<VT_UNKNOWN>(dispatch.Get()));
  EXPECT_EQ(vector.Type(), VT_DISPATCH);
  EXPECT_EQ(vector.Size(), 1U);
}

TEST(VariantVectorTest, Reset) {
  VariantVector vector;
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  vector.Insert<VT_I4>(123);
  vector.Insert<VT_I4>(456);
  EXPECT_EQ(vector.Type(), VT_I4);
  EXPECT_EQ(vector.Size(), 2U);
  vector.Reset();
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
}

TEST(VariantVectorTest, ResetWithManagedContents) {
  VariantVector vector;
  // Test that managed contents are released when cleared.
  Microsoft::WRL::ComPtr<IUnknown> unknown1 =
      Microsoft::WRL::Make<DispatchStub>();
  Microsoft::WRL::ComPtr<IUnknown> unknown2;
  unknown1.CopyTo(&unknown2);
  vector.Insert<VT_UNKNOWN>(unknown1.Get());
  EXPECT_EQ(vector.Type(), VT_UNKNOWN);
  EXPECT_EQ(vector.Size(), 1U);
  // There are now 3 references to the value owned by |unknown1|.
  // Remove ownership from |unknown2| should reduce the count to 2.
  EXPECT_EQ(unknown2.Reset(), 2U);
  // Resetting the VariantVector will reduce the count to 1.
  vector.Reset();
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  // Then resetting |unknown1| should reduce to 0.
  EXPECT_EQ(unknown1.Reset(), 0U);
}

TEST(VariantVectorTest, ScopeWithManagedContents) {
  Microsoft::WRL::ComPtr<IUnknown> unknown1 =
      Microsoft::WRL::Make<DispatchStub>();
  {
    VariantVector vector;
    vector.Insert<VT_UNKNOWN>(unknown1.Get());
    EXPECT_EQ(vector.Type(), VT_UNKNOWN);
    EXPECT_EQ(vector.Size(), 1U);

    Microsoft::WRL::ComPtr<IUnknown> unknown2;
    unknown1.CopyTo(&unknown2);
    // There are now 3 references to the value owned by |unknown1|.
    // Remove ownership from |unknown2| should reduce the count to 2.
    EXPECT_EQ(unknown2.Reset(), 2U);
  }
  // The VariantVector going out of scope will reduce the count to 1.
  // Then resetting |unknown1| should reduce to 0.
  EXPECT_EQ(unknown1.Reset(), 0U);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantEmpty) {
  VariantVector vector;
  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(variant.type(), VT_EMPTY);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleBool) {
  VariantVector vector;
  ScopedVariant expected_variant;

  expected_variant.Set(true);
  vector.Insert<VT_BOOL>(true);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleI1) {
  VariantVector vector;
  ScopedVariant expected_variant;

  expected_variant.Set((int8_t)34);
  vector.Insert<VT_I1>(34);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleUI1) {
  VariantVector vector;
  ScopedVariant expected_variant;

  expected_variant.Set((uint8_t)35U);
  vector.Insert<VT_UI1>(35U);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleI2) {
  VariantVector vector;
  ScopedVariant expected_variant;

  expected_variant.Set((int16_t)8738);
  vector.Insert<VT_I2>(8738);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleUI2) {
  VariantVector vector;
  ScopedVariant expected_variant;

  expected_variant.Set((uint16_t)8739U);
  vector.Insert<VT_UI2>(8739U);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleI4) {
  VariantVector vector;
  ScopedVariant expected_variant;

  expected_variant.Set((int32_t)572662306);
  vector.Insert<VT_I4>(572662306);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleUI4) {
  VariantVector vector;
  ScopedVariant expected_variant;

  expected_variant.Set((uint32_t)572662307U);
  vector.Insert<VT_UI4>(572662307U);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleI8) {
  VariantVector vector;
  ScopedVariant expected_variant;

  expected_variant.Set((int64_t)2459565876494606882);
  vector.Insert<VT_I8>(2459565876494606882);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleUI8) {
  VariantVector vector;
  ScopedVariant expected_variant;

  expected_variant.Set((uint64_t)2459565876494606883U);
  vector.Insert<VT_UI8>(2459565876494606883U);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleR4) {
  VariantVector vector;
  ScopedVariant expected_variant;

  expected_variant.Set(3.14159f);
  vector.Insert<VT_R4>(3.14159f);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleR8) {
  VariantVector vector;
  ScopedVariant expected_variant;

  expected_variant.Set(6.28318);
  vector.Insert<VT_R8>(6.28318);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleDate) {
  VariantVector vector;
  ScopedVariant expected_variant;

  SYSTEMTIME sys_time;
  ::GetSystemTime(&sys_time);
  DATE date;
  ::SystemTimeToVariantTime(&sys_time, &date);
  expected_variant.SetDate(date);
  vector.Insert<VT_DATE>(date);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleBstr) {
  VariantVector vector;
  ScopedVariant expected_variant;

  wchar_t test_string[] = L"Test string for BSTRs.";
  expected_variant.Set(test_string);
  vector.Insert<VT_BSTR>(test_string);
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleUnknown) {
  VariantVector vector;
  ScopedVariant expected_variant;

  Microsoft::WRL::ComPtr<IUnknown> unknown =
      Microsoft::WRL::Make<DispatchStub>();
  expected_variant.Set(unknown.Get());
  vector.Insert<VT_UNKNOWN>(unknown.Get());
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantSingleDispatch) {
  VariantVector vector;
  ScopedVariant expected_variant;

  Microsoft::WRL::ComPtr<IDispatch> dispatch =
      Microsoft::WRL::Make<DispatchStub>();
  expected_variant.Set(dispatch.Get());
  vector.Insert<VT_DISPATCH>(dispatch.Get());
  EXPECT_EQ(vector.Type(), expected_variant.type());
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsScalarVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.Compare(expected_variant), 0);
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleBool) {
  constexpr VARTYPE kVariantType = VT_BOOL;
  VariantVector vector;
  ScopedVariant variant;

  vector.Insert<kVariantType>(true);
  vector.Insert<kVariantType>(false);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleI1) {
  constexpr VARTYPE kVariantType = VT_I1;
  VariantVector vector;
  ScopedVariant variant;

  vector.Insert<kVariantType>(34);
  vector.Insert<kVariantType>(52);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleUI1) {
  constexpr VARTYPE kVariantType = VT_UI1;
  VariantVector vector;
  ScopedVariant variant;

  vector.Insert<kVariantType>(34U);
  vector.Insert<kVariantType>(52U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleI2) {
  constexpr VARTYPE kVariantType = VT_I2;
  VariantVector vector;
  ScopedVariant variant;

  vector.Insert<kVariantType>(8738);
  vector.Insert<kVariantType>(8758);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleUI2) {
  constexpr VARTYPE kVariantType = VT_UI2;
  VariantVector vector;
  ScopedVariant variant;

  vector.Insert<kVariantType>(8739U);
  vector.Insert<kVariantType>(8759U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleI4) {
  constexpr VARTYPE kVariantType = VT_I4;
  VariantVector vector;
  ScopedVariant variant;

  vector.Insert<kVariantType>(572662306);
  vector.Insert<kVariantType>(572662307);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleUI4) {
  constexpr VARTYPE kVariantType = VT_UI4;
  VariantVector vector;
  ScopedVariant variant;

  vector.Insert<kVariantType>(578662306U);
  vector.Insert<kVariantType>(578662307U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleI8) {
  constexpr VARTYPE kVariantType = VT_I8;
  VariantVector vector;
  ScopedVariant variant;

  vector.Insert<kVariantType>(2459565876494606882);
  vector.Insert<kVariantType>(2459565876494606883);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleUI8) {
  constexpr VARTYPE kVariantType = VT_UI8;
  VariantVector vector;
  ScopedVariant variant;

  vector.Insert<kVariantType>(2459565876494606883U);
  vector.Insert<kVariantType>(2459565876494606884U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleR4) {
  constexpr VARTYPE kVariantType = VT_R4;
  VariantVector vector;
  ScopedVariant variant;

  vector.Insert<kVariantType>(3.14159f);
  vector.Insert<kVariantType>(6.28318f);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleR8) {
  constexpr VARTYPE kVariantType = VT_R8;
  VariantVector vector;
  ScopedVariant variant;

  vector.Insert<kVariantType>(6.28318);
  vector.Insert<kVariantType>(3.14159);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleDate) {
  constexpr VARTYPE kVariantType = VT_DATE;
  VariantVector vector;
  ScopedVariant variant;

  SYSTEMTIME sys_time;
  ::GetSystemTime(&sys_time);
  DATE date;
  ::SystemTimeToVariantTime(&sys_time, &date);

  vector.Insert<kVariantType>(date);
  vector.Insert<kVariantType>(date);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleBstr) {
  constexpr VARTYPE kVariantType = VT_BSTR;
  VariantVector vector;
  ScopedVariant variant;

  wchar_t some_text[] = L"some text";
  wchar_t more_text[] = L"more text";
  vector.Insert<kVariantType>(some_text);
  vector.Insert<kVariantType>(more_text);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleUnknown) {
  constexpr VARTYPE kVariantType = VT_UNKNOWN;
  VariantVector vector;
  ScopedVariant variant;

  Microsoft::WRL::ComPtr<IUnknown> unknown1 =
      Microsoft::WRL::Make<DispatchStub>();
  Microsoft::WRL::ComPtr<IUnknown> unknown2 =
      Microsoft::WRL::Make<DispatchStub>();

  vector.Insert<kVariantType>(unknown1.Get());
  vector.Insert<kVariantType>(unknown2.Get());
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsScalarVariantMultipleDispatch) {
  constexpr VARTYPE kVariantType = VT_DISPATCH;
  VariantVector vector;
  ScopedVariant variant;

  Microsoft::WRL::ComPtr<IDispatch> dispatch1 =
      Microsoft::WRL::Make<DispatchStub>();
  Microsoft::WRL::ComPtr<IDispatch> dispatch2 =
      Microsoft::WRL::Make<DispatchStub>();

  vector.Insert<kVariantType>(dispatch1.Get());
  vector.Insert<kVariantType>(dispatch2.Get());
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);
  EXPECT_DCHECK_DEATH(vector.ReleaseAsScalarVariant());
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantEmpty) {
  VariantVector vector;
  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(variant.type(), VT_EMPTY);
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleBool) {
  constexpr VARTYPE kVariantType = VT_BOOL;
  VariantVector vector;

  vector.Insert<kVariantType>(true);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), VARIANT_TRUE);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleI1) {
  constexpr VARTYPE kVariantType = VT_I1;
  VariantVector vector;

  vector.Insert<kVariantType>(34);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), 34);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleUI1) {
  constexpr VARTYPE kVariantType = VT_UI1;
  VariantVector vector;

  vector.Insert<kVariantType>(34U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), 34U);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleI2) {
  constexpr VARTYPE kVariantType = VT_I2;
  VariantVector vector;

  vector.Insert<kVariantType>(8738);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), 8738);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleUI2) {
  constexpr VARTYPE kVariantType = VT_UI2;
  VariantVector vector;

  vector.Insert<kVariantType>(8739U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), 8739U);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleI4) {
  constexpr VARTYPE kVariantType = VT_I4;
  VariantVector vector;

  vector.Insert<kVariantType>(572662306);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), 572662306);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleUI4) {
  constexpr VARTYPE kVariantType = VT_UI4;
  VariantVector vector;

  vector.Insert<kVariantType>(578662306U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), 578662306U);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleI8) {
  constexpr VARTYPE kVariantType = VT_I8;
  VariantVector vector;

  vector.Insert<kVariantType>(2459565876494606882);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), 2459565876494606882);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleUI8) {
  constexpr VARTYPE kVariantType = VT_UI8;
  VariantVector vector;

  vector.Insert<kVariantType>(2459565876494606883U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), 2459565876494606883U);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleR4) {
  constexpr VARTYPE kVariantType = VT_R4;
  VariantVector vector;

  vector.Insert<kVariantType>(3.14159f);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), 3.14159f);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleR8) {
  constexpr VARTYPE kVariantType = VT_R8;
  VariantVector vector;

  vector.Insert<kVariantType>(6.28318);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), 6.28318);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleDate) {
  constexpr VARTYPE kVariantType = VT_DATE;
  VariantVector vector;

  SYSTEMTIME sys_time;
  ::GetSystemTime(&sys_time);
  DATE date;
  ::SystemTimeToVariantTime(&sys_time, &date);

  vector.Insert<kVariantType>(date);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), date);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleBstr) {
  constexpr VARTYPE kVariantType = VT_BSTR;
  VariantVector vector;

  wchar_t some_text[] = L"some text";
  vector.Insert<kVariantType>(some_text);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_STREQ(lock_scope->at(0), some_text);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleUnknown) {
  constexpr VARTYPE kVariantType = VT_UNKNOWN;
  VariantVector vector;

  Microsoft::WRL::ComPtr<IUnknown> unknown =
      Microsoft::WRL::Make<DispatchStub>();

  vector.Insert<kVariantType>(unknown.Get());
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), unknown.Get());
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantSingleDispatch) {
  constexpr VARTYPE kVariantType = VT_DISPATCH;
  VariantVector vector;

  Microsoft::WRL::ComPtr<IDispatch> dispatch =
      Microsoft::WRL::Make<DispatchStub>();

  vector.Insert<kVariantType>(dispatch.Get());
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 1U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 1U);
  EXPECT_EQ(lock_scope->at(0), dispatch.Get());
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleBool) {
  constexpr VARTYPE kVariantType = VT_BOOL;
  VariantVector vector;

  vector.Insert<kVariantType>(true);
  vector.Insert<kVariantType>(false);
  vector.Insert<kVariantType>(true);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 3U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 3U);
  EXPECT_EQ(lock_scope->at(0), VARIANT_TRUE);
  EXPECT_EQ(lock_scope->at(1), VARIANT_FALSE);
  EXPECT_EQ(lock_scope->at(2), VARIANT_TRUE);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleI1) {
  constexpr VARTYPE kVariantType = VT_I1;
  VariantVector vector;

  vector.Insert<kVariantType>(34);
  vector.Insert<kVariantType>(52);
  vector.Insert<kVariantType>(12);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 3U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 3U);
  EXPECT_EQ(lock_scope->at(0), 34);
  EXPECT_EQ(lock_scope->at(1), 52);
  EXPECT_EQ(lock_scope->at(2), 12);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleUI1) {
  constexpr VARTYPE kVariantType = VT_UI1;
  VariantVector vector;

  vector.Insert<kVariantType>(34U);
  vector.Insert<kVariantType>(52U);
  vector.Insert<kVariantType>(12U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 3U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 3U);
  EXPECT_EQ(lock_scope->at(0), 34U);
  EXPECT_EQ(lock_scope->at(1), 52U);
  EXPECT_EQ(lock_scope->at(2), 12U);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleI2) {
  constexpr VARTYPE kVariantType = VT_I2;
  VariantVector vector;

  vector.Insert<kVariantType>(8738);
  vector.Insert<kVariantType>(8758);
  vector.Insert<kVariantType>(42);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 3U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 3U);
  EXPECT_EQ(lock_scope->at(0), 8738);
  EXPECT_EQ(lock_scope->at(1), 8758);
  EXPECT_EQ(lock_scope->at(2), 42);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleUI2) {
  constexpr VARTYPE kVariantType = VT_UI2;
  VariantVector vector;

  vector.Insert<kVariantType>(8739U);
  vector.Insert<kVariantType>(8759U);
  vector.Insert<kVariantType>(42U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 3U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 3U);
  EXPECT_EQ(lock_scope->at(0), 8739U);
  EXPECT_EQ(lock_scope->at(1), 8759U);
  EXPECT_EQ(lock_scope->at(2), 42U);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleI4) {
  constexpr VARTYPE kVariantType = VT_I4;
  VariantVector vector;

  vector.Insert<kVariantType>(572662306);
  vector.Insert<kVariantType>(572662307);
  vector.Insert<kVariantType>(572662308);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 3U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 3U);
  EXPECT_EQ(lock_scope->at(0), 572662306);
  EXPECT_EQ(lock_scope->at(1), 572662307);
  EXPECT_EQ(lock_scope->at(2), 572662308);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleUI4) {
  constexpr VARTYPE kVariantType = VT_UI4;
  VariantVector vector;

  vector.Insert<kVariantType>(578662306U);
  vector.Insert<kVariantType>(578662307U);
  vector.Insert<kVariantType>(578662308U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 3U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 3U);
  EXPECT_EQ(lock_scope->at(0), 578662306U);
  EXPECT_EQ(lock_scope->at(1), 578662307U);
  EXPECT_EQ(lock_scope->at(2), 578662308U);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleI8) {
  constexpr VARTYPE kVariantType = VT_I8;
  VariantVector vector;

  vector.Insert<kVariantType>(2459565876494606882);
  vector.Insert<kVariantType>(2459565876494606883);
  vector.Insert<kVariantType>(2459565876494606884);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 3U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 3U);
  EXPECT_EQ(lock_scope->at(0), 2459565876494606882);
  EXPECT_EQ(lock_scope->at(1), 2459565876494606883);
  EXPECT_EQ(lock_scope->at(2), 2459565876494606884);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleUI8) {
  constexpr VARTYPE kVariantType = VT_UI8;
  VariantVector vector;

  vector.Insert<kVariantType>(2459565876494606883U);
  vector.Insert<kVariantType>(2459565876494606884U);
  vector.Insert<kVariantType>(2459565876494606885U);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 3U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 3U);
  EXPECT_EQ(lock_scope->at(0), 2459565876494606883U);
  EXPECT_EQ(lock_scope->at(1), 2459565876494606884U);
  EXPECT_EQ(lock_scope->at(2), 2459565876494606885U);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleR4) {
  constexpr VARTYPE kVariantType = VT_R4;
  VariantVector vector;

  vector.Insert<kVariantType>(3.14159f);
  vector.Insert<kVariantType>(6.28318f);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 2U);
  EXPECT_EQ(lock_scope->at(0), 3.14159f);
  EXPECT_EQ(lock_scope->at(1), 6.28318f);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleR8) {
  constexpr VARTYPE kVariantType = VT_R8;
  VariantVector vector;

  vector.Insert<kVariantType>(6.28318);
  vector.Insert<kVariantType>(3.14159);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 2U);
  EXPECT_EQ(lock_scope->at(0), 6.28318);
  EXPECT_EQ(lock_scope->at(1), 3.14159);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleDate) {
  constexpr VARTYPE kVariantType = VT_DATE;
  VariantVector vector;
  SYSTEMTIME sys_time;
  ::GetSystemTime(&sys_time);
  DATE date;
  ::SystemTimeToVariantTime(&sys_time, &date);

  vector.Insert<kVariantType>(date);
  vector.Insert<kVariantType>(date);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 2U);
  EXPECT_EQ(lock_scope->at(0), date);
  EXPECT_EQ(lock_scope->at(1), date);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleBstr) {
  constexpr VARTYPE kVariantType = VT_BSTR;
  VariantVector vector;
  wchar_t some_text[] = L"some text";
  wchar_t more_text[] = L"more text";
  vector.Insert<kVariantType>(some_text);
  vector.Insert<kVariantType>(more_text);
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 2U);
  EXPECT_STREQ(lock_scope->at(0), some_text);
  EXPECT_STREQ(lock_scope->at(1), more_text);
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleUnknown) {
  constexpr VARTYPE kVariantType = VT_UNKNOWN;
  VariantVector vector;

  Microsoft::WRL::ComPtr<IUnknown> unknown1 =
      Microsoft::WRL::Make<DispatchStub>();
  Microsoft::WRL::ComPtr<IUnknown> unknown2 =
      Microsoft::WRL::Make<DispatchStub>();

  vector.Insert<kVariantType>(unknown1.Get());
  vector.Insert<kVariantType>(unknown2.Get());
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 2U);
  EXPECT_EQ(lock_scope->at(0), unknown1.Get());
  EXPECT_EQ(lock_scope->at(1), unknown2.Get());
  safearray.Release();
}

TEST(VariantVectorTest, ReleaseAsSafearrayVariantMultipleDispatch) {
  constexpr VARTYPE kVariantType = VT_DISPATCH;
  VariantVector vector;

  Microsoft::WRL::ComPtr<IDispatch> dispatch1 =
      Microsoft::WRL::Make<DispatchStub>();
  Microsoft::WRL::ComPtr<IDispatch> dispatch2 =
      Microsoft::WRL::Make<DispatchStub>();

  vector.Insert<kVariantType>(dispatch1.Get());
  vector.Insert<kVariantType>(dispatch2.Get());
  EXPECT_EQ(vector.Type(), kVariantType);
  EXPECT_EQ(vector.Size(), 2U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);
  EXPECT_EQ(variant.type(), VT_ARRAY | kVariantType);

  ScopedSafearray safearray(V_ARRAY(variant.ptr()));
  std::optional<ScopedSafearray::LockScope<kVariantType>> lock_scope =
      safearray.CreateLockScope<kVariantType>();
  ASSERT_TRUE(lock_scope.has_value());
  ASSERT_EQ(lock_scope->size(), 2U);
  EXPECT_EQ(lock_scope->at(0), dispatch1.Get());
  EXPECT_EQ(lock_scope->at(1), dispatch2.Get());
  safearray.Release();
}

TEST(VariantVectorTest, CompareVariant) {
  VariantVector vector;
  ScopedVariant variant;
  EXPECT_EQ(vector.Compare(variant), 0);

  vector.Insert<VT_I4>(123);
  EXPECT_EQ(vector.Type(), VT_I4);
  EXPECT_EQ(vector.Size(), 1U);

  variant.Set(123);
  EXPECT_EQ(vector.Compare(variant), 0);
  variant.Set(4);
  EXPECT_EQ(vector.Compare(variant), 1);
  variant.Set(567);
  EXPECT_EQ(vector.Compare(variant), -1);
  // Because the types do not match and VT_I4 is less-than VT_R8,
  // |vector| compares as less-than |variant|, even though the value
  // in |vector| is greater.
  variant.Set(1.0);
  EXPECT_EQ(variant.type(), VT_R8);
  EXPECT_LT(vector.Type(), variant.type());
  EXPECT_EQ(vector.Compare(variant), -1);

  vector.Insert<VT_I4>(456);
  EXPECT_EQ(vector.Size(), 2U);

  // The first element of |vector| is equal to |variant|, but |vector|
  // has more than one element so it is greater-than |variant|.
  variant.Set(123);
  EXPECT_EQ(vector.Compare(variant), 1);
  // The first element of |vector| is greater-than |variant|.
  variant.Set(5);
  EXPECT_EQ(vector.Compare(variant), 1);
  // The first element of |vector| is less-than |variant|.
  variant.Set(1000);
  EXPECT_EQ(vector.Compare(variant), -1);
}

TEST(VariantVectorTest, CompareSafearray) {
  VariantVector vector;
  vector.Insert<VT_I4>(123);
  vector.Insert<VT_I4>(456);
  EXPECT_EQ(vector.Type(), VT_I4);
  EXPECT_EQ(vector.Size(), 2U);

  ScopedVariant variant(vector.ReleaseAsSafearrayVariant());
  EXPECT_EQ(variant.type(), VT_ARRAY | VT_I4);
  EXPECT_EQ(vector.Type(), VT_EMPTY);
  EXPECT_EQ(vector.Size(), 0U);

  // Because |vector| is now empty, it will compare as less-than the array.
  EXPECT_EQ(vector.Compare(V_ARRAY(variant.ptr())), -1);
  EXPECT_EQ(vector.Compare(variant), -1);

  vector.Insert<VT_I4>(123);
  EXPECT_EQ(vector.Type(), VT_I4);
  EXPECT_EQ(vector.Size(), 1U);
  // |vector| has fewer elements than |variant|.
  EXPECT_EQ(vector.Compare(V_ARRAY(variant.ptr())), -1);
  EXPECT_EQ(vector.Compare(variant), -1);

  vector.Insert<VT_I4>(456);
  EXPECT_EQ(vector.Type(), VT_I4);
  EXPECT_EQ(vector.Size(), 2U);
  // |vector| is now equal to |variant|.
  EXPECT_EQ(vector.Compare(V_ARRAY(variant.ptr())), 0);
  EXPECT_EQ(vector.Compare(variant), 0);

  vector.Insert<VT_I4>(789);
  EXPECT_EQ(vector.Type(), VT_I4);
  EXPECT_EQ(vector.Size(), 3U);
  // |vector| contains |variant| but has more elements so
  // |vector| is now greater-than |variant|.
  EXPECT_EQ(vector.Compare(V_ARRAY(variant.ptr())), 1);
  EXPECT_EQ(vector.Compare(variant), 1);

  vector.Reset();
  vector.Insert<VT_I4>(456);
  EXPECT_EQ(vector.Type(), VT_I4);
  EXPECT_EQ(vector.Size(), 1U);
  // |vector| has fewer elements than |variant|, but the first element in
  // |vector| compares as greater-than the first element in |variant|.
  EXPECT_EQ(vector.Compare(V_ARRAY(variant.ptr())), 1);
  EXPECT_EQ(vector.Compare(variant), 1);

  vector.Reset();
  vector.Insert<VT_R8>(0.0);
  vector.Insert<VT_R8>(0.0);
  EXPECT_EQ(vector.Type(), VT_R8);
  // Because the types do not match and VT_R8 is greater-than VT_I4,
  // |vector| compares as greater-than |variant|, even though the values
  // in |vector| are less-than the values in |variant|.
  EXPECT_GT(VT_R8, VT_I4);
  EXPECT_EQ(vector.Compare(V_ARRAY(variant.ptr())), 1);
  EXPECT_EQ(vector.Compare(variant), 1);

  vector.Reset();
  vector.Insert<VT_I2>(1000);
  vector.Insert<VT_I2>(1000);
  EXPECT_EQ(vector.Type(), VT_I2);
  // Because the types do not match and VT_I2 is less-than VT_I4,
  // |vector| compares as less-than |variant|, even though the values
  // in |vector| are greater-than the values in |variant|.
  EXPECT_LT(VT_I2, VT_I4);
  EXPECT_EQ(vector.Compare(V_ARRAY(variant.ptr())), -1);
  EXPECT_EQ(vector.Compare(variant), -1);
}

TEST(VariantVectorTest, CompareVariantVector) {
  VariantVector vector1, vector2;
  EXPECT_EQ(vector1.Compare(vector2), 0);
  EXPECT_EQ(vector1, vector2);

  vector1.Insert<VT_I4>(1);
  EXPECT_EQ(vector1.Compare(vector2), 1);
  EXPECT_EQ(vector2.Compare(vector1), -1);
  EXPECT_NE(vector1, vector2);

  vector2.Insert<VT_I4>(1);
  EXPECT_EQ(vector1.Compare(vector2), 0);
  EXPECT_EQ(vector2.Compare(vector1), 0);
  EXPECT_EQ(vector1, vector2);

  vector1.Insert<VT_I4>(1);
  EXPECT_EQ(vector1.Compare(vector2), 1);
  EXPECT_EQ(vector2.Compare(vector1), -1);
  EXPECT_NE(vector1, vector2);

  vector2.Insert<VT_I4>(2);
  EXPECT_EQ(vector1.Compare(vector2), -1);
  EXPECT_EQ(vector2.Compare(vector1), 1);
  EXPECT_NE(vector1, vector2);

  vector1.Reset();
  vector1.Insert<VT_I4>(10);
  vector2.Reset();
  vector2.Insert<VT_R8>(5.0);
  // Because the types do not match and VT_I4 is less-than VT_R8,
  // |vector1| compares as less-than |vector2|, even though the value
  // in |vector1| is greater.
  EXPECT_LT(vector1.Type(), vector2.Type());
  EXPECT_EQ(vector1.Compare(vector2), -1);
  EXPECT_EQ(vector2.Compare(vector1), 1);
  EXPECT_NE(vector1, vector2);
}

}  // namespace win
}  // namespace base