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