// Copyright 2020 The Tint Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "src/castable.h" #include #include #include "gtest/gtest.h" namespace tint { namespace { struct Animal : public tint::Castable { explicit Animal(std::string n) : name(n) {} const std::string name; }; struct Amphibian : public tint::Castable { explicit Amphibian(std::string n) : Base(n) {} }; struct Mammal : public tint::Castable { explicit Mammal(std::string n) : Base(n) {} }; struct Reptile : public tint::Castable { explicit Reptile(std::string n) : Base(n) {} }; struct Frog : public tint::Castable { Frog() : Base("Frog") {} }; struct Bear : public tint::Castable { Bear() : Base("Bear") {} }; struct Gecko : public tint::Castable { Gecko() : Base("Gecko") {} }; TEST(CastableBase, Is) { std::unique_ptr frog = std::make_unique(); std::unique_ptr bear = std::make_unique(); std::unique_ptr gecko = std::make_unique(); ASSERT_TRUE(frog->Is()); ASSERT_TRUE(bear->Is()); ASSERT_TRUE(gecko->Is()); ASSERT_TRUE(frog->Is()); ASSERT_FALSE(bear->Is()); ASSERT_FALSE(gecko->Is()); ASSERT_FALSE(frog->Is()); ASSERT_TRUE(bear->Is()); ASSERT_FALSE(gecko->Is()); ASSERT_FALSE(frog->Is()); ASSERT_FALSE(bear->Is()); ASSERT_TRUE(gecko->Is()); } TEST(CastableBase, Is_kDontErrorOnImpossibleCast) { // Unlike TEST(CastableBase, Is), we're dynamically querying [A -> B] without // going via CastableBase. auto frog = std::make_unique(); auto bear = std::make_unique(); auto gecko = std::make_unique(); ASSERT_TRUE((frog->Is())); ASSERT_TRUE((bear->Is())); ASSERT_TRUE((gecko->Is())); ASSERT_TRUE((frog->Is())); ASSERT_FALSE((bear->Is())); ASSERT_FALSE((gecko->Is())); ASSERT_FALSE((frog->Is())); ASSERT_TRUE((bear->Is())); ASSERT_FALSE((gecko->Is())); ASSERT_FALSE((frog->Is())); ASSERT_FALSE((bear->Is())); ASSERT_TRUE((gecko->Is())); } TEST(CastableBase, IsWithPredicate) { std::unique_ptr frog = std::make_unique(); frog->Is([&frog](const Animal* a) { EXPECT_EQ(a, frog.get()); return true; }); ASSERT_TRUE((frog->Is([](const Animal*) { return true; }))); ASSERT_FALSE((frog->Is([](const Animal*) { return false; }))); // Predicate not called if cast is invalid auto expect_not_called = [] { FAIL() << "Should not be called"; }; ASSERT_FALSE((frog->Is([&](const Animal*) { expect_not_called(); return true; }))); } TEST(CastableBase, IsAnyOf) { std::unique_ptr frog = std::make_unique(); std::unique_ptr bear = std::make_unique(); std::unique_ptr gecko = std::make_unique(); ASSERT_TRUE((frog->IsAnyOf())); ASSERT_TRUE((frog->IsAnyOf())); ASSERT_TRUE((frog->IsAnyOf())); ASSERT_FALSE((frog->IsAnyOf())); ASSERT_TRUE((bear->IsAnyOf())); ASSERT_TRUE((bear->IsAnyOf())); ASSERT_TRUE((bear->IsAnyOf())); ASSERT_FALSE((bear->IsAnyOf())); ASSERT_TRUE((gecko->IsAnyOf())); ASSERT_TRUE((gecko->IsAnyOf())); ASSERT_TRUE((gecko->IsAnyOf())); ASSERT_FALSE((gecko->IsAnyOf())); } TEST(CastableBase, As) { std::unique_ptr frog = std::make_unique(); std::unique_ptr bear = std::make_unique(); std::unique_ptr gecko = std::make_unique(); ASSERT_EQ(frog->As(), static_cast(frog.get())); ASSERT_EQ(bear->As(), static_cast(bear.get())); ASSERT_EQ(gecko->As(), static_cast(gecko.get())); ASSERT_EQ(frog->As(), static_cast(frog.get())); ASSERT_EQ(bear->As(), nullptr); ASSERT_EQ(gecko->As(), nullptr); ASSERT_EQ(frog->As(), nullptr); ASSERT_EQ(bear->As(), static_cast(bear.get())); ASSERT_EQ(gecko->As(), nullptr); ASSERT_EQ(frog->As(), nullptr); ASSERT_EQ(bear->As(), nullptr); ASSERT_EQ(gecko->As(), static_cast(gecko.get())); } TEST(CastableBase, As_kDontErrorOnImpossibleCast) { // Unlike TEST(CastableBase, As), we're dynamically casting [A -> B] without // going via CastableBase. auto frog = std::make_unique(); auto bear = std::make_unique(); auto gecko = std::make_unique(); ASSERT_EQ((frog->As()), static_cast(frog.get())); ASSERT_EQ((bear->As()), static_cast(bear.get())); ASSERT_EQ((gecko->As()), static_cast(gecko.get())); ASSERT_EQ((frog->As()), static_cast(frog.get())); ASSERT_EQ((bear->As()), nullptr); ASSERT_EQ((gecko->As()), nullptr); ASSERT_EQ((frog->As()), nullptr); ASSERT_EQ((bear->As()), static_cast(bear.get())); ASSERT_EQ((gecko->As()), nullptr); ASSERT_EQ((frog->As()), nullptr); ASSERT_EQ((bear->As()), nullptr); ASSERT_EQ((gecko->As()), static_cast(gecko.get())); } TEST(Castable, Is) { std::unique_ptr frog = std::make_unique(); std::unique_ptr bear = std::make_unique(); std::unique_ptr gecko = std::make_unique(); ASSERT_TRUE(frog->Is()); ASSERT_TRUE(bear->Is()); ASSERT_TRUE(gecko->Is()); ASSERT_TRUE(frog->Is()); ASSERT_FALSE(bear->Is()); ASSERT_FALSE(gecko->Is()); ASSERT_FALSE(frog->Is()); ASSERT_TRUE(bear->Is()); ASSERT_FALSE(gecko->Is()); ASSERT_FALSE(frog->Is()); ASSERT_FALSE(bear->Is()); ASSERT_TRUE(gecko->Is()); } TEST(Castable, IsWithPredicate) { std::unique_ptr frog = std::make_unique(); frog->Is([&frog](const Animal* a) { EXPECT_EQ(a, frog.get()); return true; }); ASSERT_TRUE((frog->Is([](const Animal*) { return true; }))); ASSERT_FALSE((frog->Is([](const Animal*) { return false; }))); // Predicate not called if cast is invalid auto expect_not_called = [] { FAIL() << "Should not be called"; }; ASSERT_FALSE((frog->Is([&](const Animal*) { expect_not_called(); return true; }))); } TEST(Castable, As) { std::unique_ptr frog = std::make_unique(); std::unique_ptr bear = std::make_unique(); std::unique_ptr gecko = std::make_unique(); ASSERT_EQ(frog->As(), static_cast(frog.get())); ASSERT_EQ(bear->As(), static_cast(bear.get())); ASSERT_EQ(gecko->As(), static_cast(gecko.get())); ASSERT_EQ(frog->As(), static_cast(frog.get())); ASSERT_EQ(bear->As(), nullptr); ASSERT_EQ(gecko->As(), nullptr); ASSERT_EQ(frog->As(), nullptr); ASSERT_EQ(bear->As(), static_cast(bear.get())); ASSERT_EQ(gecko->As(), nullptr); ASSERT_EQ(frog->As(), nullptr); ASSERT_EQ(bear->As(), nullptr); ASSERT_EQ(gecko->As(), static_cast(gecko.get())); } } // namespace TINT_INSTANTIATE_TYPEINFO(Animal); TINT_INSTANTIATE_TYPEINFO(Amphibian); TINT_INSTANTIATE_TYPEINFO(Mammal); TINT_INSTANTIATE_TYPEINFO(Reptile); TINT_INSTANTIATE_TYPEINFO(Frog); TINT_INSTANTIATE_TYPEINFO(Bear); TINT_INSTANTIATE_TYPEINFO(Gecko); } // namespace tint