• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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/castable.h"
16 
17 #include <memory>
18 #include <string>
19 
20 #include "gtest/gtest.h"
21 
22 namespace tint {
23 namespace {
24 
25 struct Animal : public tint::Castable<Animal> {
Animaltint::__anon8381b6cf0111::Animal26   explicit Animal(std::string n) : name(n) {}
27   const std::string name;
28 };
29 
30 struct Amphibian : public tint::Castable<Amphibian, Animal> {
Amphibiantint::__anon8381b6cf0111::Amphibian31   explicit Amphibian(std::string n) : Base(n) {}
32 };
33 
34 struct Mammal : public tint::Castable<Mammal, Animal> {
Mammaltint::__anon8381b6cf0111::Mammal35   explicit Mammal(std::string n) : Base(n) {}
36 };
37 
38 struct Reptile : public tint::Castable<Reptile, Animal> {
Reptiletint::__anon8381b6cf0111::Reptile39   explicit Reptile(std::string n) : Base(n) {}
40 };
41 
42 struct Frog : public tint::Castable<Frog, Amphibian> {
Frogtint::__anon8381b6cf0111::Frog43   Frog() : Base("Frog") {}
44 };
45 
46 struct Bear : public tint::Castable<Bear, Mammal> {
Beartint::__anon8381b6cf0111::Bear47   Bear() : Base("Bear") {}
48 };
49 
50 struct Gecko : public tint::Castable<Gecko, Reptile> {
Geckotint::__anon8381b6cf0111::Gecko51   Gecko() : Base("Gecko") {}
52 };
53 
TEST(CastableBase,Is)54 TEST(CastableBase, Is) {
55   std::unique_ptr<CastableBase> frog = std::make_unique<Frog>();
56   std::unique_ptr<CastableBase> bear = std::make_unique<Bear>();
57   std::unique_ptr<CastableBase> gecko = std::make_unique<Gecko>();
58 
59   ASSERT_TRUE(frog->Is<Animal>());
60   ASSERT_TRUE(bear->Is<Animal>());
61   ASSERT_TRUE(gecko->Is<Animal>());
62 
63   ASSERT_TRUE(frog->Is<Amphibian>());
64   ASSERT_FALSE(bear->Is<Amphibian>());
65   ASSERT_FALSE(gecko->Is<Amphibian>());
66 
67   ASSERT_FALSE(frog->Is<Mammal>());
68   ASSERT_TRUE(bear->Is<Mammal>());
69   ASSERT_FALSE(gecko->Is<Mammal>());
70 
71   ASSERT_FALSE(frog->Is<Reptile>());
72   ASSERT_FALSE(bear->Is<Reptile>());
73   ASSERT_TRUE(gecko->Is<Reptile>());
74 }
75 
TEST(CastableBase,Is_kDontErrorOnImpossibleCast)76 TEST(CastableBase, Is_kDontErrorOnImpossibleCast) {
77   // Unlike TEST(CastableBase, Is), we're dynamically querying [A -> B] without
78   // going via CastableBase.
79   auto frog = std::make_unique<Frog>();
80   auto bear = std::make_unique<Bear>();
81   auto gecko = std::make_unique<Gecko>();
82 
83   ASSERT_TRUE((frog->Is<Animal, kDontErrorOnImpossibleCast>()));
84   ASSERT_TRUE((bear->Is<Animal, kDontErrorOnImpossibleCast>()));
85   ASSERT_TRUE((gecko->Is<Animal, kDontErrorOnImpossibleCast>()));
86 
87   ASSERT_TRUE((frog->Is<Amphibian, kDontErrorOnImpossibleCast>()));
88   ASSERT_FALSE((bear->Is<Amphibian, kDontErrorOnImpossibleCast>()));
89   ASSERT_FALSE((gecko->Is<Amphibian, kDontErrorOnImpossibleCast>()));
90 
91   ASSERT_FALSE((frog->Is<Mammal, kDontErrorOnImpossibleCast>()));
92   ASSERT_TRUE((bear->Is<Mammal, kDontErrorOnImpossibleCast>()));
93   ASSERT_FALSE((gecko->Is<Mammal, kDontErrorOnImpossibleCast>()));
94 
95   ASSERT_FALSE((frog->Is<Reptile, kDontErrorOnImpossibleCast>()));
96   ASSERT_FALSE((bear->Is<Reptile, kDontErrorOnImpossibleCast>()));
97   ASSERT_TRUE((gecko->Is<Reptile, kDontErrorOnImpossibleCast>()));
98 }
99 
TEST(CastableBase,IsWithPredicate)100 TEST(CastableBase, IsWithPredicate) {
101   std::unique_ptr<CastableBase> frog = std::make_unique<Frog>();
102 
103   frog->Is<Animal>([&frog](const Animal* a) {
104     EXPECT_EQ(a, frog.get());
105     return true;
106   });
107 
108   ASSERT_TRUE((frog->Is<Animal>([](const Animal*) { return true; })));
109   ASSERT_FALSE((frog->Is<Animal>([](const Animal*) { return false; })));
110 
111   // Predicate not called if cast is invalid
112   auto expect_not_called = [] { FAIL() << "Should not be called"; };
113   ASSERT_FALSE((frog->Is<Bear>([&](const Animal*) {
114     expect_not_called();
115     return true;
116   })));
117 }
118 
TEST(CastableBase,IsAnyOf)119 TEST(CastableBase, IsAnyOf) {
120   std::unique_ptr<CastableBase> frog = std::make_unique<Frog>();
121   std::unique_ptr<CastableBase> bear = std::make_unique<Bear>();
122   std::unique_ptr<CastableBase> gecko = std::make_unique<Gecko>();
123 
124   ASSERT_TRUE((frog->IsAnyOf<Animal, Mammal, Amphibian, Reptile>()));
125   ASSERT_TRUE((frog->IsAnyOf<Mammal, Amphibian>()));
126   ASSERT_TRUE((frog->IsAnyOf<Amphibian, Reptile>()));
127   ASSERT_FALSE((frog->IsAnyOf<Mammal, Reptile>()));
128 
129   ASSERT_TRUE((bear->IsAnyOf<Animal, Mammal, Amphibian, Reptile>()));
130   ASSERT_TRUE((bear->IsAnyOf<Mammal, Amphibian>()));
131   ASSERT_TRUE((bear->IsAnyOf<Mammal, Reptile>()));
132   ASSERT_FALSE((bear->IsAnyOf<Amphibian, Reptile>()));
133 
134   ASSERT_TRUE((gecko->IsAnyOf<Animal, Mammal, Amphibian, Reptile>()));
135   ASSERT_TRUE((gecko->IsAnyOf<Mammal, Reptile>()));
136   ASSERT_TRUE((gecko->IsAnyOf<Amphibian, Reptile>()));
137   ASSERT_FALSE((gecko->IsAnyOf<Mammal, Amphibian>()));
138 }
139 
TEST(CastableBase,As)140 TEST(CastableBase, As) {
141   std::unique_ptr<CastableBase> frog = std::make_unique<Frog>();
142   std::unique_ptr<CastableBase> bear = std::make_unique<Bear>();
143   std::unique_ptr<CastableBase> gecko = std::make_unique<Gecko>();
144 
145   ASSERT_EQ(frog->As<Animal>(), static_cast<Animal*>(frog.get()));
146   ASSERT_EQ(bear->As<Animal>(), static_cast<Animal*>(bear.get()));
147   ASSERT_EQ(gecko->As<Animal>(), static_cast<Animal*>(gecko.get()));
148 
149   ASSERT_EQ(frog->As<Amphibian>(), static_cast<Amphibian*>(frog.get()));
150   ASSERT_EQ(bear->As<Amphibian>(), nullptr);
151   ASSERT_EQ(gecko->As<Amphibian>(), nullptr);
152 
153   ASSERT_EQ(frog->As<Mammal>(), nullptr);
154   ASSERT_EQ(bear->As<Mammal>(), static_cast<Mammal*>(bear.get()));
155   ASSERT_EQ(gecko->As<Mammal>(), nullptr);
156 
157   ASSERT_EQ(frog->As<Reptile>(), nullptr);
158   ASSERT_EQ(bear->As<Reptile>(), nullptr);
159   ASSERT_EQ(gecko->As<Reptile>(), static_cast<Reptile*>(gecko.get()));
160 }
161 
TEST(CastableBase,As_kDontErrorOnImpossibleCast)162 TEST(CastableBase, As_kDontErrorOnImpossibleCast) {
163   // Unlike TEST(CastableBase, As), we're dynamically casting [A -> B] without
164   // going via CastableBase.
165   auto frog = std::make_unique<Frog>();
166   auto bear = std::make_unique<Bear>();
167   auto gecko = std::make_unique<Gecko>();
168 
169   ASSERT_EQ((frog->As<Animal, kDontErrorOnImpossibleCast>()),
170             static_cast<Animal*>(frog.get()));
171   ASSERT_EQ((bear->As<Animal, kDontErrorOnImpossibleCast>()),
172             static_cast<Animal*>(bear.get()));
173   ASSERT_EQ((gecko->As<Animal, kDontErrorOnImpossibleCast>()),
174             static_cast<Animal*>(gecko.get()));
175 
176   ASSERT_EQ((frog->As<Amphibian, kDontErrorOnImpossibleCast>()),
177             static_cast<Amphibian*>(frog.get()));
178   ASSERT_EQ((bear->As<Amphibian, kDontErrorOnImpossibleCast>()), nullptr);
179   ASSERT_EQ((gecko->As<Amphibian, kDontErrorOnImpossibleCast>()), nullptr);
180 
181   ASSERT_EQ((frog->As<Mammal, kDontErrorOnImpossibleCast>()), nullptr);
182   ASSERT_EQ((bear->As<Mammal, kDontErrorOnImpossibleCast>()),
183             static_cast<Mammal*>(bear.get()));
184   ASSERT_EQ((gecko->As<Mammal, kDontErrorOnImpossibleCast>()), nullptr);
185 
186   ASSERT_EQ((frog->As<Reptile, kDontErrorOnImpossibleCast>()), nullptr);
187   ASSERT_EQ((bear->As<Reptile, kDontErrorOnImpossibleCast>()), nullptr);
188   ASSERT_EQ((gecko->As<Reptile, kDontErrorOnImpossibleCast>()),
189             static_cast<Reptile*>(gecko.get()));
190 }
191 
TEST(Castable,Is)192 TEST(Castable, Is) {
193   std::unique_ptr<Animal> frog = std::make_unique<Frog>();
194   std::unique_ptr<Animal> bear = std::make_unique<Bear>();
195   std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
196 
197   ASSERT_TRUE(frog->Is<Animal>());
198   ASSERT_TRUE(bear->Is<Animal>());
199   ASSERT_TRUE(gecko->Is<Animal>());
200 
201   ASSERT_TRUE(frog->Is<Amphibian>());
202   ASSERT_FALSE(bear->Is<Amphibian>());
203   ASSERT_FALSE(gecko->Is<Amphibian>());
204 
205   ASSERT_FALSE(frog->Is<Mammal>());
206   ASSERT_TRUE(bear->Is<Mammal>());
207   ASSERT_FALSE(gecko->Is<Mammal>());
208 
209   ASSERT_FALSE(frog->Is<Reptile>());
210   ASSERT_FALSE(bear->Is<Reptile>());
211   ASSERT_TRUE(gecko->Is<Reptile>());
212 }
213 
TEST(Castable,IsWithPredicate)214 TEST(Castable, IsWithPredicate) {
215   std::unique_ptr<Animal> frog = std::make_unique<Frog>();
216 
217   frog->Is([&frog](const Animal* a) {
218     EXPECT_EQ(a, frog.get());
219     return true;
220   });
221 
222   ASSERT_TRUE((frog->Is([](const Animal*) { return true; })));
223   ASSERT_FALSE((frog->Is([](const Animal*) { return false; })));
224 
225   // Predicate not called if cast is invalid
226   auto expect_not_called = [] { FAIL() << "Should not be called"; };
227   ASSERT_FALSE((frog->Is([&](const Bear*) {
228     expect_not_called();
229     return true;
230   })));
231 }
232 
TEST(Castable,As)233 TEST(Castable, As) {
234   std::unique_ptr<Animal> frog = std::make_unique<Frog>();
235   std::unique_ptr<Animal> bear = std::make_unique<Bear>();
236   std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
237 
238   ASSERT_EQ(frog->As<Animal>(), static_cast<Animal*>(frog.get()));
239   ASSERT_EQ(bear->As<Animal>(), static_cast<Animal*>(bear.get()));
240   ASSERT_EQ(gecko->As<Animal>(), static_cast<Animal*>(gecko.get()));
241 
242   ASSERT_EQ(frog->As<Amphibian>(), static_cast<Amphibian*>(frog.get()));
243   ASSERT_EQ(bear->As<Amphibian>(), nullptr);
244   ASSERT_EQ(gecko->As<Amphibian>(), nullptr);
245 
246   ASSERT_EQ(frog->As<Mammal>(), nullptr);
247   ASSERT_EQ(bear->As<Mammal>(), static_cast<Mammal*>(bear.get()));
248   ASSERT_EQ(gecko->As<Mammal>(), nullptr);
249 
250   ASSERT_EQ(frog->As<Reptile>(), nullptr);
251   ASSERT_EQ(bear->As<Reptile>(), nullptr);
252   ASSERT_EQ(gecko->As<Reptile>(), static_cast<Reptile*>(gecko.get()));
253 }
254 
255 }  // namespace
256 
257 TINT_INSTANTIATE_TYPEINFO(Animal);
258 TINT_INSTANTIATE_TYPEINFO(Amphibian);
259 TINT_INSTANTIATE_TYPEINFO(Mammal);
260 TINT_INSTANTIATE_TYPEINFO(Reptile);
261 TINT_INSTANTIATE_TYPEINFO(Frog);
262 TINT_INSTANTIATE_TYPEINFO(Bear);
263 TINT_INSTANTIATE_TYPEINFO(Gecko);
264 
265 }  // namespace tint
266