123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- // Copyright 2019 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/win/scoped_safearray.h"
- #include <stddef.h>
- #include <array>
- #include <utility>
- #include <vector>
- #include "base/test/gtest_util.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- namespace base {
- namespace win {
- namespace {
- static constexpr std::array<int, 5> kInputValues = {0, 1, 2, 1, 0};
- static void PopulateScopedSafearrayOfInts(ScopedSafearray& scoped_safe_array) {
- // TODO(crbug.com/1082005): Create a safer alternative to SAFEARRAY methods.
- scoped_safe_array.Reset(SafeArrayCreateVector(
- /*vartype=*/VT_I4, /*lower_bound=*/2,
- /*element_count=*/kInputValues.size()));
- ASSERT_NE(scoped_safe_array.Get(), nullptr);
- ASSERT_EQ(SafeArrayGetDim(scoped_safe_array.Get()), 1U);
- ASSERT_EQ(scoped_safe_array.GetCount(), kInputValues.size());
- int* int_array;
- ASSERT_HRESULT_SUCCEEDED(SafeArrayAccessData(
- scoped_safe_array.Get(), reinterpret_cast<void**>(&int_array)));
- for (size_t i = 0; i < kInputValues.size(); ++i)
- int_array[i] = kInputValues[i];
- ASSERT_HRESULT_SUCCEEDED(SafeArrayUnaccessData(scoped_safe_array.Get()));
- }
- } // namespace
- TEST(ScopedSafearrayTest, ScopedSafearrayMethods) {
- ScopedSafearray empty_safe_array;
- EXPECT_EQ(empty_safe_array.Get(), nullptr);
- EXPECT_EQ(empty_safe_array.Release(), nullptr);
- EXPECT_NE(empty_safe_array.Receive(), nullptr);
- SAFEARRAY* safe_array = SafeArrayCreateVector(
- VT_R8 /* element type */, 0 /* lower bound */, 4 /* elements */);
- ScopedSafearray scoped_safe_array(safe_array);
- EXPECT_EQ(scoped_safe_array.Get(), safe_array);
- EXPECT_EQ(scoped_safe_array.Release(), safe_array);
- EXPECT_NE(scoped_safe_array.Receive(), nullptr);
- // The Release() call should have set the internal pointer to nullptr
- EXPECT_EQ(scoped_safe_array.Get(), nullptr);
- scoped_safe_array.Reset(safe_array);
- EXPECT_EQ(scoped_safe_array.Get(), safe_array);
- ScopedSafearray moved_safe_array(std::move(scoped_safe_array));
- EXPECT_EQ(moved_safe_array.Get(), safe_array);
- EXPECT_EQ(moved_safe_array.Release(), safe_array);
- EXPECT_NE(moved_safe_array.Receive(), nullptr);
- // std::move should have cleared the values of scoped_safe_array
- EXPECT_EQ(scoped_safe_array.Get(), nullptr);
- EXPECT_EQ(scoped_safe_array.Release(), nullptr);
- EXPECT_NE(scoped_safe_array.Receive(), nullptr);
- scoped_safe_array.Reset(safe_array);
- EXPECT_EQ(scoped_safe_array.Get(), safe_array);
- ScopedSafearray assigment_moved_safe_array = std::move(scoped_safe_array);
- EXPECT_EQ(assigment_moved_safe_array.Get(), safe_array);
- EXPECT_EQ(assigment_moved_safe_array.Release(), safe_array);
- EXPECT_NE(assigment_moved_safe_array.Receive(), nullptr);
- // The move-assign operator= should have cleared the values of
- // scoped_safe_array
- EXPECT_EQ(scoped_safe_array.Get(), nullptr);
- EXPECT_EQ(scoped_safe_array.Release(), nullptr);
- EXPECT_NE(scoped_safe_array.Receive(), nullptr);
- // Calling Receive() will free the existing reference
- ScopedSafearray safe_array_received(SafeArrayCreateVector(
- VT_R8 /* element type */, 0 /* lower bound */, 4 /* elements */));
- EXPECT_NE(safe_array_received.Receive(), nullptr);
- EXPECT_EQ(safe_array_received.Get(), nullptr);
- }
- TEST(ScopedSafearrayTest, ScopedSafearrayMoveConstructor) {
- ScopedSafearray first;
- PopulateScopedSafearrayOfInts(first);
- EXPECT_NE(first.Get(), nullptr);
- EXPECT_EQ(first.GetCount(), kInputValues.size());
- SAFEARRAY* safearray = first.Get();
- ScopedSafearray second(std::move(first));
- EXPECT_EQ(first.Get(), nullptr);
- EXPECT_EQ(second.Get(), safearray);
- }
- TEST(ScopedSafearrayTest, ScopedSafearrayMoveAssignOperator) {
- ScopedSafearray first, second;
- PopulateScopedSafearrayOfInts(first);
- EXPECT_NE(first.Get(), nullptr);
- EXPECT_EQ(first.GetCount(), kInputValues.size());
- SAFEARRAY* safearray = first.Get();
- second = std::move(first);
- EXPECT_EQ(first.Get(), nullptr);
- EXPECT_EQ(second.Get(), safearray);
- // Indirectly move |second| into itself.
- ScopedSafearray& reference_to_second = second;
- second = std::move(reference_to_second);
- EXPECT_EQ(second.GetCount(), kInputValues.size());
- EXPECT_EQ(second.Get(), safearray);
- }
- TEST(ScopedSafearrayTest, ScopedSafearrayCast) {
- SAFEARRAY* safe_array = SafeArrayCreateVector(
- VT_R8 /* element type */, 1 /* lower bound */, 5 /* elements */);
- ScopedSafearray scoped_safe_array(safe_array);
- EXPECT_EQ(SafeArrayGetDim(scoped_safe_array.Get()), 1U);
- LONG lower_bound;
- EXPECT_HRESULT_SUCCEEDED(
- SafeArrayGetLBound(scoped_safe_array.Get(), 1, &lower_bound));
- EXPECT_EQ(lower_bound, 1);
- LONG upper_bound;
- EXPECT_HRESULT_SUCCEEDED(
- SafeArrayGetUBound(scoped_safe_array.Get(), 1, &upper_bound));
- EXPECT_EQ(upper_bound, 5);
- VARTYPE variable_type;
- EXPECT_HRESULT_SUCCEEDED(
- SafeArrayGetVartype(scoped_safe_array.Get(), &variable_type));
- EXPECT_EQ(variable_type, VT_R8);
- }
- TEST(ScopedSafearrayTest, InitiallyEmpty) {
- ScopedSafearray empty_safe_array;
- EXPECT_EQ(empty_safe_array.Get(), nullptr);
- EXPECT_DCHECK_DEATH(empty_safe_array.GetCount());
- }
- TEST(ScopedSafearrayTest, ScopedSafearrayGetCount) {
- // TODO(crbug.com/1082005): Create a safer alternative to SAFEARRAY methods.
- ScopedSafearray scoped_safe_array(SafeArrayCreateVector(
- /*vartype=*/VT_I4, /*lower_bound=*/2, /*element_count=*/5));
- ASSERT_NE(scoped_safe_array.Get(), nullptr);
- EXPECT_EQ(SafeArrayGetDim(scoped_safe_array.Get()), 1U);
- LONG lower_bound;
- EXPECT_HRESULT_SUCCEEDED(
- SafeArrayGetLBound(scoped_safe_array.Get(), 1, &lower_bound));
- EXPECT_EQ(lower_bound, 2);
- LONG upper_bound;
- EXPECT_HRESULT_SUCCEEDED(
- SafeArrayGetUBound(scoped_safe_array.Get(), 1, &upper_bound));
- EXPECT_EQ(upper_bound, 6);
- EXPECT_EQ(scoped_safe_array.GetCount(), 5U);
- }
- TEST(ScopedSafearrayTest, ScopedSafearrayInitialLockScope) {
- ScopedSafearray scoped_safe_array;
- absl::optional<ScopedSafearray::LockScope<VT_I4>> lock_scope =
- scoped_safe_array.CreateLockScope<VT_I4>();
- EXPECT_FALSE(lock_scope.has_value());
- }
- TEST(ScopedSafearrayTest, ScopedSafearrayLockScopeMoveConstructor) {
- ScopedSafearray scoped_safe_array;
- PopulateScopedSafearrayOfInts(scoped_safe_array);
- absl::optional<ScopedSafearray::LockScope<VT_I4>> first =
- scoped_safe_array.CreateLockScope<VT_I4>();
- ASSERT_TRUE(first.has_value());
- EXPECT_EQ(first->Type(), VT_I4);
- EXPECT_EQ(first->size(), kInputValues.size());
- ScopedSafearray::LockScope<VT_I4> second(std::move(*first));
- EXPECT_EQ(first->Type(), VT_EMPTY);
- EXPECT_EQ(first->size(), 0U);
- EXPECT_EQ(second.Type(), VT_I4);
- EXPECT_EQ(second.size(), kInputValues.size());
- }
- TEST(ScopedSafearrayTest, ScopedSafearrayLockScopeMoveAssignOperator) {
- ScopedSafearray scoped_safe_array;
- PopulateScopedSafearrayOfInts(scoped_safe_array);
- absl::optional<ScopedSafearray::LockScope<VT_I4>> first =
- scoped_safe_array.CreateLockScope<VT_I4>();
- ASSERT_TRUE(first.has_value());
- EXPECT_EQ(first->Type(), VT_I4);
- EXPECT_EQ(first->size(), kInputValues.size());
- ScopedSafearray::LockScope<VT_I4> second;
- second = std::move(*first);
- EXPECT_EQ(first->Type(), VT_EMPTY);
- EXPECT_EQ(first->size(), 0U);
- EXPECT_EQ(second.Type(), VT_I4);
- EXPECT_EQ(second.size(), kInputValues.size());
- // Indirectly move |second| into itself.
- ScopedSafearray::LockScope<VT_I4>& reference_to_second = second;
- EXPECT_DCHECK_DEATH(second = std::move(reference_to_second));
- }
- TEST(ScopedSafearrayTest, ScopedSafearrayLockScopeTypeMismatch) {
- ScopedSafearray scoped_safe_array;
- PopulateScopedSafearrayOfInts(scoped_safe_array);
- {
- absl::optional<ScopedSafearray::LockScope<VT_BSTR>> invalid_lock_scope =
- scoped_safe_array.CreateLockScope<VT_BSTR>();
- EXPECT_FALSE(invalid_lock_scope.has_value());
- }
- {
- absl::optional<ScopedSafearray::LockScope<VT_UI4>> invalid_lock_scope =
- scoped_safe_array.CreateLockScope<VT_UI4>();
- EXPECT_FALSE(invalid_lock_scope.has_value());
- }
- }
- TEST(ScopedSafearrayTest, ScopedSafearrayLockScopeRandomAccess) {
- ScopedSafearray scoped_safe_array;
- PopulateScopedSafearrayOfInts(scoped_safe_array);
- absl::optional<ScopedSafearray::LockScope<VT_I4>> lock_scope =
- scoped_safe_array.CreateLockScope<VT_I4>();
- ASSERT_TRUE(lock_scope.has_value());
- EXPECT_EQ(lock_scope->Type(), VT_I4);
- EXPECT_EQ(lock_scope->size(), kInputValues.size());
- for (size_t i = 0; i < kInputValues.size(); ++i) {
- EXPECT_EQ(lock_scope->at(i), kInputValues[i]);
- EXPECT_EQ((*lock_scope)[i], kInputValues[i]);
- }
- }
- TEST(ScopedSafearrayTest, ScopedSafearrayLockScopeIterator) {
- ScopedSafearray scoped_safe_array;
- PopulateScopedSafearrayOfInts(scoped_safe_array);
- absl::optional<ScopedSafearray::LockScope<VT_I4>> lock_scope =
- scoped_safe_array.CreateLockScope<VT_I4>();
- std::vector<int> unpacked_vector(lock_scope->begin(), lock_scope->end());
- ASSERT_EQ(unpacked_vector.size(), kInputValues.size());
- for (size_t i = 0; i < kInputValues.size(); ++i)
- EXPECT_EQ(unpacked_vector[i], kInputValues[i]);
- }
- } // namespace win
- } // namespace base
|