object_test.cxx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //
  2. // object_test.cxx
  3. // reflection-test
  4. //
  5. // Created by Sam Jaffe on 7/4/22.
  6. // Copyright © 2022 Sam Jaffe. All rights reserved.
  7. //
  8. #include "reflection/object.h"
  9. #include "xcode_gtest_helper.h"
  10. using reflection::Object;
  11. using reflection::Reflection;
  12. using testing::Eq;
  13. using testing::NotNull;
  14. namespace {
  15. struct Example {
  16. int a;
  17. int get_c() const { return a + 4; }
  18. void set_c(int c) { a = c - 4; }
  19. };
  20. struct Compound {
  21. Example ex;
  22. };
  23. bool _1 = Reflection<Example>()
  24. .bind("a", &Example::a)
  25. .bind("c", &Example::get_c, &Example::set_c);
  26. bool _2 = Reflection<Compound>().bind("ex", &Compound::ex);
  27. }
  28. TEST(ObjectTest, CanFetchData) {
  29. Example ex{.a = 1};
  30. Object a = Object(ex).get("a");
  31. EXPECT_NO_THROW((void)int(a)) << a.type();
  32. EXPECT_THAT(int(a), 1);
  33. }
  34. TEST(ObjectTest, CanSetDataOnNonConst) {
  35. Example ex{.a = 1};
  36. {
  37. Object a = Object(ex).get("a");
  38. EXPECT_NO_THROW((void)static_cast<int &>(a)) << a.type();
  39. static_cast<int &>(a) = 2;
  40. }
  41. EXPECT_THAT(ex.a, 2);
  42. }
  43. TEST(ObjectTest, ThrowsWhenTryingToEditConst) {
  44. Example const ex{.a = 1};
  45. Object a = Object(ex).get("a");
  46. EXPECT_THROW((void)static_cast<int &>(a), std::bad_cast);
  47. }
  48. TEST(ObjectTest, ThrowsWhenTryingToEditMoved) {
  49. Object a = Object(Example{.a = 1}).get("a");
  50. EXPECT_THROW((void)static_cast<int &>(a), std::bad_cast);
  51. }
  52. TEST(ObjectTest, ThrowsWhenPerformingTypeCoersion) {
  53. Example const ex{.a = 1};
  54. Object a = Object(ex).get("a");
  55. EXPECT_THROW((void)double(a), std::bad_cast);
  56. }
  57. TEST(ObjectTest, CanFetchWithGetter) {
  58. Example ex{.a = 1};
  59. Object c = Object(ex).get("c");
  60. EXPECT_NO_THROW((void)int(c)) << c.type();
  61. EXPECT_THAT(int(c), Eq(5));
  62. static_cast<int &>(c) = 4;
  63. }
  64. TEST(ObjectTest, CanModifyWithSetter) {
  65. Example ex{.a = 1};
  66. {
  67. Object c = Object(ex).get("c");
  68. EXPECT_NO_THROW((void)static_cast<int &>(c)) << c.type();
  69. static_cast<int &>(c) = 4;
  70. // Notice that the setter is scoped on the Object expiring
  71. EXPECT_THAT(ex.a, Eq(1));
  72. }
  73. EXPECT_THAT(ex.a, Eq(0));
  74. }
  75. TEST(ObjectTest, ThrowsWhenUsingSetterOnConst) {
  76. Example const ex{.a = 1};
  77. Object c = Object(ex).get("c");
  78. EXPECT_THROW((void)static_cast<int &>(c), std::bad_cast);
  79. }
  80. TEST(ObjectTest, CanDive) {
  81. Compound cm{.ex = {.a = 2}};
  82. Object a = Object(cm).get(std::vector{"ex", "a"});
  83. EXPECT_NO_THROW((void)int(a));
  84. EXPECT_THAT(int(a), Eq(2));
  85. }
  86. TEST(ObjectTest, AttachesNameInfo) {
  87. Compound cm{.ex = {.a = 2}};
  88. Object a = Object(cm).get(std::vector{"ex", "a"});
  89. EXPECT_THAT(a.path(), Eq("this.ex.a"));
  90. EXPECT_THAT(a.name(), Eq("a"));
  91. }
  92. TEST(ObjectTest, CanReflectVariableName) {
  93. Compound cm{.ex = {.a = 2}};
  94. Object a = reflect(cm).get(std::vector{"ex", "a"});
  95. EXPECT_THAT(a.path(), Eq("cm.ex.a"));
  96. EXPECT_THAT(a.name(), Eq("a"));
  97. }