blob: f35192e66dad13a36b5eef5a88e36b227e5e7474 [file] [log] [blame]
Ben Clayton23946b32023-03-09 16:50:19 +00001// Copyright 2023 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "src/tint/switch.h"
16
17#include <memory>
18#include <string>
19
20#include "gtest/gtest.h"
21
22namespace tint {
23namespace {
24
dan sinclair12fa3032023-04-19 23:52:33 +000025struct Animal : public tint::utils::Castable<Animal> {};
26struct Amphibian : public tint::utils::Castable<Amphibian, Animal> {};
27struct Mammal : public tint::utils::Castable<Mammal, Animal> {};
28struct Reptile : public tint::utils::Castable<Reptile, Animal> {};
29struct Frog : public tint::utils::Castable<Frog, Amphibian> {};
30struct Bear : public tint::utils::Castable<Bear, Mammal> {};
31struct Lizard : public tint::utils::Castable<Lizard, Reptile> {};
32struct Gecko : public tint::utils::Castable<Gecko, Lizard> {};
33struct Iguana : public tint::utils::Castable<Iguana, Lizard> {};
Ben Clayton23946b32023-03-09 16:50:19 +000034
35TEST(Castable, SwitchNoDefault) {
36 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
37 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
38 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
39 {
40 bool frog_matched_amphibian = false;
41 Switch(
42 frog.get(), //
43 [&](Reptile*) { FAIL() << "frog is not reptile"; },
44 [&](Mammal*) { FAIL() << "frog is not mammal"; },
45 [&](Amphibian* amphibian) {
46 EXPECT_EQ(amphibian, frog.get());
47 frog_matched_amphibian = true;
48 });
49 EXPECT_TRUE(frog_matched_amphibian);
50 }
51 {
52 bool bear_matched_mammal = false;
53 Switch(
54 bear.get(), //
55 [&](Reptile*) { FAIL() << "bear is not reptile"; },
56 [&](Amphibian*) { FAIL() << "bear is not amphibian"; },
57 [&](Mammal* mammal) {
58 EXPECT_EQ(mammal, bear.get());
59 bear_matched_mammal = true;
60 });
61 EXPECT_TRUE(bear_matched_mammal);
62 }
63 {
64 bool gecko_matched_reptile = false;
65 Switch(
66 gecko.get(), //
67 [&](Mammal*) { FAIL() << "gecko is not mammal"; },
68 [&](Amphibian*) { FAIL() << "gecko is not amphibian"; },
69 [&](Reptile* reptile) {
70 EXPECT_EQ(reptile, gecko.get());
71 gecko_matched_reptile = true;
72 });
73 EXPECT_TRUE(gecko_matched_reptile);
74 }
75}
76
77TEST(Castable, SwitchWithUnusedDefault) {
78 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
79 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
80 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
81 {
82 bool frog_matched_amphibian = false;
83 Switch(
84 frog.get(), //
85 [&](Reptile*) { FAIL() << "frog is not reptile"; },
86 [&](Mammal*) { FAIL() << "frog is not mammal"; },
87 [&](Amphibian* amphibian) {
88 EXPECT_EQ(amphibian, frog.get());
89 frog_matched_amphibian = true;
90 },
91 [&](Default) { FAIL() << "default should not have been selected"; });
92 EXPECT_TRUE(frog_matched_amphibian);
93 }
94 {
95 bool bear_matched_mammal = false;
96 Switch(
97 bear.get(), //
98 [&](Reptile*) { FAIL() << "bear is not reptile"; },
99 [&](Amphibian*) { FAIL() << "bear is not amphibian"; },
100 [&](Mammal* mammal) {
101 EXPECT_EQ(mammal, bear.get());
102 bear_matched_mammal = true;
103 },
104 [&](Default) { FAIL() << "default should not have been selected"; });
105 EXPECT_TRUE(bear_matched_mammal);
106 }
107 {
108 bool gecko_matched_reptile = false;
109 Switch(
110 gecko.get(), //
111 [&](Mammal*) { FAIL() << "gecko is not mammal"; },
112 [&](Amphibian*) { FAIL() << "gecko is not amphibian"; },
113 [&](Reptile* reptile) {
114 EXPECT_EQ(reptile, gecko.get());
115 gecko_matched_reptile = true;
116 },
117 [&](Default) { FAIL() << "default should not have been selected"; });
118 EXPECT_TRUE(gecko_matched_reptile);
119 }
120}
121
122TEST(Castable, SwitchDefault) {
123 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
124 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
125 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
126 {
127 bool frog_matched_default = false;
128 Switch(
129 frog.get(), //
130 [&](Reptile*) { FAIL() << "frog is not reptile"; },
131 [&](Mammal*) { FAIL() << "frog is not mammal"; },
132 [&](Default) { frog_matched_default = true; });
133 EXPECT_TRUE(frog_matched_default);
134 }
135 {
136 bool bear_matched_default = false;
137 Switch(
138 bear.get(), //
139 [&](Reptile*) { FAIL() << "bear is not reptile"; },
140 [&](Amphibian*) { FAIL() << "bear is not amphibian"; },
141 [&](Default) { bear_matched_default = true; });
142 EXPECT_TRUE(bear_matched_default);
143 }
144 {
145 bool gecko_matched_default = false;
146 Switch(
147 gecko.get(), //
148 [&](Mammal*) { FAIL() << "gecko is not mammal"; },
149 [&](Amphibian*) { FAIL() << "gecko is not amphibian"; },
150 [&](Default) { gecko_matched_default = true; });
151 EXPECT_TRUE(gecko_matched_default);
152 }
153}
154
155TEST(Castable, SwitchMatchFirst) {
156 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
157 {
158 bool frog_matched_animal = false;
159 Switch(
160 frog.get(),
161 [&](Animal* animal) {
162 EXPECT_EQ(animal, frog.get());
163 frog_matched_animal = true;
164 },
165 [&](Amphibian*) { FAIL() << "animal should have been matched first"; });
166 EXPECT_TRUE(frog_matched_animal);
167 }
168 {
169 bool frog_matched_amphibian = false;
170 Switch(
171 frog.get(),
172 [&](Amphibian* amphibain) {
173 EXPECT_EQ(amphibain, frog.get());
174 frog_matched_amphibian = true;
175 },
176 [&](Animal*) { FAIL() << "amphibian should have been matched first"; });
177 EXPECT_TRUE(frog_matched_amphibian);
178 }
179}
180
181TEST(Castable, SwitchReturnValueWithDefault) {
182 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
183 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
184 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
185 {
186 const char* result = Switch(
187 frog.get(), //
188 [](Mammal*) { return "mammal"; }, //
189 [](Amphibian*) { return "amphibian"; }, //
190 [](Default) { return "unknown"; });
191 static_assert(std::is_same_v<decltype(result), const char*>);
192 EXPECT_EQ(std::string(result), "amphibian");
193 }
194 {
195 const char* result = Switch(
196 bear.get(), //
197 [](Mammal*) { return "mammal"; }, //
198 [](Amphibian*) { return "amphibian"; }, //
199 [](Default) { return "unknown"; });
200 static_assert(std::is_same_v<decltype(result), const char*>);
201 EXPECT_EQ(std::string(result), "mammal");
202 }
203 {
204 const char* result = Switch(
205 gecko.get(), //
206 [](Mammal*) { return "mammal"; }, //
207 [](Amphibian*) { return "amphibian"; }, //
208 [](Default) { return "unknown"; });
209 static_assert(std::is_same_v<decltype(result), const char*>);
210 EXPECT_EQ(std::string(result), "unknown");
211 }
212}
213
214TEST(Castable, SwitchReturnValueWithoutDefault) {
215 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
216 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
217 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
218 {
219 const char* result = Switch(
220 frog.get(), //
221 [](Mammal*) { return "mammal"; }, //
222 [](Amphibian*) { return "amphibian"; });
223 static_assert(std::is_same_v<decltype(result), const char*>);
224 EXPECT_EQ(std::string(result), "amphibian");
225 }
226 {
227 const char* result = Switch(
228 bear.get(), //
229 [](Mammal*) { return "mammal"; }, //
230 [](Amphibian*) { return "amphibian"; });
231 static_assert(std::is_same_v<decltype(result), const char*>);
232 EXPECT_EQ(std::string(result), "mammal");
233 }
234 {
235 auto* result = Switch(
236 gecko.get(), //
237 [](Mammal*) { return "mammal"; }, //
238 [](Amphibian*) { return "amphibian"; });
239 static_assert(std::is_same_v<decltype(result), const char*>);
240 EXPECT_EQ(result, nullptr);
241 }
242}
243
244TEST(Castable, SwitchInferPODReturnTypeWithDefault) {
245 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
246 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
247 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
248 {
249 auto result = Switch(
250 frog.get(), //
251 [](Mammal*) { return 1; }, //
252 [](Amphibian*) { return 2.0f; }, //
253 [](Default) { return 3.0; });
254 static_assert(std::is_same_v<decltype(result), double>);
255 EXPECT_EQ(result, 2.0);
256 }
257 {
258 auto result = Switch(
259 bear.get(), //
260 [](Mammal*) { return 1.0; }, //
261 [](Amphibian*) { return 2.0f; }, //
262 [](Default) { return 3; });
263 static_assert(std::is_same_v<decltype(result), double>);
264 EXPECT_EQ(result, 1.0);
265 }
266 {
267 auto result = Switch(
268 gecko.get(), //
269 [](Mammal*) { return 1.0f; }, //
270 [](Amphibian*) { return 2; }, //
271 [](Default) { return 3.0; });
272 static_assert(std::is_same_v<decltype(result), double>);
273 EXPECT_EQ(result, 3.0);
274 }
275}
276
277TEST(Castable, SwitchInferPODReturnTypeWithoutDefault) {
278 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
279 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
280 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
281 {
282 auto result = Switch(
283 frog.get(), //
284 [](Mammal*) { return 1; }, //
285 [](Amphibian*) { return 2.0f; });
286 static_assert(std::is_same_v<decltype(result), float>);
287 EXPECT_EQ(result, 2.0f);
288 }
289 {
290 auto result = Switch(
291 bear.get(), //
292 [](Mammal*) { return 1.0f; }, //
293 [](Amphibian*) { return 2; });
294 static_assert(std::is_same_v<decltype(result), float>);
295 EXPECT_EQ(result, 1.0f);
296 }
297 {
298 auto result = Switch(
299 gecko.get(), //
300 [](Mammal*) { return 1.0; }, //
301 [](Amphibian*) { return 2.0f; });
302 static_assert(std::is_same_v<decltype(result), double>);
303 EXPECT_EQ(result, 0.0);
304 }
305}
306
307TEST(Castable, SwitchInferCastableReturnTypeWithDefault) {
308 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
309 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
310 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
311 {
312 auto* result = Switch(
313 frog.get(), //
314 [](Mammal* p) { return p; }, //
315 [](Amphibian*) { return nullptr; }, //
316 [](Default) { return nullptr; });
317 static_assert(std::is_same_v<decltype(result), Mammal*>);
318 EXPECT_EQ(result, nullptr);
319 }
320 {
321 auto* result = Switch(
322 bear.get(), //
323 [](Mammal* p) { return p; }, //
324 [](Amphibian* p) { return const_cast<const Amphibian*>(p); },
325 [](Default) { return nullptr; });
326 static_assert(std::is_same_v<decltype(result), const Animal*>);
327 EXPECT_EQ(result, bear.get());
328 }
329 {
330 auto* result = Switch(
331 gecko.get(), //
332 [](Mammal* p) { return p; }, //
333 [](Amphibian* p) { return p; }, //
dan sinclair12fa3032023-04-19 23:52:33 +0000334 [](Default) -> utils::CastableBase* { return nullptr; });
335 static_assert(std::is_same_v<decltype(result), utils::CastableBase*>);
Ben Clayton23946b32023-03-09 16:50:19 +0000336 EXPECT_EQ(result, nullptr);
337 }
338}
339
340TEST(Castable, SwitchInferCastableReturnTypeWithoutDefault) {
341 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
342 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
343 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
344 {
345 auto* result = Switch(
346 frog.get(), //
347 [](Mammal* p) { return p; }, //
348 [](Amphibian*) { return nullptr; });
349 static_assert(std::is_same_v<decltype(result), Mammal*>);
350 EXPECT_EQ(result, nullptr);
351 }
352 {
353 auto* result = Switch(
354 bear.get(), //
355 [](Mammal* p) { return p; }, //
356 [](Amphibian* p) { return const_cast<const Amphibian*>(p); }); //
357 static_assert(std::is_same_v<decltype(result), const Animal*>);
358 EXPECT_EQ(result, bear.get());
359 }
360 {
361 auto* result = Switch(
362 gecko.get(), //
363 [](Mammal* p) { return p; }, //
364 [](Amphibian* p) { return p; });
365 static_assert(std::is_same_v<decltype(result), Animal*>);
366 EXPECT_EQ(result, nullptr);
367 }
368}
369
370TEST(Castable, SwitchExplicitPODReturnTypeWithDefault) {
371 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
372 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
373 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
374 {
375 auto result = Switch<double>(
376 frog.get(), //
377 [](Mammal*) { return 1; }, //
378 [](Amphibian*) { return 2.0f; }, //
379 [](Default) { return 3.0; });
380 static_assert(std::is_same_v<decltype(result), double>);
381 EXPECT_EQ(result, 2.0f);
382 }
383 {
384 auto result = Switch<double>(
385 bear.get(), //
386 [](Mammal*) { return 1; }, //
387 [](Amphibian*) { return 2; }, //
388 [](Default) { return 3; });
389 static_assert(std::is_same_v<decltype(result), double>);
390 EXPECT_EQ(result, 1.0f);
391 }
392 {
393 auto result = Switch<double>(
394 gecko.get(), //
395 [](Mammal*) { return 1.0f; }, //
396 [](Amphibian*) { return 2.0f; }, //
397 [](Default) { return 3.0f; });
398 static_assert(std::is_same_v<decltype(result), double>);
399 EXPECT_EQ(result, 3.0f);
400 }
401}
402
403TEST(Castable, SwitchExplicitPODReturnTypeWithoutDefault) {
404 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
405 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
406 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
407 {
408 auto result = Switch<double>(
409 frog.get(), //
410 [](Mammal*) { return 1; }, //
411 [](Amphibian*) { return 2.0f; });
412 static_assert(std::is_same_v<decltype(result), double>);
413 EXPECT_EQ(result, 2.0f);
414 }
415 {
416 auto result = Switch<double>(
417 bear.get(), //
418 [](Mammal*) { return 1.0f; }, //
419 [](Amphibian*) { return 2; });
420 static_assert(std::is_same_v<decltype(result), double>);
421 EXPECT_EQ(result, 1.0f);
422 }
423 {
424 auto result = Switch<double>(
425 gecko.get(), //
426 [](Mammal*) { return 1.0; }, //
427 [](Amphibian*) { return 2.0f; });
428 static_assert(std::is_same_v<decltype(result), double>);
429 EXPECT_EQ(result, 0.0);
430 }
431}
432
433TEST(Castable, SwitchExplicitCastableReturnTypeWithDefault) {
434 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
435 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
436 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
437 {
438 auto* result = Switch<Animal>(
439 frog.get(), //
440 [](Mammal* p) { return p; }, //
441 [](Amphibian*) { return nullptr; }, //
442 [](Default) { return nullptr; });
443 static_assert(std::is_same_v<decltype(result), Animal*>);
444 EXPECT_EQ(result, nullptr);
445 }
446 {
dan sinclair12fa3032023-04-19 23:52:33 +0000447 auto* result = Switch<utils::CastableBase>(
Ben Clayton23946b32023-03-09 16:50:19 +0000448 bear.get(), //
449 [](Mammal* p) { return p; }, //
450 [](Amphibian* p) { return const_cast<const Amphibian*>(p); },
451 [](Default) { return nullptr; });
dan sinclair12fa3032023-04-19 23:52:33 +0000452 static_assert(std::is_same_v<decltype(result), const utils::CastableBase*>);
Ben Clayton23946b32023-03-09 16:50:19 +0000453 EXPECT_EQ(result, bear.get());
454 }
455 {
456 auto* result = Switch<const Animal>(
457 gecko.get(), //
458 [](Mammal* p) { return p; }, //
459 [](Amphibian* p) { return p; }, //
460 [](Default) { return nullptr; });
461 static_assert(std::is_same_v<decltype(result), const Animal*>);
462 EXPECT_EQ(result, nullptr);
463 }
464}
465
466TEST(Castable, SwitchExplicitCastableReturnTypeWithoutDefault) {
467 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
468 std::unique_ptr<Animal> bear = std::make_unique<Bear>();
469 std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
470 {
471 auto* result = Switch<Animal>(
472 frog.get(), //
473 [](Mammal* p) { return p; }, //
474 [](Amphibian*) { return nullptr; });
475 static_assert(std::is_same_v<decltype(result), Animal*>);
476 EXPECT_EQ(result, nullptr);
477 }
478 {
dan sinclair12fa3032023-04-19 23:52:33 +0000479 auto* result = Switch<utils::CastableBase>(
Ben Clayton23946b32023-03-09 16:50:19 +0000480 bear.get(), //
481 [](Mammal* p) { return p; }, //
482 [](Amphibian* p) { return const_cast<const Amphibian*>(p); }); //
dan sinclair12fa3032023-04-19 23:52:33 +0000483 static_assert(std::is_same_v<decltype(result), const utils::CastableBase*>);
Ben Clayton23946b32023-03-09 16:50:19 +0000484 EXPECT_EQ(result, bear.get());
485 }
486 {
487 auto* result = Switch<const Animal*>(
488 gecko.get(), //
489 [](Mammal* p) { return p; }, //
490 [](Amphibian* p) { return p; });
491 static_assert(std::is_same_v<decltype(result), const Animal*>);
492 EXPECT_EQ(result, nullptr);
493 }
494}
495
496TEST(Castable, SwitchNull) {
497 Animal* null = nullptr;
498 Switch(
499 null, //
500 [&](Amphibian*) { FAIL() << "should not be called"; },
501 [&](Animal*) { FAIL() << "should not be called"; });
502}
503
504TEST(Castable, SwitchNullNoDefault) {
505 Animal* null = nullptr;
506 bool default_called = false;
507 Switch(
508 null, //
509 [&](Amphibian*) { FAIL() << "should not be called"; },
510 [&](Animal*) { FAIL() << "should not be called"; },
511 [&](Default) { default_called = true; });
512 EXPECT_TRUE(default_called);
513}
514
515TEST(Castable, SwitchReturnNoDefaultInitializer) {
516 struct Object {
517 explicit Object(int v) : value(v) {}
518 int value;
519 };
520
521 std::unique_ptr<Animal> frog = std::make_unique<Frog>();
522 {
523 auto result = Switch(
524 frog.get(), //
525 [](Mammal*) { return Object(1); }, //
526 [](Amphibian*) { return Object(2); }, //
527 [](Default) { return Object(3); });
528 static_assert(std::is_same_v<decltype(result), Object>);
529 EXPECT_EQ(result.value, 2);
530 }
531 {
532 auto result = Switch(
533 frog.get(), //
534 [](Mammal*) { return Object(1); }, //
535 [](Default) { return Object(3); });
536 static_assert(std::is_same_v<decltype(result), Object>);
537 EXPECT_EQ(result.value, 3);
538 }
539}
540
541} // namespace
542
543TINT_INSTANTIATE_TYPEINFO(Animal);
544TINT_INSTANTIATE_TYPEINFO(Amphibian);
545TINT_INSTANTIATE_TYPEINFO(Mammal);
546TINT_INSTANTIATE_TYPEINFO(Reptile);
547TINT_INSTANTIATE_TYPEINFO(Frog);
548TINT_INSTANTIATE_TYPEINFO(Bear);
549TINT_INSTANTIATE_TYPEINFO(Lizard);
550TINT_INSTANTIATE_TYPEINFO(Gecko);
551
552} // namespace tint