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