• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
DEF_TEST(SkTOptionalEmpty,r)13 DEF_TEST(SkTOptionalEmpty, r) {
14     skstd::optional<int> o;
15     REPORTER_ASSERT(r, !o);
16     REPORTER_ASSERT(r, !o.has_value());
17 }
18 
DEF_TEST(SkTOptionalNulloptCtor,r)19 DEF_TEST(SkTOptionalNulloptCtor, r) {
20     skstd::optional<int> o(skstd::nullopt);
21     REPORTER_ASSERT(r, !o);
22     REPORTER_ASSERT(r, !o.has_value());
23 }
24 
DEF_TEST(SkTOptionalValueOr,r)25 DEF_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 
DEF_TEST(SkTOptionalValue,r)46 DEF_TEST(SkTOptionalValue, r) {
47     skstd::optional<const char*> o("test");
48     REPORTER_ASSERT(r, o);
49     REPORTER_ASSERT(r, o.has_value());
50     REPORTER_ASSERT(r, !strcmp(*o, "test"));
51     REPORTER_ASSERT(r, !strcmp(o.value(), "test"));
52     o.reset();
53     REPORTER_ASSERT(r, !o);
54     REPORTER_ASSERT(r, !o.has_value());
55 }
56 
DEF_TEST(SkTOptionalNulloptAssignment,r)57 DEF_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 
DEF_TEST(SkTOptionalNulloptReturn,r)66 DEF_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 
DEF_TEST(SkTOptionalComparisons,r)74 DEF_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 
152 class SkTOptionalTestPayload {
153 public:
154     enum State {
155         kConstructed,
156         kCopyConstructed,
157         kCopyAssigned,
158         kMoveConstructed,
159         kMoveAssigned,
160         kMovedFrom
161     };
162 
SkTOptionalTestPayload(int payload)163     SkTOptionalTestPayload(int payload)
164         : fState(kConstructed)
165         , fPayload(payload) {}
166 
SkTOptionalTestPayload(const SkTOptionalTestPayload & other)167     SkTOptionalTestPayload(const SkTOptionalTestPayload& other)
168         : fState(kCopyConstructed)
169         , fPayload(other.fPayload) {}
170 
SkTOptionalTestPayload(SkTOptionalTestPayload && other)171     SkTOptionalTestPayload(SkTOptionalTestPayload&& other)
172         : fState(kMoveConstructed)
173         , fPayload(other.fPayload) {
174             other.fState = kMovedFrom;
175         }
176 
operator =(const SkTOptionalTestPayload & other)177     SkTOptionalTestPayload& operator=(const SkTOptionalTestPayload& other) {
178         fState = kCopyAssigned;
179         fPayload = other.fPayload;
180         return *this;
181     }
182 
operator =(SkTOptionalTestPayload && other)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 
DEF_TEST(SkTOptionalConstruction,r)193 DEF_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 
DEF_TEST(SkTOptionalMoveAssignment,r)213 DEF_TEST(SkTOptionalMoveAssignment, r) {
214     skstd::optional<SkTOptionalTestPayload> o;
215     REPORTER_ASSERT(r, !o);
216 
217     // assign to an empty optional from an empty optional
218     o = skstd::optional<SkTOptionalTestPayload>();
219     REPORTER_ASSERT(r, !o);
220 
221     // assign to an empty optional from a full optional
222     skstd::optional<SkTOptionalTestPayload> full(1);
223     o = std::move(full);
224     REPORTER_ASSERT(r, o);
225     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);
229 
230     // 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 
DEF_TEST(SkTOptionalCopyAssignment,r)244 DEF_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;
269     REPORTER_ASSERT(r, !o);
270 }
271 
DEF_TEST(SkTOptionalEmplace,r)272 DEF_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 
DEF_TEST(SkTOptionalNoDefaultConstructor,r)293 DEF_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 
DEF_TEST(SkTOptionalDestroyed,r)312 DEF_TEST(SkTOptionalDestroyed, r) {
313     bool destroyed = false;
314     struct NotifyWhenDestroyed {
315         NotifyWhenDestroyed(bool* e) : fE(e) {}
316         ~NotifyWhenDestroyed() { *fE = true; }
317         bool* fE;
318     };
319     {
320         skstd::optional<NotifyWhenDestroyed> notify(&destroyed);
321     }
322     REPORTER_ASSERT(r, destroyed);
323 }
324 
DEF_TEST(SkTOptionalSelfAssignment,r)325 DEF_TEST(SkTOptionalSelfAssignment, r) {
326     skstd::optional<SkString> empty;
327     skstd::optional<SkString>& emptyRef = empty;
328     empty = emptyRef;
329     REPORTER_ASSERT(r, !empty);
330     empty = std::move(emptyRef);
331     REPORTER_ASSERT(r, !empty);
332 
333     skstd::optional<SkString> full("full");
334     skstd::optional<SkString>& fullRef = full;
335     full = fullRef;
336     REPORTER_ASSERT(r, full);
337     REPORTER_ASSERT(r, *full == SkString("full"));
338     full = std::move(fullRef);
339     REPORTER_ASSERT(r, full);
340     REPORTER_ASSERT(r, *full == SkString("full"));
341 }
342