scoped_safearray_unittest.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. // Copyright 2019 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. #include "base/win/scoped_safearray.h"
  5. #include <stddef.h>
  6. #include <array>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/test/gtest_util.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. #include "third_party/abseil-cpp/absl/types/optional.h"
  12. namespace base {
  13. namespace win {
  14. namespace {
  15. static constexpr std::array<int, 5> kInputValues = {0, 1, 2, 1, 0};
  16. static void PopulateScopedSafearrayOfInts(ScopedSafearray& scoped_safe_array) {
  17. // TODO(crbug.com/1082005): Create a safer alternative to SAFEARRAY methods.
  18. scoped_safe_array.Reset(SafeArrayCreateVector(
  19. /*vartype=*/VT_I4, /*lower_bound=*/2,
  20. /*element_count=*/kInputValues.size()));
  21. ASSERT_NE(scoped_safe_array.Get(), nullptr);
  22. ASSERT_EQ(SafeArrayGetDim(scoped_safe_array.Get()), 1U);
  23. ASSERT_EQ(scoped_safe_array.GetCount(), kInputValues.size());
  24. int* int_array;
  25. ASSERT_HRESULT_SUCCEEDED(SafeArrayAccessData(
  26. scoped_safe_array.Get(), reinterpret_cast<void**>(&int_array)));
  27. for (size_t i = 0; i < kInputValues.size(); ++i)
  28. int_array[i] = kInputValues[i];
  29. ASSERT_HRESULT_SUCCEEDED(SafeArrayUnaccessData(scoped_safe_array.Get()));
  30. }
  31. } // namespace
  32. TEST(ScopedSafearrayTest, ScopedSafearrayMethods) {
  33. ScopedSafearray empty_safe_array;
  34. EXPECT_EQ(empty_safe_array.Get(), nullptr);
  35. EXPECT_EQ(empty_safe_array.Release(), nullptr);
  36. EXPECT_NE(empty_safe_array.Receive(), nullptr);
  37. SAFEARRAY* safe_array = SafeArrayCreateVector(
  38. VT_R8 /* element type */, 0 /* lower bound */, 4 /* elements */);
  39. ScopedSafearray scoped_safe_array(safe_array);
  40. EXPECT_EQ(scoped_safe_array.Get(), safe_array);
  41. EXPECT_EQ(scoped_safe_array.Release(), safe_array);
  42. EXPECT_NE(scoped_safe_array.Receive(), nullptr);
  43. // The Release() call should have set the internal pointer to nullptr
  44. EXPECT_EQ(scoped_safe_array.Get(), nullptr);
  45. scoped_safe_array.Reset(safe_array);
  46. EXPECT_EQ(scoped_safe_array.Get(), safe_array);
  47. ScopedSafearray moved_safe_array(std::move(scoped_safe_array));
  48. EXPECT_EQ(moved_safe_array.Get(), safe_array);
  49. EXPECT_EQ(moved_safe_array.Release(), safe_array);
  50. EXPECT_NE(moved_safe_array.Receive(), nullptr);
  51. // std::move should have cleared the values of scoped_safe_array
  52. EXPECT_EQ(scoped_safe_array.Get(), nullptr);
  53. EXPECT_EQ(scoped_safe_array.Release(), nullptr);
  54. EXPECT_NE(scoped_safe_array.Receive(), nullptr);
  55. scoped_safe_array.Reset(safe_array);
  56. EXPECT_EQ(scoped_safe_array.Get(), safe_array);
  57. ScopedSafearray assigment_moved_safe_array = std::move(scoped_safe_array);
  58. EXPECT_EQ(assigment_moved_safe_array.Get(), safe_array);
  59. EXPECT_EQ(assigment_moved_safe_array.Release(), safe_array);
  60. EXPECT_NE(assigment_moved_safe_array.Receive(), nullptr);
  61. // The move-assign operator= should have cleared the values of
  62. // scoped_safe_array
  63. EXPECT_EQ(scoped_safe_array.Get(), nullptr);
  64. EXPECT_EQ(scoped_safe_array.Release(), nullptr);
  65. EXPECT_NE(scoped_safe_array.Receive(), nullptr);
  66. // Calling Receive() will free the existing reference
  67. ScopedSafearray safe_array_received(SafeArrayCreateVector(
  68. VT_R8 /* element type */, 0 /* lower bound */, 4 /* elements */));
  69. EXPECT_NE(safe_array_received.Receive(), nullptr);
  70. EXPECT_EQ(safe_array_received.Get(), nullptr);
  71. }
  72. TEST(ScopedSafearrayTest, ScopedSafearrayMoveConstructor) {
  73. ScopedSafearray first;
  74. PopulateScopedSafearrayOfInts(first);
  75. EXPECT_NE(first.Get(), nullptr);
  76. EXPECT_EQ(first.GetCount(), kInputValues.size());
  77. SAFEARRAY* safearray = first.Get();
  78. ScopedSafearray second(std::move(first));
  79. EXPECT_EQ(first.Get(), nullptr);
  80. EXPECT_EQ(second.Get(), safearray);
  81. }
  82. TEST(ScopedSafearrayTest, ScopedSafearrayMoveAssignOperator) {
  83. ScopedSafearray first, second;
  84. PopulateScopedSafearrayOfInts(first);
  85. EXPECT_NE(first.Get(), nullptr);
  86. EXPECT_EQ(first.GetCount(), kInputValues.size());
  87. SAFEARRAY* safearray = first.Get();
  88. second = std::move(first);
  89. EXPECT_EQ(first.Get(), nullptr);
  90. EXPECT_EQ(second.Get(), safearray);
  91. // Indirectly move |second| into itself.
  92. ScopedSafearray& reference_to_second = second;
  93. second = std::move(reference_to_second);
  94. EXPECT_EQ(second.GetCount(), kInputValues.size());
  95. EXPECT_EQ(second.Get(), safearray);
  96. }
  97. TEST(ScopedSafearrayTest, ScopedSafearrayCast) {
  98. SAFEARRAY* safe_array = SafeArrayCreateVector(
  99. VT_R8 /* element type */, 1 /* lower bound */, 5 /* elements */);
  100. ScopedSafearray scoped_safe_array(safe_array);
  101. EXPECT_EQ(SafeArrayGetDim(scoped_safe_array.Get()), 1U);
  102. LONG lower_bound;
  103. EXPECT_HRESULT_SUCCEEDED(
  104. SafeArrayGetLBound(scoped_safe_array.Get(), 1, &lower_bound));
  105. EXPECT_EQ(lower_bound, 1);
  106. LONG upper_bound;
  107. EXPECT_HRESULT_SUCCEEDED(
  108. SafeArrayGetUBound(scoped_safe_array.Get(), 1, &upper_bound));
  109. EXPECT_EQ(upper_bound, 5);
  110. VARTYPE variable_type;
  111. EXPECT_HRESULT_SUCCEEDED(
  112. SafeArrayGetVartype(scoped_safe_array.Get(), &variable_type));
  113. EXPECT_EQ(variable_type, VT_R8);
  114. }
  115. TEST(ScopedSafearrayTest, InitiallyEmpty) {
  116. ScopedSafearray empty_safe_array;
  117. EXPECT_EQ(empty_safe_array.Get(), nullptr);
  118. EXPECT_DCHECK_DEATH(empty_safe_array.GetCount());
  119. }
  120. TEST(ScopedSafearrayTest, ScopedSafearrayGetCount) {
  121. // TODO(crbug.com/1082005): Create a safer alternative to SAFEARRAY methods.
  122. ScopedSafearray scoped_safe_array(SafeArrayCreateVector(
  123. /*vartype=*/VT_I4, /*lower_bound=*/2, /*element_count=*/5));
  124. ASSERT_NE(scoped_safe_array.Get(), nullptr);
  125. EXPECT_EQ(SafeArrayGetDim(scoped_safe_array.Get()), 1U);
  126. LONG lower_bound;
  127. EXPECT_HRESULT_SUCCEEDED(
  128. SafeArrayGetLBound(scoped_safe_array.Get(), 1, &lower_bound));
  129. EXPECT_EQ(lower_bound, 2);
  130. LONG upper_bound;
  131. EXPECT_HRESULT_SUCCEEDED(
  132. SafeArrayGetUBound(scoped_safe_array.Get(), 1, &upper_bound));
  133. EXPECT_EQ(upper_bound, 6);
  134. EXPECT_EQ(scoped_safe_array.GetCount(), 5U);
  135. }
  136. TEST(ScopedSafearrayTest, ScopedSafearrayInitialLockScope) {
  137. ScopedSafearray scoped_safe_array;
  138. absl::optional<ScopedSafearray::LockScope<VT_I4>> lock_scope =
  139. scoped_safe_array.CreateLockScope<VT_I4>();
  140. EXPECT_FALSE(lock_scope.has_value());
  141. }
  142. TEST(ScopedSafearrayTest, ScopedSafearrayLockScopeMoveConstructor) {
  143. ScopedSafearray scoped_safe_array;
  144. PopulateScopedSafearrayOfInts(scoped_safe_array);
  145. absl::optional<ScopedSafearray::LockScope<VT_I4>> first =
  146. scoped_safe_array.CreateLockScope<VT_I4>();
  147. ASSERT_TRUE(first.has_value());
  148. EXPECT_EQ(first->Type(), VT_I4);
  149. EXPECT_EQ(first->size(), kInputValues.size());
  150. ScopedSafearray::LockScope<VT_I4> second(std::move(*first));
  151. EXPECT_EQ(first->Type(), VT_EMPTY);
  152. EXPECT_EQ(first->size(), 0U);
  153. EXPECT_EQ(second.Type(), VT_I4);
  154. EXPECT_EQ(second.size(), kInputValues.size());
  155. }
  156. TEST(ScopedSafearrayTest, ScopedSafearrayLockScopeMoveAssignOperator) {
  157. ScopedSafearray scoped_safe_array;
  158. PopulateScopedSafearrayOfInts(scoped_safe_array);
  159. absl::optional<ScopedSafearray::LockScope<VT_I4>> first =
  160. scoped_safe_array.CreateLockScope<VT_I4>();
  161. ASSERT_TRUE(first.has_value());
  162. EXPECT_EQ(first->Type(), VT_I4);
  163. EXPECT_EQ(first->size(), kInputValues.size());
  164. ScopedSafearray::LockScope<VT_I4> second;
  165. second = std::move(*first);
  166. EXPECT_EQ(first->Type(), VT_EMPTY);
  167. EXPECT_EQ(first->size(), 0U);
  168. EXPECT_EQ(second.Type(), VT_I4);
  169. EXPECT_EQ(second.size(), kInputValues.size());
  170. // Indirectly move |second| into itself.
  171. ScopedSafearray::LockScope<VT_I4>& reference_to_second = second;
  172. EXPECT_DCHECK_DEATH(second = std::move(reference_to_second));
  173. }
  174. TEST(ScopedSafearrayTest, ScopedSafearrayLockScopeTypeMismatch) {
  175. ScopedSafearray scoped_safe_array;
  176. PopulateScopedSafearrayOfInts(scoped_safe_array);
  177. {
  178. absl::optional<ScopedSafearray::LockScope<VT_BSTR>> invalid_lock_scope =
  179. scoped_safe_array.CreateLockScope<VT_BSTR>();
  180. EXPECT_FALSE(invalid_lock_scope.has_value());
  181. }
  182. {
  183. absl::optional<ScopedSafearray::LockScope<VT_UI4>> invalid_lock_scope =
  184. scoped_safe_array.CreateLockScope<VT_UI4>();
  185. EXPECT_FALSE(invalid_lock_scope.has_value());
  186. }
  187. }
  188. TEST(ScopedSafearrayTest, ScopedSafearrayLockScopeRandomAccess) {
  189. ScopedSafearray scoped_safe_array;
  190. PopulateScopedSafearrayOfInts(scoped_safe_array);
  191. absl::optional<ScopedSafearray::LockScope<VT_I4>> lock_scope =
  192. scoped_safe_array.CreateLockScope<VT_I4>();
  193. ASSERT_TRUE(lock_scope.has_value());
  194. EXPECT_EQ(lock_scope->Type(), VT_I4);
  195. EXPECT_EQ(lock_scope->size(), kInputValues.size());
  196. for (size_t i = 0; i < kInputValues.size(); ++i) {
  197. EXPECT_EQ(lock_scope->at(i), kInputValues[i]);
  198. EXPECT_EQ((*lock_scope)[i], kInputValues[i]);
  199. }
  200. }
  201. TEST(ScopedSafearrayTest, ScopedSafearrayLockScopeIterator) {
  202. ScopedSafearray scoped_safe_array;
  203. PopulateScopedSafearrayOfInts(scoped_safe_array);
  204. absl::optional<ScopedSafearray::LockScope<VT_I4>> lock_scope =
  205. scoped_safe_array.CreateLockScope<VT_I4>();
  206. std::vector<int> unpacked_vector(lock_scope->begin(), lock_scope->end());
  207. ASSERT_EQ(unpacked_vector.size(), kInputValues.size());
  208. for (size_t i = 0; i < kInputValues.size(); ++i)
  209. EXPECT_EQ(unpacked_vector[i], kInputValues[i]);
  210. }
  211. } // namespace win
  212. } // namespace base