| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- //
- // object_test.cxx
- // reflection-test
- //
- // Created by Sam Jaffe on 7/4/22.
- // Copyright © 2022 Sam Jaffe. All rights reserved.
- //
- #include "reflection/object.h"
- #include "xcode_gtest_helper.h"
- using reflection::Object;
- using reflection::Reflection;
- using testing::Eq;
- using testing::NotNull;
- namespace {
- struct Example {
- int a;
- int get_c() const { return a + 4; }
- void set_c(int c) { a = c - 4; }
- };
- struct Compound {
- Example ex;
- };
- }
- namespace reflection {
- INSTANTIATE_REFLECTION(Example);
- INSTANTIATE_REFLECTION(Compound);
- }
- REFLECTION(Example)
- .bind("a", &Example::a)
- .bind("c", &Example::get_c, &Example::set_c);
- REFLECTION(Compound).bind("ex", &Compound::ex);
- TEST(ObjectTest, CanFetchData) {
- Example ex{.a = 1};
- Object a = Object(ex).get("a");
- EXPECT_NO_THROW((void)int(a)) << a.type().name();
- EXPECT_THAT(int(a), 1);
- }
- TEST(ObjectTest, CanSetDataOnNonConst) {
- Example ex{.a = 1};
- {
- Object a = Object(ex).get("a");
- EXPECT_NO_THROW((void)static_cast<int &>(a)) << a.type().name();
- static_cast<int &>(a) = 2;
- }
- EXPECT_THAT(ex.a, 2);
- }
- TEST(ObjectTest, ThrowsWhenTryingToEditConst) {
- Example const ex{.a = 1};
- Object a = Object(ex).get("a");
- EXPECT_THROW((void)static_cast<int &>(a), std::bad_cast);
- }
- TEST(ObjectTest, ThrowsWhenTryingToEditMoved) {
- Object a = Object(Example{.a = 1}).get("a");
- EXPECT_THROW((void)static_cast<int &>(a), std::bad_cast);
- }
- TEST(ObjectTest, CanCoerceNumericTypes) {
- Example const ex{.a = 1};
- Object a = Object(ex).get("a");
- EXPECT_THAT(double(a), 1.0);
- }
- TEST(ObjectTest, ThrowsWhenPerformingIllegalTypeCoersion) {
- Example const ex{.a = 1};
- Object a = Object(ex).get("a");
- EXPECT_THROW((void)std::string(a), std::bad_cast);
- }
- TEST(ObjectTest, CanFetchWithGetter) {
- Example ex{.a = 1};
- Object c = Object(ex).get("c");
- EXPECT_NO_THROW((void)int(c)) << c.type().name();
- EXPECT_THAT(int(c), Eq(5));
- static_cast<int &>(c) = 4;
- }
- TEST(ObjectTest, CanModifyWithSetter) {
- Example ex{.a = 1};
- {
- Object c = Object(ex).get("c");
- EXPECT_NO_THROW((void)static_cast<int &>(c)) << c.type().name();
- static_cast<int &>(c) = 4;
- // Notice that the setter is scoped on the Object expiring
- EXPECT_THAT(ex.a, Eq(1));
- }
- EXPECT_THAT(ex.a, Eq(0));
- }
- TEST(ObjectTest, ThrowsWhenUsingSetterOnConst) {
- Example const ex{.a = 1};
- Object c = Object(ex).get("c");
- EXPECT_THROW((void)static_cast<int &>(c), std::bad_cast);
- }
- TEST(ObjectTest, CanDive) {
- Compound cm{.ex = {.a = 2}};
- Object a = Object(cm).get(std::vector{"ex", "a"});
- EXPECT_NO_THROW((void)int(a));
- EXPECT_THAT(int(a), Eq(2));
- }
- TEST(ObjectTest, AttachesNameInfo) {
- Compound cm{.ex = {.a = 2}};
- Object a = Object(cm).get(std::vector{"ex", "a"});
- EXPECT_THAT(a.path(), Eq("this.ex.a"));
- EXPECT_THAT(a.name(), Eq("a"));
- }
- TEST(ObjectTest, CanReflectVariableName) {
- Compound cm{.ex = {.a = 2}};
- Object a = reflect(cm).get(std::vector{"ex", "a"});
- EXPECT_THAT(a.path(), Eq("cm.ex.a"));
- EXPECT_THAT(a.name(), Eq("a"));
- }
|