Skip to content

Commit 6252a85

Browse files
committed
add test case: nested_objects
1 parent a11683f commit 6252a85

File tree

1 file changed

+250
-0
lines changed

1 file changed

+250
-0
lines changed

test/unit_test/nested_objects.cpp

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
// Copyright (c) 2024 Li Shuangquan. All Rights Reserved.
2+
//
3+
// Licensed under the MIT License (the "License"); you may not use this file
4+
// except in compliance with the License. You may obtain a copy of the License
5+
// at
6+
//
7+
// http://opensource.org/licenses/MIT
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
// License for the specific language governing permissions and limitations
13+
// under the License.
14+
15+
#include "main.h"
16+
17+
#if 1
18+
namespace {
19+
20+
struct A {
21+
int i = 1;
22+
};
23+
24+
struct Ac {
25+
const int ci = 11;
26+
};
27+
28+
struct B {
29+
int i = 2;
30+
A a;
31+
};
32+
33+
struct Bac {
34+
Ac ac;
35+
};
36+
37+
struct Bcac {
38+
const Ac cac;
39+
};
40+
41+
TEST(nested_objects, register_nested_members) {
42+
peacalm::luaw l;
43+
l.register_member("i", &A::i);
44+
l.register_member("ci", &Ac::ci);
45+
l.register_member("i", &B::i);
46+
l.register_member("a", &B::a);
47+
l.register_member<const A(B::*)>("a_as_c", &B::a);
48+
49+
// l.register_member("ac", &Bac::ac); // Error: no operator=
50+
l.register_member<const Ac(Bac::*)>("ac_as_c", &Bac::ac); // OK: set ac const
51+
52+
l.register_member("cac", &Bcac::cac); // OK cac already const
53+
}
54+
55+
TEST(nested_objects, register_solid_nested_member) {
56+
peacalm::luaw l;
57+
l.register_member("i", &A::i);
58+
l.register_member("i", &B::i);
59+
l.register_member("a", &B::a); // solid member a, which can not be modified
60+
61+
auto b = std::make_shared<B>();
62+
l.set("b", b);
63+
64+
EXPECT_EQ(l.eval<int>("return b.i"), b->i);
65+
EXPECT_TRUE(l.dostring("b.i = 5") == LUA_OK);
66+
EXPECT_TRUE(l.dostring("assert(b.i == 5)") == LUA_OK);
67+
EXPECT_EQ(l.eval<int>("return b.i"), b->i);
68+
EXPECT_EQ(b->i, 5);
69+
70+
// can't modify b's a
71+
int oldbai = b->a.i;
72+
EXPECT_EQ(l.eval<int>("return b.a.i"), b->a.i);
73+
EXPECT_TRUE(l.dostring("b.a.i = 5") == LUA_OK);
74+
EXPECT_TRUE(l.dostring("assert(b.a.i ~= 5);") == LUA_OK);
75+
EXPECT_EQ(l.eval<int>("return b.a.i"), oldbai);
76+
EXPECT_EQ(b->a.i, oldbai);
77+
78+
// get a copy of b'a, and can modify it's i
79+
EXPECT_EQ(l.dostring("a = b.a"), LUA_OK);
80+
EXPECT_EQ(l.eval<int>("return a.i"), oldbai);
81+
EXPECT_EQ(l.dostring("a.i = 1212"), LUA_OK);
82+
EXPECT_EQ(l.eval<int>("return a.i"), 1212);
83+
}
84+
85+
TEST(nested_objects, register_member_address) {
86+
peacalm::luaw l;
87+
l.register_member("i", &A::i);
88+
l.register_member("i", &B::i);
89+
l.register_member("a", &B::a);
90+
91+
auto b = std::make_shared<B>();
92+
l.set("b", b);
93+
94+
// get a's non-const ptr.
95+
// The first arg could be "const B*" or "auto*", both ok.
96+
l.register_member<A* const B::*>(
97+
"aptr", [](const B* p) { return &(const_cast<B*>(p)->a); });
98+
l.register_member<A* const B::*>(
99+
"aptr2", [](auto* p) { return &(const_cast<B*>(p)->a); });
100+
101+
EXPECT_TRUE(l.dostring("assert(b.aptr == b.aptr2)") == LUA_OK);
102+
EXPECT_EQ(l.eval<void*>("return b.aptr"), (void*)(&b->a));
103+
EXPECT_EQ(l.eval<void*>("return b.aptr2"), (void*)(&b->a));
104+
{
105+
auto t = l.eval<std::tuple<void*, void*>>("return b.aptr, b.aptr2");
106+
EXPECT_EQ(std::get<0>(t), std::get<1>(t));
107+
}
108+
109+
#if 0
110+
{
111+
// maybe compile error after cpp17
112+
auto vb = std::make_shared<volatile B>();
113+
114+
l.set("vb", vb);
115+
EXPECT_TRUE(l.dostring("assert(vb.aptr == vb.aptr2)") == LUA_OK);
116+
bool supportv = PEACALM_LUAW_SUPPORT_VOLATILE_OBJECT;
117+
EXPECT_EQ((l.eval<void*>("return vb.aptr") == (void*)(&vb->a)), supportv);
118+
EXPECT_EQ((l.eval<void*>("return vb.aptr2") == (void*)(&vb->a)), supportv);
119+
}
120+
#endif
121+
122+
// get a's const ptr
123+
l.register_member<const A* const B::*>("acptr",
124+
[](const B* p) { return &(p->a); });
125+
l.register_member<const A* const B::*>("acptr2",
126+
[](auto* p) { return &(p->a); });
127+
128+
EXPECT_TRUE(l.dostring("assert(b.acptr == b.acptr2)") == LUA_OK);
129+
EXPECT_EQ(l.eval<void*>("return b.acptr"), (void*)(&b->a));
130+
EXPECT_EQ(l.eval<void*>("return b.acptr2"), (void*)(&b->a));
131+
{
132+
auto t = l.eval<std::tuple<void*, void*>>("return b.acptr, b.acptr2");
133+
EXPECT_EQ(std::get<0>(t), std::get<1>(t));
134+
}
135+
136+
// check metatable of ptr
137+
{
138+
EXPECT_EQ(l.gettop(), 0);
139+
140+
EXPECT_EQ(l.dostring("aptr = b.aptr"), LUA_OK);
141+
l.gseek("aptr");
142+
std::string mtaptr = l.get_metatable_name(-1);
143+
l.pop();
144+
145+
EXPECT_EQ(l.dostring("acptr = b.acptr"), LUA_OK);
146+
l.gseek("acptr");
147+
std::string mtacptr = l.get_metatable_name(-1);
148+
l.pop();
149+
150+
watch(mtaptr, mtacptr);
151+
EXPECT_NE(mtaptr, mtacptr);
152+
153+
EXPECT_EQ(l.gettop(), 0);
154+
155+
{
156+
l.eval<void>("print('b.aptr = ', b.aptr, b.aptr2)");
157+
l.eval<void>("print('b.acptr = ', b.acptr, b.acptr2)");
158+
159+
// metatable of aptr now equals to acptr's
160+
l.eval<void>("print('aptr = ', aptr)");
161+
l.eval<void>("print('acptr = ', acptr)");
162+
}
163+
164+
puts("");
165+
166+
{
167+
// modify order
168+
l.eval<void>("print('b.acptr = ', b.acptr, b.acptr2)");
169+
l.eval<void>("print('b.aptr = ', b.aptr, b.aptr2)");
170+
171+
// metatable of acptr now equals to aptr's
172+
l.eval<void>("print('aptr = ', aptr)");
173+
l.eval<void>("print('acptr = ', acptr)");
174+
}
175+
}
176+
177+
// change member a
178+
{
179+
EXPECT_EQ(b->a.i, 1);
180+
EXPECT_EQ(l.eval<int>("return b.a.i"), 1);
181+
b->a.i = 2;
182+
EXPECT_EQ(l.eval<int>("return b.a.i"), 2);
183+
A* p = l.eval<A*>("return b.aptr");
184+
p->i = 3;
185+
EXPECT_EQ(l.eval<int>("return b.a.i"), 3);
186+
EXPECT_EQ(b->a.i, 3);
187+
188+
// modify b.a.i in Lua by aptr
189+
EXPECT_EQ(l.eval<int>("return b.aptr.i"), 3);
190+
EXPECT_EQ(l.dostring("b.aptr.i = 4"), LUA_OK);
191+
EXPECT_EQ(l.eval<int>("return b.aptr.i"), 4);
192+
EXPECT_EQ(l.eval<int>("return b.acptr.i"), 4);
193+
194+
// can't modify by acptr
195+
EXPECT_NE(l.dostring("b.acptr.i = 5"), LUA_OK);
196+
l.log_error_out();
197+
}
198+
}
199+
200+
// TEST(nested_objects, volatile_outer) {
201+
// peacalm::luaw l;
202+
203+
// B x, y;
204+
// x = y;
205+
206+
// {
207+
// volatile B b;
208+
// l.set("b", &b);
209+
// bool failed;
210+
// int bi = l.eval_int("return b.i", 0, false, &failed);
211+
// EXPECT_FALSE(failed);
212+
213+
// #if PEACALM_LUAW_SUPPORT_VOLATILE_OBJECT
214+
// EXPECT_EQ(bi, 1);
215+
// #else
216+
// EXPECT_EQ(bi, 0);
217+
// #endif
218+
// // int retcode = l.dostring("acopy = b.a; acopy.i = 100");
219+
// // if (retcode != LUA_OK) l.log_error_out();
220+
// // A a = l.eval<A>("return acopy");
221+
// // watch(a.i);
222+
// }
223+
// EXPECT_TRUE(true);
224+
// }
225+
226+
// TEST(nested_objects, raw) {
227+
// peacalm::luaw l;
228+
// l.register_member("i", &A::i);
229+
// l.register_member("i", &B::i);
230+
// // l.register_member("a", &B::a);
231+
232+
// // VA va{};
233+
// // l.set("va", &va);
234+
235+
// // auto sva = std::make_shared<VA>();
236+
// // l.set("sva", sva);
237+
238+
// EXPECT_TRUE(true);
239+
// watch(PEACALM_LUAW_SUPPORT_VOLATILE_OBJECT);
240+
// watch(PEACALM_LUAW_SUPPORT_VOLATILE_OBJECT + 1);
241+
242+
// #if PEACALM_LUAW_SUPPORT_VOLATILE_OBJECT
243+
// // EXPECT_TRUE(0);
244+
// #else
245+
246+
// #endif
247+
// }
248+
249+
} // namespace
250+
#endif

0 commit comments

Comments
 (0)