xref: /netbsd-src/external/bsd/lutok/dist/operations_test.cpp (revision a15637525a498a84b68d8b44b1c7ec01de4b564a)
1 // Copyright 2011 Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 //   notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 //   notice, this list of conditions and the following disclaimer in the
12 //   documentation and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors
14 //   may be used to endorse or promote products derived from this software
15 //   without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 #include "operations.hpp"
30 
31 #include <fstream>
32 
33 #include <atf-c++.hpp>
34 
35 #include "exceptions.hpp"
36 #include "state.ipp"
37 #include "test_utils.hpp"
38 
39 
40 namespace {
41 
42 
43 /// Addition function for injection into Lua.
44 ///
45 /// \pre stack(-2) The first summand.
46 /// \pre stack(-1) The second summand.
47 /// \post stack(-1) The result of the sum.
48 ///
49 /// \param state The Lua state.
50 ///
51 /// \return The number of results (1).
52 static int
hook_add(lutok::state & state)53 hook_add(lutok::state& state)
54 {
55     state.push_integer(state.to_integer(-1) + state.to_integer(-2));
56     return 1;
57 }
58 
59 
60 /// Multiplication function for injection into Lua.
61 ///
62 /// \pre stack(-2) The first factor.
63 /// \pre stack(-1) The second factor.
64 /// \post stack(-1) The product.
65 ///
66 /// \param state The Lua state.
67 ///
68 /// \return The number of results (1).
69 static int
hook_multiply(lutok::state & state)70 hook_multiply(lutok::state& state)
71 {
72     state.push_integer(state.to_integer(-1) * state.to_integer(-2));
73     return 1;
74 }
75 
76 
77 }  // anonymous namespace
78 
79 
80 ATF_TEST_CASE_WITHOUT_HEAD(create_module__empty);
ATF_TEST_CASE_BODY(create_module__empty)81 ATF_TEST_CASE_BODY(create_module__empty)
82 {
83     lutok::state state;
84     std::map< std::string, lutok::cxx_function > members;
85     lutok::create_module(state, "my_math", members);
86 
87     state.open_base();
88     lutok::do_string(state, "return next(my_math) == nil", 1);
89     ATF_REQUIRE(state.to_boolean());
90     state.pop(1);
91 }
92 
93 
94 ATF_TEST_CASE_WITHOUT_HEAD(create_module__one);
ATF_TEST_CASE_BODY(create_module__one)95 ATF_TEST_CASE_BODY(create_module__one)
96 {
97     lutok::state state;
98     std::map< std::string, lutok::cxx_function > members;
99     members["add"] = hook_add;
100     lutok::create_module(state, "my_math", members);
101 
102     lutok::do_string(state, "return my_math.add(10, 20)", 1);
103     ATF_REQUIRE_EQ(30, state.to_integer());
104     state.pop(1);
105 }
106 
107 
108 ATF_TEST_CASE_WITHOUT_HEAD(create_module__many);
ATF_TEST_CASE_BODY(create_module__many)109 ATF_TEST_CASE_BODY(create_module__many)
110 {
111     lutok::state state;
112     std::map< std::string, lutok::cxx_function > members;
113     members["add"] = hook_add;
114     members["multiply"] = hook_multiply;
115     members["add2"] = hook_add;
116     lutok::create_module(state, "my_math", members);
117 
118     lutok::do_string(state, "return my_math.add(10, 20)", 1);
119     ATF_REQUIRE_EQ(30, state.to_integer());
120     lutok::do_string(state, "return my_math.multiply(10, 20)", 1);
121     ATF_REQUIRE_EQ(200, state.to_integer());
122     lutok::do_string(state, "return my_math.add2(20, 30)", 1);
123     ATF_REQUIRE_EQ(50, state.to_integer());
124     state.pop(3);
125 }
126 
127 
128 ATF_TEST_CASE_WITHOUT_HEAD(do_file__any_results);
ATF_TEST_CASE_BODY(do_file__any_results)129 ATF_TEST_CASE_BODY(do_file__any_results)
130 {
131     std::ofstream output("test.lua");
132     output << "return 10, 20, 30\n";
133     output.close();
134 
135     lutok::state state;
136     ATF_REQUIRE_EQ(3, lutok::do_file(state, "test.lua", -1));
137     ATF_REQUIRE_EQ(3, state.get_top());
138     ATF_REQUIRE_EQ(10, state.to_integer(-3));
139     ATF_REQUIRE_EQ(20, state.to_integer(-2));
140     ATF_REQUIRE_EQ(30, state.to_integer(-1));
141     state.pop(3);
142 }
143 
144 
145 ATF_TEST_CASE_WITHOUT_HEAD(do_file__no_results);
ATF_TEST_CASE_BODY(do_file__no_results)146 ATF_TEST_CASE_BODY(do_file__no_results)
147 {
148     std::ofstream output("test.lua");
149     output << "return 10, 20, 30\n";
150     output.close();
151 
152     lutok::state state;
153     ATF_REQUIRE_EQ(0, lutok::do_file(state, "test.lua"));
154     ATF_REQUIRE_EQ(0, state.get_top());
155 }
156 
157 
158 ATF_TEST_CASE_WITHOUT_HEAD(do_file__many_results);
ATF_TEST_CASE_BODY(do_file__many_results)159 ATF_TEST_CASE_BODY(do_file__many_results)
160 {
161     std::ofstream output("test.lua");
162     output << "return 10, 20, 30\n";
163     output.close();
164 
165     lutok::state state;
166     ATF_REQUIRE_EQ(2, lutok::do_file(state, "test.lua", 2));
167     ATF_REQUIRE_EQ(2, state.get_top());
168     ATF_REQUIRE_EQ(10, state.to_integer(-2));
169     ATF_REQUIRE_EQ(20, state.to_integer(-1));
170     state.pop(2);
171 }
172 
173 
174 ATF_TEST_CASE_WITHOUT_HEAD(do_file__not_found);
ATF_TEST_CASE_BODY(do_file__not_found)175 ATF_TEST_CASE_BODY(do_file__not_found)
176 {
177     lutok::state state;
178     stack_balance_checker checker(state);
179     ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua",
180                          lutok::do_file(state, "missing.lua"));
181 }
182 
183 
184 ATF_TEST_CASE_WITHOUT_HEAD(do_file__error);
ATF_TEST_CASE_BODY(do_file__error)185 ATF_TEST_CASE_BODY(do_file__error)
186 {
187     std::ofstream output("test.lua");
188     output << "a b c\n";
189     output.close();
190 
191     lutok::state state;
192     stack_balance_checker checker(state);
193     ATF_REQUIRE_THROW_RE(lutok::error, "Failed to load Lua file 'test.lua'",
194                          lutok::do_file(state, "test.lua"));
195 }
196 
197 
198 ATF_TEST_CASE_WITHOUT_HEAD(do_string__any_results);
ATF_TEST_CASE_BODY(do_string__any_results)199 ATF_TEST_CASE_BODY(do_string__any_results)
200 {
201     lutok::state state;
202     ATF_REQUIRE_EQ(3, lutok::do_string(state, "return 10, 20, 30", -1));
203     ATF_REQUIRE_EQ(3, state.get_top());
204     ATF_REQUIRE_EQ(10, state.to_integer(-3));
205     ATF_REQUIRE_EQ(20, state.to_integer(-2));
206     ATF_REQUIRE_EQ(30, state.to_integer(-1));
207     state.pop(3);
208 }
209 
210 
211 ATF_TEST_CASE_WITHOUT_HEAD(do_string__no_results);
ATF_TEST_CASE_BODY(do_string__no_results)212 ATF_TEST_CASE_BODY(do_string__no_results)
213 {
214     lutok::state state;
215     ATF_REQUIRE_EQ(0, lutok::do_string(state, "return 10, 20, 30"));
216     ATF_REQUIRE_EQ(0, state.get_top());
217 }
218 
219 
220 ATF_TEST_CASE_WITHOUT_HEAD(do_string__many_results);
ATF_TEST_CASE_BODY(do_string__many_results)221 ATF_TEST_CASE_BODY(do_string__many_results)
222 {
223     lutok::state state;
224     ATF_REQUIRE_EQ(2, lutok::do_string(state, "return 10, 20, 30", 2));
225     ATF_REQUIRE_EQ(2, state.get_top());
226     ATF_REQUIRE_EQ(10, state.to_integer(-2));
227     ATF_REQUIRE_EQ(20, state.to_integer(-1));
228     state.pop(2);
229 }
230 
231 
232 ATF_TEST_CASE_WITHOUT_HEAD(do_string__error);
ATF_TEST_CASE_BODY(do_string__error)233 ATF_TEST_CASE_BODY(do_string__error)
234 {
235     lutok::state state;
236     stack_balance_checker checker(state);
237     ATF_REQUIRE_THROW_RE(lutok::error, "Failed to process Lua string 'a b c'",
238                          lutok::do_string(state, "a b c"));
239 }
240 
241 
242 ATF_TEST_CASE_WITHOUT_HEAD(eval__one_result);
ATF_TEST_CASE_BODY(eval__one_result)243 ATF_TEST_CASE_BODY(eval__one_result)
244 {
245     lutok::state state;
246     stack_balance_checker checker(state);
247     lutok::eval(state, "3 + 10");
248     ATF_REQUIRE_EQ(13, state.to_integer());
249     state.pop(1);
250 }
251 
252 
253 ATF_TEST_CASE_WITHOUT_HEAD(eval__many_results);
ATF_TEST_CASE_BODY(eval__many_results)254 ATF_TEST_CASE_BODY(eval__many_results)
255 {
256     lutok::state state;
257     stack_balance_checker checker(state);
258     lutok::eval(state, "5, 8, 10", 3);
259     ATF_REQUIRE_EQ(5, state.to_integer(-3));
260     ATF_REQUIRE_EQ(8, state.to_integer(-2));
261     ATF_REQUIRE_EQ(10, state.to_integer(-1));
262     state.pop(3);
263 }
264 
265 
266 ATF_TEST_CASE_WITHOUT_HEAD(eval__error);
ATF_TEST_CASE_BODY(eval__error)267 ATF_TEST_CASE_BODY(eval__error)
268 {
269     lutok::state state;
270     stack_balance_checker checker(state);
271     ATF_REQUIRE_THROW(lutok::error,
272                       lutok::eval(state, "non_existent.method()"));
273 }
274 
275 
ATF_INIT_TEST_CASES(tcs)276 ATF_INIT_TEST_CASES(tcs)
277 {
278     ATF_ADD_TEST_CASE(tcs, create_module__empty);
279     ATF_ADD_TEST_CASE(tcs, create_module__one);
280     ATF_ADD_TEST_CASE(tcs, create_module__many);
281 
282     ATF_ADD_TEST_CASE(tcs, do_file__any_results);
283     ATF_ADD_TEST_CASE(tcs, do_file__no_results);
284     ATF_ADD_TEST_CASE(tcs, do_file__many_results);
285     ATF_ADD_TEST_CASE(tcs, do_file__not_found);
286     ATF_ADD_TEST_CASE(tcs, do_file__error);
287 
288     ATF_ADD_TEST_CASE(tcs, do_string__any_results);
289     ATF_ADD_TEST_CASE(tcs, do_string__no_results);
290     ATF_ADD_TEST_CASE(tcs, do_string__many_results);
291     ATF_ADD_TEST_CASE(tcs, do_string__error);
292 
293     ATF_ADD_TEST_CASE(tcs, eval__one_result);
294     ATF_ADD_TEST_CASE(tcs, eval__many_results);
295     ATF_ADD_TEST_CASE(tcs, eval__error);
296 }
297