blob: 4f8c0b764f340cf173b5f07573f5271e064f23f0 [file] [log] [blame]
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -04001/*
2 * Copyright 2021 Google LLC.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "include/private/SkTArray.h"
9#include "include/private/SkTOptional.h"
10
11#include "tests/Test.h"
12
13DEF_TEST(SkTOptionalEmpty, r) {
14 skstd::optional<int> o;
15 REPORTER_ASSERT(r, !o);
Ethan Nicholas8f73ede2021-06-01 13:25:22 -040016 REPORTER_ASSERT(r, !o.has_value());
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -040017}
18
John Stilese53cf992021-06-22 11:18:53 -040019DEF_TEST(SkTOptionalNulloptCtor, r) {
20 skstd::optional<int> o(skstd::nullopt);
21 REPORTER_ASSERT(r, !o);
22 REPORTER_ASSERT(r, !o.has_value());
23}
24
Herb Derbyd390c642021-07-07 17:43:57 -040025DEF_TEST(SkTOptionalValueOr, r) {
26 {
27 skstd::optional<const char*> o;
28 REPORTER_ASSERT(r, !strcmp(o.value_or("Hello"), "Hello"));
29 }
30 {
31 skstd::optional<const char*> o("Bye");
32 REPORTER_ASSERT(r, !strcmp(o.value_or("Hello"), "Bye"));
33 }
34 {
35 skstd::optional<std::unique_ptr<int>> o;
36 std::unique_ptr<int> a = std::move(o).value_or(std::make_unique<int>(5));
37 REPORTER_ASSERT(r, *a == 5);
38 }
39 {
40 skstd::optional<std::unique_ptr<int>> o(std::make_unique<int>(3));
41 std::unique_ptr<int> a = std::move(o).value_or(std::make_unique<int>(5));
42 REPORTER_ASSERT(r, *a == 3);
43 }
44}
45
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -040046DEF_TEST(SkTOptionalValue, r) {
47 skstd::optional<const char*> o("test");
48 REPORTER_ASSERT(r, o);
Ethan Nicholas8f73ede2021-06-01 13:25:22 -040049 REPORTER_ASSERT(r, o.has_value());
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -040050 REPORTER_ASSERT(r, !strcmp(*o, "test"));
Ethan Nicholas8f73ede2021-06-01 13:25:22 -040051 REPORTER_ASSERT(r, !strcmp(o.value(), "test"));
52 o.reset();
53 REPORTER_ASSERT(r, !o);
54 REPORTER_ASSERT(r, !o.has_value());
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -040055}
56
John Stilese53cf992021-06-22 11:18:53 -040057DEF_TEST(SkTOptionalNulloptAssignment, r) {
58 skstd::optional<const char*> o("test");
59 REPORTER_ASSERT(r, o);
60 REPORTER_ASSERT(r, o.has_value());
61 o = skstd::nullopt;
62 REPORTER_ASSERT(r, !o);
63 REPORTER_ASSERT(r, !o.has_value());
64}
65
66DEF_TEST(SkTOptionalNulloptReturn, r) {
67 auto fn = []() -> skstd::optional<float> { return skstd::nullopt; };
68
69 skstd::optional<float> o = fn();
70 REPORTER_ASSERT(r, !o);
71 REPORTER_ASSERT(r, !o.has_value());
72}
73
John Stilese2c4e7e2021-06-22 15:43:05 -040074DEF_TEST(SkTOptionalComparisons, r) {
75 int v[] = { 1, 2, 3, 4, 5 };
76 skstd::optional<int> o[] = {1, 2, skstd::nullopt, 4, 5};
77 skstd::optional<int> five = 5;
78 skstd::optional<int> six = 6;
79
80 for (int index = 0; index < (int)SK_ARRAY_COUNT(v); ++index) {
81 REPORTER_ASSERT(r, v[index] < six);
82 REPORTER_ASSERT(r, o[index] < six);
83 REPORTER_ASSERT(r, six > v[index]);
84 REPORTER_ASSERT(r, six > o[index]);
85
86 REPORTER_ASSERT(r, v[index] < 6);
87 REPORTER_ASSERT(r, o[index] < 6);
88 REPORTER_ASSERT(r, 6 > v[index]);
89 REPORTER_ASSERT(r, 6 > o[index]);
90
91 REPORTER_ASSERT(r, !(six < v[index]));
92 REPORTER_ASSERT(r, !(six < o[index]));
93 REPORTER_ASSERT(r, !(v[index] > six));
94 REPORTER_ASSERT(r, !(o[index] > six));
95
96 REPORTER_ASSERT(r, !(6 < v[index]));
97 REPORTER_ASSERT(r, !(6 < o[index]));
98 REPORTER_ASSERT(r, !(v[index] > 6));
99 REPORTER_ASSERT(r, !(o[index] > 6));
100
101 REPORTER_ASSERT(r, v[index] <= five);
102 REPORTER_ASSERT(r, o[index] <= five);
103 REPORTER_ASSERT(r, five >= v[index]);
104 REPORTER_ASSERT(r, five >= o[index]);
105
106 REPORTER_ASSERT(r, v[index] <= 5);
107 REPORTER_ASSERT(r, o[index] <= 5);
108 REPORTER_ASSERT(r, 5 >= v[index]);
109 REPORTER_ASSERT(r, 5 >= o[index]);
110
111 REPORTER_ASSERT(r, skstd::nullopt <= o[index]);
112 REPORTER_ASSERT(r, !(skstd::nullopt > o[index]));
113 REPORTER_ASSERT(r, o[index] >= skstd::nullopt);
114 REPORTER_ASSERT(r, !(o[index] < skstd::nullopt));
115
116 if (o[index].has_value()) {
117 REPORTER_ASSERT(r, o[index] != skstd::nullopt);
118 REPORTER_ASSERT(r, skstd::nullopt != o[index]);
119
120 REPORTER_ASSERT(r, o[index] == o[index]);
121 REPORTER_ASSERT(r, o[index] != six);
122 REPORTER_ASSERT(r, o[index] == v[index]);
123 REPORTER_ASSERT(r, v[index] == o[index]);
124 REPORTER_ASSERT(r, o[index] > 0);
125 REPORTER_ASSERT(r, o[index] >= 1);
126 REPORTER_ASSERT(r, o[index] <= 5);
127 REPORTER_ASSERT(r, o[index] < 6);
128 REPORTER_ASSERT(r, 0 < o[index]);
129 REPORTER_ASSERT(r, 1 <= o[index]);
130 REPORTER_ASSERT(r, 5 >= o[index]);
131 REPORTER_ASSERT(r, 6 > o[index]);
132 } else {
133 REPORTER_ASSERT(r, o[index] == skstd::nullopt);
134 REPORTER_ASSERT(r, skstd::nullopt == o[index]);
135
136 REPORTER_ASSERT(r, o[index] == o[index]);
137 REPORTER_ASSERT(r, o[index] != five);
138 REPORTER_ASSERT(r, o[index] != v[index]);
139 REPORTER_ASSERT(r, v[index] != o[index]);
140 REPORTER_ASSERT(r, o[index] < 0);
141 REPORTER_ASSERT(r, o[index] <= 0);
142 REPORTER_ASSERT(r, 0 > o[index]);
143 REPORTER_ASSERT(r, 0 >= o[index]);
144 REPORTER_ASSERT(r, !(o[index] > 0));
145 REPORTER_ASSERT(r, !(o[index] >= 0));
146 REPORTER_ASSERT(r, !(0 < o[index]));
147 REPORTER_ASSERT(r, !(0 <= o[index]));
148 }
149 }
150}
151
Ethan Nicholas8f73ede2021-06-01 13:25:22 -0400152class SkTOptionalTestPayload {
153public:
154 enum State {
155 kConstructed,
156 kCopyConstructed,
157 kCopyAssigned,
158 kMoveConstructed,
159 kMoveAssigned,
160 kMovedFrom
161 };
162
163 SkTOptionalTestPayload(int payload)
164 : fState(kConstructed)
165 , fPayload(payload) {}
166
167 SkTOptionalTestPayload(const SkTOptionalTestPayload& other)
168 : fState(kCopyConstructed)
169 , fPayload(other.fPayload) {}
170
171 SkTOptionalTestPayload(SkTOptionalTestPayload&& other)
172 : fState(kMoveConstructed)
173 , fPayload(other.fPayload) {
174 other.fState = kMovedFrom;
175 }
176
177 SkTOptionalTestPayload& operator=(const SkTOptionalTestPayload& other) {
178 fState = kCopyAssigned;
179 fPayload = other.fPayload;
180 return *this;
181 }
182
183 SkTOptionalTestPayload& operator=(SkTOptionalTestPayload&& other) {
184 fState = kMoveAssigned;
185 fPayload = other.fPayload;
186 other.fState = kMovedFrom;
187 return *this;
188 }
189 State fState;
190 int fPayload;
191};
192
193DEF_TEST(SkTOptionalConstruction, r) {
194 skstd::optional<SkTOptionalTestPayload> o(1);
195 REPORTER_ASSERT(r, o);
196 REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kConstructed);
197 REPORTER_ASSERT(r, o->fPayload == 1);
198
199 skstd::optional<SkTOptionalTestPayload> copy(o);
200 REPORTER_ASSERT(r, copy);
201 REPORTER_ASSERT(r, copy->fState == SkTOptionalTestPayload::kCopyConstructed);
202 REPORTER_ASSERT(r, copy->fPayload == 1);
203 REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kConstructed);
204
205 skstd::optional<SkTOptionalTestPayload> move(std::move(o));
206 REPORTER_ASSERT(r, move);
207 REPORTER_ASSERT(r, move->fState == SkTOptionalTestPayload::kMoveConstructed);
208 REPORTER_ASSERT(r, move->fPayload == 1);
209 // NOLINTNEXTLINE(bugprone-use-after-move)
210 REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kMovedFrom);
211}
212
213DEF_TEST(SkTOptionalMoveAssignment, r) {
214 skstd::optional<SkTOptionalTestPayload> o;
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -0400215 REPORTER_ASSERT(r, !o);
216
Ethan Nicholas8f73ede2021-06-01 13:25:22 -0400217 // assign to an empty optional from an empty optional
218 o = skstd::optional<SkTOptionalTestPayload>();
219 REPORTER_ASSERT(r, !o);
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -0400220
Ethan Nicholas8f73ede2021-06-01 13:25:22 -0400221 // assign to an empty optional from a full optional
222 skstd::optional<SkTOptionalTestPayload> full(1);
223 o = std::move(full);
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -0400224 REPORTER_ASSERT(r, o);
Ethan Nicholas8f73ede2021-06-01 13:25:22 -0400225 REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kMoveConstructed);
226 REPORTER_ASSERT(r, o->fPayload == 1);
227 // NOLINTNEXTLINE(bugprone-use-after-move)
228 REPORTER_ASSERT(r, full->fState == SkTOptionalTestPayload::kMovedFrom);
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -0400229
Ethan Nicholas8f73ede2021-06-01 13:25:22 -0400230 // assign to a full optional from a full optional
231 full = skstd::optional<SkTOptionalTestPayload>(2);
232 o = std::move(full);
233 REPORTER_ASSERT(r, o);
234 REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kMoveAssigned);
235 REPORTER_ASSERT(r, o->fPayload == 2);
236 // NOLINTNEXTLINE(bugprone-use-after-move)
237 REPORTER_ASSERT(r, full->fState == SkTOptionalTestPayload::kMovedFrom);
238
239 // assign to a full optional from an empty optional
240 o = skstd::optional<SkTOptionalTestPayload>();
241 REPORTER_ASSERT(r, !o);
242}
243
244DEF_TEST(SkTOptionalCopyAssignment, r) {
245 skstd::optional<SkTOptionalTestPayload> o;
246 REPORTER_ASSERT(r, !o);
247
248 skstd::optional<SkTOptionalTestPayload> empty;
249 skstd::optional<SkTOptionalTestPayload> full(1);
250
251 // assign to an empty optional from an empty optional
252 o = empty;
253 REPORTER_ASSERT(r, !o);
254
255 // assign to an empty optional from a full optional
256 o = full;
257 REPORTER_ASSERT(r, o);
258 REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kCopyConstructed);
259 REPORTER_ASSERT(r, o->fPayload == 1);
260
261 // assign to a full optional from a full optional
262 o = full;
263 REPORTER_ASSERT(r, o);
264 REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kCopyAssigned);
265 REPORTER_ASSERT(r, o->fPayload == 1);
266
267 // assign to a full optional from an empty optional
268 o = empty;
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -0400269 REPORTER_ASSERT(r, !o);
270}
271
John Stilesaca3f222021-08-26 13:58:05 -0400272DEF_TEST(SkTOptionalEmplace, r) {
273 skstd::optional<std::vector<int>> o;
274 REPORTER_ASSERT(r, !o);
275
276 // Emplace with the no-argument constructor
277 o.emplace();
278 REPORTER_ASSERT(r, o.has_value());
279 REPORTER_ASSERT(r, o->empty());
280
281 // Emplace with the initializer-list constructor
282 o.emplace({1, 2, 3});
283 REPORTER_ASSERT(r, o.has_value());
284 REPORTER_ASSERT(r, (*o == std::vector<int>{1, 2, 3}));
285
286 // Emplace with a normal constructor
287 std::vector<int> otherVec = {4, 5, 6};
288 o.emplace(otherVec.begin(), otherVec.end());
289 REPORTER_ASSERT(r, o.has_value());
290 REPORTER_ASSERT(r, (*o == std::vector<int>{4, 5, 6}));
291}
292
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -0400293DEF_TEST(SkTOptionalNoDefaultConstructor, r) {
294 class NoDefaultConstructor {
295 public:
296 NoDefaultConstructor(int value)
297 : fValue(value) {}
298
299 int fValue;
300 };
301
302 skstd::optional<NoDefaultConstructor> o1;
303 REPORTER_ASSERT(r, !o1);
304 skstd::optional<NoDefaultConstructor> o2(5);
305 REPORTER_ASSERT(r, o2);
306 REPORTER_ASSERT(r, o2->fValue == 5);
307 o1 = std::move(o2);
308 REPORTER_ASSERT(r, o1);
309 REPORTER_ASSERT(r, o1->fValue == 5);
310}
311
312DEF_TEST(SkTOptionalSelfAssignment, r) {
313 skstd::optional<SkString> empty;
314 skstd::optional<SkString>& emptyRef = empty;
Ethan Nicholas8f73ede2021-06-01 13:25:22 -0400315 empty = emptyRef;
316 REPORTER_ASSERT(r, !empty);
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -0400317 empty = std::move(emptyRef);
318 REPORTER_ASSERT(r, !empty);
319
320 skstd::optional<SkString> full("full");
321 skstd::optional<SkString>& fullRef = full;
Ethan Nicholas8f73ede2021-06-01 13:25:22 -0400322 full = fullRef;
323 REPORTER_ASSERT(r, full);
324 REPORTER_ASSERT(r, *full == SkString("full"));
Ethan Nicholas4ed2baa2021-05-25 09:10:14 -0400325 full = std::move(fullRef);
326 REPORTER_ASSERT(r, full);
327 REPORTER_ASSERT(r, *full == SkString("full"));
328}