1 #define SOL_CHECK_ARGUMENTS 2 3 #include <sol.hpp> 4 #include <catch.hpp> 5 6 #include <iostream> 7 8 TEST_CASE("inheritance/basic", "test that metatables are properly inherited") { 9 struct A { 10 int a = 5; 11 }; 12 13 struct B { bB14 int b() { 15 return 10; 16 } 17 }; 18 19 struct C : B, A { 20 double c = 2.4; 21 }; 22 23 struct D : C { dD24 bool d() const { 25 return true; 26 } 27 }; 28 29 sol::state lua; 30 lua.new_usertype<A>("A", 31 "a", &A::a 32 ); 33 lua.new_usertype<B>("B", 34 "b", &B::b 35 ); 36 lua.new_usertype<C>("C", 37 "c", &C::c, 38 sol::base_classes, sol::bases<B, A>() 39 ); 40 lua.new_usertype<D>("D", 41 "d", &D::d, 42 sol::base_classes, sol::bases<C, B, A>() 43 ); 44 45 lua.script("obj = D.new()"); 46 lua.script("d = obj:d()"); 47 bool d = lua["d"]; 48 lua.script("c = obj.c"); 49 double c = lua["c"]; 50 lua.script("b = obj:b()"); 51 int b = lua["b"]; 52 lua.script("a = obj.a"); 53 int a = lua["a"]; 54 55 REQUIRE(d); 56 REQUIRE(c == 2.4); 57 REQUIRE(b == 10); 58 REQUIRE(a == 5); 59 } 60 61 TEST_CASE("inheritance/multi-base", "test that multiple bases all work and overloading for constructors works with them") { 62 class TestClass00 { 63 public: Thing() const64 int Thing() const { return 123; } 65 }; 66 67 class TestClass01 : public TestClass00 { 68 public: TestClass01()69 TestClass01() : a(1) {} TestClass01(const TestClass00 & other)70 TestClass01(const TestClass00& other) : a(other.Thing()) {} 71 72 int a; 73 }; 74 75 class TestClass02 : public TestClass01 { 76 public: TestClass02()77 TestClass02() : b(2) {} TestClass02(const TestClass01 & other)78 TestClass02(const TestClass01& other) : b(other.a) {} TestClass02(const TestClass00 & other)79 TestClass02(const TestClass00& other) : b(other.Thing()) {} 80 81 int b; 82 }; 83 84 class TestClass03 : public TestClass02 { 85 public: TestClass03()86 TestClass03() : c(2) {} TestClass03(const TestClass02 & other)87 TestClass03(const TestClass02& other) : c(other.b) {} TestClass03(const TestClass01 & other)88 TestClass03(const TestClass01& other) : c(other.a) {} TestClass03(const TestClass00 & other)89 TestClass03(const TestClass00& other) : c(other.Thing()) {} 90 91 int c; 92 }; 93 94 sol::state lua; 95 96 sol::usertype<TestClass00> s_TestUsertype00( 97 sol::call_constructor, sol::constructors<sol::types<>>(), 98 "Thing", &TestClass00::Thing 99 ); 100 101 lua.set_usertype("TestClass00", s_TestUsertype00); 102 103 sol::usertype<TestClass01> s_TestUsertype01( 104 sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(), 105 sol::base_classes, sol::bases<TestClass00>(), 106 "a", &TestClass01::a 107 ); 108 109 lua.set_usertype("TestClass01", s_TestUsertype01); 110 111 sol::usertype<TestClass02> s_TestUsertype02( 112 sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), 113 sol::base_classes, sol::bases<TestClass01, TestClass00>(), 114 "b", &TestClass02::b 115 ); 116 117 lua.set_usertype("TestClass02", s_TestUsertype02); 118 119 sol::usertype<TestClass03> s_TestUsertype03( 120 sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), 121 sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(), 122 "c", &TestClass03::c 123 ); 124 125 lua.set_usertype("TestClass03", s_TestUsertype03); 126 127 lua.script(R"( 128 tc0 = TestClass00() 129 )"); 130 131 lua.script(R"( 132 tc2 = TestClass02(tc0) 133 )"); 134 135 lua.script(R"( 136 tc1 = TestClass01() 137 )"); 138 139 lua.script(R"( 140 tc3 = TestClass03(tc1) 141 )"); 142 143 TestClass00& tc0 = lua["tc0"]; 144 TestClass01& tc1 = lua["tc1"]; 145 TestClass02& tc2 = lua["tc2"]; 146 TestClass03& tc3 = lua["tc3"]; 147 REQUIRE(tc0.Thing() == 123); 148 REQUIRE(tc1.a == 1); 149 REQUIRE(tc2.a == 1); 150 REQUIRE(tc2.b == 123); 151 REQUIRE(tc3.a == 1); 152 REQUIRE(tc3.b == 2); 153 REQUIRE(tc3.c == 1); 154 } 155 156 TEST_CASE("inheritance/simple-multi-base", "test that multiple bases all work and overloading for constructors works with them") { 157 class TestClass00 { 158 public: Thing() const159 int Thing() const { return 123; } 160 }; 161 162 class TestClass01 : public TestClass00 { 163 public: TestClass01()164 TestClass01() : a(1) {} TestClass01(const TestClass00 & other)165 TestClass01(const TestClass00& other) : a(other.Thing()) {} 166 167 int a; 168 }; 169 170 class TestClass02 : public TestClass01 { 171 public: TestClass02()172 TestClass02() : b(2) {} TestClass02(const TestClass01 & other)173 TestClass02(const TestClass01& other) : b(other.a) {} TestClass02(const TestClass00 & other)174 TestClass02(const TestClass00& other) : b(other.Thing()) {} 175 176 int b; 177 }; 178 179 class TestClass03 : public TestClass02 { 180 public: TestClass03()181 TestClass03() : c(2) {} TestClass03(const TestClass02 & other)182 TestClass03(const TestClass02& other) : c(other.b) {} TestClass03(const TestClass01 & other)183 TestClass03(const TestClass01& other) : c(other.a) {} TestClass03(const TestClass00 & other)184 TestClass03(const TestClass00& other) : c(other.Thing()) {} 185 186 int c; 187 }; 188 189 sol::state lua; 190 191 sol::simple_usertype<TestClass00> s_TestUsertype00( lua, 192 sol::call_constructor, sol::constructors<sol::types<>>(), 193 "Thing", &TestClass00::Thing 194 ); 195 196 lua.set_usertype("TestClass00", s_TestUsertype00); 197 198 sol::simple_usertype<TestClass01> s_TestUsertype01( lua, 199 sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(), 200 sol::base_classes, sol::bases<TestClass00>(), 201 "a", &TestClass01::a 202 ); 203 204 lua.set_usertype("TestClass01", s_TestUsertype01); 205 206 sol::simple_usertype<TestClass02> s_TestUsertype02( lua, 207 sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), 208 sol::base_classes, sol::bases<TestClass01, TestClass00>(), 209 "b", &TestClass02::b 210 ); 211 212 lua.set_usertype("TestClass02", s_TestUsertype02); 213 214 sol::simple_usertype<TestClass03> s_TestUsertype03( lua, 215 sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), 216 sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(), 217 "c", &TestClass03::c 218 ); 219 220 lua.set_usertype("TestClass03", s_TestUsertype03); 221 222 lua.script(R"( 223 tc0 = TestClass00() 224 )"); 225 226 lua.script(R"( 227 tc2 = TestClass02(tc0) 228 )"); 229 230 lua.script(R"( 231 tc1 = TestClass01() 232 )"); 233 234 lua.script(R"( 235 tc3 = TestClass03(tc1) 236 )"); 237 238 TestClass00& tc0 = lua["tc0"]; 239 TestClass01& tc1 = lua["tc1"]; 240 TestClass02& tc2 = lua["tc2"]; 241 TestClass03& tc3 = lua["tc3"]; 242 REQUIRE(tc1.a == 1); 243 REQUIRE(tc2.a == 1); 244 REQUIRE(tc2.b == 123); 245 REQUIRE(tc3.a == 1); 246 REQUIRE(tc3.b == 2); 247 REQUIRE(tc3.c == 1); 248 } 249