xref: /netbsd/external/bsd/lutok/dist/state_test.cpp (revision d3ca3027)
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 "state.ipp"
30 
31 #include <cstring>
32 #include <fstream>
33 #include <iostream>
34 #include <stdexcept>
35 
36 #include <atf-c++.hpp>
37 #include <lua.hpp>
38 
39 #include "c_gate.hpp"
40 #include "exceptions.hpp"
41 #include "test_utils.hpp"
42 
43 
44 // A note about the lutok::state tests.
45 //
46 // The methods of lutok::state are, in general, thin wrappers around the
47 // corresponding Lua C API methods.  The tests below are simple unit tests that
48 // ensure that these functions just delegate the calls to the Lua library.  We
49 // do not intend to test the validity of the methods themselves (that's the
50 // job of the Lua authors).  That said, we test those conditions we rely on,
51 // such as the reporting of errors and the default values to the API.
52 //
53 // Lastly, for every test case that stresses a single lutok::state method, we
54 // only call that method directly.  All other Lua state manipulation operations
55 // are performed by means of direct calls to the Lua C API.  This is to ensure
56 // that the wrapped methods are really talking to Lua.
57 
58 
59 namespace {
60 
61 
62 /// Checks if a symbol is available.
63 ///
64 /// \param state The Lua state.
65 /// \param symbol The symbol to check for.
66 ///
67 /// \return True if the symbol is defined, false otherwise.
68 static bool
is_available(lutok::state & state,const char * symbol)69 is_available(lutok::state& state, const char* symbol)
70 {
71     luaL_loadstring(raw(state), (std::string("return ") + symbol).c_str());
72     const bool ok = (lua_pcall(raw(state), 0, 1, 0) == 0 &&
73                      !lua_isnil(raw(state), -1));
74     lua_pop(raw(state), 1);
75     std::cout << "Symbol " << symbol << (ok ? " found\n" : " not found\n");
76     return ok;
77 }
78 
79 
80 /// Checks that no modules are present or that only one has been loaded.
81 ///
82 /// \post The test case terminates if there is any module present when expected
83 /// is empty or if there two modules loaded when expected is defined.
84 ///
85 /// \param state The Lua state.
86 /// \param expected The module to expect.  Empty if no modules are allowed.
87 static void
check_modules(lutok::state & state,const std::string & expected)88 check_modules(lutok::state& state, const std::string& expected)
89 {
90     std::cout << "Checking loaded modules" <<
91         (expected.empty() ? "" : (" (" + expected + " expected)")) << "\n";
92     ATF_REQUIRE(!((expected == "base") ^ (is_available(state, "assert"))));
93     ATF_REQUIRE(!((expected == "string") ^
94                   (is_available(state, "string.byte"))));
95     ATF_REQUIRE(!((expected == "table") ^
96                   (is_available(state, "table.concat"))));
97 }
98 
99 
100 /// A C closure that returns its two integral upvalues.
101 ///
102 /// \post stack(-2) contains the first upvalue.
103 /// \post stack(-1) contains the second upvalue.
104 ///
105 /// \param raw_state The raw Lua state.
106 ///
107 /// \return The number of result values, i.e. 2.
108 static int
c_get_upvalues(lua_State * raw_state)109 c_get_upvalues(lua_State* raw_state)
110 {
111     lutok::state state = lutok::state_c_gate::connect(raw_state);
112     const int i1 = lua_tointeger(raw_state, state.upvalue_index(1));
113     const int i2 = lua_tointeger(raw_state, state.upvalue_index(2));
114     lua_pushinteger(raw_state, i1);
115     lua_pushinteger(raw_state, i2);
116     return 2;
117 }
118 
119 
120 /// A custom C++ multiply function with one of its factors on its closure.
121 ///
122 /// \pre stack(-1) contains the second factor.
123 /// \post stack(-1) contains the product of the two input factors.
124 ///
125 /// \param state The Lua state.
126 ///
127 /// \return The number of result values, i.e. 1.
128 static int
cxx_multiply_closure(lutok::state & state)129 cxx_multiply_closure(lutok::state& state)
130 {
131     const int f1 = lua_tointeger(raw(state), lua_upvalueindex(1));
132     const int f2 = lua_tointeger(raw(state), -1);
133     lua_pushinteger(raw(state), f1 * f2);
134     return 1;
135 }
136 
137 
138 /// A custom C++ integral division function for Lua.
139 ///
140 /// \pre stack(-2) contains the dividend.
141 /// \pre stack(-1) contains the divisor.
142 /// \post stack(-2) contains the quotient of the division.
143 /// \post stack(-1) contains the remainder of the division.
144 ///
145 /// \param state The Lua state.
146 ///
147 /// \return The number of result values, i.e. 1.
148 ///
149 /// \throw std::runtime_error If the divisor is zero.
150 /// \throw std::string If the dividend or the divisor are negative.  This is an
151 ///     exception not derived from std::exception on purpose to ensure that the
152 ///     C++ wrapping correctly captures any exception regardless of its type.
153 static int
cxx_divide(lutok::state & state)154 cxx_divide(lutok::state& state)
155 {
156     const int dividend = state.to_integer(-2);
157     const int divisor = state.to_integer(-1);
158     if (divisor == 0)
159         throw std::runtime_error("Divisor is 0");
160     if (dividend < 0 || divisor < 0)
161         throw std::string("Cannot divide negative numbers");
162     state.push_integer(dividend / divisor);
163     state.push_integer(dividend % divisor);
164     return 2;
165 }
166 
167 
168 /// A Lua function that raises a very long error message.
169 ///
170 /// \pre stack(-1) contains the length of the message to construct.
171 ///
172 /// \param state The Lua state.
173 ///
174 /// \return Never returns.
175 ///
176 /// \throw std::runtime_error Unconditionally, with an error message formed by
177 ///     the repetition of 'A' as many times as requested.
178 static int
raise_long_error(lutok::state & state)179 raise_long_error(lutok::state& state)
180 {
181     const int length = state.to_integer();
182     throw std::runtime_error(std::string(length, 'A').c_str());
183 }
184 
185 
186 }  // anonymous namespace
187 
188 
189 ATF_TEST_CASE_WITHOUT_HEAD(close);
ATF_TEST_CASE_BODY(close)190 ATF_TEST_CASE_BODY(close)
191 {
192     lutok::state state;
193     state.close();
194     // The destructor for state will run now.  If it does a second close, we may
195     // crash, so let's see if we don't.
196 }
197 
198 
199 ATF_TEST_CASE_WITHOUT_HEAD(get_global__ok);
ATF_TEST_CASE_BODY(get_global__ok)200 ATF_TEST_CASE_BODY(get_global__ok)
201 {
202     lutok::state state;
203     ATF_REQUIRE(luaL_dostring(raw(state), "test_variable = 3") == 0);
204     state.get_global("test_variable");
205     ATF_REQUIRE(lua_isnumber(raw(state), -1));
206     lua_pop(raw(state), 1);
207 }
208 
209 
210 ATF_TEST_CASE_WITHOUT_HEAD(get_global__undefined);
ATF_TEST_CASE_BODY(get_global__undefined)211 ATF_TEST_CASE_BODY(get_global__undefined)
212 {
213     lutok::state state;
214     state.get_global("test_variable");
215     ATF_REQUIRE(lua_isnil(raw(state), -1));
216     lua_pop(raw(state), 1);
217 }
218 
219 
220 ATF_TEST_CASE_WITHOUT_HEAD(get_global_table);
ATF_TEST_CASE_BODY(get_global_table)221 ATF_TEST_CASE_BODY(get_global_table)
222 {
223     lutok::state state;
224     ATF_REQUIRE(luaL_dostring(raw(state), "global_variable = 'hello'") == 0);
225     state.get_global_table();
226     lua_pushstring(raw(state), "global_variable");
227     lua_gettable(raw(state), -2);
228     ATF_REQUIRE(lua_isstring(raw(state), -1));
229     ATF_REQUIRE(std::strcmp("hello", lua_tostring(raw(state), -1)) == 0);
230     lua_pop(raw(state), 2);
231 }
232 
233 
234 ATF_TEST_CASE_WITHOUT_HEAD(get_metafield__ok);
ATF_TEST_CASE_BODY(get_metafield__ok)235 ATF_TEST_CASE_BODY(get_metafield__ok)
236 {
237     lutok::state state;
238     luaL_openlibs(raw(state));
239     ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; "
240                               "t = {}; setmetatable(t, meta)") == 0);
241     lua_getglobal(raw(state), "t");
242     ATF_REQUIRE(state.get_metafield(-1, "foo"));
243     ATF_REQUIRE(lua_isnumber(raw(state), -1));
244     ATF_REQUIRE_EQ(567, lua_tointeger(raw(state), -1));
245     lua_pop(raw(state), 2);
246 }
247 
248 
249 ATF_TEST_CASE_WITHOUT_HEAD(get_metafield__undefined);
ATF_TEST_CASE_BODY(get_metafield__undefined)250 ATF_TEST_CASE_BODY(get_metafield__undefined)
251 {
252     lutok::state state;
253     luaL_openlibs(raw(state));
254     ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; "
255                               "t = {}; setmetatable(t, meta)") == 0);
256     lua_getglobal(raw(state), "t");
257     ATF_REQUIRE(!state.get_metafield(-1, "bar"));
258     lua_pop(raw(state), 1);
259 }
260 
261 
262 ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__top);
ATF_TEST_CASE_BODY(get_metatable__top)263 ATF_TEST_CASE_BODY(get_metatable__top)
264 {
265     lutok::state state;
266     luaL_openlibs(raw(state));
267     ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; "
268                               "t = {}; setmetatable(t, meta)") == 0);
269     lua_getglobal(raw(state), "t");
270     ATF_REQUIRE(state.get_metatable());
271     ATF_REQUIRE(lua_istable(raw(state), -1));
272     lua_pushstring(raw(state), "foo");
273     lua_gettable(raw(state), -2);
274     ATF_REQUIRE(lua_isnumber(raw(state), -1));
275     ATF_REQUIRE_EQ(567, lua_tointeger(raw(state), -1));
276     lua_pop(raw(state), 3);
277 }
278 
279 
280 ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__explicit);
ATF_TEST_CASE_BODY(get_metatable__explicit)281 ATF_TEST_CASE_BODY(get_metatable__explicit)
282 {
283     lutok::state state;
284     luaL_openlibs(raw(state));
285     ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; "
286                               "t = {}; setmetatable(t, meta)") == 0);
287     lua_getglobal(raw(state), "t");
288     lua_pushinteger(raw(state), 5555);
289     ATF_REQUIRE(state.get_metatable(-2));
290     ATF_REQUIRE(lua_istable(raw(state), -1));
291     lua_pushstring(raw(state), "foo");
292     lua_gettable(raw(state), -2);
293     ATF_REQUIRE(lua_isnumber(raw(state), -1));
294     ATF_REQUIRE_EQ(567, lua_tointeger(raw(state), -1));
295     lua_pop(raw(state), 4);
296 }
297 
298 
299 ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__undefined);
ATF_TEST_CASE_BODY(get_metatable__undefined)300 ATF_TEST_CASE_BODY(get_metatable__undefined)
301 {
302     lutok::state state;
303     ATF_REQUIRE(luaL_dostring(raw(state), "t = {}") == 0);
304     lua_getglobal(raw(state), "t");
305     ATF_REQUIRE(!state.get_metatable(-1));
306     lua_pop(raw(state), 1);
307 }
308 
309 
310 ATF_TEST_CASE_WITHOUT_HEAD(get_table__ok);
ATF_TEST_CASE_BODY(get_table__ok)311 ATF_TEST_CASE_BODY(get_table__ok)
312 {
313     lutok::state state;
314     ATF_REQUIRE(luaL_dostring(raw(state), "t = { a = 1, bar = 234 }") == 0);
315     lua_getglobal(raw(state), "t");
316     lua_pushstring(raw(state), "bar");
317     state.get_table();
318     ATF_REQUIRE(lua_isnumber(raw(state), -1));
319     ATF_REQUIRE_EQ(234, lua_tointeger(raw(state), -1));
320     lua_pop(raw(state), 2);
321 }
322 
323 
324 ATF_TEST_CASE_WITHOUT_HEAD(get_table__nil);
ATF_TEST_CASE_BODY(get_table__nil)325 ATF_TEST_CASE_BODY(get_table__nil)
326 {
327     lutok::state state;
328     lua_pushnil(raw(state));
329     lua_pushinteger(raw(state), 1);
330     REQUIRE_API_ERROR("lua_gettable", state.get_table());
331     ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
332     lua_pop(raw(state), 2);
333 }
334 
335 
336 ATF_TEST_CASE_WITHOUT_HEAD(get_table__unknown_index);
ATF_TEST_CASE_BODY(get_table__unknown_index)337 ATF_TEST_CASE_BODY(get_table__unknown_index)
338 {
339     lutok::state state;
340     ATF_REQUIRE(luaL_dostring(raw(state),
341                               "the_table = { foo = 1, bar = 2 }") == 0);
342     lua_getglobal(raw(state), "the_table");
343     lua_pushstring(raw(state), "baz");
344     state.get_table();
345     ATF_REQUIRE(lua_isnil(raw(state), -1));
346     lua_pop(raw(state), 2);
347 }
348 
349 
350 ATF_TEST_CASE_WITHOUT_HEAD(get_top);
ATF_TEST_CASE_BODY(get_top)351 ATF_TEST_CASE_BODY(get_top)
352 {
353     lutok::state state;
354     ATF_REQUIRE_EQ(0, state.get_top());
355     lua_pushinteger(raw(state), 3);
356     ATF_REQUIRE_EQ(1, state.get_top());
357     lua_pushinteger(raw(state), 3);
358     ATF_REQUIRE_EQ(2, state.get_top());
359     lua_pop(raw(state), 2);
360 }
361 
362 
363 ATF_TEST_CASE_WITHOUT_HEAD(insert);
ATF_TEST_CASE_BODY(insert)364 ATF_TEST_CASE_BODY(insert)
365 {
366     lutok::state state;
367     lua_pushinteger(raw(state), 1);
368     lua_pushinteger(raw(state), 2);
369     lua_pushinteger(raw(state), 3);
370     lua_pushinteger(raw(state), 4);
371     state.insert(-3);
372     ATF_REQUIRE_EQ(3, lua_tointeger(raw(state), -1));
373     ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -2));
374     ATF_REQUIRE_EQ(4, lua_tointeger(raw(state), -3));
375     ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -4));
376     lua_pop(raw(state), 4);
377 }
378 
379 
380 ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__empty);
ATF_TEST_CASE_BODY(is_boolean__empty)381 ATF_TEST_CASE_BODY(is_boolean__empty)
382 {
383     lutok::state state;
384     ATF_REQUIRE(!state.is_boolean());
385 }
386 
387 
388 ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__top);
ATF_TEST_CASE_BODY(is_boolean__top)389 ATF_TEST_CASE_BODY(is_boolean__top)
390 {
391     lutok::state state;
392     lua_pushnil(raw(state));
393     ATF_REQUIRE(!state.is_boolean());
394     lua_pushboolean(raw(state), 1);
395     ATF_REQUIRE(state.is_boolean());
396     lua_pop(raw(state), 2);
397 }
398 
399 
400 ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__explicit);
ATF_TEST_CASE_BODY(is_boolean__explicit)401 ATF_TEST_CASE_BODY(is_boolean__explicit)
402 {
403     lutok::state state;
404     lua_pushboolean(raw(state), 1);
405     ATF_REQUIRE(state.is_boolean(-1));
406     lua_pushinteger(raw(state), 5);
407     ATF_REQUIRE(!state.is_boolean(-1));
408     ATF_REQUIRE(state.is_boolean(-2));
409     lua_pop(raw(state), 2);
410 }
411 
412 
413 ATF_TEST_CASE_WITHOUT_HEAD(is_function__empty);
ATF_TEST_CASE_BODY(is_function__empty)414 ATF_TEST_CASE_BODY(is_function__empty)
415 {
416     lutok::state state;
417     ATF_REQUIRE(!state.is_function());
418 }
419 
420 
421 ATF_TEST_CASE_WITHOUT_HEAD(is_function__top);
ATF_TEST_CASE_BODY(is_function__top)422 ATF_TEST_CASE_BODY(is_function__top)
423 {
424     lutok::state state;
425     luaL_dostring(raw(state), "function my_func(a, b) return a + b; end");
426 
427     lua_pushnil(raw(state));
428     ATF_REQUIRE(!state.is_function());
429     lua_getglobal(raw(state), "my_func");
430     ATF_REQUIRE(state.is_function());
431     lua_pop(raw(state), 2);
432 }
433 
434 
435 ATF_TEST_CASE_WITHOUT_HEAD(is_function__explicit);
ATF_TEST_CASE_BODY(is_function__explicit)436 ATF_TEST_CASE_BODY(is_function__explicit)
437 {
438     lutok::state state;
439     luaL_dostring(raw(state), "function my_func(a, b) return a + b; end");
440 
441     lua_getglobal(raw(state), "my_func");
442     ATF_REQUIRE(state.is_function(-1));
443     lua_pushinteger(raw(state), 5);
444     ATF_REQUIRE(!state.is_function(-1));
445     ATF_REQUIRE(state.is_function(-2));
446     lua_pop(raw(state), 2);
447 }
448 
449 
450 ATF_TEST_CASE_WITHOUT_HEAD(is_nil__empty);
ATF_TEST_CASE_BODY(is_nil__empty)451 ATF_TEST_CASE_BODY(is_nil__empty)
452 {
453     lutok::state state;
454     ATF_REQUIRE(state.is_nil());
455 }
456 
457 
458 ATF_TEST_CASE_WITHOUT_HEAD(is_nil__top);
ATF_TEST_CASE_BODY(is_nil__top)459 ATF_TEST_CASE_BODY(is_nil__top)
460 {
461     lutok::state state;
462     lua_pushnil(raw(state));
463     ATF_REQUIRE(state.is_nil());
464     lua_pushinteger(raw(state), 5);
465     ATF_REQUIRE(!state.is_nil());
466     lua_pop(raw(state), 2);
467 }
468 
469 
470 ATF_TEST_CASE_WITHOUT_HEAD(is_nil__explicit);
ATF_TEST_CASE_BODY(is_nil__explicit)471 ATF_TEST_CASE_BODY(is_nil__explicit)
472 {
473     lutok::state state;
474     lua_pushnil(raw(state));
475     ATF_REQUIRE(state.is_nil(-1));
476     lua_pushinteger(raw(state), 5);
477     ATF_REQUIRE(!state.is_nil(-1));
478     ATF_REQUIRE(state.is_nil(-2));
479     lua_pop(raw(state), 2);
480 }
481 
482 
483 ATF_TEST_CASE_WITHOUT_HEAD(is_number__empty);
ATF_TEST_CASE_BODY(is_number__empty)484 ATF_TEST_CASE_BODY(is_number__empty)
485 {
486     lutok::state state;
487     ATF_REQUIRE(!state.is_number());
488 }
489 
490 
491 ATF_TEST_CASE_WITHOUT_HEAD(is_number__top);
ATF_TEST_CASE_BODY(is_number__top)492 ATF_TEST_CASE_BODY(is_number__top)
493 {
494     lutok::state state;
495     lua_pushnil(raw(state));
496     ATF_REQUIRE(!state.is_number());
497     lua_pushinteger(raw(state), 5);
498     ATF_REQUIRE(state.is_number());
499     lua_pop(raw(state), 2);
500 }
501 
502 
503 ATF_TEST_CASE_WITHOUT_HEAD(is_number__explicit);
ATF_TEST_CASE_BODY(is_number__explicit)504 ATF_TEST_CASE_BODY(is_number__explicit)
505 {
506     lutok::state state;
507     lua_pushnil(raw(state));
508     ATF_REQUIRE(!state.is_number(-1));
509     lua_pushinteger(raw(state), 5);
510     ATF_REQUIRE(state.is_number(-1));
511     ATF_REQUIRE(!state.is_number(-2));
512     lua_pop(raw(state), 2);
513 }
514 
515 
516 ATF_TEST_CASE_WITHOUT_HEAD(is_string__empty);
ATF_TEST_CASE_BODY(is_string__empty)517 ATF_TEST_CASE_BODY(is_string__empty)
518 {
519     lutok::state state;
520     ATF_REQUIRE(!state.is_string());
521 }
522 
523 
524 ATF_TEST_CASE_WITHOUT_HEAD(is_string__top);
ATF_TEST_CASE_BODY(is_string__top)525 ATF_TEST_CASE_BODY(is_string__top)
526 {
527     lutok::state state;
528     lua_pushnil(raw(state));
529     ATF_REQUIRE(!state.is_string());
530     lua_pushinteger(raw(state), 3);
531     ATF_REQUIRE(state.is_string());
532     lua_pushstring(raw(state), "foo");
533     ATF_REQUIRE(state.is_string());
534     lua_pop(raw(state), 3);
535 }
536 
537 
538 ATF_TEST_CASE_WITHOUT_HEAD(is_string__explicit);
ATF_TEST_CASE_BODY(is_string__explicit)539 ATF_TEST_CASE_BODY(is_string__explicit)
540 {
541     lutok::state state;
542     lua_pushinteger(raw(state), 3);
543     ATF_REQUIRE(state.is_string(-1));
544     lua_pushnil(raw(state));
545     ATF_REQUIRE(!state.is_string(-1));
546     ATF_REQUIRE(state.is_string(-2));
547     lua_pushstring(raw(state), "foo");
548     ATF_REQUIRE(state.is_string(-1));
549     ATF_REQUIRE(!state.is_string(-2));
550     ATF_REQUIRE(state.is_string(-3));
551     lua_pop(raw(state), 3);
552 }
553 
554 
555 ATF_TEST_CASE_WITHOUT_HEAD(is_table__empty);
ATF_TEST_CASE_BODY(is_table__empty)556 ATF_TEST_CASE_BODY(is_table__empty)
557 {
558     lutok::state state;
559     ATF_REQUIRE(!state.is_table());
560 }
561 
562 
563 ATF_TEST_CASE_WITHOUT_HEAD(is_table__top);
ATF_TEST_CASE_BODY(is_table__top)564 ATF_TEST_CASE_BODY(is_table__top)
565 {
566     lutok::state state;
567     luaL_dostring(raw(state), "t = {3, 4, 5}");
568 
569     lua_pushstring(raw(state), "foo");
570     ATF_REQUIRE(!state.is_table());
571     lua_getglobal(raw(state), "t");
572     ATF_REQUIRE(state.is_table());
573     lua_pop(raw(state), 2);
574 }
575 
576 
577 ATF_TEST_CASE_WITHOUT_HEAD(is_table__explicit);
ATF_TEST_CASE_BODY(is_table__explicit)578 ATF_TEST_CASE_BODY(is_table__explicit)
579 {
580     lutok::state state;
581     luaL_dostring(raw(state), "t = {3, 4, 5}");
582 
583     lua_pushstring(raw(state), "foo");
584     ATF_REQUIRE(!state.is_table(-1));
585     lua_getglobal(raw(state), "t");
586     ATF_REQUIRE(state.is_table(-1));
587     ATF_REQUIRE(!state.is_table(-2));
588     lua_pop(raw(state), 2);
589 }
590 
591 
592 ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__empty);
ATF_TEST_CASE_BODY(is_userdata__empty)593 ATF_TEST_CASE_BODY(is_userdata__empty)
594 {
595     lutok::state state;
596     ATF_REQUIRE(!state.is_userdata());
597 }
598 
599 
600 ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__top);
ATF_TEST_CASE_BODY(is_userdata__top)601 ATF_TEST_CASE_BODY(is_userdata__top)
602 {
603     lutok::state state;
604 
605     lua_pushstring(raw(state), "foo");
606     ATF_REQUIRE(!state.is_userdata());
607     lua_newuserdata(raw(state), 1234);
608     ATF_REQUIRE(state.is_userdata());
609     lua_pop(raw(state), 2);
610 }
611 
612 
613 ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__explicit);
ATF_TEST_CASE_BODY(is_userdata__explicit)614 ATF_TEST_CASE_BODY(is_userdata__explicit)
615 {
616     lutok::state state;
617 
618     lua_pushstring(raw(state), "foo");
619     ATF_REQUIRE(!state.is_userdata(-1));
620     lua_newuserdata(raw(state), 543);
621     ATF_REQUIRE(state.is_userdata(-1));
622     ATF_REQUIRE(!state.is_userdata(-2));
623     lua_pop(raw(state), 2);
624 }
625 
626 
627 ATF_TEST_CASE_WITHOUT_HEAD(load_file__ok);
ATF_TEST_CASE_BODY(load_file__ok)628 ATF_TEST_CASE_BODY(load_file__ok)
629 {
630     std::ofstream output("test.lua");
631     output << "in_the_file = \"oh yes\"\n";
632     output.close();
633 
634     lutok::state state;
635     state.load_file("test.lua");
636     ATF_REQUIRE(lua_pcall(raw(state), 0, 0, 0) == 0);
637     lua_getglobal(raw(state), "in_the_file");
638     ATF_REQUIRE(std::strcmp("oh yes", lua_tostring(raw(state), -1)) == 0);
639     lua_pop(raw(state), 1);
640 }
641 
642 
643 ATF_TEST_CASE_WITHOUT_HEAD(load_file__api_error);
ATF_TEST_CASE_BODY(load_file__api_error)644 ATF_TEST_CASE_BODY(load_file__api_error)
645 {
646     std::ofstream output("test.lua");
647     output << "I have a bad syntax!  Wohoo!\n";
648     output.close();
649 
650     lutok::state state;
651     REQUIRE_API_ERROR("luaL_loadfile", state.load_file("test.lua"));
652 }
653 
654 
655 ATF_TEST_CASE_WITHOUT_HEAD(load_file__file_not_found_error);
ATF_TEST_CASE_BODY(load_file__file_not_found_error)656 ATF_TEST_CASE_BODY(load_file__file_not_found_error)
657 {
658     lutok::state state;
659     ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua",
660                          state.load_file("missing.lua"));
661 }
662 
663 
664 ATF_TEST_CASE_WITHOUT_HEAD(load_string__ok);
ATF_TEST_CASE_BODY(load_string__ok)665 ATF_TEST_CASE_BODY(load_string__ok)
666 {
667     lutok::state state;
668     state.load_string("return 2 + 3");
669     ATF_REQUIRE(lua_pcall(raw(state), 0, 1, 0) == 0);
670     ATF_REQUIRE_EQ(5, lua_tointeger(raw(state), -1));
671     lua_pop(raw(state), 1);
672 }
673 
674 
675 ATF_TEST_CASE_WITHOUT_HEAD(load_string__fail);
ATF_TEST_CASE_BODY(load_string__fail)676 ATF_TEST_CASE_BODY(load_string__fail)
677 {
678     lutok::state state;
679     REQUIRE_API_ERROR("luaL_loadstring", state.load_string("-"));
680 }
681 
682 
683 ATF_TEST_CASE_WITHOUT_HEAD(new_table);
ATF_TEST_CASE_BODY(new_table)684 ATF_TEST_CASE_BODY(new_table)
685 {
686     lutok::state state;
687     state.new_table();
688     ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
689     ATF_REQUIRE(lua_istable(raw(state), -1));
690     lua_pop(raw(state), 1);
691 }
692 
693 
694 ATF_TEST_CASE_WITHOUT_HEAD(new_userdata);
ATF_TEST_CASE_BODY(new_userdata)695 ATF_TEST_CASE_BODY(new_userdata)
696 {
697     lutok::state state;
698     int* pointer = state.new_userdata< int >();
699     *pointer = 1234;
700     ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
701     ATF_REQUIRE(lua_isuserdata(raw(state), -1));
702     lua_pop(raw(state), 1);
703 }
704 
705 
706 ATF_TEST_CASE_WITHOUT_HEAD(next__empty);
ATF_TEST_CASE_BODY(next__empty)707 ATF_TEST_CASE_BODY(next__empty)
708 {
709     lutok::state state;
710     luaL_dostring(raw(state), "t = {}");
711 
712     lua_getglobal(raw(state), "t");
713     lua_pushstring(raw(state), "this is a dummy value");
714     lua_pushnil(raw(state));
715     ATF_REQUIRE(!state.next(-3));
716     lua_pop(raw(state), 2);
717 }
718 
719 
720 ATF_TEST_CASE_WITHOUT_HEAD(next__many);
ATF_TEST_CASE_BODY(next__many)721 ATF_TEST_CASE_BODY(next__many)
722 {
723     lutok::state state;
724     luaL_dostring(raw(state), "t = {}; t[1] = 100; t[2] = 200");
725 
726     lua_getglobal(raw(state), "t");
727     lua_pushnil(raw(state));
728 
729     ATF_REQUIRE(state.next());
730     ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
731     ATF_REQUIRE(lua_isnumber(raw(state), -2));
732     ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -2));
733     ATF_REQUIRE(lua_isnumber(raw(state), -1));
734     ATF_REQUIRE_EQ(100, lua_tointeger(raw(state), -1));
735     lua_pop(raw(state), 1);
736 
737     ATF_REQUIRE(state.next());
738     ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
739     ATF_REQUIRE(lua_isnumber(raw(state), -2));
740     ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -2));
741     ATF_REQUIRE(lua_isnumber(raw(state), -1));
742     ATF_REQUIRE_EQ(200, lua_tointeger(raw(state), -1));
743     lua_pop(raw(state), 1);
744 
745     ATF_REQUIRE(!state.next());
746     lua_pop(raw(state), 1);
747 }
748 
749 
750 ATF_TEST_CASE_WITHOUT_HEAD(open_base);
ATF_TEST_CASE_BODY(open_base)751 ATF_TEST_CASE_BODY(open_base)
752 {
753     lutok::state state;
754     check_modules(state, "");
755     state.open_base();
756     check_modules(state, "base");
757 }
758 
759 
760 ATF_TEST_CASE_WITHOUT_HEAD(open_string);
ATF_TEST_CASE_BODY(open_string)761 ATF_TEST_CASE_BODY(open_string)
762 {
763     lutok::state state;
764     check_modules(state, "");
765     state.open_string();
766     check_modules(state, "string");
767 }
768 
769 
770 ATF_TEST_CASE_WITHOUT_HEAD(open_table);
ATF_TEST_CASE_BODY(open_table)771 ATF_TEST_CASE_BODY(open_table)
772 {
773     lutok::state state;
774     check_modules(state, "");
775     state.open_table();
776     check_modules(state, "table");
777 }
778 
779 
780 ATF_TEST_CASE_WITHOUT_HEAD(pcall__ok);
ATF_TEST_CASE_BODY(pcall__ok)781 ATF_TEST_CASE_BODY(pcall__ok)
782 {
783     lutok::state state;
784     luaL_loadstring(raw(state), "function mul(a, b) return a * b; end");
785     state.pcall(0, 0, 0);
786     state.get_global_table();
787     lua_pushstring(raw(state), "mul");
788     lua_gettable(raw(state), -2);
789     lua_pushinteger(raw(state), 3);
790     lua_pushinteger(raw(state), 5);
791     state.pcall(2, 1, 0);
792     ATF_REQUIRE_EQ(15, lua_tointeger(raw(state), -1));
793     lua_pop(raw(state), 2);
794 }
795 
796 
797 ATF_TEST_CASE_WITHOUT_HEAD(pcall__fail);
ATF_TEST_CASE_BODY(pcall__fail)798 ATF_TEST_CASE_BODY(pcall__fail)
799 {
800     lutok::state state;
801     lua_pushnil(raw(state));
802     REQUIRE_API_ERROR("lua_pcall", state.pcall(0, 0, 0));
803 }
804 
805 
806 ATF_TEST_CASE_WITHOUT_HEAD(pop__one);
ATF_TEST_CASE_BODY(pop__one)807 ATF_TEST_CASE_BODY(pop__one)
808 {
809     lutok::state state;
810     lua_pushinteger(raw(state), 10);
811     lua_pushinteger(raw(state), 20);
812     lua_pushinteger(raw(state), 30);
813     state.pop(1);
814     ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
815     ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -1));
816     lua_pop(raw(state), 2);
817 }
818 
819 
820 ATF_TEST_CASE_WITHOUT_HEAD(pop__many);
ATF_TEST_CASE_BODY(pop__many)821 ATF_TEST_CASE_BODY(pop__many)
822 {
823     lutok::state state;
824     lua_pushinteger(raw(state), 10);
825     lua_pushinteger(raw(state), 20);
826     lua_pushinteger(raw(state), 30);
827     state.pop(2);
828     ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
829     ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -1));
830     lua_pop(raw(state), 1);
831 }
832 
833 
834 ATF_TEST_CASE_WITHOUT_HEAD(push_boolean);
ATF_TEST_CASE_BODY(push_boolean)835 ATF_TEST_CASE_BODY(push_boolean)
836 {
837     lutok::state state;
838     state.push_boolean(true);
839     ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
840     ATF_REQUIRE(lua_toboolean(raw(state), -1));
841     state.push_boolean(false);
842     ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
843     ATF_REQUIRE(!lua_toboolean(raw(state), -1));
844     ATF_REQUIRE(lua_toboolean(raw(state), -2));
845     lua_pop(raw(state), 2);
846 }
847 
848 
849 ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_closure);
ATF_TEST_CASE_BODY(push_cxx_closure)850 ATF_TEST_CASE_BODY(push_cxx_closure)
851 {
852     lutok::state state;
853     state.push_integer(15);
854     state.push_cxx_closure(cxx_multiply_closure, 1);
855     lua_setglobal(raw(state), "cxx_multiply_closure");
856 
857     ATF_REQUIRE(luaL_dostring(raw(state),
858                               "return cxx_multiply_closure(10)") == 0);
859     ATF_REQUIRE_EQ(150, lua_tointeger(raw(state), -1));
860     lua_pop(raw(state), 1);
861 }
862 
863 
864 ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__ok);
ATF_TEST_CASE_BODY(push_cxx_function__ok)865 ATF_TEST_CASE_BODY(push_cxx_function__ok)
866 {
867     lutok::state state;
868     state.push_cxx_function(cxx_divide);
869     lua_setglobal(raw(state), "cxx_divide");
870 
871     ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(17, 3)") == 0);
872     ATF_REQUIRE_EQ(5, lua_tointeger(raw(state), -2));
873     ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -1));
874     lua_pop(raw(state), 2);
875 }
876 
877 
878 ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_exception);
ATF_TEST_CASE_BODY(push_cxx_function__fail_exception)879 ATF_TEST_CASE_BODY(push_cxx_function__fail_exception)
880 {
881     lutok::state state;
882     state.push_cxx_function(cxx_divide);
883     lua_setglobal(raw(state), "cxx_divide");
884 
885     ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(15, 0)") != 0);
886     ATF_REQUIRE_MATCH("Divisor is 0", lua_tostring(raw(state), -1));
887     lua_pop(raw(state), 1);
888 }
889 
890 
891 ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_anything);
ATF_TEST_CASE_BODY(push_cxx_function__fail_anything)892 ATF_TEST_CASE_BODY(push_cxx_function__fail_anything)
893 {
894     lutok::state state;
895     state.push_cxx_function(cxx_divide);
896     lua_setglobal(raw(state), "cxx_divide");
897 
898     ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(-3, -1)") != 0);
899     ATF_REQUIRE_MATCH("Unhandled exception", lua_tostring(raw(state), -1));
900     lua_pop(raw(state), 1);
901 }
902 
903 
904 ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_overflow);
ATF_TEST_CASE_BODY(push_cxx_function__fail_overflow)905 ATF_TEST_CASE_BODY(push_cxx_function__fail_overflow)
906 {
907     lutok::state state;
908     state.push_cxx_function(raise_long_error);
909     lua_setglobal(raw(state), "fail");
910 
911     ATF_REQUIRE(luaL_dostring(raw(state), "return fail(900)") != 0);
912     ATF_REQUIRE_MATCH(std::string(900, 'A'), lua_tostring(raw(state), -1));
913     lua_pop(raw(state), 1);
914 
915     ATF_REQUIRE(luaL_dostring(raw(state), "return fail(8192)") != 0);
916     ATF_REQUIRE_MATCH(std::string(900, 'A'), lua_tostring(raw(state), -1));
917     lua_pop(raw(state), 1);
918 }
919 
920 
921 ATF_TEST_CASE_WITHOUT_HEAD(push_integer);
ATF_TEST_CASE_BODY(push_integer)922 ATF_TEST_CASE_BODY(push_integer)
923 {
924     lutok::state state;
925     state.push_integer(12);
926     ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
927     ATF_REQUIRE_EQ(12, lua_tointeger(raw(state), -1));
928     state.push_integer(34);
929     ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
930     ATF_REQUIRE_EQ(34, lua_tointeger(raw(state), -1));
931     ATF_REQUIRE_EQ(12, lua_tointeger(raw(state), -2));
932     lua_pop(raw(state), 2);
933 }
934 
935 
936 ATF_TEST_CASE_WITHOUT_HEAD(push_nil);
ATF_TEST_CASE_BODY(push_nil)937 ATF_TEST_CASE_BODY(push_nil)
938 {
939     lutok::state state;
940     state.push_nil();
941     ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
942     ATF_REQUIRE(lua_isnil(raw(state), -1));
943     state.push_integer(34);
944     ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
945     ATF_REQUIRE(!lua_isnil(raw(state), -1));
946     ATF_REQUIRE(lua_isnil(raw(state), -2));
947     lua_pop(raw(state), 2);
948 }
949 
950 
951 ATF_TEST_CASE_WITHOUT_HEAD(push_string);
ATF_TEST_CASE_BODY(push_string)952 ATF_TEST_CASE_BODY(push_string)
953 {
954     lutok::state state;
955 
956     {
957         std::string str = "first";
958         state.push_string(str);
959         ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
960         ATF_REQUIRE_EQ(std::string("first"), lua_tostring(raw(state), -1));
961         str = "second";
962         state.push_string(str);
963     }
964     ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
965     ATF_REQUIRE_EQ(std::string("second"), lua_tostring(raw(state), -1));
966     ATF_REQUIRE_EQ(std::string("first"), lua_tostring(raw(state), -2));
967     lua_pop(raw(state), 2);
968 }
969 
970 
971 ATF_TEST_CASE_WITHOUT_HEAD(push_value__top);
ATF_TEST_CASE_BODY(push_value__top)972 ATF_TEST_CASE_BODY(push_value__top)
973 {
974     lutok::state state;
975 
976     lua_pushinteger(raw(state), 10);
977     lua_pushinteger(raw(state), 20);
978     state.push_value();
979     ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
980     ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -1));
981     ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -2));
982     ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -3));
983     lua_pop(raw(state), 3);
984 }
985 
986 
987 ATF_TEST_CASE_WITHOUT_HEAD(push_value__explicit);
ATF_TEST_CASE_BODY(push_value__explicit)988 ATF_TEST_CASE_BODY(push_value__explicit)
989 {
990     lutok::state state;
991 
992     lua_pushinteger(raw(state), 10);
993     lua_pushinteger(raw(state), 20);
994     state.push_value(-2);
995     ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
996     ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -1));
997     ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -2));
998     ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -3));
999     lua_pop(raw(state), 3);
1000 }
1001 
1002 
1003 ATF_TEST_CASE_WITHOUT_HEAD(raw_get__top);
ATF_TEST_CASE_BODY(raw_get__top)1004 ATF_TEST_CASE_BODY(raw_get__top)
1005 {
1006     lutok::state state;
1007 
1008     luaL_openlibs(raw(state));
1009     ATF_REQUIRE(luaL_dostring(
1010         raw(state), "t = {foo=123} ; setmetatable(t, {__index=1})") == 0);
1011     lua_getglobal(raw(state), "t");
1012     lua_pushstring(raw(state), "foo");
1013     state.raw_get();
1014     ATF_REQUIRE(lua_isnumber(raw(state), -1));
1015     ATF_REQUIRE_EQ(123, lua_tointeger(raw(state), -1));
1016     lua_pop(raw(state), 2);
1017 }
1018 
1019 
1020 ATF_TEST_CASE_WITHOUT_HEAD(raw_get__explicit);
ATF_TEST_CASE_BODY(raw_get__explicit)1021 ATF_TEST_CASE_BODY(raw_get__explicit)
1022 {
1023     lutok::state state;
1024 
1025     luaL_openlibs(raw(state));
1026     ATF_REQUIRE(luaL_dostring(
1027         raw(state), "t = {foo=123} ; setmetatable(t, {__index=1})") == 0);
1028     lua_getglobal(raw(state), "t");
1029     lua_pushinteger(raw(state), 9876);
1030     lua_pushstring(raw(state), "foo");
1031     state.raw_get(-3);
1032     ATF_REQUIRE(lua_isnumber(raw(state), -1));
1033     ATF_REQUIRE_EQ(123, lua_tointeger(raw(state), -1));
1034     ATF_REQUIRE_EQ(9876, lua_tointeger(raw(state), -2));
1035     lua_pop(raw(state), 3);
1036 }
1037 
1038 
1039 ATF_TEST_CASE_WITHOUT_HEAD(raw_set__top);
ATF_TEST_CASE_BODY(raw_set__top)1040 ATF_TEST_CASE_BODY(raw_set__top)
1041 {
1042     lutok::state state;
1043 
1044     luaL_openlibs(raw(state));
1045     ATF_REQUIRE(luaL_dostring(
1046         raw(state), "t = {} ; setmetatable(t, {__newindex=1})") == 0);
1047     lua_getglobal(raw(state), "t");
1048     lua_pushstring(raw(state), "foo");
1049     lua_pushinteger(raw(state), 345);
1050     state.raw_set();
1051     ATF_REQUIRE(luaL_dostring(raw(state), "return t.foo") == 0);
1052     ATF_REQUIRE(lua_isnumber(raw(state), -1));
1053     ATF_REQUIRE_EQ(345, lua_tointeger(raw(state), -1));
1054     lua_pop(raw(state), 2);
1055 }
1056 
1057 
1058 ATF_TEST_CASE_WITHOUT_HEAD(raw_set__explicit);
ATF_TEST_CASE_BODY(raw_set__explicit)1059 ATF_TEST_CASE_BODY(raw_set__explicit)
1060 {
1061     lutok::state state;
1062 
1063     luaL_openlibs(raw(state));
1064     ATF_REQUIRE(luaL_dostring(
1065         raw(state), "t = {} ; setmetatable(t, {__newindex=1})") == 0);
1066     lua_getglobal(raw(state), "t");
1067     lua_pushinteger(raw(state), 876);
1068     lua_pushstring(raw(state), "foo");
1069     lua_pushinteger(raw(state), 345);
1070     state.raw_set(-4);
1071     ATF_REQUIRE(luaL_dostring(raw(state), "return t.foo") == 0);
1072     ATF_REQUIRE(lua_isnumber(raw(state), -1));
1073     ATF_REQUIRE_EQ(345, lua_tointeger(raw(state), -1));
1074     ATF_REQUIRE_EQ(876, lua_tointeger(raw(state), -2));
1075     lua_pop(raw(state), 3);
1076 }
1077 
1078 
1079 ATF_TEST_CASE_WITHOUT_HEAD(registry_index);
ATF_TEST_CASE_BODY(registry_index)1080 ATF_TEST_CASE_BODY(registry_index)
1081 {
1082     lutok::state state;
1083     lua_pushvalue(raw(state), lutok::registry_index);
1084     lua_pushstring(raw(state), "custom_variable");
1085     lua_pushstring(raw(state), "custom value");
1086     lua_settable(raw(state), -3);
1087     lua_pop(raw(state), 1);
1088     ATF_REQUIRE(luaL_dostring(raw(state),
1089                               "return custom_variable == nil") == 0);
1090     ATF_REQUIRE(lua_isboolean(raw(state), -1));
1091     ATF_REQUIRE(lua_toboolean(raw(state), -1));
1092     lua_pop(raw(state), 1);
1093 }
1094 
1095 
1096 ATF_TEST_CASE_WITHOUT_HEAD(set_global);
ATF_TEST_CASE_BODY(set_global)1097 ATF_TEST_CASE_BODY(set_global)
1098 {
1099     lutok::state state;
1100     lua_pushinteger(raw(state), 3);
1101     state.set_global("test_variable");
1102     ATF_REQUIRE(luaL_dostring(raw(state), "return test_variable + 1") == 0);
1103     ATF_REQUIRE(lua_isnumber(raw(state), -1));
1104     ATF_REQUIRE_EQ(4, lua_tointeger(raw(state), -1));
1105     lua_pop(raw(state), 1);
1106 }
1107 
1108 
1109 ATF_TEST_CASE_WITHOUT_HEAD(set_metatable__top);
ATF_TEST_CASE_BODY(set_metatable__top)1110 ATF_TEST_CASE_BODY(set_metatable__top)
1111 {
1112     lutok::state state;
1113     ATF_REQUIRE(luaL_dostring(
1114         raw(state),
1115         "mt = {}\n"
1116         "mt.__add = function(a, b) return a[1] + b end\n"
1117         "numbers = {}\n"
1118         "numbers[1] = 5\n") == 0);
1119 
1120     lua_getglobal(raw(state), "numbers");
1121     lua_getglobal(raw(state), "mt");
1122     state.set_metatable();
1123     lua_pop(raw(state), 1);
1124 
1125     ATF_REQUIRE(luaL_dostring(raw(state), "return numbers + 2") == 0);
1126     ATF_REQUIRE(lua_isnumber(raw(state), -1));
1127     ATF_REQUIRE_EQ(7, lua_tointeger(raw(state), -1));
1128     lua_pop(raw(state), 1);
1129 }
1130 
1131 
1132 ATF_TEST_CASE_WITHOUT_HEAD(set_metatable__explicit);
ATF_TEST_CASE_BODY(set_metatable__explicit)1133 ATF_TEST_CASE_BODY(set_metatable__explicit)
1134 {
1135     lutok::state state;
1136     ATF_REQUIRE(luaL_dostring(
1137         raw(state),
1138         "mt = {}\n"
1139         "mt.__add = function(a, b) return a[1] + b end\n"
1140         "numbers = {}\n"
1141         "numbers[1] = 5\n") == 0);
1142 
1143     lua_getglobal(raw(state), "numbers");
1144     lua_pushinteger(raw(state), 1234);
1145     lua_getglobal(raw(state), "mt");
1146     state.set_metatable(-3);
1147     lua_pop(raw(state), 2);
1148 
1149     ATF_REQUIRE(luaL_dostring(raw(state), "return numbers + 2") == 0);
1150     ATF_REQUIRE(lua_isnumber(raw(state), -1));
1151     ATF_REQUIRE_EQ(7, lua_tointeger(raw(state), -1));
1152     lua_pop(raw(state), 1);
1153 }
1154 
1155 
1156 ATF_TEST_CASE_WITHOUT_HEAD(set_table__ok);
ATF_TEST_CASE_BODY(set_table__ok)1157 ATF_TEST_CASE_BODY(set_table__ok)
1158 {
1159     lutok::state state;
1160     ATF_REQUIRE(luaL_dostring(raw(state), "t = { a = 1, bar = 234 }") == 0);
1161     lua_getglobal(raw(state), "t");
1162 
1163     lua_pushstring(raw(state), "bar");
1164     lua_pushstring(raw(state), "baz");
1165     state.set_table();
1166     ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
1167 
1168     lua_pushstring(raw(state), "a");
1169     lua_gettable(raw(state), -2);
1170     ATF_REQUIRE(lua_isnumber(raw(state), -1));
1171     ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -1));
1172     lua_pop(raw(state), 1);
1173 
1174     lua_pushstring(raw(state), "bar");
1175     lua_gettable(raw(state), -2);
1176     ATF_REQUIRE(lua_isstring(raw(state), -1));
1177     ATF_REQUIRE_EQ(std::string("baz"), lua_tostring(raw(state), -1));
1178     lua_pop(raw(state), 1);
1179 
1180     lua_pop(raw(state), 1);
1181 }
1182 
1183 
1184 ATF_TEST_CASE_WITHOUT_HEAD(set_table__nil);
ATF_TEST_CASE_BODY(set_table__nil)1185 ATF_TEST_CASE_BODY(set_table__nil)
1186 {
1187     lutok::state state;
1188     lua_pushnil(raw(state));
1189     lua_pushinteger(raw(state), 1);
1190     lua_pushinteger(raw(state), 2);
1191     REQUIRE_API_ERROR("lua_settable", state.set_table(-3));
1192     lua_pop(raw(state), 3);
1193 }
1194 
1195 
1196 ATF_TEST_CASE_WITHOUT_HEAD(to_boolean__top);
ATF_TEST_CASE_BODY(to_boolean__top)1197 ATF_TEST_CASE_BODY(to_boolean__top)
1198 {
1199     lutok::state state;
1200     lua_pushboolean(raw(state), 1);
1201     ATF_REQUIRE(state.to_boolean());
1202     lua_pushboolean(raw(state), 0);
1203     ATF_REQUIRE(!state.to_boolean());
1204     lua_pop(raw(state), 2);
1205 }
1206 
1207 
1208 ATF_TEST_CASE_WITHOUT_HEAD(to_boolean__explicit);
ATF_TEST_CASE_BODY(to_boolean__explicit)1209 ATF_TEST_CASE_BODY(to_boolean__explicit)
1210 {
1211     lutok::state state;
1212     lua_pushboolean(raw(state), 0);
1213     lua_pushboolean(raw(state), 1);
1214     ATF_REQUIRE(!state.to_boolean(-2));
1215     ATF_REQUIRE(state.to_boolean(-1));
1216     lua_pop(raw(state), 2);
1217 }
1218 
1219 
1220 ATF_TEST_CASE_WITHOUT_HEAD(to_integer__top);
ATF_TEST_CASE_BODY(to_integer__top)1221 ATF_TEST_CASE_BODY(to_integer__top)
1222 {
1223     lutok::state state;
1224     lua_pushstring(raw(state), "34");
1225     ATF_REQUIRE_EQ(34, state.to_integer());
1226     lua_pushinteger(raw(state), 12);
1227     ATF_REQUIRE_EQ(12, state.to_integer());
1228     lua_pop(raw(state), 2);
1229 }
1230 
1231 
1232 ATF_TEST_CASE_WITHOUT_HEAD(to_integer__explicit);
ATF_TEST_CASE_BODY(to_integer__explicit)1233 ATF_TEST_CASE_BODY(to_integer__explicit)
1234 {
1235     lutok::state state;
1236     lua_pushinteger(raw(state), 12);
1237     lua_pushstring(raw(state), "foobar");
1238     ATF_REQUIRE_EQ(12, state.to_integer(-2));
1239     lua_pop(raw(state), 2);
1240 }
1241 
1242 
1243 ATF_TEST_CASE_WITHOUT_HEAD(to_string__top);
ATF_TEST_CASE_BODY(to_string__top)1244 ATF_TEST_CASE_BODY(to_string__top)
1245 {
1246     lutok::state state;
1247     lua_pushstring(raw(state), "foobar");
1248     ATF_REQUIRE_EQ("foobar", state.to_string());
1249     lua_pushinteger(raw(state), 12);
1250     ATF_REQUIRE_EQ("12", state.to_string());
1251     lua_pop(raw(state), 2);
1252 }
1253 
1254 
1255 ATF_TEST_CASE_WITHOUT_HEAD(to_string__explicit);
ATF_TEST_CASE_BODY(to_string__explicit)1256 ATF_TEST_CASE_BODY(to_string__explicit)
1257 {
1258     lutok::state state;
1259     lua_pushstring(raw(state), "foobar");
1260     lua_pushinteger(raw(state), 12);
1261     ATF_REQUIRE_EQ("foobar", state.to_string(-2));
1262     ATF_REQUIRE_EQ("12", state.to_string(-1));
1263     lua_pop(raw(state), 2);
1264 }
1265 
1266 
1267 ATF_TEST_CASE_WITHOUT_HEAD(to_userdata__top);
ATF_TEST_CASE_BODY(to_userdata__top)1268 ATF_TEST_CASE_BODY(to_userdata__top)
1269 {
1270     lutok::state state;
1271     {
1272         int* pointer = static_cast< int* >(
1273             lua_newuserdata(raw(state), sizeof(int)));
1274         *pointer = 987;
1275     }
1276 
1277     int* pointer = state.to_userdata< int >();
1278     ATF_REQUIRE_EQ(987, *pointer);
1279     lua_pop(raw(state), 1);
1280 }
1281 
1282 
1283 ATF_TEST_CASE_WITHOUT_HEAD(to_userdata__explicit);
ATF_TEST_CASE_BODY(to_userdata__explicit)1284 ATF_TEST_CASE_BODY(to_userdata__explicit)
1285 {
1286     lutok::state state;
1287     {
1288         int* pointer = static_cast< int* >(
1289             lua_newuserdata(raw(state), sizeof(int)));
1290         *pointer = 987;
1291     }
1292 
1293     lua_pushinteger(raw(state), 3);
1294     int* pointer = state.to_userdata< int >(-2);
1295     ATF_REQUIRE_EQ(987, *pointer);
1296     lua_pop(raw(state), 2);
1297 }
1298 
1299 
1300 ATF_TEST_CASE_WITHOUT_HEAD(upvalue_index);
ATF_TEST_CASE_BODY(upvalue_index)1301 ATF_TEST_CASE_BODY(upvalue_index)
1302 {
1303     lutok::state state;
1304     lua_pushinteger(raw(state), 25);
1305     lua_pushinteger(raw(state), 30);
1306     lua_pushcclosure(raw(state), c_get_upvalues, 2);
1307     lua_setglobal(raw(state), "c_get_upvalues");
1308 
1309     ATF_REQUIRE(luaL_dostring(raw(state),
1310                               "return c_get_upvalues()") == 0);
1311     ATF_REQUIRE_EQ(25, lua_tointeger(raw(state), -2));
1312     ATF_REQUIRE_EQ(30, lua_tointeger(raw(state), -1));
1313     lua_pop(raw(state), 2);
1314 }
1315 
1316 
ATF_INIT_TEST_CASES(tcs)1317 ATF_INIT_TEST_CASES(tcs)
1318 {
1319     ATF_ADD_TEST_CASE(tcs, close);
1320     ATF_ADD_TEST_CASE(tcs, get_global__ok);
1321     ATF_ADD_TEST_CASE(tcs, get_global__undefined);
1322     ATF_ADD_TEST_CASE(tcs, get_global_table);
1323     ATF_ADD_TEST_CASE(tcs, get_metafield__ok);
1324     ATF_ADD_TEST_CASE(tcs, get_metafield__undefined);
1325     ATF_ADD_TEST_CASE(tcs, get_metatable__top);
1326     ATF_ADD_TEST_CASE(tcs, get_metatable__explicit);
1327     ATF_ADD_TEST_CASE(tcs, get_metatable__undefined);
1328     ATF_ADD_TEST_CASE(tcs, get_table__ok);
1329     ATF_ADD_TEST_CASE(tcs, get_table__nil);
1330     ATF_ADD_TEST_CASE(tcs, get_table__unknown_index);
1331     ATF_ADD_TEST_CASE(tcs, get_top);
1332     ATF_ADD_TEST_CASE(tcs, insert);
1333     ATF_ADD_TEST_CASE(tcs, is_boolean__empty);
1334     ATF_ADD_TEST_CASE(tcs, is_boolean__top);
1335     ATF_ADD_TEST_CASE(tcs, is_boolean__explicit);
1336     ATF_ADD_TEST_CASE(tcs, is_function__empty);
1337     ATF_ADD_TEST_CASE(tcs, is_function__top);
1338     ATF_ADD_TEST_CASE(tcs, is_function__explicit);
1339     ATF_ADD_TEST_CASE(tcs, is_nil__empty);
1340     ATF_ADD_TEST_CASE(tcs, is_nil__top);
1341     ATF_ADD_TEST_CASE(tcs, is_nil__explicit);
1342     ATF_ADD_TEST_CASE(tcs, is_number__empty);
1343     ATF_ADD_TEST_CASE(tcs, is_number__top);
1344     ATF_ADD_TEST_CASE(tcs, is_number__explicit);
1345     ATF_ADD_TEST_CASE(tcs, is_string__empty);
1346     ATF_ADD_TEST_CASE(tcs, is_string__top);
1347     ATF_ADD_TEST_CASE(tcs, is_string__explicit);
1348     ATF_ADD_TEST_CASE(tcs, is_table__empty);
1349     ATF_ADD_TEST_CASE(tcs, is_table__top);
1350     ATF_ADD_TEST_CASE(tcs, is_table__explicit);
1351     ATF_ADD_TEST_CASE(tcs, is_userdata__empty);
1352     ATF_ADD_TEST_CASE(tcs, is_userdata__top);
1353     ATF_ADD_TEST_CASE(tcs, is_userdata__explicit);
1354     ATF_ADD_TEST_CASE(tcs, load_file__ok);
1355     ATF_ADD_TEST_CASE(tcs, load_file__api_error);
1356     ATF_ADD_TEST_CASE(tcs, load_file__file_not_found_error);
1357     ATF_ADD_TEST_CASE(tcs, load_string__ok);
1358     ATF_ADD_TEST_CASE(tcs, load_string__fail);
1359     ATF_ADD_TEST_CASE(tcs, new_table);
1360     ATF_ADD_TEST_CASE(tcs, new_userdata);
1361     ATF_ADD_TEST_CASE(tcs, next__empty);
1362     ATF_ADD_TEST_CASE(tcs, next__many);
1363     ATF_ADD_TEST_CASE(tcs, open_base);
1364     ATF_ADD_TEST_CASE(tcs, open_string);
1365     ATF_ADD_TEST_CASE(tcs, open_table);
1366     ATF_ADD_TEST_CASE(tcs, pcall__ok);
1367     ATF_ADD_TEST_CASE(tcs, pcall__fail);
1368     ATF_ADD_TEST_CASE(tcs, pop__one);
1369     ATF_ADD_TEST_CASE(tcs, pop__many);
1370     ATF_ADD_TEST_CASE(tcs, push_boolean);
1371     ATF_ADD_TEST_CASE(tcs, push_cxx_closure);
1372     ATF_ADD_TEST_CASE(tcs, push_cxx_function__ok);
1373     ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_exception);
1374     ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_anything);
1375     ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_overflow);
1376     ATF_ADD_TEST_CASE(tcs, push_integer);
1377     ATF_ADD_TEST_CASE(tcs, push_nil);
1378     ATF_ADD_TEST_CASE(tcs, push_string);
1379     ATF_ADD_TEST_CASE(tcs, push_value__top);
1380     ATF_ADD_TEST_CASE(tcs, push_value__explicit);
1381     ATF_ADD_TEST_CASE(tcs, raw_get__top);
1382     ATF_ADD_TEST_CASE(tcs, raw_get__explicit);
1383     ATF_ADD_TEST_CASE(tcs, raw_set__top);
1384     ATF_ADD_TEST_CASE(tcs, raw_set__explicit);
1385     ATF_ADD_TEST_CASE(tcs, registry_index);
1386     ATF_ADD_TEST_CASE(tcs, set_global);
1387     ATF_ADD_TEST_CASE(tcs, set_metatable__top);
1388     ATF_ADD_TEST_CASE(tcs, set_metatable__explicit);
1389     ATF_ADD_TEST_CASE(tcs, set_table__ok);
1390     ATF_ADD_TEST_CASE(tcs, set_table__nil);
1391     ATF_ADD_TEST_CASE(tcs, to_boolean__top);
1392     ATF_ADD_TEST_CASE(tcs, to_boolean__explicit);
1393     ATF_ADD_TEST_CASE(tcs, to_integer__top);
1394     ATF_ADD_TEST_CASE(tcs, to_integer__explicit);
1395     ATF_ADD_TEST_CASE(tcs, to_string__top);
1396     ATF_ADD_TEST_CASE(tcs, to_string__explicit);
1397     ATF_ADD_TEST_CASE(tcs, to_userdata__top);
1398     ATF_ADD_TEST_CASE(tcs, to_userdata__explicit);
1399     ATF_ADD_TEST_CASE(tcs, upvalue_index);
1400 }
1401