Skip to content

Commit 2c58b00

Browse files
committed
add testcase luaw_function
1 parent d2331e7 commit 2c58b00

File tree

1 file changed

+269
-0
lines changed

1 file changed

+269
-0
lines changed

test/unit_test/luaw_function.cpp

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
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+
namespace {
18+
19+
struct Obj {
20+
int i = 1;
21+
Obj() {}
22+
Obj(const Obj &r) : i(r.i) {}
23+
Obj(Obj &&r) : i(r.i) { r.i = -1; }
24+
~Obj() {}
25+
};
26+
27+
TEST(luaw_function, type_check) {
28+
(void)luaw::function<void(int)>{};
29+
(void)luaw::function<void(const int)>{};
30+
// (void)luaw::function<void( int &)>{}; // error
31+
(void)luaw::function<void(const int &)>{};
32+
(void)luaw::function<void(int &&)>{};
33+
(void)luaw::function<void(const int &&)>{};
34+
35+
(void)luaw::function<int()>{};
36+
// (void)luaw::function<int &()>{}; // error
37+
// (void)luaw::function<int && ()>{}; // error
38+
(void)luaw::function<std::tuple<int, int>()>{};
39+
// (void)luaw::function<std::tuple<int &, int>()>{}; // error
40+
41+
(void)luaw::function<void(luaw::luavalueref)>{};
42+
(void)luaw::function<void(const luaw::luavalueref &)>{};
43+
(void)luaw::function<void(luaw::luavalueref &&)>{};
44+
45+
(void)luaw::function<luaw::luavalueref()>{};
46+
// (void)luaw::function<luaw::luavalueref &()>{}; // error
47+
// (void)luaw::function<const luaw::luavalueref &()>{}; // error
48+
49+
(void)luaw::function<luaw::luavalueref(luaw::luavalueidx)>{};
50+
}
51+
52+
TEST(luaw_function, arg_can_copy_can_move) {
53+
luaw l;
54+
EXPECT_EQ(l.dostring("function echo(o) return o; end"), LUA_OK);
55+
56+
{
57+
Obj o;
58+
// Will get a copy of o
59+
auto echo = l.get<luaw::function<luaw::luavalueref(const Obj &)>>("echo");
60+
auto ref = echo(o);
61+
EXPECT_FALSE(echo.failed());
62+
l.push(ref);
63+
Obj *p = l.to<Obj *>(-1);
64+
EXPECT_NE(p, &o);
65+
l.cleartop();
66+
}
67+
{
68+
Obj o;
69+
// Will get a copy of the pointer
70+
auto echo = l.get<luaw::function<luaw::luavalueref(Obj *)>>("echo");
71+
auto ref = echo(&o);
72+
EXPECT_FALSE(echo.failed());
73+
l.push(ref);
74+
Obj *p = l.to<Obj *>(-1);
75+
EXPECT_EQ(p, &o);
76+
l.cleartop();
77+
}
78+
{
79+
Obj a;
80+
EXPECT_EQ(a.i, 1);
81+
Obj b = std::move(a);
82+
EXPECT_EQ(b.i, 1);
83+
EXPECT_EQ(a.i, -1);
84+
}
85+
{
86+
// Move o
87+
Obj o;
88+
o.i = 123;
89+
EXPECT_EQ(o.i, 123);
90+
auto echo = l.get<luaw::function<luaw::luavalueref(Obj &&)>>("echo");
91+
auto ref = echo(std::move(o));
92+
EXPECT_FALSE(echo.failed());
93+
EXPECT_EQ(o.i, -1);
94+
95+
l.push(ref);
96+
Obj *p = l.to<Obj *>(-1);
97+
EXPECT_EQ(p->i, 123);
98+
EXPECT_NE(p, &o);
99+
l.cleartop();
100+
}
101+
{
102+
// Move o
103+
Obj o;
104+
o.i = 123;
105+
EXPECT_EQ(o.i, 123);
106+
auto echo = l.get<luaw::function<luaw::luavalueref(Obj)>>("echo");
107+
auto ref = echo(std::move(o));
108+
EXPECT_FALSE(echo.failed());
109+
EXPECT_EQ(o.i, -1);
110+
111+
l.push(ref);
112+
Obj *p = l.to<Obj *>(-1);
113+
EXPECT_EQ(p->i, 123);
114+
EXPECT_NE(p, &o);
115+
l.cleartop();
116+
}
117+
}
118+
119+
TEST(luaw_function, arg_ref) {
120+
luaw l;
121+
EXPECT_EQ(l.dostring("function echo(o) return o; end"), LUA_OK);
122+
123+
// perfect echo
124+
auto echo =
125+
l.get<luaw::function<luaw::luavalueref(luaw::luavalueref)>>("echo");
126+
127+
l.set("o", Obj{});
128+
auto oref = l.get<luaw::luavalueref>("o");
129+
auto ret = echo(oref);
130+
EXPECT_FALSE(echo.failed());
131+
132+
l.push(oref);
133+
Obj *a = l.to<Obj *>(-1);
134+
l.push(ret);
135+
Obj *b = l.to<Obj *>(-1);
136+
l.cleartop();
137+
138+
// same obj
139+
EXPECT_EQ(a, b);
140+
141+
l.cleartop();
142+
}
143+
144+
TEST(luaw_function, no_result) {
145+
luaw l;
146+
EXPECT_EQ(l.dostring("function f(o) end"), LUA_OK);
147+
148+
auto f = l.get<luaw::function<int(int)>>("f");
149+
int ret = f(1);
150+
EXPECT_TRUE(f.failed());
151+
EXPECT_TRUE(!f.result_exists());
152+
EXPECT_TRUE(!f.result_enough());
153+
EXPECT_EQ(f.expected_result_size(), 1);
154+
EXPECT_EQ(f.real_result_size(), 0);
155+
}
156+
157+
TEST(luaw_function, result_not_enough) {
158+
luaw l;
159+
EXPECT_EQ(l.dostring("function f(o) return o; end"), LUA_OK);
160+
161+
auto f = l.get<luaw::function<std::tuple<int, int>(int)>>("f");
162+
auto ret = f(1);
163+
EXPECT_TRUE(f.failed());
164+
EXPECT_TRUE(f.result_exists());
165+
EXPECT_TRUE(!f.result_enough());
166+
EXPECT_TRUE(!f.result_failed()); // not fail, just not enough
167+
EXPECT_EQ(f.expected_result_size(), 2);
168+
EXPECT_EQ(f.real_result_size(), 1);
169+
170+
EXPECT_EQ(std::get<0>(ret), 1);
171+
}
172+
173+
TEST(luaw_function, expect_0_result) {
174+
luaw l;
175+
EXPECT_EQ(l.dostring("function f(o) return o; end"), LUA_OK);
176+
{
177+
auto f = l.get<luaw::function<std::tuple<>(int)>>("f");
178+
auto ret = f(1);
179+
EXPECT_EQ(std::tuple_size<decltype(ret)>(), 0);
180+
EXPECT_TRUE(!f.failed());
181+
182+
EXPECT_TRUE(f.result_enough());
183+
EXPECT_TRUE(f.result_exists());
184+
EXPECT_FALSE(f.result_failed());
185+
186+
EXPECT_EQ(f.expected_result_size(), 0);
187+
EXPECT_EQ(f.real_result_size(), 1);
188+
}
189+
{
190+
auto f = l.get<luaw::function<void(int)>>("f");
191+
f(1);
192+
EXPECT_TRUE(!f.failed());
193+
194+
EXPECT_TRUE(f.result_enough());
195+
EXPECT_TRUE(f.result_exists());
196+
EXPECT_FALSE(f.result_failed());
197+
198+
EXPECT_EQ(f.expected_result_size(), 0);
199+
EXPECT_EQ(f.real_result_size(), 1);
200+
}
201+
}
202+
203+
TEST(luaw_function, modify_arg) {
204+
luaw l;
205+
l.register_member("i", &Obj::i);
206+
207+
int retcode = l.dostring(R"(
208+
function f(o)
209+
o.i = o.i + 100
210+
return o
211+
end
212+
)");
213+
214+
{
215+
auto f = l.get<peacalm::luaw::function<Obj(Obj)>>("f");
216+
Obj o;
217+
EXPECT_EQ(o.i, 1);
218+
Obj ret = f(o);
219+
EXPECT_FALSE(f.failed());
220+
EXPECT_EQ(o.i, 1);
221+
EXPECT_EQ(ret.i, 101);
222+
}
223+
224+
{
225+
auto f = l.get<peacalm::luaw::function<Obj(Obj *)>>("f");
226+
Obj o;
227+
EXPECT_EQ(o.i, 1);
228+
Obj ret = f(&o);
229+
EXPECT_FALSE(f.failed());
230+
EXPECT_EQ(o.i, 101);
231+
EXPECT_EQ(ret.i, 101);
232+
}
233+
}
234+
235+
TEST(luaw_function, map_as_table) {
236+
luaw l;
237+
int retcode = l.dostring(R"(
238+
function f(o)
239+
o.a = 1
240+
o.b = 2
241+
return o
242+
end
243+
)");
244+
EXPECT_EQ(retcode, LUA_OK);
245+
246+
using map_t = std::map<std::string, int>;
247+
248+
auto f = l.get<peacalm::luaw::function<map_t(map_t &&)>>("f");
249+
250+
map_t m{{"b", -1}, {"c", -1}};
251+
252+
// Won't move to full userdata, because will construct a table by m.
253+
// So, m will not be cleared.
254+
auto ret = f(std::move(m));
255+
256+
EXPECT_FALSE(f.failed());
257+
258+
EXPECT_EQ(m.size(), 2);
259+
EXPECT_EQ(m["a"], 0);
260+
EXPECT_EQ(m["b"], -1);
261+
EXPECT_EQ(m["c"], -1);
262+
263+
EXPECT_EQ(ret.size(), 3);
264+
EXPECT_EQ(ret["a"], 1);
265+
EXPECT_EQ(ret["b"], 2);
266+
EXPECT_EQ(ret["c"], -1);
267+
}
268+
269+
} // namespace

0 commit comments

Comments
 (0)