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
59namespace {
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.
68static bool
69is_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.
87static void
88check_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.
108static int
109c_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.
128static int
129cxx_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.
153static int
154cxx_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.
178static int
179raise_long_error(lutok::state& state)
180{
181    const int length = state.to_integer(-1);
182    throw std::runtime_error(std::string(length, 'A').c_str());
183}
184
185
186}  // anonymous namespace
187
188
189ATF_TEST_CASE_WITHOUT_HEAD(close);
190ATF_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
199ATF_TEST_CASE_WITHOUT_HEAD(get_global__ok);
200ATF_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
210ATF_TEST_CASE_WITHOUT_HEAD(get_global__undefined);
211ATF_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
220ATF_TEST_CASE_WITHOUT_HEAD(get_global_table);
221ATF_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
234ATF_TEST_CASE_WITHOUT_HEAD(get_metafield__ok);
235ATF_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
249ATF_TEST_CASE_WITHOUT_HEAD(get_metafield__undefined);
250ATF_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
262ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__ok);
263ATF_TEST_CASE_BODY(get_metatable__ok)
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    lua_pushinteger(raw(state), 5555);
271    ATF_REQUIRE(state.get_metatable(-2));
272    ATF_REQUIRE(lua_istable(raw(state), -1));
273    lua_pushstring(raw(state), "foo");
274    lua_gettable(raw(state), -2);
275    ATF_REQUIRE(lua_isnumber(raw(state), -1));
276    ATF_REQUIRE_EQ(567, lua_tointeger(raw(state), -1));
277    lua_pop(raw(state), 4);
278}
279
280
281ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__undefined);
282ATF_TEST_CASE_BODY(get_metatable__undefined)
283{
284    lutok::state state;
285    ATF_REQUIRE(luaL_dostring(raw(state), "t = {}") == 0);
286    lua_getglobal(raw(state), "t");
287    ATF_REQUIRE(!state.get_metatable(-1));
288    lua_pop(raw(state), 1);
289}
290
291
292ATF_TEST_CASE_WITHOUT_HEAD(get_table__ok);
293ATF_TEST_CASE_BODY(get_table__ok)
294{
295    lutok::state state;
296    ATF_REQUIRE(luaL_dostring(raw(state), "t = { a = 1, bar = 234 }") == 0);
297    lua_getglobal(raw(state), "t");
298    lua_pushstring(raw(state), "bar");
299    state.get_table(-2);
300    ATF_REQUIRE(lua_isnumber(raw(state), -1));
301    ATF_REQUIRE_EQ(234, lua_tointeger(raw(state), -1));
302    lua_pop(raw(state), 2);
303}
304
305
306ATF_TEST_CASE_WITHOUT_HEAD(get_table__nil);
307ATF_TEST_CASE_BODY(get_table__nil)
308{
309    lutok::state state;
310    lua_pushnil(raw(state));
311    lua_pushinteger(raw(state), 1);
312    REQUIRE_API_ERROR("lua_gettable", state.get_table(-2));
313    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
314    lua_pop(raw(state), 2);
315}
316
317
318ATF_TEST_CASE_WITHOUT_HEAD(get_table__unknown_index);
319ATF_TEST_CASE_BODY(get_table__unknown_index)
320{
321    lutok::state state;
322    ATF_REQUIRE(luaL_dostring(raw(state),
323                              "the_table = { foo = 1, bar = 2 }") == 0);
324    lua_getglobal(raw(state), "the_table");
325    lua_pushstring(raw(state), "baz");
326    state.get_table(-2);
327    ATF_REQUIRE(lua_isnil(raw(state), -1));
328    lua_pop(raw(state), 2);
329}
330
331
332ATF_TEST_CASE_WITHOUT_HEAD(get_top);
333ATF_TEST_CASE_BODY(get_top)
334{
335    lutok::state state;
336    ATF_REQUIRE_EQ(0, state.get_top());
337    lua_pushinteger(raw(state), 3);
338    ATF_REQUIRE_EQ(1, state.get_top());
339    lua_pushinteger(raw(state), 3);
340    ATF_REQUIRE_EQ(2, state.get_top());
341    lua_pop(raw(state), 2);
342}
343
344
345ATF_TEST_CASE_WITHOUT_HEAD(insert);
346ATF_TEST_CASE_BODY(insert)
347{
348    lutok::state state;
349    lua_pushinteger(raw(state), 1);
350    lua_pushinteger(raw(state), 2);
351    lua_pushinteger(raw(state), 3);
352    lua_pushinteger(raw(state), 4);
353    state.insert(-3);
354    ATF_REQUIRE_EQ(3, lua_tointeger(raw(state), -1));
355    ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -2));
356    ATF_REQUIRE_EQ(4, lua_tointeger(raw(state), -3));
357    ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -4));
358    lua_pop(raw(state), 4);
359}
360
361
362ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__empty);
363ATF_TEST_CASE_BODY(is_boolean__empty)
364{
365    lutok::state state;
366    ATF_REQUIRE(!state.is_boolean(-1));
367}
368
369
370ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__ok);
371ATF_TEST_CASE_BODY(is_boolean__ok)
372{
373    lutok::state state;
374    lua_pushboolean(raw(state), 1);
375    ATF_REQUIRE(state.is_boolean(-1));
376    lua_pushinteger(raw(state), 5);
377    ATF_REQUIRE(!state.is_boolean(-1));
378    ATF_REQUIRE(state.is_boolean(-2));
379    lua_pop(raw(state), 2);
380}
381
382
383ATF_TEST_CASE_WITHOUT_HEAD(is_function__empty);
384ATF_TEST_CASE_BODY(is_function__empty)
385{
386    lutok::state state;
387    ATF_REQUIRE(!state.is_function(-1));
388}
389
390
391ATF_TEST_CASE_WITHOUT_HEAD(is_function__ok);
392ATF_TEST_CASE_BODY(is_function__ok)
393{
394    lutok::state state;
395    luaL_dostring(raw(state), "function my_func(a, b) return a + b; end");
396
397    lua_getglobal(raw(state), "my_func");
398    ATF_REQUIRE(state.is_function(-1));
399    lua_pushinteger(raw(state), 5);
400    ATF_REQUIRE(!state.is_function(-1));
401    ATF_REQUIRE(state.is_function(-2));
402    lua_pop(raw(state), 2);
403}
404
405
406ATF_TEST_CASE_WITHOUT_HEAD(is_nil__empty);
407ATF_TEST_CASE_BODY(is_nil__empty)
408{
409    lutok::state state;
410    ATF_REQUIRE(state.is_nil(-1));
411}
412
413
414ATF_TEST_CASE_WITHOUT_HEAD(is_nil__ok);
415ATF_TEST_CASE_BODY(is_nil__ok)
416{
417    lutok::state state;
418    lua_pushnil(raw(state));
419    ATF_REQUIRE(state.is_nil(-1));
420    lua_pushinteger(raw(state), 5);
421    ATF_REQUIRE(!state.is_nil(-1));
422    ATF_REQUIRE(state.is_nil(-2));
423    lua_pop(raw(state), 2);
424}
425
426
427ATF_TEST_CASE_WITHOUT_HEAD(is_number__empty);
428ATF_TEST_CASE_BODY(is_number__empty)
429{
430    lutok::state state;
431    ATF_REQUIRE(!state.is_number(-1));
432}
433
434
435ATF_TEST_CASE_WITHOUT_HEAD(is_number__ok);
436ATF_TEST_CASE_BODY(is_number__ok)
437{
438    lutok::state state;
439    lua_pushnil(raw(state));
440    ATF_REQUIRE(!state.is_number(-1));
441    lua_pushinteger(raw(state), 5);
442    ATF_REQUIRE(state.is_number(-1));
443    ATF_REQUIRE(!state.is_number(-2));
444    lua_pop(raw(state), 2);
445}
446
447
448ATF_TEST_CASE_WITHOUT_HEAD(is_string__empty);
449ATF_TEST_CASE_BODY(is_string__empty)
450{
451    lutok::state state;
452    ATF_REQUIRE(!state.is_string(-1));
453}
454
455
456ATF_TEST_CASE_WITHOUT_HEAD(is_string__ok);
457ATF_TEST_CASE_BODY(is_string__ok)
458{
459    lutok::state state;
460    lua_pushinteger(raw(state), 3);
461    ATF_REQUIRE(state.is_string(-1));
462    lua_pushnil(raw(state));
463    ATF_REQUIRE(!state.is_string(-1));
464    ATF_REQUIRE(state.is_string(-2));
465    lua_pushstring(raw(state), "foo");
466    ATF_REQUIRE(state.is_string(-1));
467    ATF_REQUIRE(!state.is_string(-2));
468    ATF_REQUIRE(state.is_string(-3));
469    lua_pop(raw(state), 3);
470}
471
472
473ATF_TEST_CASE_WITHOUT_HEAD(is_table__empty);
474ATF_TEST_CASE_BODY(is_table__empty)
475{
476    lutok::state state;
477    ATF_REQUIRE(!state.is_table(-1));
478}
479
480
481ATF_TEST_CASE_WITHOUT_HEAD(is_table__ok);
482ATF_TEST_CASE_BODY(is_table__ok)
483{
484    lutok::state state;
485    luaL_dostring(raw(state), "t = {3, 4, 5}");
486
487    lua_pushstring(raw(state), "foo");
488    ATF_REQUIRE(!state.is_table(-1));
489    lua_getglobal(raw(state), "t");
490    ATF_REQUIRE(state.is_table(-1));
491    ATF_REQUIRE(!state.is_table(-2));
492    lua_pop(raw(state), 2);
493}
494
495
496ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__empty);
497ATF_TEST_CASE_BODY(is_userdata__empty)
498{
499    lutok::state state;
500    ATF_REQUIRE(!state.is_userdata(-1));
501}
502
503
504ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__ok);
505ATF_TEST_CASE_BODY(is_userdata__ok)
506{
507    lutok::state state;
508
509    lua_pushstring(raw(state), "foo");
510    ATF_REQUIRE(!state.is_userdata(-1));
511    lua_newuserdata(raw(state), 543);
512    ATF_REQUIRE(state.is_userdata(-1));
513    ATF_REQUIRE(!state.is_userdata(-2));
514    lua_pop(raw(state), 2);
515}
516
517
518ATF_TEST_CASE_WITHOUT_HEAD(load_file__ok);
519ATF_TEST_CASE_BODY(load_file__ok)
520{
521    std::ofstream output("test.lua");
522    output << "in_the_file = \"oh yes\"\n";
523    output.close();
524
525    lutok::state state;
526    state.load_file("test.lua");
527    ATF_REQUIRE(lua_pcall(raw(state), 0, 0, 0) == 0);
528    lua_getglobal(raw(state), "in_the_file");
529    ATF_REQUIRE(std::strcmp("oh yes", lua_tostring(raw(state), -1)) == 0);
530    lua_pop(raw(state), 1);
531}
532
533
534ATF_TEST_CASE_WITHOUT_HEAD(load_file__api_error);
535ATF_TEST_CASE_BODY(load_file__api_error)
536{
537    std::ofstream output("test.lua");
538    output << "I have a bad syntax!  Wohoo!\n";
539    output.close();
540
541    lutok::state state;
542    REQUIRE_API_ERROR("luaL_loadfile", state.load_file("test.lua"));
543}
544
545
546ATF_TEST_CASE_WITHOUT_HEAD(load_file__file_not_found_error);
547ATF_TEST_CASE_BODY(load_file__file_not_found_error)
548{
549    lutok::state state;
550    ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua",
551                         state.load_file("missing.lua"));
552}
553
554
555ATF_TEST_CASE_WITHOUT_HEAD(load_string__ok);
556ATF_TEST_CASE_BODY(load_string__ok)
557{
558    lutok::state state;
559    state.load_string("return 2 + 3");
560    ATF_REQUIRE(lua_pcall(raw(state), 0, 1, 0) == 0);
561    ATF_REQUIRE_EQ(5, lua_tointeger(raw(state), -1));
562    lua_pop(raw(state), 1);
563}
564
565
566ATF_TEST_CASE_WITHOUT_HEAD(load_string__fail);
567ATF_TEST_CASE_BODY(load_string__fail)
568{
569    lutok::state state;
570    REQUIRE_API_ERROR("luaL_loadstring", state.load_string("-"));
571}
572
573
574ATF_TEST_CASE_WITHOUT_HEAD(new_table);
575ATF_TEST_CASE_BODY(new_table)
576{
577    lutok::state state;
578    state.new_table();
579    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
580    ATF_REQUIRE(lua_istable(raw(state), -1));
581    lua_pop(raw(state), 1);
582}
583
584
585ATF_TEST_CASE_WITHOUT_HEAD(new_userdata);
586ATF_TEST_CASE_BODY(new_userdata)
587{
588    lutok::state state;
589    int* pointer = state.new_userdata< int >();
590    *pointer = 1234;
591    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
592    ATF_REQUIRE(lua_isuserdata(raw(state), -1));
593    lua_pop(raw(state), 1);
594}
595
596
597ATF_TEST_CASE_WITHOUT_HEAD(next__empty);
598ATF_TEST_CASE_BODY(next__empty)
599{
600    lutok::state state;
601    luaL_dostring(raw(state), "t = {}");
602
603    lua_getglobal(raw(state), "t");
604    lua_pushstring(raw(state), "this is a dummy value");
605    lua_pushnil(raw(state));
606    ATF_REQUIRE(!state.next(-3));
607    lua_pop(raw(state), 2);
608}
609
610
611ATF_TEST_CASE_WITHOUT_HEAD(next__many);
612ATF_TEST_CASE_BODY(next__many)
613{
614    lutok::state state;
615    luaL_dostring(raw(state), "t = {}; t[1] = 100; t[2] = 200");
616
617    lua_getglobal(raw(state), "t");
618    lua_pushnil(raw(state));
619
620    ATF_REQUIRE(state.next(-2));
621    ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
622    ATF_REQUIRE(lua_isnumber(raw(state), -2));
623    ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -2));
624    ATF_REQUIRE(lua_isnumber(raw(state), -1));
625    ATF_REQUIRE_EQ(100, lua_tointeger(raw(state), -1));
626    lua_pop(raw(state), 1);
627
628    ATF_REQUIRE(state.next(-2));
629    ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
630    ATF_REQUIRE(lua_isnumber(raw(state), -2));
631    ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -2));
632    ATF_REQUIRE(lua_isnumber(raw(state), -1));
633    ATF_REQUIRE_EQ(200, lua_tointeger(raw(state), -1));
634    lua_pop(raw(state), 1);
635
636    ATF_REQUIRE(!state.next(-2));
637    lua_pop(raw(state), 1);
638}
639
640
641ATF_TEST_CASE_WITHOUT_HEAD(open_base);
642ATF_TEST_CASE_BODY(open_base)
643{
644    lutok::state state;
645    check_modules(state, "");
646    state.open_base();
647    check_modules(state, "base");
648}
649
650
651ATF_TEST_CASE_WITHOUT_HEAD(open_all);
652ATF_TEST_CASE_BODY(open_all)
653{
654    lutok::state state;
655    check_modules(state, "");
656    state.open_all();
657    // Best-effort attempt at looking for a bunch of possible modules.
658    ATF_REQUIRE(is_available(state, "assert"));
659    ATF_REQUIRE(is_available(state, "debug.getinfo"));
660    ATF_REQUIRE(is_available(state, "package.path"));
661    ATF_REQUIRE(is_available(state, "string.byte"));
662    ATF_REQUIRE(is_available(state, "table.concat"));
663}
664
665
666ATF_TEST_CASE_WITHOUT_HEAD(open_string);
667ATF_TEST_CASE_BODY(open_string)
668{
669    lutok::state state;
670    check_modules(state, "");
671    state.open_string();
672    check_modules(state, "string");
673}
674
675
676ATF_TEST_CASE_WITHOUT_HEAD(open_table);
677ATF_TEST_CASE_BODY(open_table)
678{
679    lutok::state state;
680    check_modules(state, "");
681    state.open_table();
682    check_modules(state, "table");
683}
684
685
686ATF_TEST_CASE_WITHOUT_HEAD(pcall__ok);
687ATF_TEST_CASE_BODY(pcall__ok)
688{
689    lutok::state state;
690    luaL_loadstring(raw(state), "function mul(a, b) return a * b; end");
691    state.pcall(0, 0, 0);
692    state.get_global_table();
693    lua_pushstring(raw(state), "mul");
694    lua_gettable(raw(state), -2);
695    lua_pushinteger(raw(state), 3);
696    lua_pushinteger(raw(state), 5);
697    state.pcall(2, 1, 0);
698    ATF_REQUIRE_EQ(15, lua_tointeger(raw(state), -1));
699    lua_pop(raw(state), 2);
700}
701
702
703ATF_TEST_CASE_WITHOUT_HEAD(pcall__fail);
704ATF_TEST_CASE_BODY(pcall__fail)
705{
706    lutok::state state;
707    lua_pushnil(raw(state));
708    REQUIRE_API_ERROR("lua_pcall", state.pcall(0, 0, 0));
709}
710
711
712ATF_TEST_CASE_WITHOUT_HEAD(pop__one);
713ATF_TEST_CASE_BODY(pop__one)
714{
715    lutok::state state;
716    lua_pushinteger(raw(state), 10);
717    lua_pushinteger(raw(state), 20);
718    lua_pushinteger(raw(state), 30);
719    state.pop(1);
720    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
721    ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -1));
722    lua_pop(raw(state), 2);
723}
724
725
726ATF_TEST_CASE_WITHOUT_HEAD(pop__many);
727ATF_TEST_CASE_BODY(pop__many)
728{
729    lutok::state state;
730    lua_pushinteger(raw(state), 10);
731    lua_pushinteger(raw(state), 20);
732    lua_pushinteger(raw(state), 30);
733    state.pop(2);
734    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
735    ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -1));
736    lua_pop(raw(state), 1);
737}
738
739
740ATF_TEST_CASE_WITHOUT_HEAD(push_boolean);
741ATF_TEST_CASE_BODY(push_boolean)
742{
743    lutok::state state;
744    state.push_boolean(true);
745    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
746    ATF_REQUIRE(lua_toboolean(raw(state), -1));
747    state.push_boolean(false);
748    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
749    ATF_REQUIRE(!lua_toboolean(raw(state), -1));
750    ATF_REQUIRE(lua_toboolean(raw(state), -2));
751    lua_pop(raw(state), 2);
752}
753
754
755ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_closure);
756ATF_TEST_CASE_BODY(push_cxx_closure)
757{
758    lutok::state state;
759    state.push_integer(15);
760    state.push_cxx_closure(cxx_multiply_closure, 1);
761    lua_setglobal(raw(state), "cxx_multiply_closure");
762
763    ATF_REQUIRE(luaL_dostring(raw(state),
764                              "return cxx_multiply_closure(10)") == 0);
765    ATF_REQUIRE_EQ(150, lua_tointeger(raw(state), -1));
766    lua_pop(raw(state), 1);
767}
768
769
770ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__ok);
771ATF_TEST_CASE_BODY(push_cxx_function__ok)
772{
773    lutok::state state;
774    state.push_cxx_function(cxx_divide);
775    lua_setglobal(raw(state), "cxx_divide");
776
777    ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(17, 3)") == 0);
778    ATF_REQUIRE_EQ(5, lua_tointeger(raw(state), -2));
779    ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -1));
780    lua_pop(raw(state), 2);
781}
782
783
784ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_exception);
785ATF_TEST_CASE_BODY(push_cxx_function__fail_exception)
786{
787    lutok::state state;
788    state.push_cxx_function(cxx_divide);
789    lua_setglobal(raw(state), "cxx_divide");
790
791    ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(15, 0)") != 0);
792    ATF_REQUIRE_MATCH("Divisor is 0", lua_tostring(raw(state), -1));
793    lua_pop(raw(state), 1);
794}
795
796
797ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_anything);
798ATF_TEST_CASE_BODY(push_cxx_function__fail_anything)
799{
800    lutok::state state;
801    state.push_cxx_function(cxx_divide);
802    lua_setglobal(raw(state), "cxx_divide");
803
804    ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(-3, -1)") != 0);
805    ATF_REQUIRE_MATCH("Unhandled exception", lua_tostring(raw(state), -1));
806    lua_pop(raw(state), 1);
807}
808
809
810ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_overflow);
811ATF_TEST_CASE_BODY(push_cxx_function__fail_overflow)
812{
813    lutok::state state;
814    state.push_cxx_function(raise_long_error);
815    lua_setglobal(raw(state), "fail");
816
817    ATF_REQUIRE(luaL_dostring(raw(state), "return fail(900)") != 0);
818    ATF_REQUIRE_MATCH(std::string(900, 'A'), lua_tostring(raw(state), -1));
819    lua_pop(raw(state), 1);
820
821    ATF_REQUIRE(luaL_dostring(raw(state), "return fail(8192)") != 0);
822    ATF_REQUIRE_MATCH(std::string(900, 'A'), lua_tostring(raw(state), -1));
823    lua_pop(raw(state), 1);
824}
825
826
827ATF_TEST_CASE_WITHOUT_HEAD(push_integer);
828ATF_TEST_CASE_BODY(push_integer)
829{
830    lutok::state state;
831    state.push_integer(12);
832    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
833    ATF_REQUIRE_EQ(12, lua_tointeger(raw(state), -1));
834    state.push_integer(34);
835    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
836    ATF_REQUIRE_EQ(34, lua_tointeger(raw(state), -1));
837    ATF_REQUIRE_EQ(12, lua_tointeger(raw(state), -2));
838    lua_pop(raw(state), 2);
839}
840
841
842ATF_TEST_CASE_WITHOUT_HEAD(push_nil);
843ATF_TEST_CASE_BODY(push_nil)
844{
845    lutok::state state;
846    state.push_nil();
847    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
848    ATF_REQUIRE(lua_isnil(raw(state), -1));
849    state.push_integer(34);
850    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
851    ATF_REQUIRE(!lua_isnil(raw(state), -1));
852    ATF_REQUIRE(lua_isnil(raw(state), -2));
853    lua_pop(raw(state), 2);
854}
855
856
857ATF_TEST_CASE_WITHOUT_HEAD(push_string);
858ATF_TEST_CASE_BODY(push_string)
859{
860    lutok::state state;
861
862    {
863        std::string str = "first";
864        state.push_string(str);
865        ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
866        ATF_REQUIRE_EQ(std::string("first"), lua_tostring(raw(state), -1));
867        str = "second";
868        state.push_string(str);
869    }
870    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
871    ATF_REQUIRE_EQ(std::string("second"), lua_tostring(raw(state), -1));
872    ATF_REQUIRE_EQ(std::string("first"), lua_tostring(raw(state), -2));
873    lua_pop(raw(state), 2);
874}
875
876
877ATF_TEST_CASE_WITHOUT_HEAD(push_value);
878ATF_TEST_CASE_BODY(push_value)
879{
880    lutok::state state;
881
882    lua_pushinteger(raw(state), 10);
883    lua_pushinteger(raw(state), 20);
884    state.push_value(-2);
885    ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
886    ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -1));
887    ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -2));
888    ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -3));
889    lua_pop(raw(state), 3);
890}
891
892
893ATF_TEST_CASE_WITHOUT_HEAD(raw_get);
894ATF_TEST_CASE_BODY(raw_get)
895{
896    lutok::state state;
897
898    luaL_openlibs(raw(state));
899    ATF_REQUIRE(luaL_dostring(
900        raw(state), "t = {foo=123} ; setmetatable(t, {__index=1})") == 0);
901    lua_getglobal(raw(state), "t");
902    lua_pushinteger(raw(state), 9876);
903    lua_pushstring(raw(state), "foo");
904    state.raw_get(-3);
905    ATF_REQUIRE(lua_isnumber(raw(state), -1));
906    ATF_REQUIRE_EQ(123, lua_tointeger(raw(state), -1));
907    ATF_REQUIRE_EQ(9876, lua_tointeger(raw(state), -2));
908    lua_pop(raw(state), 3);
909}
910
911
912ATF_TEST_CASE_WITHOUT_HEAD(raw_set);
913ATF_TEST_CASE_BODY(raw_set)
914{
915    lutok::state state;
916
917    luaL_openlibs(raw(state));
918    ATF_REQUIRE(luaL_dostring(
919        raw(state), "t = {} ; setmetatable(t, {__newindex=1})") == 0);
920    lua_getglobal(raw(state), "t");
921    lua_pushinteger(raw(state), 876);
922    lua_pushstring(raw(state), "foo");
923    lua_pushinteger(raw(state), 345);
924    state.raw_set(-4);
925    ATF_REQUIRE(luaL_dostring(raw(state), "return t.foo") == 0);
926    ATF_REQUIRE(lua_isnumber(raw(state), -1));
927    ATF_REQUIRE_EQ(345, lua_tointeger(raw(state), -1));
928    ATF_REQUIRE_EQ(876, lua_tointeger(raw(state), -2));
929    lua_pop(raw(state), 3);
930}
931
932
933ATF_TEST_CASE_WITHOUT_HEAD(registry_index);
934ATF_TEST_CASE_BODY(registry_index)
935{
936    lutok::state state;
937    lua_pushvalue(raw(state), lutok::registry_index);
938    lua_pushstring(raw(state), "custom_variable");
939    lua_pushstring(raw(state), "custom value");
940    lua_settable(raw(state), -3);
941    lua_pop(raw(state), 1);
942    ATF_REQUIRE(luaL_dostring(raw(state),
943                              "return custom_variable == nil") == 0);
944    ATF_REQUIRE(lua_isboolean(raw(state), -1));
945    ATF_REQUIRE(lua_toboolean(raw(state), -1));
946    lua_pop(raw(state), 1);
947}
948
949
950ATF_TEST_CASE_WITHOUT_HEAD(set_global);
951ATF_TEST_CASE_BODY(set_global)
952{
953    lutok::state state;
954    lua_pushinteger(raw(state), 3);
955    state.set_global("test_variable");
956    ATF_REQUIRE(luaL_dostring(raw(state), "return test_variable + 1") == 0);
957    ATF_REQUIRE(lua_isnumber(raw(state), -1));
958    ATF_REQUIRE_EQ(4, lua_tointeger(raw(state), -1));
959    lua_pop(raw(state), 1);
960}
961
962
963ATF_TEST_CASE_WITHOUT_HEAD(set_metatable);
964ATF_TEST_CASE_BODY(set_metatable)
965{
966    lutok::state state;
967    ATF_REQUIRE(luaL_dostring(
968        raw(state),
969        "mt = {}\n"
970        "mt.__add = function(a, b) return a[1] + b end\n"
971        "numbers = {}\n"
972        "numbers[1] = 5\n") == 0);
973
974    lua_getglobal(raw(state), "numbers");
975    lua_pushinteger(raw(state), 1234);
976    lua_getglobal(raw(state), "mt");
977    state.set_metatable(-3);
978    lua_pop(raw(state), 2);
979
980    ATF_REQUIRE(luaL_dostring(raw(state), "return numbers + 2") == 0);
981    ATF_REQUIRE(lua_isnumber(raw(state), -1));
982    ATF_REQUIRE_EQ(7, lua_tointeger(raw(state), -1));
983    lua_pop(raw(state), 1);
984}
985
986
987ATF_TEST_CASE_WITHOUT_HEAD(set_table__ok);
988ATF_TEST_CASE_BODY(set_table__ok)
989{
990    lutok::state state;
991    ATF_REQUIRE(luaL_dostring(raw(state), "t = { a = 1, bar = 234 }") == 0);
992    lua_getglobal(raw(state), "t");
993
994    lua_pushstring(raw(state), "bar");
995    lua_pushstring(raw(state), "baz");
996    state.set_table(-3);
997    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
998
999    lua_pushstring(raw(state), "a");
1000    lua_gettable(raw(state), -2);
1001    ATF_REQUIRE(lua_isnumber(raw(state), -1));
1002    ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -1));
1003    lua_pop(raw(state), 1);
1004
1005    lua_pushstring(raw(state), "bar");
1006    lua_gettable(raw(state), -2);
1007    ATF_REQUIRE(lua_isstring(raw(state), -1));
1008    ATF_REQUIRE_EQ(std::string("baz"), lua_tostring(raw(state), -1));
1009    lua_pop(raw(state), 1);
1010
1011    lua_pop(raw(state), 1);
1012}
1013
1014
1015ATF_TEST_CASE_WITHOUT_HEAD(set_table__nil);
1016ATF_TEST_CASE_BODY(set_table__nil)
1017{
1018    lutok::state state;
1019    lua_pushnil(raw(state));
1020    lua_pushinteger(raw(state), 1);
1021    lua_pushinteger(raw(state), 2);
1022    REQUIRE_API_ERROR("lua_settable", state.set_table(-3));
1023    lua_pop(raw(state), 3);
1024}
1025
1026
1027ATF_TEST_CASE_WITHOUT_HEAD(to_boolean);
1028ATF_TEST_CASE_BODY(to_boolean)
1029{
1030    lutok::state state;
1031    lua_pushboolean(raw(state), 0);
1032    lua_pushboolean(raw(state), 1);
1033    ATF_REQUIRE(!state.to_boolean(-2));
1034    ATF_REQUIRE(state.to_boolean(-1));
1035    lua_pop(raw(state), 2);
1036}
1037
1038
1039ATF_TEST_CASE_WITHOUT_HEAD(to_integer);
1040ATF_TEST_CASE_BODY(to_integer)
1041{
1042    lutok::state state;
1043    lua_pushinteger(raw(state), 12);
1044    lua_pushstring(raw(state), "foobar");
1045    ATF_REQUIRE_EQ(12, state.to_integer(-2));
1046    lua_pop(raw(state), 2);
1047}
1048
1049
1050ATF_TEST_CASE_WITHOUT_HEAD(to_string);
1051ATF_TEST_CASE_BODY(to_string)
1052{
1053    lutok::state state;
1054    lua_pushstring(raw(state), "foobar");
1055    lua_pushinteger(raw(state), 12);
1056    ATF_REQUIRE_EQ("foobar", state.to_string(-2));
1057    ATF_REQUIRE_EQ("12", state.to_string(-1));
1058    lua_pop(raw(state), 2);
1059}
1060
1061
1062ATF_TEST_CASE_WITHOUT_HEAD(to_userdata);
1063ATF_TEST_CASE_BODY(to_userdata)
1064{
1065    lutok::state state;
1066    {
1067        int* pointer = static_cast< int* >(
1068            lua_newuserdata(raw(state), sizeof(int)));
1069        *pointer = 987;
1070    }
1071
1072    lua_pushinteger(raw(state), 3);
1073    int* pointer = state.to_userdata< int >(-2);
1074    ATF_REQUIRE_EQ(987, *pointer);
1075    lua_pop(raw(state), 2);
1076}
1077
1078
1079ATF_TEST_CASE_WITHOUT_HEAD(upvalue_index);
1080ATF_TEST_CASE_BODY(upvalue_index)
1081{
1082    lutok::state state;
1083    lua_pushinteger(raw(state), 25);
1084    lua_pushinteger(raw(state), 30);
1085    lua_pushcclosure(raw(state), c_get_upvalues, 2);
1086    lua_setglobal(raw(state), "c_get_upvalues");
1087
1088    ATF_REQUIRE(luaL_dostring(raw(state),
1089                              "return c_get_upvalues()") == 0);
1090    ATF_REQUIRE_EQ(25, lua_tointeger(raw(state), -2));
1091    ATF_REQUIRE_EQ(30, lua_tointeger(raw(state), -1));
1092    lua_pop(raw(state), 2);
1093}
1094
1095
1096ATF_INIT_TEST_CASES(tcs)
1097{
1098    ATF_ADD_TEST_CASE(tcs, close);
1099    ATF_ADD_TEST_CASE(tcs, get_global__ok);
1100    ATF_ADD_TEST_CASE(tcs, get_global__undefined);
1101    ATF_ADD_TEST_CASE(tcs, get_global_table);
1102    ATF_ADD_TEST_CASE(tcs, get_metafield__ok);
1103    ATF_ADD_TEST_CASE(tcs, get_metafield__undefined);
1104    ATF_ADD_TEST_CASE(tcs, get_metatable__ok);
1105    ATF_ADD_TEST_CASE(tcs, get_metatable__undefined);
1106    ATF_ADD_TEST_CASE(tcs, get_table__ok);
1107    ATF_ADD_TEST_CASE(tcs, get_table__nil);
1108    ATF_ADD_TEST_CASE(tcs, get_table__unknown_index);
1109    ATF_ADD_TEST_CASE(tcs, get_top);
1110    ATF_ADD_TEST_CASE(tcs, insert);
1111    ATF_ADD_TEST_CASE(tcs, is_boolean__empty);
1112    ATF_ADD_TEST_CASE(tcs, is_boolean__ok);
1113    ATF_ADD_TEST_CASE(tcs, is_function__empty);
1114    ATF_ADD_TEST_CASE(tcs, is_function__ok);
1115    ATF_ADD_TEST_CASE(tcs, is_nil__empty);
1116    ATF_ADD_TEST_CASE(tcs, is_nil__ok);
1117    ATF_ADD_TEST_CASE(tcs, is_number__empty);
1118    ATF_ADD_TEST_CASE(tcs, is_number__ok);
1119    ATF_ADD_TEST_CASE(tcs, is_string__empty);
1120    ATF_ADD_TEST_CASE(tcs, is_string__ok);
1121    ATF_ADD_TEST_CASE(tcs, is_table__empty);
1122    ATF_ADD_TEST_CASE(tcs, is_table__ok);
1123    ATF_ADD_TEST_CASE(tcs, is_userdata__empty);
1124    ATF_ADD_TEST_CASE(tcs, is_userdata__ok);
1125    ATF_ADD_TEST_CASE(tcs, load_file__ok);
1126    ATF_ADD_TEST_CASE(tcs, load_file__api_error);
1127    ATF_ADD_TEST_CASE(tcs, load_file__file_not_found_error);
1128    ATF_ADD_TEST_CASE(tcs, load_string__ok);
1129    ATF_ADD_TEST_CASE(tcs, load_string__fail);
1130    ATF_ADD_TEST_CASE(tcs, new_table);
1131    ATF_ADD_TEST_CASE(tcs, new_userdata);
1132    ATF_ADD_TEST_CASE(tcs, next__empty);
1133    ATF_ADD_TEST_CASE(tcs, next__many);
1134    ATF_ADD_TEST_CASE(tcs, open_all);
1135    ATF_ADD_TEST_CASE(tcs, open_base);
1136    ATF_ADD_TEST_CASE(tcs, open_string);
1137    ATF_ADD_TEST_CASE(tcs, open_table);
1138    ATF_ADD_TEST_CASE(tcs, pcall__ok);
1139    ATF_ADD_TEST_CASE(tcs, pcall__fail);
1140    ATF_ADD_TEST_CASE(tcs, pop__one);
1141    ATF_ADD_TEST_CASE(tcs, pop__many);
1142    ATF_ADD_TEST_CASE(tcs, push_boolean);
1143    ATF_ADD_TEST_CASE(tcs, push_cxx_closure);
1144    ATF_ADD_TEST_CASE(tcs, push_cxx_function__ok);
1145    ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_exception);
1146    ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_anything);
1147    ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_overflow);
1148    ATF_ADD_TEST_CASE(tcs, push_integer);
1149    ATF_ADD_TEST_CASE(tcs, push_nil);
1150    ATF_ADD_TEST_CASE(tcs, push_string);
1151    ATF_ADD_TEST_CASE(tcs, push_value);
1152    ATF_ADD_TEST_CASE(tcs, raw_get);
1153    ATF_ADD_TEST_CASE(tcs, raw_set);
1154    ATF_ADD_TEST_CASE(tcs, registry_index);
1155    ATF_ADD_TEST_CASE(tcs, set_global);
1156    ATF_ADD_TEST_CASE(tcs, set_metatable);
1157    ATF_ADD_TEST_CASE(tcs, set_table__ok);
1158    ATF_ADD_TEST_CASE(tcs, set_table__nil);
1159    ATF_ADD_TEST_CASE(tcs, to_boolean);
1160    ATF_ADD_TEST_CASE(tcs, to_integer);
1161    ATF_ADD_TEST_CASE(tcs, to_string);
1162    ATF_ADD_TEST_CASE(tcs, to_userdata);
1163    ATF_ADD_TEST_CASE(tcs, upvalue_index);
1164}
1165