xLua - Lua C++ API

Check-in [14a84d3be5]
Login
Overview
Comment:xlua
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | master | trunk
Files: files | file ages | folders
SHA3-256:14a84d3be54d05edb1f1a199391b0bc59fc1ed9f0379c65748013fa509d8fc03
User & Date: xjail 2018-07-04 21:16:22
Context
2018-07-05
21:11
xlua check-in: 9ebeabe199 user: xjail tags: master, trunk
2018-07-04
21:16
xlua check-in: 14a84d3be5 user: xjail tags: master, trunk
01:55
xLua check-in: bb690c0ec0 user: xjail tags: master, trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Deleted Doxyfile.in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Copyright 2010 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
# * Neither the name of Google Inc. nor the names of its contributors
#   may be used to endorse or promote products derived from this software
#   without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

BUILTIN_STL_SUPPORT = YES
ENABLE_PREPROCESSING = YES
EXTRACT_ANON_NSPACES = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
EXPAND_ONLY_PREDEF = YES
FILE_PATTERNS = *.cpp *.hpp *.ipp
GENERATE_LATEX = NO
GENERATE_TAGFILE = @top_builddir@/api-docs/api-docs.tag
INPUT = @top_srcdir@
INPUT_ENCODING = ISO-8859-1
JAVADOC_AUTOBRIEF = YES
MACRO_EXPANSION = YES
OUTPUT_DIRECTORY = @top_builddir@/api-docs
OUTPUT_LANGUAGE = English
PREDEFINED = "UTILS_UNUSED_PARAM(name)=unused_ ## name"
PROJECT_NAME = "@PACKAGE_NAME@"
PROJECT_NUMBER = @VERSION@
QUIET = YES
RECURSIVE = NO
SHORT_NAMES = YES  # Cope with gnutar limitations during 'make dist'.
SORT_BY_SCOPE_NAME = YES
SORT_MEMBERS_CTORS_1ST = YES
WARN_NO_PARAMDOC = YES
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































Deleted INSTALL.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
Introduction
============

Lutok uses the GNU Automake, GNU Autoconf and GNU Libtool utilities as
its build system.  These are used only when compiling the library from
the source code package.  If you want to install Lutok from a binary
package, you do not need to read this document.

For the impatient:

    $ ./configure
    $ make
    $ make check
    Gain root privileges
    # make install
    Drop root privileges
    $ make installcheck

Or alternatively, install as a regular user into your home directory:

    $ ./configure --prefix ~/local
    $ make
    $ make check
    $ make install
    $ make installcheck


Dependencies
============

To build and use Lutok successfully you need:

* A standards-compliant C++ complier.
* Lua 5.1 or greater.
* pkg-config.

Optionally, if you want to build and run the tests (recommended), you
need:

* Kyua 0.5 or greater.
* ATF 0.15 or greater.

If you are building Lutok from the code on the repository, you will also
need the following tools:

* GNU Autoconf.
* GNU Automake.
* GNU Libtool.


Regenerating the build system
=============================

This is not necessary if you are building from a formal release
distribution file.

On the other hand, if you are building Lutok from code extracted from
the repository, you must first regenerate the files used by the build
system.  You will also need to do this if you modify configure.ac,
Makefile.am or any of the other build system files.  To do this, simply
run:

    $ autoreconf -i -s

If ATF is installed in a different prefix than Autoconf, you will also
need to tell autoreconf where the ATF M4 macros are located.  Otherwise,
the configure script will be incomplete and will show confusing syntax
errors mentioning, for example, ATF_CHECK_SH.  To fix this, you have
to run autoreconf in the following manner, replacing '<atf-prefix>' with
the appropriate path:

    $ autoreconf -i -s -I <atf-prefix>/share/aclocal


General build procedure
=======================

To build and install the source package, you must follow these steps:

1. Configure the sources to adapt to your operating system.  This is
   done using the 'configure' script located on the sources' top
   directory, and it is usually invoked without arguments unless you
   want to change the installation prefix.  More details on this
   procedure are given on a later section.

2. Build the sources to generate the binaries and scripts.  Simply run
   'make' on the sources' top directory after configuring them.  No
   problems should arise.

3. Install the library by running 'make install'.  You may need to
   become root to issue this step.

4. Issue any manual installation steps that may be required.  These are
   described later in their own section.

5. Check that the installed library works by running 'make
   installcheck'.  You do not need to be root to do this.


Configuration flags
===================

The most common, standard flags given to 'configure' are:

* --prefix=directory
  Possible values: Any path
  Default: /usr/local

  Specifies where the library (binaries and all associated files) will
  be installed.

* --help
  Shows information about all available flags and exits immediately,
  without running any configuration tasks.

The following flags are specific to Lutok's 'configure' script:

* --enable-developer
  Possible values: yes, no
  Default: 'yes' in Git HEAD builds; 'no' in formal releases.

  Enables several features useful for development, such as the inclusion
  of debugging symbols in all objects or the enforcement of compilation
  warnings.

  The compiler will be executed with an exhaustive collection of warning
  detection features regardless of the value of this flag.  However, such
  warnings are only fatal when --enable-developer is 'yes'.

* --with-atf
  Possible values: yes, no, auto.
  Default: auto.

  Enables usage of ATF to build (and later install) the tests.

  Setting this to 'yes' causes the configure script to look for ATF
  unconditionally and abort if not found.  Setting this to 'auto' lets
  configure perform the best decision based on availability of ATF.
  Setting this to 'no' explicitly disables ATF usage.

  When support for tests is enabled, the build process will generate the
  test programs and will later install them into the tests tree.
  Running 'make check' or 'make installcheck' from within the source
  directory will cause these tests to be run with Kyua (assuming it is
  also installed).

* --with-doxygen
  Possible values: yes, no, auto or a path.
  Default: auto.

  Enables usage of Doxygen to generate documentation for internal APIs.

  Setting this to 'yes' causes the configure script to look for Doxygen
  unconditionally and abort if not found.  Setting this to 'auto' lets
  configure perform the best decision based on availability of Doxygen.
  Setting this to 'no' explicitly disables Doxygen usage.  And, lastly,
  setting this to a path forces configure to use a specific Doxygen
  binary, which must exist.

  When support for Doxygen is enabled, the build process will generate
  HTML documentation for the Lutok API.  This documentation will later
  be installed in the HTML directory specified by the configure script.
  You can change the location of the HTML documents by providing your
  desired override with the '--htmldir' flag to the configure script.


Run the tests!
==============

Lastly, after a successful installation (and assuming you built the
sources with support for ATF), you should periodically run the tests
from the final location to ensure things remain stable.  Do so as
follows:

    $ kyua test -k /usr/local/tests/lutok/Kyuafile

And if you see any tests fail, do not hesitate to report them in:

    https://github.com/jmmv/lutok/issues/

Thank you!
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































































































































































































































































































Deleted Kyuafile.

1
2
3
4
5
6
7
8
9
10
11
syntax("kyuafile", 1)

test_suite("lutok")

atf_test_program{name="c_gate_test"}
atf_test_program{name="debug_test"}
atf_test_program{name="examples_test"}
atf_test_program{name="exceptions_test"}
atf_test_program{name="operations_test"}
atf_test_program{name="stack_cleaner_test"}
atf_test_program{name="state_test"}
<
<
<
<
<
<
<
<
<
<
<






















Deleted Makefile.am.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# Copyright 2010 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
# * Neither the name of Google Inc. nor the names of its contributors
#   may be used to endorse or promote products derived from this software
#   without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

ACLOCAL_AMFLAGS = -I m4

doc_DATA = AUTHORS COPYING NEWS README
noinst_DATA = INSTALL README
EXTRA_DIST = $(doc_DATA) INSTALL README

LUTOK_CFLAGS = -I$(srcdir)/include $(LUA_CFLAGS)
LUTOK_LIBS = liblutok.la $(LUA_LIBS)

pkginclude_HEADERS  = c_gate.hpp
pkginclude_HEADERS += debug.hpp
pkginclude_HEADERS += exceptions.hpp
pkginclude_HEADERS += operations.hpp
pkginclude_HEADERS += stack_cleaner.hpp
pkginclude_HEADERS += state.hpp
pkginclude_HEADERS += state.ipp
pkginclude_HEADERS += test_utils.hpp

EXTRA_DIST += include/lutok/README
EXTRA_DIST += include/lutok/c_gate.hpp
EXTRA_DIST += include/lutok/debug.hpp
EXTRA_DIST += include/lutok/exceptions.hpp
EXTRA_DIST += include/lutok/operations.hpp
EXTRA_DIST += include/lutok/stack_cleaner.hpp
EXTRA_DIST += include/lutok/state.hpp
EXTRA_DIST += include/lutok/state.ipp

lib_LTLIBRARIES = liblutok.la
liblutok_la_SOURCES  = c_gate.cpp
liblutok_la_SOURCES += c_gate.hpp
liblutok_la_SOURCES += debug.cpp
liblutok_la_SOURCES += debug.hpp
liblutok_la_SOURCES += exceptions.cpp
liblutok_la_SOURCES += exceptions.hpp
liblutok_la_SOURCES += operations.cpp
liblutok_la_SOURCES += operations.hpp
liblutok_la_SOURCES += stack_cleaner.cpp
liblutok_la_SOURCES += stack_cleaner.hpp
liblutok_la_SOURCES += state.cpp
liblutok_la_SOURCES += state.hpp
liblutok_la_SOURCES += state.ipp
liblutok_la_SOURCES += test_utils.hpp
liblutok_la_CPPFLAGS = $(LUTOK_CFLAGS)
liblutok_la_LDFLAGS = -version-info 3:0:0
liblutok_la_LIBADD = $(LUA_LIBS)

pkgconfig_DATA = lutok.pc
CLEANFILES = lutok.pc
EXTRA_DIST += lutok.pc.in
lutok.pc: $(srcdir)/lutok.pc.in Makefile
	$(AM_V_GEN)sed -e 's#__INCLUDEDIR__#$(includedir)#g' \
	    -e 's#__LIBDIR__#$(libdir)#g' \
	    -e 's#__LUA_CFLAGS__#$(LUA_CFLAGS)#g' \
	    -e 's#__LUA_LIBS__#$(LUA_LIBS)#g' \
	    -e 's#__VERSION__#$(PACKAGE_VERSION)#g' \
	    <$(srcdir)/lutok.pc.in >lutok.pc.tmp; \
	mv lutok.pc.tmp lutok.pc

CLEAN_TARGETS =
DIST_HOOKS =
PHONY_TARGETS =

examplesdir = $(docdir)/examples
examples_DATA  = examples/Makefile
examples_DATA += examples/bindings.cpp
examples_DATA += examples/hello.cpp
examples_DATA += examples/interpreter.cpp
examples_DATA += examples/raii.cpp
EXTRA_DIST += $(examples_DATA)

if WITH_ATF
tests_DATA = Kyuafile
EXTRA_DIST += $(tests_DATA)

tests_PROGRAMS = c_gate_test
c_gate_test_SOURCES = c_gate_test.cpp test_utils.hpp
c_gate_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS)
c_gate_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS)

tests_PROGRAMS += debug_test
debug_test_SOURCES = debug_test.cpp test_utils.hpp
debug_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS)
debug_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS)

tests_SCRIPTS = examples_test
CLEANFILES += examples_test
EXTRA_DIST += examples_test.sh
examples_test: $(srcdir)/examples_test.sh
	$(AM_V_GEN)sed -e 's,__ATF_SH__,$(ATF_SH),g' \
	    -e 's,__CXX__,$(CXX),g' \
	    -e 's,__EXAMPLESDIR__,$(examplesdir),g' \
	    -e 's,__LIBDIR__,$(libdir),g' \
	    <$(srcdir)/examples_test.sh >examples_test.tmp; \
	chmod +x examples_test.tmp; \
	rm -f examples_test; \
	mv examples_test.tmp examples_test

tests_PROGRAMS += exceptions_test
exceptions_test_SOURCES = exceptions_test.cpp
exceptions_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS)
exceptions_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS)

tests_PROGRAMS += operations_test
operations_test_SOURCES = operations_test.cpp test_utils.hpp
operations_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS)
operations_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS)

tests_PROGRAMS += stack_cleaner_test
stack_cleaner_test_SOURCES = stack_cleaner_test.cpp test_utils.hpp
stack_cleaner_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS)
stack_cleaner_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS)

tests_PROGRAMS += state_test
state_test_SOURCES = state_test.cpp test_utils.hpp
state_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS)
state_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS)

if HAVE_KYUA
check-local: check-kyua
PHONY_TARGETS += check-kyua
check-kyua:
	$(TESTS_ENVIRONMENT) kyua test \
	    --kyuafile='$(top_srcdir)/Kyuafile' --build-root='$(top_builddir)'

installcheck-local: installcheck-kyua
PHONY_TARGETS += installcheck-kyua
installcheck-kyua:
	cd $(testsdir) && $(TESTS_ENVIRONMENT) kyua test
endif
else
DIST_HOOKS += dist-no-atf
PHONY_TARGETS += dist-no-atf
dist-no-atf:
	@echo "Sorry; cannot build a distfile without atf"
	@false
endif

if WITH_DOXYGEN
# This should probably be html-local, but it seems better to generate the
# documentation in all cases to get warnings about missing documentation every
# time the code is modified.  (And, after all, the documentation is not
# installed so generating it unconditionally is not a big problem.)
all-local: api-docs/api-docs.tag

api-docs/api-docs.tag: $(builddir)/Doxyfile $(SOURCES)
	$(AM_V_GEN)rm -rf api-docs; \
	mkdir -p api-docs; \
	${DOXYGEN} $(builddir)/Doxyfile 2>&1 | tee api-docs/warnings; \
	rm -f api-docs/html/installdox
api-docs/html: api-docs/api-docs.tag

CLEAN_TARGETS += clean-api-docs
clean-api-docs:
	rm -rf api-docs

EXTRA_DIST += api-docs/html
else
DIST_HOOKS += dist-no-doxygen
PHONY_TARGETS += dist-no-doxygen
dist-no-doxygen:
	@echo "Sorry; cannot build a distfile without Doxygen"
	@false
endif

install-data-local: install-api-docs
install-api-docs: install-docDATA
	@echo "Installing HTML documentation into $(DESTDIR)$(htmldir)"
	@if [ -d api-docs/html ]; then \
	    test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)"; \
	    ( cd api-docs/html && tar cf - . ) | \
                ( cd "$(DESTDIR)$(htmldir)" && tar xf - ); \
	elif [ -d "$(srcdir)/api-docs/html" ]; then \
	    test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)"; \
	    ( cd "$(srcdir)/api-docs/html" && tar cf - . ) | \
                ( cd "$(DESTDIR)$(htmldir)" && tar xf - ); \
	else \
	    echo "Doxygen not installed and prebuilt documents not found"; \
	fi

uninstall-local: uninstall-api-docs
uninstall-api-docs:
	find "$(DESTDIR)$(htmldir)" -type d -exec chmod 755 {} \;
	rm -rf "$(DESTDIR)$(htmldir)"

clean-local: $(CLEAN_TARGETS)

PHONY_TARGETS += clean-all
clean-all:
	GIT="$(GIT)" $(SH) $(srcdir)/admin/clean-all.sh

dist-hook: $(DIST_HOOKS)

.PHONY: ${PHONY_TARGETS}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































































































































































































































































































































































Deleted admin/.gitignore.

1
2
3
4
5
6
7
8
ar-lib
compile
config.guess
config.sub
depcomp
install-sh
ltmain.sh
missing
<
<
<
<
<
<
<
<
















Deleted admin/clean-all.sh.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#! /bin/sh
# Copyright 2010 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
# * Neither the name of Google Inc. nor the names of its contributors
#   may be used to endorse or promote products derived from this software
#   without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Prog_Name=${0##*/}

if [ ! -f ./state.hpp ]; then
    echo "${Prog_Name}: must be run from the source top directory" 1>&2
    exit 1
fi

if [ ! -f configure ]; then
    echo "${Prog_Name}: configure not found; nothing to clean?" 1>&2
    exit 1
fi

[ -f Makefile ] || ./configure
make distclean

# Top-level directory.
rm -f Makefile.in
rm -f aclocal.m4
rm -rf autom4te.cache
rm -f config.h.in
rm -f configure
rm -f mkinstalldirs
rm -f lutok-*.tar.gz

# admin directory.
rm -f admin/compile
rm -f admin/config.guess
rm -f admin/config.sub
rm -f admin/depcomp
rm -f admin/install-sh
rm -f admin/ltmain.sh
rm -f admin/mdate-sh
rm -f admin/missing
rm -f admin/texinfo.tex

# bootstrap directory.
rm -f bootstrap/package.m4
rm -f bootstrap/testsuite

# doc directory.
rm -f doc/*.info
rm -f doc/stamp-vti
rm -f doc/version.texi

# m4 directory.
rm -f m4/libtool.m4
rm -f m4/lt*.m4

# Files and directories spread all around the tree.
find . -name '#*' | xargs rm -rf
find . -name '*~' | xargs rm -rf
find . -name .deps | xargs rm -rf
find . -name .gdb_history | xargs rm -rf
find . -name .libs | xargs rm -rf
find . -name .tmp | xargs rm -rf

# Show remaining files.
if [ -n "${GIT}" ]; then
    echo ">>> untracked and ignored files"
    "${GIT}" status --porcelain --ignored | grep -E '^(\?\?|!!)' || true
fi
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































































































































Deleted admin/travis-build.sh.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#! /bin/sh
# Copyright 2014 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
# * Neither the name of Google Inc. nor the names of its contributors
#   may be used to endorse or promote products derived from this software
#   without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

set -e -x

if [ -d /usr/local/share/aclocal ]; then
    autoreconf -isv -I/usr/local/share/aclocal
else
    autoreconf -isv
fi
./configure

archflags=
[ "${ARCH?}" != i386 ] || archflags=-m32

f=
f="${f} CPPFLAGS='-I/usr/local/include'"
f="${f} CXX='${CXX} ${archflags}'"
f="${f} LDFLAGS='-L/usr/local/lib -Wl,-R/usr/local/lib'"
f="${f} PKG_CONFIG_PATH='/usr/local/lib/pkgconfig'"
if [ "${AS_ROOT:-no}" = yes ]; then
    sudo -H PATH="${PATH}" make distcheck DISTCHECK_CONFIGURE_FLAGS="${f}"
else
    make distcheck DISTCHECK_CONFIGURE_FLAGS="${f}"
fi
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































































Deleted admin/travis-install-deps.sh.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#! /bin/sh
# Copyright 2014 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
# * Neither the name of Google Inc. nor the names of its contributors
#   may be used to endorse or promote products derived from this software
#   without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

set -e -x

install_deps() {
    sudo apt-get update -qq

    local pkgsuffix=
    local packages=
    if [ "${ARCH?}" = i386 ]; then
         pkgsuffix=:i386
         packages="${packages} gcc-multilib"
         packages="${packages} g++-multilib"
    fi
    packages="${packages} doxygen"
    packages="${packages} gdb"
    packages="${packages} liblua5.2-0${pkgsuffix}"
    packages="${packages} liblua5.2-dev${pkgsuffix}"
    packages="${packages} libsqlite3-0${pkgsuffix}"
    packages="${packages} libsqlite3-dev${pkgsuffix}"
    packages="${packages} pkg-config${pkgsuffix}"
    packages="${packages} sqlite3"
    sudo apt-get install -y ${packages}
}

install_from_github() {
    local project="${1}"; shift
    local name="${1}"; shift
    local release="${1}"; shift

    local distname="${name}-${release}"

    local baseurl="https://github.com/jmmv/${project}"
    wget --no-check-certificate \
        "${baseurl}/releases/download/${distname}/${distname}.tar.gz"
    tar -xzvf "${distname}.tar.gz"

    local archflags=
    [ "${ARCH?}" != i386 ] || archflags=-m32

    cd "${distname}"
    ./configure \
        --disable-developer \
        --without-atf \
        --without-doxygen \
        CFLAGS="${archflags}" \
        CPPFLAGS="-I/usr/local/include" \
        CXXFLAGS="${archflags}" \
        LDFLAGS="-L/usr/local/lib -Wl,-R/usr/local/lib" \
        PKG_CONFIG_PATH="/usr/local/lib/pkgconfig"
    make
    sudo make install
    cd -

    rm -rf "${distname}" "${distname}.tar.gz"
}

install_from_bintray() {
    case "${ARCH?}" in
        amd64)
            name="20160204-usr-local-kyua-ubuntu-12-04-amd64-${CC?}.tar.gz"
            ;;
        i386)
            name="20160714-usr-local-kyua-ubuntu-12-04-i386-${CC?}.tar.gz"
            ;;
        *)
            echo "ERROR: Unknown ARCH value ${ARCH}" 1>&2
            exit 1
            ;;
    esac
    wget "http://dl.bintray.com/jmmv/kyua/${name}" || return 1
    sudo tar -xzvp -C / -f "${name}"
    rm -f "${name}"
}

install_deps
if ! install_from_bintray; then
    install_from_github atf atf 0.20
    install_from_github lutok lutok 0.4
    install_from_github kyua kyua-testers 0.2
    install_from_github kyua kyua-cli 0.8
fi
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































































































































Deleted c_gate.hpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file c_gate.hpp
/// Provides direct access to the C state of the Lua wrappers.

#if !defined(LUTOK_C_GATE_HPP)
#define LUTOK_C_GATE_HPP

#include <lua.hpp>

namespace lutok {


class state;


/// Gateway to the raw C state of Lua.
///
/// This class provides a mechanism to muck with the internals of the state
/// wrapper class.  Client code may wish to do so if Lutok is missing some
/// features of the performance of Lutok in a particular situation is not
/// reasonable.
///
/// \warning The use of this class is discouraged.  By using this class, you are
/// entering the world of unsafety.  Anything you do through the objects exposed
/// through this class will not be controlled by RAII patterns not validated in
/// any other way, so you can end up corrupting the Lua state and later get
/// crashes on otherwise perfectly-valid C++ code.
class state_c_gate {
    /// The C++ state that this class wraps.
    state& _state;

public:
    state_c_gate(state&);
    ~state_c_gate(void);

    static state connect(lua_State*);

    lua_State* c_state(void);
};


}  // namespace lutok

#endif  // !defined(LUTOK_C_GATE_HPP)
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














































































































































Deleted c_gate_test.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "c_gate.hpp"

#include <atf-c++.hpp>
#include <lua.hpp>

#include "state.ipp"
#include "test_utils.hpp"


ATF_TEST_CASE_WITHOUT_HEAD(connect);
ATF_TEST_CASE_BODY(connect)
{
    lua_State* raw_state = luaL_newstate();
    ATF_REQUIRE(raw_state != NULL);

    {
        lutok::state state = lutok::state_c_gate::connect(raw_state);
        lua_pushinteger(raw(state), 123);
    }
    // If the wrapper object had closed the Lua state, we could very well crash
    // here.
    ATF_REQUIRE_EQ(123, lua_tointeger(raw_state, -1));

    lua_close(raw_state);
}


ATF_TEST_CASE_WITHOUT_HEAD(c_state);
ATF_TEST_CASE_BODY(c_state)
{
    lutok::state state;
    state.push_integer(5);
    {
        lutok::state_c_gate gate(state);
        lua_State* raw_state = gate.c_state();
        ATF_REQUIRE_EQ(5, lua_tointeger(raw_state, -1));
    }
    state.pop(1);
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, c_state);
    ATF_ADD_TEST_CASE(tcs, connect);
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































































































Deleted configure.ac.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
dnl Copyright 2011 Google Inc.
dnl All rights reserved.
dnl
dnl Redistribution and use in source and binary forms, with or without
dnl modification, are permitted provided that the following conditions are
dnl met:
dnl
dnl * Redistributions of source code must retain the above copyright
dnl   notice, this list of conditions and the following disclaimer.
dnl * Redistributions in binary form must reproduce the above copyright
dnl   notice, this list of conditions and the following disclaimer in the
dnl   documentation and/or other materials provided with the distribution.
dnl * Neither the name of Google Inc. nor the names of its contributors
dnl   may be used to endorse or promote products derived from this software
dnl   without specific prior written permission.
dnl
dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

AC_INIT([Lutok], [0.4],
        [lutok-discuss@googlegroups.com], [lutok],
        [https://github.com/jmmv/lutok/])
AC_PREREQ([2.65])


AC_COPYRIGHT([Copyright 2011 Google Inc.])
AC_CONFIG_AUX_DIR([admin])
AC_CONFIG_FILES([Doxyfile Makefile])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([state.hpp])


AM_INIT_AUTOMAKE([1.9 check-news foreign subdir-objects -Wall])
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
LT_INIT


AC_LANG([C++])
AC_PROG_CXX
KYUA_REQUIRE_CXX
KYUA_DEVELOPER_MODE([C++])


ATF_CHECK_CXX([>= 0.15])
ATF_CHECK_SH([>= 0.15])
ATF_ARG_WITH
KYUA_DOXYGEN
KYUA_LUA


AC_PATH_PROG([KYUA], [kyua])
AM_CONDITIONAL([HAVE_KYUA], [test -n "${KYUA}"])
AC_PATH_PROG([GIT], [git])


AC_SUBST(pkgconfigdir, \${libdir}/pkgconfig)
AC_SUBST(testsdir, \${exec_prefix}/tests/lutok)


AC_OUTPUT
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































































































































Changes to debug.cpp.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <cassert>

#include <lua.hpp>

#include <lutok/c_gate.hpp>
#include <lutok/debug.hpp>
#include <lutok/exceptions.hpp>
#include <lutok/state.ipp>


/// Internal implementation for lutok::debug.
struct lutok::debug::impl {
    /// The Lua internal debug state.
    lua_Debug lua_debug;
};







|
|
|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <cassert>

#include <lua.hpp>

#include <xlua/c_gate.hpp>
#include <xlua/debug.hpp>
#include <xlua/exceptions.hpp>
#include <xlua/state.ipp>


/// Internal implementation for lutok::debug.
struct lutok::debug::impl {
    /// The Lua internal debug state.
    lua_Debug lua_debug;
};

Deleted debug.hpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file debug.hpp
/// Provides the debug wrapper class for the Lua C debug state.

#if !defined(LUTOK_DEBUG_HPP)
#define LUTOK_DEBUG_HPP

#include <string>
#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L
#include <memory>
#else
#include <tr1/memory>
#endif

namespace lutok {


class state;


/// A model for the Lua debug state.
///
/// This extremely-simple class provides a mechanism to hide the internals of
/// the C native lua_Debug type, exposing its internal fields using friendlier
/// C++ types.
///
/// This class also acts as a complement to the state class by exposing any
/// state-related functions as methods of this function.  For example, while it
/// might seem that get_info() belongs in state, we expose it from here because
/// its result is really mutating a debug object, not the state object.
class debug {
    struct impl;

    /// Pointer to the shared internal implementation.
#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L
    std::shared_ptr< impl > _pimpl;
#else
    std::tr1::shared_ptr< impl > _pimpl;
#endif

public:
    debug(void);
    ~debug(void);

    void get_info(state&, const std::string&);
    void get_stack(state&, const int);

    int event(void) const;
    std::string name(void) const;
    std::string name_what(void) const;
    std::string what(void) const;
    std::string source(void) const;
    int current_line(void) const;
    int n_ups(void) const;
    int line_defined(void) const;
    int last_line_defined(void) const;
    std::string short_src(void) const;
};


}  // namespace lutok

#endif  // !defined(LUTOK_DEBUG_HPP)
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































































































































Deleted debug_test.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "debug.hpp"

#include <atf-c++.hpp>
#include <lua.hpp>

#include "state.ipp"
#include "test_utils.hpp"


ATF_TEST_CASE_WITHOUT_HEAD(get_info);
ATF_TEST_CASE_BODY(get_info)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "\n\nfunction hello() end\n"
                              "return hello") == 0);
    lutok::debug debug;
    debug.get_info(state, ">S");
    ATF_REQUIRE_EQ(3, debug.line_defined());
}


ATF_TEST_CASE_WITHOUT_HEAD(get_stack);
ATF_TEST_CASE_BODY(get_stack)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "error('Hello')") == 1);
    lutok::debug debug;
    debug.get_stack(state, 0);
    lua_pop(raw(state), 1);
    // Not sure if we can actually validate anything here, other than we did not
    // crash... (because get_stack only is supposed to update internal values of
    // the debug structure).
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, get_info);
    ATF_ADD_TEST_CASE(tcs, get_stack);
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































































Changes to examples/bindings.cpp.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <cstdlib>
#include <iostream>
#include <map>
#include <sstream>
#include <stdexcept>
#include <string>

#include <lutok/exceptions.hpp>
#include <lutok/operations.hpp>
#include <lutok/state.ipp>


/// Calculates the factorial of a given number.
///
/// \param i The postivie number to calculate the factorial of.
///
/// \return The factorial of i.







|
|
|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <cstdlib>
#include <iostream>
#include <map>
#include <sstream>
#include <stdexcept>
#include <string>

#include <xlua/exceptions.hpp>
#include <xlua/operations.hpp>
#include <xlua/state.ipp>


/// Calculates the factorial of a given number.
///
/// \param i The postivie number to calculate the factorial of.
///
/// \return The factorial of i.

Changes to examples/hello.cpp.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file examples/hello.cpp
/// Minimal example using Lua code to print a traditional hello-world message.

#include <cstdlib>

#include <lutok/state.ipp>


/// Program's entry point.
///
/// \return A system exit code.
int
main(void)







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file examples/hello.cpp
/// Minimal example using Lua code to print a traditional hello-world message.

#include <cstdlib>

#include <xlua/state.ipp>


/// Program's entry point.
///
/// \return A system exit code.
int
main(void)

Changes to examples/interpreter.cpp.

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/// \file examples/interpreter.cpp
/// Implementation of a basic command-line Lua interpreter.

#include <cstdlib>
#include <iostream>
#include <string>

#include <lutok/exceptions.hpp>
#include <lutok/operations.hpp>
#include <lutok/state.ipp>


/// Executes a Lua statement provided by the user with error checking.
///
/// \param state The Lua state in which to process the statement.
/// \param line The textual statement provided by the user.
static void







|
|
|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/// \file examples/interpreter.cpp
/// Implementation of a basic command-line Lua interpreter.

#include <cstdlib>
#include <iostream>
#include <string>

#include <xlua/exceptions.hpp>
#include <xlua/operations.hpp>
#include <xlua/state.ipp>


/// Executes a Lua statement provided by the user with error checking.
///
/// \param state The Lua state in which to process the statement.
/// \param line The textual statement provided by the user.
static void

Changes to examples/raii.cpp.

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/// transparent manner.  This example program attempts to illustrate this.

#include <cassert>
#include <cstdlib>
#include <iostream>
#include <string>

#include <lutok/operations.hpp>
#include <lutok/stack_cleaner.hpp>
#include <lutok/state.ipp>


/// Prints the string-typed field of a table.
///
/// If the field contains a string, this function prints its value.  If the
/// field contains any other type, this prints an error message.
///







|
|
|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/// transparent manner.  This example program attempts to illustrate this.

#include <cassert>
#include <cstdlib>
#include <iostream>
#include <string>

#include <xlua/operations.hpp>
#include <xlua/stack_cleaner.hpp>
#include <xlua/state.ipp>


/// Prints the string-typed field of a table.
///
/// If the field contains a string, this function prints its value.  If the
/// field contains any other type, this prints an error message.
///

Deleted examples_test.sh.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#! __ATF_SH__
# Copyright 2012 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
# * Neither the name of Google Inc. nor the names of its contributors
#   may be used to endorse or promote products derived from this software
#   without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Cxx="__CXX__"
ExamplesDir="__EXAMPLESDIR__"
LibDir="__LIBDIR__"


make_example() {
    cp "${ExamplesDir}/Makefile" "${ExamplesDir}/${1}.cpp" .
    make CXX="${Cxx}" "${1}"

    # Ensure that the binary we just built can find liblutok.  This is
    # needed because the lutok.pc file (which the Makefile used above
    # queries) does not provide rpaths to the installed library and
    # therefore the binary may not be able to locate it.  Hardcoding the
    # rpath flags into lutok.pc is non-trivial because we simply don't
    # have any knowledge about what the correct flag to set an rpath is.
    #
    # Additionally, setting rpaths is not always the right thing to do.
    # For example, pkgsrc will automatically change lutok.pc to add the
    # missing rpath, in which case this is unnecessary.  But in the case
    # of Fedora, adding rpaths goes against the packaging guidelines.
    if [ -n "${LD_LIBRARY_PATH}" ]; then
        export LD_LIBRARY_PATH="${LibDir}:${LD_LIBRARY_PATH}"
    else
        export LD_LIBRARY_PATH="${LibDir}"
    fi
}


example_test_case() {
    local name="${1}"; shift

    atf_test_case "${name}"
    eval "${name}_head() { \
        atf_set 'require.files' '${ExamplesDir}/${name}.cpp'; \
        atf_set 'require.progs' 'make pkg-config'; \
    }"
    eval "${name}_body() { \
        make_example '${name}'; \
        ${name}_validate; \
    }"
}


example_test_case bindings
bindings_validate() {
    atf_check -s exit:0 -o inline:'120\n' ./bindings 5
    atf_check -s exit:1 -e match:'Argument.*must be an integer' ./bindings foo
    atf_check -s exit:1 -e match:'Argument.*must be positive' ./bindings -5
}


example_test_case hello
hello_validate() {
    atf_check -s exit:0 -o inline:'Hello, world!\n' ./hello
}


example_test_case interpreter
interpreter_validate() {
    cat >script.lua <<EOF
test_variable = 12345
print("From the interpreter: " .. (test_variable - 345))
EOF

    atf_check -s exit:0 -o match:"From the interpreter: 12000" \
        -x "./interpreter <script.lua"
}


example_test_case raii
raii_validate() {
cat >expout <<EOF
String in field foo: hello
String in field bar: 123
String in field baz: bye
EOF
    atf_check -s exit:0 -o file:expout ./raii
}


atf_init_test_cases() {
    atf_add_test_case bindings
    atf_add_test_case hello
    atf_add_test_case interpreter
    atf_add_test_case raii
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































































































































































































Deleted exceptions.hpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file exceptions.hpp
/// Exception types raised by lutok.

#if !defined(LUTOK_EXCEPTIONS_HPP)
#define LUTOK_EXCEPTIONS_HPP

#include <stdexcept>
#include <string>

namespace lutok {


class state;


/// Base exception for lua errors.
class error : public std::runtime_error {
public:
    explicit error(const std::string&);
    virtual ~error(void) throw();
};


/// Exception for errors raised by the Lua API library.
class api_error : public error {
    /// Name of the Lua C API function that caused the error.
    std::string _api_function;

public:
    explicit api_error(const std::string&, const std::string&);
    virtual ~api_error(void) throw();

    static api_error from_stack(state&, const std::string&);

    const std::string& api_function(void) const;
};


/// File not found error.
class file_not_found_error : public error {
    /// Name of the not-found file.
    std::string _filename;

public:
    explicit file_not_found_error(const std::string&);
    virtual ~file_not_found_error(void) throw();

    const std::string& filename(void) const;
};


}  // namespace lutok


#endif  // !defined(LUTOK_EXCEPTIONS_HPP)
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































































































































Deleted exceptions_test.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "exceptions.hpp"

#include <cstring>

#include <atf-c++.hpp>

#include "state.ipp"


ATF_TEST_CASE_WITHOUT_HEAD(error);
ATF_TEST_CASE_BODY(error)
{
    const lutok::error e("Some text");
    ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0);
}


ATF_TEST_CASE_WITHOUT_HEAD(api_error__explicit);
ATF_TEST_CASE_BODY(api_error__explicit)
{
    const lutok::api_error e("some_function", "Some text");
    ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0);
    ATF_REQUIRE_EQ("some_function", e.api_function());
}


ATF_TEST_CASE_WITHOUT_HEAD(api_error__from_stack);
ATF_TEST_CASE_BODY(api_error__from_stack)
{
    lutok::state state;
    state.push_integer(123);
    state.push_string("The error message");
    const lutok::api_error e = lutok::api_error::from_stack(state,
                                                            "the_function");
    ATF_REQUIRE_EQ(1, state.get_top());
    ATF_REQUIRE_EQ(123, state.to_integer(-1));
    state.pop(1);
    ATF_REQUIRE(std::strcmp("The error message", e.what()) == 0);
    ATF_REQUIRE_EQ("the_function", e.api_function());
}


ATF_TEST_CASE_WITHOUT_HEAD(file_not_found_error);
ATF_TEST_CASE_BODY(file_not_found_error)
{
    const lutok::file_not_found_error e("missing-file");
    ATF_REQUIRE(std::strcmp("File 'missing-file' not found", e.what()) == 0);
    ATF_REQUIRE_EQ("missing-file", e.filename());
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, error);

    ATF_ADD_TEST_CASE(tcs, api_error__explicit);
    ATF_ADD_TEST_CASE(tcs, api_error__from_stack);

    ATF_ADD_TEST_CASE(tcs, file_not_found_error);
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































































































































Deleted include/lutok/README.

1
2
3
4
This directory contains forward includes for the public header files of
Lutok.  These files are only necessary during the build of Lutok itself
so that the compiler can locate the include files in a path that mimics
the final installation location.
<
<
<
<








Deleted include/lutok/c_gate.hpp.

1
#include "../../c_gate.hpp"
<


Deleted include/lutok/debug.hpp.

1
#include "../../debug.hpp"
<


Deleted include/lutok/exceptions.hpp.

1
#include "../../exceptions.hpp"
<


Deleted include/lutok/operations.hpp.

1
#include "../../operations.hpp"
<


Deleted include/lutok/stack_cleaner.hpp.

1
#include "../../stack_cleaner.hpp"
<


Deleted include/lutok/state.hpp.

1
#include "../../state.hpp"
<


Deleted include/lutok/state.ipp.

1
#include "../../state.ipp"
<


Added include/xlua/c_gate.hpp.















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file c_gate.hpp
/// Provides direct access to the C state of the Lua wrappers.

#if !defined(LUTOK_C_GATE_HPP)
#define LUTOK_C_GATE_HPP

#include <lua.hpp>

namespace lutok {


class state;


/// Gateway to the raw C state of Lua.
///
/// This class provides a mechanism to muck with the internals of the state
/// wrapper class.  Client code may wish to do so if Lutok is missing some
/// features of the performance of Lutok in a particular situation is not
/// reasonable.
///
/// \warning The use of this class is discouraged.  By using this class, you are
/// entering the world of unsafety.  Anything you do through the objects exposed
/// through this class will not be controlled by RAII patterns not validated in
/// any other way, so you can end up corrupting the Lua state and later get
/// crashes on otherwise perfectly-valid C++ code.
class state_c_gate {
    /// The C++ state that this class wraps.
    state& _state;

public:
    state_c_gate(state&);
    ~state_c_gate(void);

    static state connect(lua_State*);

    lua_State* c_state(void);
};


}  // namespace lutok

#endif  // !defined(LUTOK_C_GATE_HPP)

Added include/xlua/debug.hpp.





















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file debug.hpp
/// Provides the debug wrapper class for the Lua C debug state.

#if !defined(LUTOK_DEBUG_HPP)
#define LUTOK_DEBUG_HPP

#include <string>
#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L
#include <memory>
#else
#include <tr1/memory>
#endif

namespace lutok {


class state;


/// A model for the Lua debug state.
///
/// This extremely-simple class provides a mechanism to hide the internals of
/// the C native lua_Debug type, exposing its internal fields using friendlier
/// C++ types.
///
/// This class also acts as a complement to the state class by exposing any
/// state-related functions as methods of this function.  For example, while it
/// might seem that get_info() belongs in state, we expose it from here because
/// its result is really mutating a debug object, not the state object.
class debug {
    struct impl;

    /// Pointer to the shared internal implementation.
#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L
    std::shared_ptr< impl > _pimpl;
#else
    std::tr1::shared_ptr< impl > _pimpl;
#endif

public:
    debug(void);
    ~debug(void);

    void get_info(state&, const std::string&);
    void get_stack(state&, const int);

    int event(void) const;
    std::string name(void) const;
    std::string name_what(void) const;
    std::string what(void) const;
    std::string source(void) const;
    int current_line(void) const;
    int n_ups(void) const;
    int line_defined(void) const;
    int last_line_defined(void) const;
    std::string short_src(void) const;
};


}  // namespace lutok

#endif  // !defined(LUTOK_DEBUG_HPP)

Added include/xlua/exceptions.hpp.







































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file exceptions.hpp
/// Exception types raised by lutok.

#if !defined(LUTOK_EXCEPTIONS_HPP)
#define LUTOK_EXCEPTIONS_HPP

#include <stdexcept>
#include <string>

namespace lutok {


class state;


/// Base exception for lua errors.
class error : public std::runtime_error {
public:
    explicit error(const std::string&);
    virtual ~error(void) throw();
};


/// Exception for errors raised by the Lua API library.
class api_error : public error {
    /// Name of the Lua C API function that caused the error.
    std::string _api_function;

public:
    explicit api_error(const std::string&, const std::string&);
    virtual ~api_error(void) throw();

    static api_error from_stack(state&, const std::string&);

    const std::string& api_function(void) const;
};


/// File not found error.
class file_not_found_error : public error {
    /// Name of the not-found file.
    std::string _filename;

public:
    explicit file_not_found_error(const std::string&);
    virtual ~file_not_found_error(void) throw();

    const std::string& filename(void) const;
};


}  // namespace lutok


#endif  // !defined(LUTOK_EXCEPTIONS_HPP)

Added include/xlua/operations.hpp.















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file operations.hpp
/// Extra generic functions to interact with Lua.

#if !defined(LUTOK_OPERATIONS_HPP)
#define LUTOK_OPERATIONS_HPP

#include <map>
#include <string>
#include <vector>

#include <xlua/state.hpp>

namespace lutok {


void create_module(state&, const std::string&,
                   const std::map< std::string, cxx_function >&);
unsigned int do_file(state&, const std::string&, const int, const int,
                     const int);
unsigned int do_string(state&, const std::string&, const int, const int,
                       const int);
void eval(state&, const std::string&, const int);


}  // namespace lutok

#endif  // !defined(LUTOK_OPERATIONS_HPP)

Added include/xlua/stack_cleaner.hpp.



























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file stack_cleaner.hpp
/// Provides the stack_cleaner class.

#if !defined(LUTOK_STACK_CLEANER_HPP)
#define LUTOK_STACK_CLEANER_HPP

#include <memory>

#include <xlua/state.hpp>

namespace lutok {


/// A RAII model for values on the Lua stack.
///
/// At creation time, the object records the current depth of the Lua stack and,
/// during destruction, restores the recorded depth by popping as many stack
/// entries as required.  As a corollary, the stack can only grow during the
/// lifetime of a stack_cleaner object (or shrink, but cannot become shorter
/// than the depth recorded at creation time).
///
/// Use this class as follows:
///
/// state s;
/// {
///     stack_cleaner cleaner1(s);
///     s.push_integer(3);
///     s.push_integer(5);
///     ... do stuff here ...
///     for (...) {
///         stack_cleaner cleaner2(s);
///         s.load_string("...");
///         s.pcall(0, 1, 0);
///         ... do stuff here ...
///     }
///     // cleaner2 destroyed; the result of pcall is gone.
/// }
/// // cleaner1 destroyed; the integers 3 and 5 are gone.
///
/// You must give a name to the instantiated objects even if they cannot be
/// accessed later.  Otherwise, the instance will be destroyed right away and
/// will not have the desired effect.
class stack_cleaner {
    struct impl;

    /// Pointer to the shared internal implementation.
    std::auto_ptr< impl > _pimpl;

    /// Disallow copies.
    stack_cleaner(const stack_cleaner&);

    /// Disallow assignment.
    stack_cleaner& operator=(const stack_cleaner&);

public:
    stack_cleaner(state&);
    ~stack_cleaner(void);

    void forget(void);
};


}  // namespace lutok

#endif  // !defined(LUTOK_STACK_CLEANER_HPP)

Added include/xlua/state.hpp.



































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file state.hpp
/// Provides the state wrapper class for the Lua C state.

#if !defined(LUTOK_STATE_HPP)
#define LUTOK_STATE_HPP

#include <string>

#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L
#include <memory>
#else
#include <tr1/memory>
#endif

namespace lutok {


class debug;
class state;


/// The type of a C++ function that can be bound into Lua.
///
/// Functions of this type are free to raise exceptions.  These will not
/// propagate into the Lua C API.  However, any such exceptions will be reported
/// as a Lua error and their type will be lost.
typedef int (*cxx_function)(state&);


/// Stack index constant pointing to the registry table.
extern const int registry_index;


/// A RAII model for the Lua state.
///
/// This class holds the state of the Lua interpreter during its existence and
/// provides wrappers around several Lua library functions that operate on such
/// state.
///
/// These wrapper functions differ from the C versions in that they use the
/// implicit state hold by the class, they use C++ types where appropriate and
/// they use exceptions to report errors.
///
/// The wrappers intend to be as lightweight as possible but, in some
/// situations, they are pretty complex because they need to do extra work to
/// capture the errors reported by the Lua C API.  We prefer having fine-grained
/// error control rather than efficiency, so this is OK.
class state {
    struct impl;

    /// Pointer to the shared internal implementation.
#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L
    std::shared_ptr< impl > _pimpl;
#else
    std::tr1::shared_ptr< impl > _pimpl;
#endif

    void* new_userdata_voidp(const size_t);
    void* to_userdata_voidp(const int);

    friend class state_c_gate;
    explicit state(void*);
    void* raw_state(void);

public:
    state(void);
    ~state(void);

    void close(void);
    void get_global(const std::string&);
    void get_global_table(void);
    bool get_metafield(const int, const std::string&);
    bool get_metatable(const int);
    void get_table(const int);
    int get_top(void);
    void insert(const int);
    bool is_boolean(const int);
    bool is_function(const int);
    bool is_nil(const int);
    bool is_number(const int);
    bool is_string(const int);
    bool is_table(const int);
    bool is_userdata(const int);
    void load_file(const std::string&);
    void load_string(const std::string&);
    void new_table(void);
    template< typename Type > Type* new_userdata(void);
    bool next(const int);
    void open_all(void);
    void open_base(void);
    void open_string(void);
    void open_table(void);
    void pcall(const int, const int, const int);
    void pop(const int);
    void push_boolean(const bool);
    void push_cxx_closure(cxx_function, const int);
    void push_cxx_function(cxx_function);
    void push_integer(const int);
    void push_nil(void);
    void push_string(const std::string&);
    void push_value(const int);
    void raw_get(const int);
    void raw_set(const int);
    void set_global(const std::string&);
    void set_metatable(const int);
    void set_table(const int);
    bool to_boolean(const int);
    long to_integer(const int);
    template< typename Type > Type* to_userdata(const int);
    std::string to_string(const int);
    int upvalue_index(const int);
};


}  // namespace lutok

#endif  // !defined(LUTOK_STATE_HPP)

Added include/xlua/state.ipp.







































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#if !defined(LUTOK_STATE_IPP)
#define LUTOK_STATE_IPP

#include <xlua/state.hpp>

namespace lutok {


/// Wrapper around lua_newuserdata.
///
/// This allocates an object as big as the size of the provided Type.
///
/// \return The pointer to the allocated userdata object.
///
/// \warning Terminates execution if there is not enough memory.
template< typename Type >
Type*
state::new_userdata(void)
{
    return static_cast< Type* >(new_userdata_voidp(sizeof(Type)));
}


/// Wrapper around lua_touserdata.
///
/// \param index The second parameter to lua_touserdata.
///
/// \return The return value of lua_touserdata.
template< typename Type >
Type*
state::to_userdata(const int index)
{
    return static_cast< Type* >(to_userdata_voidp(index));
}


}  // namespace lutok

#endif  // !defined(LUTOK_STATE_IPP)

Added include/xlua/test_utils.hpp.



























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file test_utils.hpp
/// Utilities for tests of the lua modules.
///
/// This file is intended to be included once, and only once, for every test
/// program that needs it.  All the code is herein contained to simplify the
/// dependency chain in the build rules.

#if !defined(LUTOK_TEST_UTILS_HPP)
#   define LUTOK_TEST_UTILS_HPP
#else
#   error "test_utils.hpp can only be included once"
#endif

#include <atf-c++.hpp>

#include "c_gate.hpp"
#include "exceptions.hpp"
#include "state.hpp"


namespace {


/// Checks that a given expression raises a particular lutok::api_error.
///
/// We cannot make any assumptions regarding the error text provided by Lua, so
/// we resort to checking only which API function raised the error (because our
/// code is the one hardcoding these strings).
///
/// \param exp_api_function The name of the Lua C API function that causes the
///     error.
/// \param statement The statement to execute.
#define REQUIRE_API_ERROR(exp_api_function, statement) \
    do { \
        try { \
            statement; \
            ATF_FAIL("api_error not raised by " #statement); \
        } catch (const lutok::api_error& api_error) { \
            ATF_REQUIRE_EQ(exp_api_function, api_error.api_function()); \
        } \
    } while (0)


/// Gets the pointer to the internal lua_State of a state object.
///
/// This is pure syntactic sugar to simplify typing in the test cases.
///
/// \param state The Lua state.
///
/// \return The internal lua_State of the input Lua state.
static inline lua_State*
raw(lutok::state& state)
{
    return lutok::state_c_gate(state).c_state();
}


/// Ensures that the Lua stack maintains its original height upon exit.
///
/// Use an instance of this class to check that a piece of code does not have
/// side-effects on the Lua stack.
///
/// To be used within a test case only.
class stack_balance_checker {
    /// The Lua state.
    lutok::state& _state;

    /// Whether to install a sentinel on the stack for balance enforcement.
    bool _with_sentinel;

    /// The height of the stack on creation.
    unsigned int _old_count;

public:
    /// Constructs a new stack balance checker.
    ///
    /// \param state_ The Lua state to validate.
    /// \param with_sentinel_ If true, insert a sentinel item into the stack and
    ///     validate upon exit that the item is still there.  This is an attempt
    ///     to ensure that already-existing items are not removed from the stack
    ///     by the code under test.
    stack_balance_checker(lutok::state& state_,
                          const bool with_sentinel_ = true) :
        _state(state_),
        _with_sentinel(with_sentinel_),
        _old_count(_state.get_top())
    {
        if (_with_sentinel)
            _state.push_integer(987654321);
    }

    /// Destructor for the object.
    ///
    /// If the stack height does not match the height when the instance was
    /// created, this fails the test case.
    ~stack_balance_checker(void)
    {
        if (_with_sentinel) {
            if (!_state.is_number(-1) || _state.to_integer(-1) != 987654321)
                ATF_FAIL("Stack corrupted: sentinel not found");
            _state.pop(1);
        }

        unsigned int new_count = _state.get_top();
        if (_old_count != new_count)
            //ATF_FAIL(F("Stack not balanced: before %d, after %d") %
            //         _old_count % new_count);
            ATF_FAIL("Stack not balanced");
    }
};


}  // anonymous namespace

Deleted lutok.pc.in.

1
2
3
4
5
6
7
8
includedir=__INCLUDEDIR__
libdir=__LIBDIR__

Name: lutok
Description: Lightweight C++ API for Lua
Version: __VERSION__
Cflags: __LUA_CFLAGS__ -I${includedir}
Libs: __LUA_LIBS__ -L${libdir} -llutok
<
<
<
<
<
<
<
<
















Deleted m4/.gitignore.

1
2
3
4
5
libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
<
<
<
<
<










Deleted m4/compiler-features.m4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
dnl Copyright 2010 Google Inc.
dnl All rights reserved.
dnl
dnl Redistribution and use in source and binary forms, with or without
dnl modification, are permitted provided that the following conditions are
dnl met:
dnl
dnl * Redistributions of source code must retain the above copyright
dnl   notice, this list of conditions and the following disclaimer.
dnl * Redistributions in binary form must reproduce the above copyright
dnl   notice, this list of conditions and the following disclaimer in the
dnl   documentation and/or other materials provided with the distribution.
dnl * Neither the name of Google Inc. nor the names of its contributors
dnl   may be used to endorse or promote products derived from this software
dnl   without specific prior written permission.
dnl
dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

dnl
dnl KYUA_REQUIRE_CXX
dnl
dnl Ensures the C++ compiler detected by AC_PROG_CXX is present and works.
dnl The compiler check should be performed here, but it seems like Autoconf
dnl does not allow it.
dnl
AC_DEFUN([KYUA_REQUIRE_CXX], [
    AC_CACHE_CHECK([whether the C++ compiler works],
                   [atf_cv_prog_cxx_works],
                   [AC_LANG_PUSH([C++])
                    AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
                                   [atf_cv_prog_cxx_works=yes],
                                   [atf_cv_prog_cxx_works=no])
                    AC_LANG_POP([C++])])
    if test "${atf_cv_prog_cxx_works}" = no; then
        AC_MSG_ERROR([C++ compiler cannot create executables])
    fi
])

dnl
dnl KYUA_ATTRIBUTE_NORETURN
dnl
dnl Checks if the current compiler has a way to mark functions that do not
dnl return and defines ATTRIBUTE_NORETURN to the appropriate string.
dnl
AC_DEFUN([KYUA_ATTRIBUTE_NORETURN], [
    dnl This check is overly simple and should be fixed.  For example,
    dnl Sun's cc does support the noreturn attribute but CC (the C++
    dnl compiler) does not.  And in that case, CC just raises a warning
    dnl during compilation, not an error.
    AC_MSG_CHECKING(whether __attribute__((noreturn)) is supported)
    AC_RUN_IFELSE([AC_LANG_PROGRAM([], [
#if ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
    return 0;
#else
    return 1;
#endif
        ])],
        [AC_MSG_RESULT(yes)
         value="__attribute__((noreturn))"],
        [AC_MSG_RESULT(no)
         value=""]
    )
    AC_SUBST([ATTRIBUTE_NORETURN], [${value}])
])


dnl
dnl KYUA_ATTRIBUTE_UNUSED
dnl
dnl Checks if the current compiler has a way to mark parameters as unused
dnl so that the -Wunused-parameter warning can be avoided.
dnl
AC_DEFUN([KYUA_ATTRIBUTE_UNUSED], [
    AC_MSG_CHECKING(whether __attribute__((__unused__)) is supported)
    AC_COMPILE_IFELSE(
        [AC_LANG_PROGRAM([
static void
function(int a __attribute__((__unused__)))
{
}], [
    function(3);
    return 0;
])],
        [AC_MSG_RESULT(yes)
         value="__attribute__((__unused__))"],
        [AC_MSG_RESULT(no)
         value=""]
    )
    AC_SUBST([ATTRIBUTE_UNUSED], [${value}])
])
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































































































































Deleted m4/compiler-flags.m4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
dnl Copyright 2010 Google Inc.
dnl All rights reserved.
dnl
dnl Redistribution and use in source and binary forms, with or without
dnl modification, are permitted provided that the following conditions are
dnl met:
dnl
dnl * Redistributions of source code must retain the above copyright
dnl   notice, this list of conditions and the following disclaimer.
dnl * Redistributions in binary form must reproduce the above copyright
dnl   notice, this list of conditions and the following disclaimer in the
dnl   documentation and/or other materials provided with the distribution.
dnl * Neither the name of Google Inc. nor the names of its contributors
dnl   may be used to endorse or promote products derived from this software
dnl   without specific prior written permission.
dnl
dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

dnl \file compiler-flags.m4
dnl
dnl Macros to check for the existence of compiler flags.  The macros in this
dnl file support both C and C++.
dnl
dnl Be aware that, in order to detect a flag accurately, we may need to enable
dnl strict warning checking in the compiler (i.e. enable -Werror).  Some
dnl compilers, e.g. Clang, report unknown -W flags as warnings unless -Werror is
dnl selected.  This fact would confuse the flag checks below because we would
dnl conclude that a flag is valid while in reality it is not.  To resolve this,
dnl the macros below will pass -Werror to the compiler along with any other flag
dnl being checked.


dnl Checks for a compiler flag and sets a result variable.
dnl
dnl This is an auxiliary macro for the implementation of _KYUA_FLAG.
dnl
dnl \param 1 The shell variable containing the compiler name.  Used for
dnl     reporting purposes only.  C or CXX.
dnl \param 2 The shell variable containing the flags for the compiler.
dnl     CFLAGS or CXXFLAGS.
dnl \param 3 The name of the compiler flag to check for.
dnl \param 4 The shell variable to set with the result of the test.  Will
dnl     be set to 'yes' if the flag is valid, 'no' otherwise.
dnl \param 5 Additional, optional flags to pass to the C compiler while
dnl     looking for the flag in $3.  We use this here to pass -Werror to the
dnl     flag checks (unless we are checking for -Werror already).
AC_DEFUN([_KYUA_FLAG_AUX], [
    if test x"${$4-unset}" = xunset; then
        AC_MSG_CHECKING(whether ${$1} supports $3)
        saved_flags="${$2}"
        $4=no
        $2="${$2} $5 $3"
        AC_LINK_IFELSE([AC_LANG_PROGRAM([], [return 0;])],
                       AC_MSG_RESULT(yes)
                       $4=yes,
                       AC_MSG_RESULT(no))
        $2="${saved_flags}"
    fi
])


dnl Checks for a compiler flag and appends it to a result variable.
dnl
dnl \param 1 The shell variable containing the compiler name.  Used for
dnl     reporting purposes only.  CC or CXX.
dnl \param 2 The shell variable containing the flags for the compiler.
dnl     CFLAGS or CXXFLAGS.
dnl \param 3 The name of the compiler flag to check for.
dnl \param 4 The shell variable to which to append $3 if the flag is valid.
AC_DEFUN([_KYUA_FLAG], [
    _KYUA_FLAG_AUX([$1], [$2], [-Werror], [kyua_$1_has_werror])
    if test "$3" = "-Werror"; then
        found=${kyua_$1_has_werror}
    else
        found=unset
        if test ${kyua_$1_has_werror} = yes; then
            _KYUA_FLAG_AUX([$1], [$2], [$3], [found], [-Werror])
        else
            _KYUA_FLAG_AUX([$1], [$2], [$3], [found], [])
        fi
    fi
    if test ${found} = yes; then
        $4="${$4} $3"
    fi
])


dnl Checks for a C compiler flag and appends it to a variable.
dnl
dnl \pre The current language is C.
dnl
dnl \param 1 The name of the compiler flag to check for.
dnl \param 2 The shell variable to which to append $1 if the flag is valid.
AC_DEFUN([KYUA_CC_FLAG], [
    AC_LANG_ASSERT([C])
    _KYUA_FLAG([CC], [CFLAGS], [$1], [$2])
])


dnl Checks for a C++ compiler flag and appends it to a variable.
dnl
dnl \pre The current language is C++.
dnl
dnl \param 1 The name of the compiler flag to check for.
dnl \param 2 The shell variable to which to append $1 if the flag is valid.
AC_DEFUN([KYUA_CXX_FLAG], [
    AC_LANG_ASSERT([C++])
    _KYUA_FLAG([CXX], [CXXFLAGS], [$1], [$2])
])


dnl Checks for a set of C compiler flags and appends them to CFLAGS.
dnl
dnl The checks are performed independently and only when all the checks are
dnl done, the output variable is modified.
dnl
dnl \param 1 Whitespace-separated list of C flags to check.
AC_DEFUN([KYUA_CC_FLAGS], [
    AC_LANG_PUSH([C])
    valid_cflags=
    for f in $1; do
        KYUA_CC_FLAG(${f}, valid_cflags)
    done
    if test -n "${valid_cflags}"; then
        CFLAGS="${CFLAGS} ${valid_cflags}"
    fi
    AC_LANG_POP([C])
])


dnl Checks for a set of C++ compiler flags and appends them to CXXFLAGS.
dnl
dnl The checks are performed independently and only when all the checks are
dnl done, the output variable is modified.
dnl
dnl \pre The current language is C++.
dnl
dnl \param 1 Whitespace-separated list of C flags to check.
AC_DEFUN([KYUA_CXX_FLAGS], [
    AC_LANG_PUSH([C++])
    valid_cxxflags=
    for f in $1; do
        KYUA_CXX_FLAG(${f}, valid_cxxflags)
    done
    if test -n "${valid_cxxflags}"; then
        CXXFLAGS="${CXXFLAGS} ${valid_cxxflags}"
    fi
    AC_LANG_POP([C++])
])
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































































































































































































































































































Deleted m4/developer-mode.m4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
dnl Copyright 2010 Google Inc.
dnl All rights reserved.
dnl
dnl Redistribution and use in source and binary forms, with or without
dnl modification, are permitted provided that the following conditions are
dnl met:
dnl
dnl * Redistributions of source code must retain the above copyright
dnl   notice, this list of conditions and the following disclaimer.
dnl * Redistributions in binary form must reproduce the above copyright
dnl   notice, this list of conditions and the following disclaimer in the
dnl   documentation and/or other materials provided with the distribution.
dnl * Neither the name of Google Inc. nor the names of its contributors
dnl   may be used to endorse or promote products derived from this software
dnl   without specific prior written permission.
dnl
dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

dnl \file developer-mode.m4
dnl
dnl "Developer mode" is a mode in which the build system reports any
dnl build-time warnings as fatal errors.  This helps in minimizing the
dnl amount of trivial coding problems introduced in the code.
dnl Unfortunately, this is not bullet-proof due to the wide variety of
dnl compilers available and their different warning diagnostics.
dnl
dnl When developer mode support is added to a package, the compilation will
dnl gain a bunch of extra warning diagnostics.  These will NOT be enforced
dnl unless developer mode is enabled.
dnl
dnl Developer mode is enabled when the user requests it through the
dnl configure command line, or when building from the repository.  The
dnl latter is to minimize the risk of committing new code with warnings
dnl into the tree.


dnl Adds "developer mode" support to the package.
dnl
dnl This macro performs the actual definition of the --enable-developer
dnl flag and implements all of its logic.  See the file-level comment for
dnl details as to what this implies.
AC_DEFUN([KYUA_DEVELOPER_MODE], [
    m4_foreach([language], [$1], [m4_set_add([languages], language)])

    AC_ARG_ENABLE(
        [developer],
        AS_HELP_STRING([--enable-developer], [enable developer features]),,
        [if test -d ${srcdir}/.git; then
             AC_MSG_NOTICE([building from HEAD; developer mode autoenabled])
             enable_developer=yes
         else
             enable_developer=no
         fi])

    #
    # The following warning flags should also be enabled but cannot be.
    # Reasons given below.
    #
    # -Wold-style-cast: Raises errors when using TIOCGWINSZ, at least under
    #                   Mac OS X.  This is due to the way _IOR is defined.
    #

    try_c_cxx_flags="-D_FORTIFY_SOURCE=2 \
                     -Wall \
                     -Wcast-qual \
                     -Wextra \
                     -Wpointer-arith \
                     -Wredundant-decls \
                     -Wreturn-type \
                     -Wshadow \
                     -Wsign-compare \
                     -Wswitch \
                     -Wwrite-strings"

    try_c_flags="-Wmissing-prototypes \
                 -Wno-traditional \
                 -Wstrict-prototypes"

    try_cxx_flags="-Wabi \
                   -Wctor-dtor-privacy \
                   -Wno-deprecated \
                   -Wno-non-template-friend \
                   -Wno-pmf-conversions \
                   -Wnon-virtual-dtor \
                   -Woverloaded-virtual \
                   -Wreorder \
                   -Wsign-promo \
                   -Wsynth"

    if test ${enable_developer} = yes; then
        try_werror=yes
        try_c_cxx_flags="${try_c_cxx_flags} -g -Werror"
    else
        try_werror=no
        try_c_cxx_flags="${try_c_cxx_flags} -DNDEBUG"
    fi

    m4_set_contains([languages], [C],
                    [KYUA_CC_FLAGS(${try_c_cxx_flags} ${try_c_flags})])
    m4_set_contains([languages], [C++],
                    [KYUA_CXX_FLAGS(${try_c_cxx_flags} ${try_cxx_flags})])
])
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































Deleted m4/doxygen.m4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
dnl Copyright 2010 Google Inc.
dnl All rights reserved.
dnl
dnl Redistribution and use in source and binary forms, with or without
dnl modification, are permitted provided that the following conditions are
dnl met:
dnl
dnl * Redistributions of source code must retain the above copyright
dnl   notice, this list of conditions and the following disclaimer.
dnl * Redistributions in binary form must reproduce the above copyright
dnl   notice, this list of conditions and the following disclaimer in the
dnl   documentation and/or other materials provided with the distribution.
dnl * Neither the name of Google Inc. nor the names of its contributors
dnl   may be used to endorse or promote products derived from this software
dnl   without specific prior written permission.
dnl
dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

dnl
dnl KYUA_DOXYGEN
dnl
dnl Adds a --with-doxygen flag to the configure script and, when Doxygen support
dnl is requested by the user, sets DOXYGEN to the path of the Doxygen binary and
dnl enables the WITH_DOXYGEN Automake conditional.
dnl
AC_DEFUN([KYUA_DOXYGEN], [
    AC_ARG_WITH([doxygen],
                AS_HELP_STRING([--with-doxygen],
                               [build documentation for internal APIs]),
                [],
                [with_doxygen=auto])

    if test "${with_doxygen}" = yes; then
        AC_PATH_PROG([DOXYGEN], [doxygen], [])
        if test -z "${DOXYGEN}"; then
            AC_MSG_ERROR([Doxygen explicitly requested but not found])
        fi
    elif test "${with_doxygen}" = auto; then
        AC_PATH_PROG([DOXYGEN], [doxygen], [])
    elif test "${with_doxygen}" = no; then
        DOXYGEN=
    else
        AC_MSG_CHECKING([for doxygen])
        DOXYGEN="${with_doxygen}"
        AC_MSG_RESULT([${DOXYGEN}])
        if test ! -x "${DOXYGEN}"; then
            AC_MSG_ERROR([Doxygen binary ${DOXYGEN} is not executable])
        fi
    fi
    AM_CONDITIONAL([WITH_DOXYGEN], [test -n "${DOXYGEN}"])
    AC_SUBST([DOXYGEN])
])
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































Deleted m4/lua.m4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
dnl Copyright 2011 Google Inc.
dnl All rights reserved.
dnl
dnl Redistribution and use in source and binary forms, with or without
dnl modification, are permitted provided that the following conditions are
dnl met:
dnl
dnl * Redistributions of source code must retain the above copyright
dnl   notice, this list of conditions and the following disclaimer.
dnl * Redistributions in binary form must reproduce the above copyright
dnl   notice, this list of conditions and the following disclaimer in the
dnl   documentation and/or other materials provided with the distribution.
dnl * Neither the name of Google Inc. nor the names of its contributors
dnl   may be used to endorse or promote products derived from this software
dnl   without specific prior written permission.
dnl
dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

dnl
dnl KYUA_LUA
dnl
dnl Helper macro to detect Lua in a variety of systems.
dnl
AC_DEFUN([KYUA_LUA], [
    lua_found=no

    for lua_release in 5.2 5.1; do
        if test "${lua_found}" = no; then
            PKG_CHECK_MODULES([LUA], [lua${lua_release} >= ${lua_release}],
                              [lua_found=yes], [true])
        fi
        if test "${lua_found}" = no; then
            PKG_CHECK_MODULES([LUA], [lua-${lua_release} >= ${lua_release}],
                              [lua_found=yes], [true])
        fi
        if test "${lua_found}" = no; then
            PKG_CHECK_MODULES([LUA], [lua >= ${lua_release}],
                              [lua_found=yes], [true])
        fi

        test "${lua_found}" = no || break
    done

    if test "${lua_found}" = no; then
        AC_PATH_PROGS([LUA_CONFIG], [lua-config], [unset])
        if test "${LUA_CONFIG}" != unset; then
            AC_SUBST([LUA_CFLAGS], [$(${LUA_CONFIG} --include)])
            AC_SUBST([LUA_LIBS], [$(${LUA_CONFIG} --libs)])
            lua_found=yes
        fi
    fi

    if test "${lua_found}" = no; then
        AC_MSG_ERROR([lua (5.1 or newer) is required])
    else
        AC_MSG_NOTICE([using LUA_CFLAGS = ${LUA_CFLAGS}])
        AC_MSG_NOTICE([using LUA_LIBS = ${LUA_LIBS}])
    fi
])
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































































Deleted operations.hpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file operations.hpp
/// Extra generic functions to interact with Lua.

#if !defined(LUTOK_OPERATIONS_HPP)
#define LUTOK_OPERATIONS_HPP

#include <map>
#include <string>
#include <vector>

#include <lutok/state.hpp>

namespace lutok {


void create_module(state&, const std::string&,
                   const std::map< std::string, cxx_function >&);
unsigned int do_file(state&, const std::string&, const int, const int,
                     const int);
unsigned int do_string(state&, const std::string&, const int, const int,
                       const int);
void eval(state&, const std::string&, const int);


}  // namespace lutok

#endif  // !defined(LUTOK_OPERATIONS_HPP)
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














































































































Deleted operations_test.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "operations.hpp"

#include <fstream>

#include <atf-c++.hpp>

#include "exceptions.hpp"
#include "state.ipp"
#include "test_utils.hpp"


namespace {


/// Addition function for injection into Lua.
///
/// \pre stack(-2) The first summand.
/// \pre stack(-1) The second summand.
/// \post stack(-1) The result of the sum.
///
/// \param state The Lua state.
///
/// \return The number of results (1).
static int
hook_add(lutok::state& state)
{
    state.push_integer(state.to_integer(-1) + state.to_integer(-2));
    return 1;
}


/// Multiplication function for injection into Lua.
///
/// \pre stack(-2) The first factor.
/// \pre stack(-1) The second factor.
/// \post stack(-1) The product.
///
/// \param state The Lua state.
///
/// \return The number of results (1).
static int
hook_multiply(lutok::state& state)
{
    state.push_integer(state.to_integer(-1) * state.to_integer(-2));
    return 1;
}


}  // anonymous namespace


ATF_TEST_CASE_WITHOUT_HEAD(create_module__empty);
ATF_TEST_CASE_BODY(create_module__empty)
{
    lutok::state state;
    std::map< std::string, lutok::cxx_function > members;
    lutok::create_module(state, "my_math", members);

    state.open_base();
    lutok::do_string(state, "return next(my_math) == nil", 0, 1, 0);
    ATF_REQUIRE(state.to_boolean(-1));
    state.pop(1);
}


ATF_TEST_CASE_WITHOUT_HEAD(create_module__one);
ATF_TEST_CASE_BODY(create_module__one)
{
    lutok::state state;
    std::map< std::string, lutok::cxx_function > members;
    members["add"] = hook_add;
    lutok::create_module(state, "my_math", members);

    lutok::do_string(state, "return my_math.add(10, 20)", 0, 1, 0);
    ATF_REQUIRE_EQ(30, state.to_integer(-1));
    state.pop(1);
}


ATF_TEST_CASE_WITHOUT_HEAD(create_module__many);
ATF_TEST_CASE_BODY(create_module__many)
{
    lutok::state state;
    std::map< std::string, lutok::cxx_function > members;
    members["add"] = hook_add;
    members["multiply"] = hook_multiply;
    members["add2"] = hook_add;
    lutok::create_module(state, "my_math", members);

    lutok::do_string(state, "return my_math.add(10, 20)", 0, 1, 0);
    ATF_REQUIRE_EQ(30, state.to_integer(-1));
    lutok::do_string(state, "return my_math.multiply(10, 20)", 0, 1, 0);
    ATF_REQUIRE_EQ(200, state.to_integer(-1));
    lutok::do_string(state, "return my_math.add2(20, 30)", 0, 1, 0);
    ATF_REQUIRE_EQ(50, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__some_args);
ATF_TEST_CASE_BODY(do_file__some_args)
{
    std::ofstream output("test.lua");
    output << "local a1, a2 = ...\nreturn a1 * 2, a2 * 2\n";
    output.close();

    lutok::state state;
    state.push_integer(456);
    state.push_integer(3);
    state.push_integer(5);
    state.push_integer(123);
    ATF_REQUIRE_EQ(2, lutok::do_file(state, "test.lua", 3, -1, 0));
    ATF_REQUIRE_EQ(3, state.get_top());
    ATF_REQUIRE_EQ(456, state.to_integer(-3));
    ATF_REQUIRE_EQ(6, state.to_integer(-2));
    ATF_REQUIRE_EQ(10, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__any_results);
ATF_TEST_CASE_BODY(do_file__any_results)
{
    std::ofstream output("test.lua");
    output << "return 10, 20, 30\n";
    output.close();

    lutok::state state;
    ATF_REQUIRE_EQ(3, lutok::do_file(state, "test.lua", 0, -1, 0));
    ATF_REQUIRE_EQ(3, state.get_top());
    ATF_REQUIRE_EQ(10, state.to_integer(-3));
    ATF_REQUIRE_EQ(20, state.to_integer(-2));
    ATF_REQUIRE_EQ(30, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__no_results);
ATF_TEST_CASE_BODY(do_file__no_results)
{
    std::ofstream output("test.lua");
    output << "return 10, 20, 30\n";
    output.close();

    lutok::state state;
    ATF_REQUIRE_EQ(0, lutok::do_file(state, "test.lua", 0, 0, 0));
    ATF_REQUIRE_EQ(0, state.get_top());
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__many_results);
ATF_TEST_CASE_BODY(do_file__many_results)
{
    std::ofstream output("test.lua");
    output << "return 10, 20, 30\n";
    output.close();

    lutok::state state;
    ATF_REQUIRE_EQ(2, lutok::do_file(state, "test.lua", 0, 2, 0));
    ATF_REQUIRE_EQ(2, state.get_top());
    ATF_REQUIRE_EQ(10, state.to_integer(-2));
    ATF_REQUIRE_EQ(20, state.to_integer(-1));
    state.pop(2);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__not_found);
ATF_TEST_CASE_BODY(do_file__not_found)
{
    lutok::state state;
    stack_balance_checker checker(state);
    ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua",
                         lutok::do_file(state, "missing.lua", 0, 0, 0));
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__error);
ATF_TEST_CASE_BODY(do_file__error)
{
    std::ofstream output("test.lua");
    output << "a b c\n";
    output.close();

    lutok::state state;
    stack_balance_checker checker(state);
    ATF_REQUIRE_THROW_RE(lutok::error, "Failed to load Lua file 'test.lua'",
                         lutok::do_file(state, "test.lua", 0, 0, 0));
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__error_with_errfunc);
ATF_TEST_CASE_BODY(do_file__error_with_errfunc)
{
    std::ofstream output("test.lua");
    output << "unknown_function()\n";
    output.close();

    lutok::state state;
    lutok::eval(state, "function(message) return 'This is an error!' end", 1);
    {
        stack_balance_checker checker(state);
        ATF_REQUIRE_THROW_RE(lutok::error, "This is an error!",
                             lutok::do_file(state, "test.lua", 0, 0, -2));
    }
    state.pop(1);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__some_args);
ATF_TEST_CASE_BODY(do_string__some_args)
{
    lutok::state state;
    state.push_integer(456);
    state.push_integer(3);
    state.push_integer(5);
    state.push_integer(123);
    ATF_REQUIRE_EQ(2, lutok::do_string(
        state, "local a1, a2 = ...\nreturn a1 * 2, a2 * 2\n", 3, -1, 0));
    ATF_REQUIRE_EQ(3, state.get_top());
    ATF_REQUIRE_EQ(456, state.to_integer(-3));
    ATF_REQUIRE_EQ(6, state.to_integer(-2));
    ATF_REQUIRE_EQ(10, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__any_results);
ATF_TEST_CASE_BODY(do_string__any_results)
{
    lutok::state state;
    ATF_REQUIRE_EQ(3, lutok::do_string(state, "return 10, 20, 30", 0, -1, 0));
    ATF_REQUIRE_EQ(3, state.get_top());
    ATF_REQUIRE_EQ(10, state.to_integer(-3));
    ATF_REQUIRE_EQ(20, state.to_integer(-2));
    ATF_REQUIRE_EQ(30, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__no_results);
ATF_TEST_CASE_BODY(do_string__no_results)
{
    lutok::state state;
    ATF_REQUIRE_EQ(0, lutok::do_string(state, "return 10, 20, 30", 0, 0, 0));
    ATF_REQUIRE_EQ(0, state.get_top());
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__many_results);
ATF_TEST_CASE_BODY(do_string__many_results)
{
    lutok::state state;
    ATF_REQUIRE_EQ(2, lutok::do_string(state, "return 10, 20, 30", 0, 2, 0));
    ATF_REQUIRE_EQ(2, state.get_top());
    ATF_REQUIRE_EQ(10, state.to_integer(-2));
    ATF_REQUIRE_EQ(20, state.to_integer(-1));
    state.pop(2);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__error);
ATF_TEST_CASE_BODY(do_string__error)
{
    lutok::state state;
    stack_balance_checker checker(state);
    ATF_REQUIRE_THROW_RE(lutok::error, "Failed to process Lua string 'a b c'",
                         lutok::do_string(state, "a b c", 0, 0, 0));
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__error_with_errfunc);
ATF_TEST_CASE_BODY(do_string__error_with_errfunc)
{
    lutok::state state;
    lutok::eval(state, "function(message) return 'This is an error!' end", 1);
    {
        stack_balance_checker checker(state);
        ATF_REQUIRE_THROW_RE(lutok::error, "This is an error!",
                             lutok::do_string(state, "unknown_function()",
                                              0, 0, -2));
    }
    state.pop(1);
}


ATF_TEST_CASE_WITHOUT_HEAD(eval__one_result);
ATF_TEST_CASE_BODY(eval__one_result)
{
    lutok::state state;
    stack_balance_checker checker(state);
    lutok::eval(state, "3 + 10", 1);
    ATF_REQUIRE_EQ(13, state.to_integer(-1));
    state.pop(1);
}


ATF_TEST_CASE_WITHOUT_HEAD(eval__many_results);
ATF_TEST_CASE_BODY(eval__many_results)
{
    lutok::state state;
    stack_balance_checker checker(state);
    lutok::eval(state, "5, 8, 10", 3);
    ATF_REQUIRE_EQ(5, state.to_integer(-3));
    ATF_REQUIRE_EQ(8, state.to_integer(-2));
    ATF_REQUIRE_EQ(10, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(eval__error);
ATF_TEST_CASE_BODY(eval__error)
{
    lutok::state state;
    stack_balance_checker checker(state);
    ATF_REQUIRE_THROW(lutok::error,
                      lutok::eval(state, "non_existent.method()", 1));
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, create_module__empty);
    ATF_ADD_TEST_CASE(tcs, create_module__one);
    ATF_ADD_TEST_CASE(tcs, create_module__many);

    ATF_ADD_TEST_CASE(tcs, do_file__some_args);
    ATF_ADD_TEST_CASE(tcs, do_file__any_results);
    ATF_ADD_TEST_CASE(tcs, do_file__no_results);
    ATF_ADD_TEST_CASE(tcs, do_file__many_results);
    ATF_ADD_TEST_CASE(tcs, do_file__not_found);
    ATF_ADD_TEST_CASE(tcs, do_file__error);
    ATF_ADD_TEST_CASE(tcs, do_file__error_with_errfunc);

    ATF_ADD_TEST_CASE(tcs, do_string__some_args);
    ATF_ADD_TEST_CASE(tcs, do_string__any_results);
    ATF_ADD_TEST_CASE(tcs, do_string__no_results);
    ATF_ADD_TEST_CASE(tcs, do_string__many_results);
    ATF_ADD_TEST_CASE(tcs, do_string__error);
    ATF_ADD_TEST_CASE(tcs, do_string__error_with_errfunc);

    ATF_ADD_TEST_CASE(tcs, eval__one_result);
    ATF_ADD_TEST_CASE(tcs, eval__many_results);
    ATF_ADD_TEST_CASE(tcs, eval__error);
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































































































































































































































































































































































































































































































































































































































































































Deleted stack_cleaner.hpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file stack_cleaner.hpp
/// Provides the stack_cleaner class.

#if !defined(LUTOK_STACK_CLEANER_HPP)
#define LUTOK_STACK_CLEANER_HPP

#include <memory>

#include <lutok/state.hpp>

namespace lutok {


/// A RAII model for values on the Lua stack.
///
/// At creation time, the object records the current depth of the Lua stack and,
/// during destruction, restores the recorded depth by popping as many stack
/// entries as required.  As a corollary, the stack can only grow during the
/// lifetime of a stack_cleaner object (or shrink, but cannot become shorter
/// than the depth recorded at creation time).
///
/// Use this class as follows:
///
/// state s;
/// {
///     stack_cleaner cleaner1(s);
///     s.push_integer(3);
///     s.push_integer(5);
///     ... do stuff here ...
///     for (...) {
///         stack_cleaner cleaner2(s);
///         s.load_string("...");
///         s.pcall(0, 1, 0);
///         ... do stuff here ...
///     }
///     // cleaner2 destroyed; the result of pcall is gone.
/// }
/// // cleaner1 destroyed; the integers 3 and 5 are gone.
///
/// You must give a name to the instantiated objects even if they cannot be
/// accessed later.  Otherwise, the instance will be destroyed right away and
/// will not have the desired effect.
class stack_cleaner {
    struct impl;

    /// Pointer to the shared internal implementation.
    std::auto_ptr< impl > _pimpl;

    /// Disallow copies.
    stack_cleaner(const stack_cleaner&);

    /// Disallow assignment.
    stack_cleaner& operator=(const stack_cleaner&);

public:
    stack_cleaner(state&);
    ~stack_cleaner(void);

    void forget(void);
};


}  // namespace lutok

#endif  // !defined(LUTOK_STACK_CLEANER_HPP)
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































































































Deleted stack_cleaner_test.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "stack_cleaner.hpp"

#include <atf-c++.hpp>


ATF_TEST_CASE_WITHOUT_HEAD(empty);
ATF_TEST_CASE_BODY(empty)
{
    lutok::state state;
    {
        lutok::stack_cleaner cleaner(state);
        ATF_REQUIRE_EQ(0, state.get_top());
    }
    ATF_REQUIRE_EQ(0, state.get_top());
}


ATF_TEST_CASE_WITHOUT_HEAD(some);
ATF_TEST_CASE_BODY(some)
{
    lutok::state state;
    {
        lutok::stack_cleaner cleaner(state);
        state.push_integer(15);
        ATF_REQUIRE_EQ(1, state.get_top());
        state.push_integer(30);
        ATF_REQUIRE_EQ(2, state.get_top());
    }
    ATF_REQUIRE_EQ(0, state.get_top());
}


ATF_TEST_CASE_WITHOUT_HEAD(nested);
ATF_TEST_CASE_BODY(nested)
{
    lutok::state state;
    {
        lutok::stack_cleaner cleaner1(state);
        state.push_integer(10);
        ATF_REQUIRE_EQ(1, state.get_top());
        ATF_REQUIRE_EQ(10, state.to_integer(-1));
        {
            lutok::stack_cleaner cleaner2(state);
            state.push_integer(20);
            ATF_REQUIRE_EQ(2, state.get_top());
            ATF_REQUIRE_EQ(20, state.to_integer(-1));
            ATF_REQUIRE_EQ(10, state.to_integer(-2));
        }
        ATF_REQUIRE_EQ(1, state.get_top());
        ATF_REQUIRE_EQ(10, state.to_integer(-1));
    }
    ATF_REQUIRE_EQ(0, state.get_top());
}


ATF_TEST_CASE_WITHOUT_HEAD(forget);
ATF_TEST_CASE_BODY(forget)
{
    lutok::state state;
    {
        lutok::stack_cleaner cleaner(state);
        state.push_integer(15);
        state.push_integer(30);
        cleaner.forget();
        state.push_integer(60);
        ATF_REQUIRE_EQ(3, state.get_top());
    }
    ATF_REQUIRE_EQ(2, state.get_top());
    ATF_REQUIRE_EQ(30, state.to_integer(-1));
    state.pop(2);
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, empty);
    ATF_ADD_TEST_CASE(tcs, some);
    ATF_ADD_TEST_CASE(tcs, nested);
    ATF_ADD_TEST_CASE(tcs, forget);
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































































































Deleted state.hpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file state.hpp
/// Provides the state wrapper class for the Lua C state.

#if !defined(LUTOK_STATE_HPP)
#define LUTOK_STATE_HPP

#include <string>

#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L
#include <memory>
#else
#include <tr1/memory>
#endif

namespace lutok {


class debug;
class state;


/// The type of a C++ function that can be bound into Lua.
///
/// Functions of this type are free to raise exceptions.  These will not
/// propagate into the Lua C API.  However, any such exceptions will be reported
/// as a Lua error and their type will be lost.
typedef int (*cxx_function)(state&);


/// Stack index constant pointing to the registry table.
extern const int registry_index;


/// A RAII model for the Lua state.
///
/// This class holds the state of the Lua interpreter during its existence and
/// provides wrappers around several Lua library functions that operate on such
/// state.
///
/// These wrapper functions differ from the C versions in that they use the
/// implicit state hold by the class, they use C++ types where appropriate and
/// they use exceptions to report errors.
///
/// The wrappers intend to be as lightweight as possible but, in some
/// situations, they are pretty complex because they need to do extra work to
/// capture the errors reported by the Lua C API.  We prefer having fine-grained
/// error control rather than efficiency, so this is OK.
class state {
    struct impl;

    /// Pointer to the shared internal implementation.
#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L
    std::shared_ptr< impl > _pimpl;
#else
    std::tr1::shared_ptr< impl > _pimpl;
#endif

    void* new_userdata_voidp(const size_t);
    void* to_userdata_voidp(const int);

    friend class state_c_gate;
    explicit state(void*);
    void* raw_state(void);

public:
    state(void);
    ~state(void);

    void close(void);
    void get_global(const std::string&);
    void get_global_table(void);
    bool get_metafield(const int, const std::string&);
    bool get_metatable(const int);
    void get_table(const int);
    int get_top(void);
    void insert(const int);
    bool is_boolean(const int);
    bool is_function(const int);
    bool is_nil(const int);
    bool is_number(const int);
    bool is_string(const int);
    bool is_table(const int);
    bool is_userdata(const int);
    void load_file(const std::string&);
    void load_string(const std::string&);
    void new_table(void);
    template< typename Type > Type* new_userdata(void);
    bool next(const int);
    void open_all(void);
    void open_base(void);
    void open_string(void);
    void open_table(void);
    void pcall(const int, const int, const int);
    void pop(const int);
    void push_boolean(const bool);
    void push_cxx_closure(cxx_function, const int);
    void push_cxx_function(cxx_function);
    void push_integer(const int);
    void push_nil(void);
    void push_string(const std::string&);
    void push_value(const int);
    void raw_get(const int);
    void raw_set(const int);
    void set_global(const std::string&);
    void set_metatable(const int);
    void set_table(const int);
    bool to_boolean(const int);
    long to_integer(const int);
    template< typename Type > Type* to_userdata(const int);
    std::string to_string(const int);
    int upvalue_index(const int);
};


}  // namespace lutok

#endif  // !defined(LUTOK_STATE_HPP)
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































































































































































































































Deleted state.ipp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#if !defined(LUTOK_STATE_IPP)
#define LUTOK_STATE_IPP

#include <lutok/state.hpp>

namespace lutok {


/// Wrapper around lua_newuserdata.
///
/// This allocates an object as big as the size of the provided Type.
///
/// \return The pointer to the allocated userdata object.
///
/// \warning Terminates execution if there is not enough memory.
template< typename Type >
Type*
state::new_userdata(void)
{
    return static_cast< Type* >(new_userdata_voidp(sizeof(Type)));
}


/// Wrapper around lua_touserdata.
///
/// \param index The second parameter to lua_touserdata.
///
/// \return The return value of lua_touserdata.
template< typename Type >
Type*
state::to_userdata(const int index)
{
    return static_cast< Type* >(to_userdata_voidp(index));
}


}  // namespace lutok

#endif  // !defined(LUTOK_STATE_IPP)
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































































































Deleted state_test.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "state.ipp"

#include <cstring>
#include <fstream>
#include <iostream>
#include <stdexcept>

#include <atf-c++.hpp>
#include <lua.hpp>

#include "c_gate.hpp"
#include "exceptions.hpp"
#include "test_utils.hpp"


// A note about the lutok::state tests.
//
// The methods of lutok::state are, in general, thin wrappers around the
// corresponding Lua C API methods.  The tests below are simple unit tests that
// ensure that these functions just delegate the calls to the Lua library.  We
// do not intend to test the validity of the methods themselves (that's the
// job of the Lua authors).  That said, we test those conditions we rely on,
// such as the reporting of errors and the default values to the API.
//
// Lastly, for every test case that stresses a single lutok::state method, we
// only call that method directly.  All other Lua state manipulation operations
// are performed by means of direct calls to the Lua C API.  This is to ensure
// that the wrapped methods are really talking to Lua.


namespace {


/// Checks if a symbol is available.
///
/// \param state The Lua state.
/// \param symbol The symbol to check for.
///
/// \return True if the symbol is defined, false otherwise.
static bool
is_available(lutok::state& state, const char* symbol)
{
    luaL_loadstring(raw(state), (std::string("return ") + symbol).c_str());
    const bool ok = (lua_pcall(raw(state), 0, 1, 0) == 0 &&
                     !lua_isnil(raw(state), -1));
    lua_pop(raw(state), 1);
    std::cout << "Symbol " << symbol << (ok ? " found\n" : " not found\n");
    return ok;
}


/// Checks that no modules are present or that only one has been loaded.
///
/// \post The test case terminates if there is any module present when expected
/// is empty or if there two modules loaded when expected is defined.
///
/// \param state The Lua state.
/// \param expected The module to expect.  Empty if no modules are allowed.
static void
check_modules(lutok::state& state, const std::string& expected)
{
    std::cout << "Checking loaded modules" <<
        (expected.empty() ? "" : (" (" + expected + " expected)")) << "\n";
    ATF_REQUIRE(!((expected == "base") ^ (is_available(state, "assert"))));
    ATF_REQUIRE(!((expected == "string") ^
                  (is_available(state, "string.byte"))));
    ATF_REQUIRE(!((expected == "table") ^
                  (is_available(state, "table.concat"))));
}


/// A C closure that returns its two integral upvalues.
///
/// \post stack(-2) contains the first upvalue.
/// \post stack(-1) contains the second upvalue.
///
/// \param raw_state The raw Lua state.
///
/// \return The number of result values, i.e. 2.
static int
c_get_upvalues(lua_State* raw_state)
{
    lutok::state state = lutok::state_c_gate::connect(raw_state);
    const int i1 = lua_tointeger(raw_state, state.upvalue_index(1));
    const int i2 = lua_tointeger(raw_state, state.upvalue_index(2));
    lua_pushinteger(raw_state, i1);
    lua_pushinteger(raw_state, i2);
    return 2;
}


/// A custom C++ multiply function with one of its factors on its closure.
///
/// \pre stack(-1) contains the second factor.
/// \post stack(-1) contains the product of the two input factors.
///
/// \param state The Lua state.
///
/// \return The number of result values, i.e. 1.
static int
cxx_multiply_closure(lutok::state& state)
{
    const int f1 = lua_tointeger(raw(state), lua_upvalueindex(1));
    const int f2 = lua_tointeger(raw(state), -1);
    lua_pushinteger(raw(state), f1 * f2);
    return 1;
}


/// A custom C++ integral division function for Lua.
///
/// \pre stack(-2) contains the dividend.
/// \pre stack(-1) contains the divisor.
/// \post stack(-2) contains the quotient of the division.
/// \post stack(-1) contains the remainder of the division.
///
/// \param state The Lua state.
///
/// \return The number of result values, i.e. 1.
///
/// \throw std::runtime_error If the divisor is zero.
/// \throw std::string If the dividend or the divisor are negative.  This is an
///     exception not derived from std::exception on purpose to ensure that the
///     C++ wrapping correctly captures any exception regardless of its type.
static int
cxx_divide(lutok::state& state)
{
    const int dividend = state.to_integer(-2);
    const int divisor = state.to_integer(-1);
    if (divisor == 0)
        throw std::runtime_error("Divisor is 0");
    if (dividend < 0 || divisor < 0)
        throw std::string("Cannot divide negative numbers");
    state.push_integer(dividend / divisor);
    state.push_integer(dividend % divisor);
    return 2;
}


/// A Lua function that raises a very long error message.
///
/// \pre stack(-1) contains the length of the message to construct.
///
/// \param state The Lua state.
///
/// \return Never returns.
///
/// \throw std::runtime_error Unconditionally, with an error message formed by
///     the repetition of 'A' as many times as requested.
static int
raise_long_error(lutok::state& state)
{
    const int length = state.to_integer(-1);
    throw std::runtime_error(std::string(length, 'A').c_str());
}


}  // anonymous namespace


ATF_TEST_CASE_WITHOUT_HEAD(close);
ATF_TEST_CASE_BODY(close)
{
    lutok::state state;
    state.close();
    // The destructor for state will run now.  If it does a second close, we may
    // crash, so let's see if we don't.
}


ATF_TEST_CASE_WITHOUT_HEAD(get_global__ok);
ATF_TEST_CASE_BODY(get_global__ok)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "test_variable = 3") == 0);
    state.get_global("test_variable");
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_global__undefined);
ATF_TEST_CASE_BODY(get_global__undefined)
{
    lutok::state state;
    state.get_global("test_variable");
    ATF_REQUIRE(lua_isnil(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_global_table);
ATF_TEST_CASE_BODY(get_global_table)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "global_variable = 'hello'") == 0);
    state.get_global_table();
    lua_pushstring(raw(state), "global_variable");
    lua_gettable(raw(state), -2);
    ATF_REQUIRE(lua_isstring(raw(state), -1));
    ATF_REQUIRE(std::strcmp("hello", lua_tostring(raw(state), -1)) == 0);
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_metafield__ok);
ATF_TEST_CASE_BODY(get_metafield__ok)
{
    lutok::state state;
    luaL_openlibs(raw(state));
    ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; "
                              "t = {}; setmetatable(t, meta)") == 0);
    lua_getglobal(raw(state), "t");
    ATF_REQUIRE(state.get_metafield(-1, "foo"));
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(567, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_metafield__undefined);
ATF_TEST_CASE_BODY(get_metafield__undefined)
{
    lutok::state state;
    luaL_openlibs(raw(state));
    ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; "
                              "t = {}; setmetatable(t, meta)") == 0);
    lua_getglobal(raw(state), "t");
    ATF_REQUIRE(!state.get_metafield(-1, "bar"));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__ok);
ATF_TEST_CASE_BODY(get_metatable__ok)
{
    lutok::state state;
    luaL_openlibs(raw(state));
    ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; "
                              "t = {}; setmetatable(t, meta)") == 0);
    lua_getglobal(raw(state), "t");
    lua_pushinteger(raw(state), 5555);
    ATF_REQUIRE(state.get_metatable(-2));
    ATF_REQUIRE(lua_istable(raw(state), -1));
    lua_pushstring(raw(state), "foo");
    lua_gettable(raw(state), -2);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(567, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 4);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__undefined);
ATF_TEST_CASE_BODY(get_metatable__undefined)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "t = {}") == 0);
    lua_getglobal(raw(state), "t");
    ATF_REQUIRE(!state.get_metatable(-1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_table__ok);
ATF_TEST_CASE_BODY(get_table__ok)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "t = { a = 1, bar = 234 }") == 0);
    lua_getglobal(raw(state), "t");
    lua_pushstring(raw(state), "bar");
    state.get_table(-2);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(234, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_table__nil);
ATF_TEST_CASE_BODY(get_table__nil)
{
    lutok::state state;
    lua_pushnil(raw(state));
    lua_pushinteger(raw(state), 1);
    REQUIRE_API_ERROR("lua_gettable", state.get_table(-2));
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_table__unknown_index);
ATF_TEST_CASE_BODY(get_table__unknown_index)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state),
                              "the_table = { foo = 1, bar = 2 }") == 0);
    lua_getglobal(raw(state), "the_table");
    lua_pushstring(raw(state), "baz");
    state.get_table(-2);
    ATF_REQUIRE(lua_isnil(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_top);
ATF_TEST_CASE_BODY(get_top)
{
    lutok::state state;
    ATF_REQUIRE_EQ(0, state.get_top());
    lua_pushinteger(raw(state), 3);
    ATF_REQUIRE_EQ(1, state.get_top());
    lua_pushinteger(raw(state), 3);
    ATF_REQUIRE_EQ(2, state.get_top());
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(insert);
ATF_TEST_CASE_BODY(insert)
{
    lutok::state state;
    lua_pushinteger(raw(state), 1);
    lua_pushinteger(raw(state), 2);
    lua_pushinteger(raw(state), 3);
    lua_pushinteger(raw(state), 4);
    state.insert(-3);
    ATF_REQUIRE_EQ(3, lua_tointeger(raw(state), -1));
    ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -2));
    ATF_REQUIRE_EQ(4, lua_tointeger(raw(state), -3));
    ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -4));
    lua_pop(raw(state), 4);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__empty);
ATF_TEST_CASE_BODY(is_boolean__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_boolean(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__ok);
ATF_TEST_CASE_BODY(is_boolean__ok)
{
    lutok::state state;
    lua_pushboolean(raw(state), 1);
    ATF_REQUIRE(state.is_boolean(-1));
    lua_pushinteger(raw(state), 5);
    ATF_REQUIRE(!state.is_boolean(-1));
    ATF_REQUIRE(state.is_boolean(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_function__empty);
ATF_TEST_CASE_BODY(is_function__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_function(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_function__ok);
ATF_TEST_CASE_BODY(is_function__ok)
{
    lutok::state state;
    luaL_dostring(raw(state), "function my_func(a, b) return a + b; end");

    lua_getglobal(raw(state), "my_func");
    ATF_REQUIRE(state.is_function(-1));
    lua_pushinteger(raw(state), 5);
    ATF_REQUIRE(!state.is_function(-1));
    ATF_REQUIRE(state.is_function(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_nil__empty);
ATF_TEST_CASE_BODY(is_nil__empty)
{
    lutok::state state;
    ATF_REQUIRE(state.is_nil(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_nil__ok);
ATF_TEST_CASE_BODY(is_nil__ok)
{
    lutok::state state;
    lua_pushnil(raw(state));
    ATF_REQUIRE(state.is_nil(-1));
    lua_pushinteger(raw(state), 5);
    ATF_REQUIRE(!state.is_nil(-1));
    ATF_REQUIRE(state.is_nil(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_number__empty);
ATF_TEST_CASE_BODY(is_number__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_number(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_number__ok);
ATF_TEST_CASE_BODY(is_number__ok)
{
    lutok::state state;
    lua_pushnil(raw(state));
    ATF_REQUIRE(!state.is_number(-1));
    lua_pushinteger(raw(state), 5);
    ATF_REQUIRE(state.is_number(-1));
    ATF_REQUIRE(!state.is_number(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_string__empty);
ATF_TEST_CASE_BODY(is_string__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_string(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_string__ok);
ATF_TEST_CASE_BODY(is_string__ok)
{
    lutok::state state;
    lua_pushinteger(raw(state), 3);
    ATF_REQUIRE(state.is_string(-1));
    lua_pushnil(raw(state));
    ATF_REQUIRE(!state.is_string(-1));
    ATF_REQUIRE(state.is_string(-2));
    lua_pushstring(raw(state), "foo");
    ATF_REQUIRE(state.is_string(-1));
    ATF_REQUIRE(!state.is_string(-2));
    ATF_REQUIRE(state.is_string(-3));
    lua_pop(raw(state), 3);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_table__empty);
ATF_TEST_CASE_BODY(is_table__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_table(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_table__ok);
ATF_TEST_CASE_BODY(is_table__ok)
{
    lutok::state state;
    luaL_dostring(raw(state), "t = {3, 4, 5}");

    lua_pushstring(raw(state), "foo");
    ATF_REQUIRE(!state.is_table(-1));
    lua_getglobal(raw(state), "t");
    ATF_REQUIRE(state.is_table(-1));
    ATF_REQUIRE(!state.is_table(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__empty);
ATF_TEST_CASE_BODY(is_userdata__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_userdata(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__ok);
ATF_TEST_CASE_BODY(is_userdata__ok)
{
    lutok::state state;

    lua_pushstring(raw(state), "foo");
    ATF_REQUIRE(!state.is_userdata(-1));
    lua_newuserdata(raw(state), 543);
    ATF_REQUIRE(state.is_userdata(-1));
    ATF_REQUIRE(!state.is_userdata(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(load_file__ok);
ATF_TEST_CASE_BODY(load_file__ok)
{
    std::ofstream output("test.lua");
    output << "in_the_file = \"oh yes\"\n";
    output.close();

    lutok::state state;
    state.load_file("test.lua");
    ATF_REQUIRE(lua_pcall(raw(state), 0, 0, 0) == 0);
    lua_getglobal(raw(state), "in_the_file");
    ATF_REQUIRE(std::strcmp("oh yes", lua_tostring(raw(state), -1)) == 0);
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(load_file__api_error);
ATF_TEST_CASE_BODY(load_file__api_error)
{
    std::ofstream output("test.lua");
    output << "I have a bad syntax!  Wohoo!\n";
    output.close();

    lutok::state state;
    REQUIRE_API_ERROR("luaL_loadfile", state.load_file("test.lua"));
}


ATF_TEST_CASE_WITHOUT_HEAD(load_file__file_not_found_error);
ATF_TEST_CASE_BODY(load_file__file_not_found_error)
{
    lutok::state state;
    ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua",
                         state.load_file("missing.lua"));
}


ATF_TEST_CASE_WITHOUT_HEAD(load_string__ok);
ATF_TEST_CASE_BODY(load_string__ok)
{
    lutok::state state;
    state.load_string("return 2 + 3");
    ATF_REQUIRE(lua_pcall(raw(state), 0, 1, 0) == 0);
    ATF_REQUIRE_EQ(5, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(load_string__fail);
ATF_TEST_CASE_BODY(load_string__fail)
{
    lutok::state state;
    REQUIRE_API_ERROR("luaL_loadstring", state.load_string("-"));
}


ATF_TEST_CASE_WITHOUT_HEAD(new_table);
ATF_TEST_CASE_BODY(new_table)
{
    lutok::state state;
    state.new_table();
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_istable(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(new_userdata);
ATF_TEST_CASE_BODY(new_userdata)
{
    lutok::state state;
    int* pointer = state.new_userdata< int >();
    *pointer = 1234;
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_isuserdata(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(next__empty);
ATF_TEST_CASE_BODY(next__empty)
{
    lutok::state state;
    luaL_dostring(raw(state), "t = {}");

    lua_getglobal(raw(state), "t");
    lua_pushstring(raw(state), "this is a dummy value");
    lua_pushnil(raw(state));
    ATF_REQUIRE(!state.next(-3));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(next__many);
ATF_TEST_CASE_BODY(next__many)
{
    lutok::state state;
    luaL_dostring(raw(state), "t = {}; t[1] = 100; t[2] = 200");

    lua_getglobal(raw(state), "t");
    lua_pushnil(raw(state));

    ATF_REQUIRE(state.next(-2));
    ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_isnumber(raw(state), -2));
    ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -2));
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(100, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);

    ATF_REQUIRE(state.next(-2));
    ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_isnumber(raw(state), -2));
    ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -2));
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(200, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);

    ATF_REQUIRE(!state.next(-2));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(open_base);
ATF_TEST_CASE_BODY(open_base)
{
    lutok::state state;
    check_modules(state, "");
    state.open_base();
    check_modules(state, "base");
}


ATF_TEST_CASE_WITHOUT_HEAD(open_all);
ATF_TEST_CASE_BODY(open_all)
{
    lutok::state state;
    check_modules(state, "");
    state.open_all();
    // Best-effort attempt at looking for a bunch of possible modules.
    ATF_REQUIRE(is_available(state, "assert"));
    ATF_REQUIRE(is_available(state, "debug.getinfo"));
    ATF_REQUIRE(is_available(state, "package.path"));
    ATF_REQUIRE(is_available(state, "string.byte"));
    ATF_REQUIRE(is_available(state, "table.concat"));
}


ATF_TEST_CASE_WITHOUT_HEAD(open_string);
ATF_TEST_CASE_BODY(open_string)
{
    lutok::state state;
    check_modules(state, "");
    state.open_string();
    check_modules(state, "string");
}


ATF_TEST_CASE_WITHOUT_HEAD(open_table);
ATF_TEST_CASE_BODY(open_table)
{
    lutok::state state;
    check_modules(state, "");
    state.open_table();
    check_modules(state, "table");
}


ATF_TEST_CASE_WITHOUT_HEAD(pcall__ok);
ATF_TEST_CASE_BODY(pcall__ok)
{
    lutok::state state;
    luaL_loadstring(raw(state), "function mul(a, b) return a * b; end");
    state.pcall(0, 0, 0);
    state.get_global_table();
    lua_pushstring(raw(state), "mul");
    lua_gettable(raw(state), -2);
    lua_pushinteger(raw(state), 3);
    lua_pushinteger(raw(state), 5);
    state.pcall(2, 1, 0);
    ATF_REQUIRE_EQ(15, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(pcall__fail);
ATF_TEST_CASE_BODY(pcall__fail)
{
    lutok::state state;
    lua_pushnil(raw(state));
    REQUIRE_API_ERROR("lua_pcall", state.pcall(0, 0, 0));
}


ATF_TEST_CASE_WITHOUT_HEAD(pop__one);
ATF_TEST_CASE_BODY(pop__one)
{
    lutok::state state;
    lua_pushinteger(raw(state), 10);
    lua_pushinteger(raw(state), 20);
    lua_pushinteger(raw(state), 30);
    state.pop(1);
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(pop__many);
ATF_TEST_CASE_BODY(pop__many)
{
    lutok::state state;
    lua_pushinteger(raw(state), 10);
    lua_pushinteger(raw(state), 20);
    lua_pushinteger(raw(state), 30);
    state.pop(2);
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_boolean);
ATF_TEST_CASE_BODY(push_boolean)
{
    lutok::state state;
    state.push_boolean(true);
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_toboolean(raw(state), -1));
    state.push_boolean(false);
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    ATF_REQUIRE(!lua_toboolean(raw(state), -1));
    ATF_REQUIRE(lua_toboolean(raw(state), -2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_closure);
ATF_TEST_CASE_BODY(push_cxx_closure)
{
    lutok::state state;
    state.push_integer(15);
    state.push_cxx_closure(cxx_multiply_closure, 1);
    lua_setglobal(raw(state), "cxx_multiply_closure");

    ATF_REQUIRE(luaL_dostring(raw(state),
                              "return cxx_multiply_closure(10)") == 0);
    ATF_REQUIRE_EQ(150, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__ok);
ATF_TEST_CASE_BODY(push_cxx_function__ok)
{
    lutok::state state;
    state.push_cxx_function(cxx_divide);
    lua_setglobal(raw(state), "cxx_divide");

    ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(17, 3)") == 0);
    ATF_REQUIRE_EQ(5, lua_tointeger(raw(state), -2));
    ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_exception);
ATF_TEST_CASE_BODY(push_cxx_function__fail_exception)
{
    lutok::state state;
    state.push_cxx_function(cxx_divide);
    lua_setglobal(raw(state), "cxx_divide");

    ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(15, 0)") != 0);
    ATF_REQUIRE_MATCH("Divisor is 0", lua_tostring(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_anything);
ATF_TEST_CASE_BODY(push_cxx_function__fail_anything)
{
    lutok::state state;
    state.push_cxx_function(cxx_divide);
    lua_setglobal(raw(state), "cxx_divide");

    ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(-3, -1)") != 0);
    ATF_REQUIRE_MATCH("Unhandled exception", lua_tostring(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_overflow);
ATF_TEST_CASE_BODY(push_cxx_function__fail_overflow)
{
    lutok::state state;
    state.push_cxx_function(raise_long_error);
    lua_setglobal(raw(state), "fail");

    ATF_REQUIRE(luaL_dostring(raw(state), "return fail(900)") != 0);
    ATF_REQUIRE_MATCH(std::string(900, 'A'), lua_tostring(raw(state), -1));
    lua_pop(raw(state), 1);

    ATF_REQUIRE(luaL_dostring(raw(state), "return fail(8192)") != 0);
    ATF_REQUIRE_MATCH(std::string(900, 'A'), lua_tostring(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_integer);
ATF_TEST_CASE_BODY(push_integer)
{
    lutok::state state;
    state.push_integer(12);
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(12, lua_tointeger(raw(state), -1));
    state.push_integer(34);
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(34, lua_tointeger(raw(state), -1));
    ATF_REQUIRE_EQ(12, lua_tointeger(raw(state), -2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_nil);
ATF_TEST_CASE_BODY(push_nil)
{
    lutok::state state;
    state.push_nil();
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_isnil(raw(state), -1));
    state.push_integer(34);
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    ATF_REQUIRE(!lua_isnil(raw(state), -1));
    ATF_REQUIRE(lua_isnil(raw(state), -2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_string);
ATF_TEST_CASE_BODY(push_string)
{
    lutok::state state;

    {
        std::string str = "first";
        state.push_string(str);
        ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
        ATF_REQUIRE_EQ(std::string("first"), lua_tostring(raw(state), -1));
        str = "second";
        state.push_string(str);
    }
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(std::string("second"), lua_tostring(raw(state), -1));
    ATF_REQUIRE_EQ(std::string("first"), lua_tostring(raw(state), -2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_value);
ATF_TEST_CASE_BODY(push_value)
{
    lutok::state state;

    lua_pushinteger(raw(state), 10);
    lua_pushinteger(raw(state), 20);
    state.push_value(-2);
    ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -1));
    ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -2));
    ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -3));
    lua_pop(raw(state), 3);
}


ATF_TEST_CASE_WITHOUT_HEAD(raw_get);
ATF_TEST_CASE_BODY(raw_get)
{
    lutok::state state;

    luaL_openlibs(raw(state));
    ATF_REQUIRE(luaL_dostring(
        raw(state), "t = {foo=123} ; setmetatable(t, {__index=1})") == 0);
    lua_getglobal(raw(state), "t");
    lua_pushinteger(raw(state), 9876);
    lua_pushstring(raw(state), "foo");
    state.raw_get(-3);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(123, lua_tointeger(raw(state), -1));
    ATF_REQUIRE_EQ(9876, lua_tointeger(raw(state), -2));
    lua_pop(raw(state), 3);
}


ATF_TEST_CASE_WITHOUT_HEAD(raw_set);
ATF_TEST_CASE_BODY(raw_set)
{
    lutok::state state;

    luaL_openlibs(raw(state));
    ATF_REQUIRE(luaL_dostring(
        raw(state), "t = {} ; setmetatable(t, {__newindex=1})") == 0);
    lua_getglobal(raw(state), "t");
    lua_pushinteger(raw(state), 876);
    lua_pushstring(raw(state), "foo");
    lua_pushinteger(raw(state), 345);
    state.raw_set(-4);
    ATF_REQUIRE(luaL_dostring(raw(state), "return t.foo") == 0);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(345, lua_tointeger(raw(state), -1));
    ATF_REQUIRE_EQ(876, lua_tointeger(raw(state), -2));
    lua_pop(raw(state), 3);
}


ATF_TEST_CASE_WITHOUT_HEAD(registry_index);
ATF_TEST_CASE_BODY(registry_index)
{
    lutok::state state;
    lua_pushvalue(raw(state), lutok::registry_index);
    lua_pushstring(raw(state), "custom_variable");
    lua_pushstring(raw(state), "custom value");
    lua_settable(raw(state), -3);
    lua_pop(raw(state), 1);
    ATF_REQUIRE(luaL_dostring(raw(state),
                              "return custom_variable == nil") == 0);
    ATF_REQUIRE(lua_isboolean(raw(state), -1));
    ATF_REQUIRE(lua_toboolean(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(set_global);
ATF_TEST_CASE_BODY(set_global)
{
    lutok::state state;
    lua_pushinteger(raw(state), 3);
    state.set_global("test_variable");
    ATF_REQUIRE(luaL_dostring(raw(state), "return test_variable + 1") == 0);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(4, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(set_metatable);
ATF_TEST_CASE_BODY(set_metatable)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(
        raw(state),
        "mt = {}\n"
        "mt.__add = function(a, b) return a[1] + b end\n"
        "numbers = {}\n"
        "numbers[1] = 5\n") == 0);

    lua_getglobal(raw(state), "numbers");
    lua_pushinteger(raw(state), 1234);
    lua_getglobal(raw(state), "mt");
    state.set_metatable(-3);
    lua_pop(raw(state), 2);

    ATF_REQUIRE(luaL_dostring(raw(state), "return numbers + 2") == 0);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(7, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(set_table__ok);
ATF_TEST_CASE_BODY(set_table__ok)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "t = { a = 1, bar = 234 }") == 0);
    lua_getglobal(raw(state), "t");

    lua_pushstring(raw(state), "bar");
    lua_pushstring(raw(state), "baz");
    state.set_table(-3);
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));

    lua_pushstring(raw(state), "a");
    lua_gettable(raw(state), -2);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);

    lua_pushstring(raw(state), "bar");
    lua_gettable(raw(state), -2);
    ATF_REQUIRE(lua_isstring(raw(state), -1));
    ATF_REQUIRE_EQ(std::string("baz"), lua_tostring(raw(state), -1));
    lua_pop(raw(state), 1);

    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(set_table__nil);
ATF_TEST_CASE_BODY(set_table__nil)
{
    lutok::state state;
    lua_pushnil(raw(state));
    lua_pushinteger(raw(state), 1);
    lua_pushinteger(raw(state), 2);
    REQUIRE_API_ERROR("lua_settable", state.set_table(-3));
    lua_pop(raw(state), 3);
}


ATF_TEST_CASE_WITHOUT_HEAD(to_boolean);
ATF_TEST_CASE_BODY(to_boolean)
{
    lutok::state state;
    lua_pushboolean(raw(state), 0);
    lua_pushboolean(raw(state), 1);
    ATF_REQUIRE(!state.to_boolean(-2));
    ATF_REQUIRE(state.to_boolean(-1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(to_integer);
ATF_TEST_CASE_BODY(to_integer)
{
    lutok::state state;
    lua_pushinteger(raw(state), 12);
    lua_pushstring(raw(state), "foobar");
    ATF_REQUIRE_EQ(12, state.to_integer(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(to_string);
ATF_TEST_CASE_BODY(to_string)
{
    lutok::state state;
    lua_pushstring(raw(state), "foobar");
    lua_pushinteger(raw(state), 12);
    ATF_REQUIRE_EQ("foobar", state.to_string(-2));
    ATF_REQUIRE_EQ("12", state.to_string(-1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(to_userdata);
ATF_TEST_CASE_BODY(to_userdata)
{
    lutok::state state;
    {
        int* pointer = static_cast< int* >(
            lua_newuserdata(raw(state), sizeof(int)));
        *pointer = 987;
    }

    lua_pushinteger(raw(state), 3);
    int* pointer = state.to_userdata< int >(-2);
    ATF_REQUIRE_EQ(987, *pointer);
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(upvalue_index);
ATF_TEST_CASE_BODY(upvalue_index)
{
    lutok::state state;
    lua_pushinteger(raw(state), 25);
    lua_pushinteger(raw(state), 30);
    lua_pushcclosure(raw(state), c_get_upvalues, 2);
    lua_setglobal(raw(state), "c_get_upvalues");

    ATF_REQUIRE(luaL_dostring(raw(state),
                              "return c_get_upvalues()") == 0);
    ATF_REQUIRE_EQ(25, lua_tointeger(raw(state), -2));
    ATF_REQUIRE_EQ(30, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, close);
    ATF_ADD_TEST_CASE(tcs, get_global__ok);
    ATF_ADD_TEST_CASE(tcs, get_global__undefined);
    ATF_ADD_TEST_CASE(tcs, get_global_table);
    ATF_ADD_TEST_CASE(tcs, get_metafield__ok);
    ATF_ADD_TEST_CASE(tcs, get_metafield__undefined);
    ATF_ADD_TEST_CASE(tcs, get_metatable__ok);
    ATF_ADD_TEST_CASE(tcs, get_metatable__undefined);
    ATF_ADD_TEST_CASE(tcs, get_table__ok);
    ATF_ADD_TEST_CASE(tcs, get_table__nil);
    ATF_ADD_TEST_CASE(tcs, get_table__unknown_index);
    ATF_ADD_TEST_CASE(tcs, get_top);
    ATF_ADD_TEST_CASE(tcs, insert);
    ATF_ADD_TEST_CASE(tcs, is_boolean__empty);
    ATF_ADD_TEST_CASE(tcs, is_boolean__ok);
    ATF_ADD_TEST_CASE(tcs, is_function__empty);
    ATF_ADD_TEST_CASE(tcs, is_function__ok);
    ATF_ADD_TEST_CASE(tcs, is_nil__empty);
    ATF_ADD_TEST_CASE(tcs, is_nil__ok);
    ATF_ADD_TEST_CASE(tcs, is_number__empty);
    ATF_ADD_TEST_CASE(tcs, is_number__ok);
    ATF_ADD_TEST_CASE(tcs, is_string__empty);
    ATF_ADD_TEST_CASE(tcs, is_string__ok);
    ATF_ADD_TEST_CASE(tcs, is_table__empty);
    ATF_ADD_TEST_CASE(tcs, is_table__ok);
    ATF_ADD_TEST_CASE(tcs, is_userdata__empty);
    ATF_ADD_TEST_CASE(tcs, is_userdata__ok);
    ATF_ADD_TEST_CASE(tcs, load_file__ok);
    ATF_ADD_TEST_CASE(tcs, load_file__api_error);
    ATF_ADD_TEST_CASE(tcs, load_file__file_not_found_error);
    ATF_ADD_TEST_CASE(tcs, load_string__ok);
    ATF_ADD_TEST_CASE(tcs, load_string__fail);
    ATF_ADD_TEST_CASE(tcs, new_table);
    ATF_ADD_TEST_CASE(tcs, new_userdata);
    ATF_ADD_TEST_CASE(tcs, next__empty);
    ATF_ADD_TEST_CASE(tcs, next__many);
    ATF_ADD_TEST_CASE(tcs, open_all);
    ATF_ADD_TEST_CASE(tcs, open_base);
    ATF_ADD_TEST_CASE(tcs, open_string);
    ATF_ADD_TEST_CASE(tcs, open_table);
    ATF_ADD_TEST_CASE(tcs, pcall__ok);
    ATF_ADD_TEST_CASE(tcs, pcall__fail);
    ATF_ADD_TEST_CASE(tcs, pop__one);
    ATF_ADD_TEST_CASE(tcs, pop__many);
    ATF_ADD_TEST_CASE(tcs, push_boolean);
    ATF_ADD_TEST_CASE(tcs, push_cxx_closure);
    ATF_ADD_TEST_CASE(tcs, push_cxx_function__ok);
    ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_exception);
    ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_anything);
    ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_overflow);
    ATF_ADD_TEST_CASE(tcs, push_integer);
    ATF_ADD_TEST_CASE(tcs, push_nil);
    ATF_ADD_TEST_CASE(tcs, push_string);
    ATF_ADD_TEST_CASE(tcs, push_value);
    ATF_ADD_TEST_CASE(tcs, raw_get);
    ATF_ADD_TEST_CASE(tcs, raw_set);
    ATF_ADD_TEST_CASE(tcs, registry_index);
    ATF_ADD_TEST_CASE(tcs, set_global);
    ATF_ADD_TEST_CASE(tcs, set_metatable);
    ATF_ADD_TEST_CASE(tcs, set_table__ok);
    ATF_ADD_TEST_CASE(tcs, set_table__nil);
    ATF_ADD_TEST_CASE(tcs, to_boolean);
    ATF_ADD_TEST_CASE(tcs, to_integer);
    ATF_ADD_TEST_CASE(tcs, to_string);
    ATF_ADD_TEST_CASE(tcs, to_userdata);
    ATF_ADD_TEST_CASE(tcs, upvalue_index);
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted test_utils.hpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// \file test_utils.hpp
/// Utilities for tests of the lua modules.
///
/// This file is intended to be included once, and only once, for every test
/// program that needs it.  All the code is herein contained to simplify the
/// dependency chain in the build rules.

#if !defined(LUTOK_TEST_UTILS_HPP)
#   define LUTOK_TEST_UTILS_HPP
#else
#   error "test_utils.hpp can only be included once"
#endif

#include <atf-c++.hpp>

#include "c_gate.hpp"
#include "exceptions.hpp"
#include "state.hpp"


namespace {


/// Checks that a given expression raises a particular lutok::api_error.
///
/// We cannot make any assumptions regarding the error text provided by Lua, so
/// we resort to checking only which API function raised the error (because our
/// code is the one hardcoding these strings).
///
/// \param exp_api_function The name of the Lua C API function that causes the
///     error.
/// \param statement The statement to execute.
#define REQUIRE_API_ERROR(exp_api_function, statement) \
    do { \
        try { \
            statement; \
            ATF_FAIL("api_error not raised by " #statement); \
        } catch (const lutok::api_error& api_error) { \
            ATF_REQUIRE_EQ(exp_api_function, api_error.api_function()); \
        } \
    } while (0)


/// Gets the pointer to the internal lua_State of a state object.
///
/// This is pure syntactic sugar to simplify typing in the test cases.
///
/// \param state The Lua state.
///
/// \return The internal lua_State of the input Lua state.
static inline lua_State*
raw(lutok::state& state)
{
    return lutok::state_c_gate(state).c_state();
}


/// Ensures that the Lua stack maintains its original height upon exit.
///
/// Use an instance of this class to check that a piece of code does not have
/// side-effects on the Lua stack.
///
/// To be used within a test case only.
class stack_balance_checker {
    /// The Lua state.
    lutok::state& _state;

    /// Whether to install a sentinel on the stack for balance enforcement.
    bool _with_sentinel;

    /// The height of the stack on creation.
    unsigned int _old_count;

public:
    /// Constructs a new stack balance checker.
    ///
    /// \param state_ The Lua state to validate.
    /// \param with_sentinel_ If true, insert a sentinel item into the stack and
    ///     validate upon exit that the item is still there.  This is an attempt
    ///     to ensure that already-existing items are not removed from the stack
    ///     by the code under test.
    stack_balance_checker(lutok::state& state_,
                          const bool with_sentinel_ = true) :
        _state(state_),
        _with_sentinel(with_sentinel_),
        _old_count(_state.get_top())
    {
        if (_with_sentinel)
            _state.push_integer(987654321);
    }

    /// Destructor for the object.
    ///
    /// If the stack height does not match the height when the instance was
    /// created, this fails the test case.
    ~stack_balance_checker(void)
    {
        if (_with_sentinel) {
            if (!_state.is_number(-1) || _state.to_integer(-1) != 987654321)
                ATF_FAIL("Stack corrupted: sentinel not found");
            _state.pop(1);
        }

        unsigned int new_count = _state.get_top();
        if (_old_count != new_count)
            //ATF_FAIL(F("Stack not balanced: before %d, after %d") %
            //         _old_count % new_count);
            ATF_FAIL("Stack not balanced");
    }
};


}  // anonymous namespace
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































































































































































































Added tests/c_gate_test.cpp.





















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "xlua/c_gate.hpp"

#include <atf-c++.hpp>
#include <lua.hpp>

#include "xlua/state.ipp"
#include "xlua/test_utils.hpp"


ATF_TEST_CASE_WITHOUT_HEAD(connect);
ATF_TEST_CASE_BODY(connect)
{
    lua_State* raw_state = luaL_newstate();
    ATF_REQUIRE(raw_state != NULL);

    {
        lutok::state state = lutok::state_c_gate::connect(raw_state);
        lua_pushinteger(raw(state), 123);
    }
    // If the wrapper object had closed the Lua state, we could very well crash
    // here.
    ATF_REQUIRE_EQ(123, lua_tointeger(raw_state, -1));

    lua_close(raw_state);
}


ATF_TEST_CASE_WITHOUT_HEAD(c_state);
ATF_TEST_CASE_BODY(c_state)
{
    lutok::state state;
    state.push_integer(5);
    {
        lutok::state_c_gate gate(state);
        lua_State* raw_state = gate.c_state();
        ATF_REQUIRE_EQ(5, lua_tointeger(raw_state, -1));
    }
    state.pop(1);
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, c_state);
    ATF_ADD_TEST_CASE(tcs, connect);
}

Added tests/debug_test.cpp.









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "xlua/debug.hpp"

#include <xlua/atf-c++.hpp>
#include <lua.hpp>

#include "xlua/state.ipp"
#include "xlua/test_utils.hpp"


ATF_TEST_CASE_WITHOUT_HEAD(get_info);
ATF_TEST_CASE_BODY(get_info)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "\n\nfunction hello() end\n"
                              "return hello") == 0);
    lutok::debug debug;
    debug.get_info(state, ">S");
    ATF_REQUIRE_EQ(3, debug.line_defined());
}


ATF_TEST_CASE_WITHOUT_HEAD(get_stack);
ATF_TEST_CASE_BODY(get_stack)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "error('Hello')") == 1);
    lutok::debug debug;
    debug.get_stack(state, 0);
    lua_pop(raw(state), 1);
    // Not sure if we can actually validate anything here, other than we did not
    // crash... (because get_stack only is supposed to update internal values of
    // the debug structure).
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, get_info);
    ATF_ADD_TEST_CASE(tcs, get_stack);
}

Added tests/exceptions_test.cpp.

















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "xlua/exceptions.hpp"

#include <cstring>

#include <atf-c++.hpp>

#include "xlua/state.ipp"


ATF_TEST_CASE_WITHOUT_HEAD(error);
ATF_TEST_CASE_BODY(error)
{
    const lutok::error e("Some text");
    ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0);
}


ATF_TEST_CASE_WITHOUT_HEAD(api_error__explicit);
ATF_TEST_CASE_BODY(api_error__explicit)
{
    const lutok::api_error e("some_function", "Some text");
    ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0);
    ATF_REQUIRE_EQ("some_function", e.api_function());
}


ATF_TEST_CASE_WITHOUT_HEAD(api_error__from_stack);
ATF_TEST_CASE_BODY(api_error__from_stack)
{
    lutok::state state;
    state.push_integer(123);
    state.push_string("The error message");
    const lutok::api_error e = lutok::api_error::from_stack(state,
                                                            "the_function");
    ATF_REQUIRE_EQ(1, state.get_top());
    ATF_REQUIRE_EQ(123, state.to_integer(-1));
    state.pop(1);
    ATF_REQUIRE(std::strcmp("The error message", e.what()) == 0);
    ATF_REQUIRE_EQ("the_function", e.api_function());
}


ATF_TEST_CASE_WITHOUT_HEAD(file_not_found_error);
ATF_TEST_CASE_BODY(file_not_found_error)
{
    const lutok::file_not_found_error e("missing-file");
    ATF_REQUIRE(std::strcmp("File 'missing-file' not found", e.what()) == 0);
    ATF_REQUIRE_EQ("missing-file", e.filename());
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, error);

    ATF_ADD_TEST_CASE(tcs, api_error__explicit);
    ATF_ADD_TEST_CASE(tcs, api_error__from_stack);

    ATF_ADD_TEST_CASE(tcs, file_not_found_error);
}

Added tests/operations_test.cpp.









































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "xlua/operations.hpp"

#include <fstream>

#include <atf-c++.hpp>

#include "xlua/exceptions.hpp"
#include "xlua/state.ipp"
#include "xlua/test_utils.hpp"


namespace {


/// Addition function for injection into Lua.
///
/// \pre stack(-2) The first summand.
/// \pre stack(-1) The second summand.
/// \post stack(-1) The result of the sum.
///
/// \param state The Lua state.
///
/// \return The number of results (1).
static int
hook_add(lutok::state& state)
{
    state.push_integer(state.to_integer(-1) + state.to_integer(-2));
    return 1;
}


/// Multiplication function for injection into Lua.
///
/// \pre stack(-2) The first factor.
/// \pre stack(-1) The second factor.
/// \post stack(-1) The product.
///
/// \param state The Lua state.
///
/// \return The number of results (1).
static int
hook_multiply(lutok::state& state)
{
    state.push_integer(state.to_integer(-1) * state.to_integer(-2));
    return 1;
}


}  // anonymous namespace


ATF_TEST_CASE_WITHOUT_HEAD(create_module__empty);
ATF_TEST_CASE_BODY(create_module__empty)
{
    lutok::state state;
    std::map< std::string, lutok::cxx_function > members;
    lutok::create_module(state, "my_math", members);

    state.open_base();
    lutok::do_string(state, "return next(my_math) == nil", 0, 1, 0);
    ATF_REQUIRE(state.to_boolean(-1));
    state.pop(1);
}


ATF_TEST_CASE_WITHOUT_HEAD(create_module__one);
ATF_TEST_CASE_BODY(create_module__one)
{
    lutok::state state;
    std::map< std::string, lutok::cxx_function > members;
    members["add"] = hook_add;
    lutok::create_module(state, "my_math", members);

    lutok::do_string(state, "return my_math.add(10, 20)", 0, 1, 0);
    ATF_REQUIRE_EQ(30, state.to_integer(-1));
    state.pop(1);
}


ATF_TEST_CASE_WITHOUT_HEAD(create_module__many);
ATF_TEST_CASE_BODY(create_module__many)
{
    lutok::state state;
    std::map< std::string, lutok::cxx_function > members;
    members["add"] = hook_add;
    members["multiply"] = hook_multiply;
    members["add2"] = hook_add;
    lutok::create_module(state, "my_math", members);

    lutok::do_string(state, "return my_math.add(10, 20)", 0, 1, 0);
    ATF_REQUIRE_EQ(30, state.to_integer(-1));
    lutok::do_string(state, "return my_math.multiply(10, 20)", 0, 1, 0);
    ATF_REQUIRE_EQ(200, state.to_integer(-1));
    lutok::do_string(state, "return my_math.add2(20, 30)", 0, 1, 0);
    ATF_REQUIRE_EQ(50, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__some_args);
ATF_TEST_CASE_BODY(do_file__some_args)
{
    std::ofstream output("test.lua");
    output << "local a1, a2 = ...\nreturn a1 * 2, a2 * 2\n";
    output.close();

    lutok::state state;
    state.push_integer(456);
    state.push_integer(3);
    state.push_integer(5);
    state.push_integer(123);
    ATF_REQUIRE_EQ(2, lutok::do_file(state, "test.lua", 3, -1, 0));
    ATF_REQUIRE_EQ(3, state.get_top());
    ATF_REQUIRE_EQ(456, state.to_integer(-3));
    ATF_REQUIRE_EQ(6, state.to_integer(-2));
    ATF_REQUIRE_EQ(10, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__any_results);
ATF_TEST_CASE_BODY(do_file__any_results)
{
    std::ofstream output("test.lua");
    output << "return 10, 20, 30\n";
    output.close();

    lutok::state state;
    ATF_REQUIRE_EQ(3, lutok::do_file(state, "test.lua", 0, -1, 0));
    ATF_REQUIRE_EQ(3, state.get_top());
    ATF_REQUIRE_EQ(10, state.to_integer(-3));
    ATF_REQUIRE_EQ(20, state.to_integer(-2));
    ATF_REQUIRE_EQ(30, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__no_results);
ATF_TEST_CASE_BODY(do_file__no_results)
{
    std::ofstream output("test.lua");
    output << "return 10, 20, 30\n";
    output.close();

    lutok::state state;
    ATF_REQUIRE_EQ(0, lutok::do_file(state, "test.lua", 0, 0, 0));
    ATF_REQUIRE_EQ(0, state.get_top());
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__many_results);
ATF_TEST_CASE_BODY(do_file__many_results)
{
    std::ofstream output("test.lua");
    output << "return 10, 20, 30\n";
    output.close();

    lutok::state state;
    ATF_REQUIRE_EQ(2, lutok::do_file(state, "test.lua", 0, 2, 0));
    ATF_REQUIRE_EQ(2, state.get_top());
    ATF_REQUIRE_EQ(10, state.to_integer(-2));
    ATF_REQUIRE_EQ(20, state.to_integer(-1));
    state.pop(2);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__not_found);
ATF_TEST_CASE_BODY(do_file__not_found)
{
    lutok::state state;
    stack_balance_checker checker(state);
    ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua",
                         lutok::do_file(state, "missing.lua", 0, 0, 0));
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__error);
ATF_TEST_CASE_BODY(do_file__error)
{
    std::ofstream output("test.lua");
    output << "a b c\n";
    output.close();

    lutok::state state;
    stack_balance_checker checker(state);
    ATF_REQUIRE_THROW_RE(lutok::error, "Failed to load Lua file 'test.lua'",
                         lutok::do_file(state, "test.lua", 0, 0, 0));
}


ATF_TEST_CASE_WITHOUT_HEAD(do_file__error_with_errfunc);
ATF_TEST_CASE_BODY(do_file__error_with_errfunc)
{
    std::ofstream output("test.lua");
    output << "unknown_function()\n";
    output.close();

    lutok::state state;
    lutok::eval(state, "function(message) return 'This is an error!' end", 1);
    {
        stack_balance_checker checker(state);
        ATF_REQUIRE_THROW_RE(lutok::error, "This is an error!",
                             lutok::do_file(state, "test.lua", 0, 0, -2));
    }
    state.pop(1);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__some_args);
ATF_TEST_CASE_BODY(do_string__some_args)
{
    lutok::state state;
    state.push_integer(456);
    state.push_integer(3);
    state.push_integer(5);
    state.push_integer(123);
    ATF_REQUIRE_EQ(2, lutok::do_string(
        state, "local a1, a2 = ...\nreturn a1 * 2, a2 * 2\n", 3, -1, 0));
    ATF_REQUIRE_EQ(3, state.get_top());
    ATF_REQUIRE_EQ(456, state.to_integer(-3));
    ATF_REQUIRE_EQ(6, state.to_integer(-2));
    ATF_REQUIRE_EQ(10, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__any_results);
ATF_TEST_CASE_BODY(do_string__any_results)
{
    lutok::state state;
    ATF_REQUIRE_EQ(3, lutok::do_string(state, "return 10, 20, 30", 0, -1, 0));
    ATF_REQUIRE_EQ(3, state.get_top());
    ATF_REQUIRE_EQ(10, state.to_integer(-3));
    ATF_REQUIRE_EQ(20, state.to_integer(-2));
    ATF_REQUIRE_EQ(30, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__no_results);
ATF_TEST_CASE_BODY(do_string__no_results)
{
    lutok::state state;
    ATF_REQUIRE_EQ(0, lutok::do_string(state, "return 10, 20, 30", 0, 0, 0));
    ATF_REQUIRE_EQ(0, state.get_top());
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__many_results);
ATF_TEST_CASE_BODY(do_string__many_results)
{
    lutok::state state;
    ATF_REQUIRE_EQ(2, lutok::do_string(state, "return 10, 20, 30", 0, 2, 0));
    ATF_REQUIRE_EQ(2, state.get_top());
    ATF_REQUIRE_EQ(10, state.to_integer(-2));
    ATF_REQUIRE_EQ(20, state.to_integer(-1));
    state.pop(2);
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__error);
ATF_TEST_CASE_BODY(do_string__error)
{
    lutok::state state;
    stack_balance_checker checker(state);
    ATF_REQUIRE_THROW_RE(lutok::error, "Failed to process Lua string 'a b c'",
                         lutok::do_string(state, "a b c", 0, 0, 0));
}


ATF_TEST_CASE_WITHOUT_HEAD(do_string__error_with_errfunc);
ATF_TEST_CASE_BODY(do_string__error_with_errfunc)
{
    lutok::state state;
    lutok::eval(state, "function(message) return 'This is an error!' end", 1);
    {
        stack_balance_checker checker(state);
        ATF_REQUIRE_THROW_RE(lutok::error, "This is an error!",
                             lutok::do_string(state, "unknown_function()",
                                              0, 0, -2));
    }
    state.pop(1);
}


ATF_TEST_CASE_WITHOUT_HEAD(eval__one_result);
ATF_TEST_CASE_BODY(eval__one_result)
{
    lutok::state state;
    stack_balance_checker checker(state);
    lutok::eval(state, "3 + 10", 1);
    ATF_REQUIRE_EQ(13, state.to_integer(-1));
    state.pop(1);
}


ATF_TEST_CASE_WITHOUT_HEAD(eval__many_results);
ATF_TEST_CASE_BODY(eval__many_results)
{
    lutok::state state;
    stack_balance_checker checker(state);
    lutok::eval(state, "5, 8, 10", 3);
    ATF_REQUIRE_EQ(5, state.to_integer(-3));
    ATF_REQUIRE_EQ(8, state.to_integer(-2));
    ATF_REQUIRE_EQ(10, state.to_integer(-1));
    state.pop(3);
}


ATF_TEST_CASE_WITHOUT_HEAD(eval__error);
ATF_TEST_CASE_BODY(eval__error)
{
    lutok::state state;
    stack_balance_checker checker(state);
    ATF_REQUIRE_THROW(lutok::error,
                      lutok::eval(state, "non_existent.method()", 1));
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, create_module__empty);
    ATF_ADD_TEST_CASE(tcs, create_module__one);
    ATF_ADD_TEST_CASE(tcs, create_module__many);

    ATF_ADD_TEST_CASE(tcs, do_file__some_args);
    ATF_ADD_TEST_CASE(tcs, do_file__any_results);
    ATF_ADD_TEST_CASE(tcs, do_file__no_results);
    ATF_ADD_TEST_CASE(tcs, do_file__many_results);
    ATF_ADD_TEST_CASE(tcs, do_file__not_found);
    ATF_ADD_TEST_CASE(tcs, do_file__error);
    ATF_ADD_TEST_CASE(tcs, do_file__error_with_errfunc);

    ATF_ADD_TEST_CASE(tcs, do_string__some_args);
    ATF_ADD_TEST_CASE(tcs, do_string__any_results);
    ATF_ADD_TEST_CASE(tcs, do_string__no_results);
    ATF_ADD_TEST_CASE(tcs, do_string__many_results);
    ATF_ADD_TEST_CASE(tcs, do_string__error);
    ATF_ADD_TEST_CASE(tcs, do_string__error_with_errfunc);

    ATF_ADD_TEST_CASE(tcs, eval__one_result);
    ATF_ADD_TEST_CASE(tcs, eval__many_results);
    ATF_ADD_TEST_CASE(tcs, eval__error);
}

Added tests/stack_cleaner_test.cpp.

























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "xlua/stack_cleaner.hpp"

#include <atf-c++.hpp>


ATF_TEST_CASE_WITHOUT_HEAD(empty);
ATF_TEST_CASE_BODY(empty)
{
    lutok::state state;
    {
        lutok::stack_cleaner cleaner(state);
        ATF_REQUIRE_EQ(0, state.get_top());
    }
    ATF_REQUIRE_EQ(0, state.get_top());
}


ATF_TEST_CASE_WITHOUT_HEAD(some);
ATF_TEST_CASE_BODY(some)
{
    lutok::state state;
    {
        lutok::stack_cleaner cleaner(state);
        state.push_integer(15);
        ATF_REQUIRE_EQ(1, state.get_top());
        state.push_integer(30);
        ATF_REQUIRE_EQ(2, state.get_top());
    }
    ATF_REQUIRE_EQ(0, state.get_top());
}


ATF_TEST_CASE_WITHOUT_HEAD(nested);
ATF_TEST_CASE_BODY(nested)
{
    lutok::state state;
    {
        lutok::stack_cleaner cleaner1(state);
        state.push_integer(10);
        ATF_REQUIRE_EQ(1, state.get_top());
        ATF_REQUIRE_EQ(10, state.to_integer(-1));
        {
            lutok::stack_cleaner cleaner2(state);
            state.push_integer(20);
            ATF_REQUIRE_EQ(2, state.get_top());
            ATF_REQUIRE_EQ(20, state.to_integer(-1));
            ATF_REQUIRE_EQ(10, state.to_integer(-2));
        }
        ATF_REQUIRE_EQ(1, state.get_top());
        ATF_REQUIRE_EQ(10, state.to_integer(-1));
    }
    ATF_REQUIRE_EQ(0, state.get_top());
}


ATF_TEST_CASE_WITHOUT_HEAD(forget);
ATF_TEST_CASE_BODY(forget)
{
    lutok::state state;
    {
        lutok::stack_cleaner cleaner(state);
        state.push_integer(15);
        state.push_integer(30);
        cleaner.forget();
        state.push_integer(60);
        ATF_REQUIRE_EQ(3, state.get_top());
    }
    ATF_REQUIRE_EQ(2, state.get_top());
    ATF_REQUIRE_EQ(30, state.to_integer(-1));
    state.pop(2);
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, empty);
    ATF_ADD_TEST_CASE(tcs, some);
    ATF_ADD_TEST_CASE(tcs, nested);
    ATF_ADD_TEST_CASE(tcs, forget);
}

Added tests/state_test.cpp.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
// Copyright 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "xlua/state.ipp"

#include <cstring>
#include <fstream>
#include <iostream>
#include <stdexcept>

#include <atf-c++.hpp>
#include <lua.hpp>

#include "xlua/c_gate.hpp"
#include "xlua/exceptions.hpp"
#include "xlua/test_utils.hpp"


// A note about the lutok::state tests.
//
// The methods of lutok::state are, in general, thin wrappers around the
// corresponding Lua C API methods.  The tests below are simple unit tests that
// ensure that these functions just delegate the calls to the Lua library.  We
// do not intend to test the validity of the methods themselves (that's the
// job of the Lua authors).  That said, we test those conditions we rely on,
// such as the reporting of errors and the default values to the API.
//
// Lastly, for every test case that stresses a single lutok::state method, we
// only call that method directly.  All other Lua state manipulation operations
// are performed by means of direct calls to the Lua C API.  This is to ensure
// that the wrapped methods are really talking to Lua.


namespace {


/// Checks if a symbol is available.
///
/// \param state The Lua state.
/// \param symbol The symbol to check for.
///
/// \return True if the symbol is defined, false otherwise.
static bool
is_available(lutok::state& state, const char* symbol)
{
    luaL_loadstring(raw(state), (std::string("return ") + symbol).c_str());
    const bool ok = (lua_pcall(raw(state), 0, 1, 0) == 0 &&
                     !lua_isnil(raw(state), -1));
    lua_pop(raw(state), 1);
    std::cout << "Symbol " << symbol << (ok ? " found\n" : " not found\n");
    return ok;
}


/// Checks that no modules are present or that only one has been loaded.
///
/// \post The test case terminates if there is any module present when expected
/// is empty or if there two modules loaded when expected is defined.
///
/// \param state The Lua state.
/// \param expected The module to expect.  Empty if no modules are allowed.
static void
check_modules(lutok::state& state, const std::string& expected)
{
    std::cout << "Checking loaded modules" <<
        (expected.empty() ? "" : (" (" + expected + " expected)")) << "\n";
    ATF_REQUIRE(!((expected == "base") ^ (is_available(state, "assert"))));
    ATF_REQUIRE(!((expected == "string") ^
                  (is_available(state, "string.byte"))));
    ATF_REQUIRE(!((expected == "table") ^
                  (is_available(state, "table.concat"))));
}


/// A C closure that returns its two integral upvalues.
///
/// \post stack(-2) contains the first upvalue.
/// \post stack(-1) contains the second upvalue.
///
/// \param raw_state The raw Lua state.
///
/// \return The number of result values, i.e. 2.
static int
c_get_upvalues(lua_State* raw_state)
{
    lutok::state state = lutok::state_c_gate::connect(raw_state);
    const int i1 = lua_tointeger(raw_state, state.upvalue_index(1));
    const int i2 = lua_tointeger(raw_state, state.upvalue_index(2));
    lua_pushinteger(raw_state, i1);
    lua_pushinteger(raw_state, i2);
    return 2;
}


/// A custom C++ multiply function with one of its factors on its closure.
///
/// \pre stack(-1) contains the second factor.
/// \post stack(-1) contains the product of the two input factors.
///
/// \param state The Lua state.
///
/// \return The number of result values, i.e. 1.
static int
cxx_multiply_closure(lutok::state& state)
{
    const int f1 = lua_tointeger(raw(state), lua_upvalueindex(1));
    const int f2 = lua_tointeger(raw(state), -1);
    lua_pushinteger(raw(state), f1 * f2);
    return 1;
}


/// A custom C++ integral division function for Lua.
///
/// \pre stack(-2) contains the dividend.
/// \pre stack(-1) contains the divisor.
/// \post stack(-2) contains the quotient of the division.
/// \post stack(-1) contains the remainder of the division.
///
/// \param state The Lua state.
///
/// \return The number of result values, i.e. 1.
///
/// \throw std::runtime_error If the divisor is zero.
/// \throw std::string If the dividend or the divisor are negative.  This is an
///     exception not derived from std::exception on purpose to ensure that the
///     C++ wrapping correctly captures any exception regardless of its type.
static int
cxx_divide(lutok::state& state)
{
    const int dividend = state.to_integer(-2);
    const int divisor = state.to_integer(-1);
    if (divisor == 0)
        throw std::runtime_error("Divisor is 0");
    if (dividend < 0 || divisor < 0)
        throw std::string("Cannot divide negative numbers");
    state.push_integer(dividend / divisor);
    state.push_integer(dividend % divisor);
    return 2;
}


/// A Lua function that raises a very long error message.
///
/// \pre stack(-1) contains the length of the message to construct.
///
/// \param state The Lua state.
///
/// \return Never returns.
///
/// \throw std::runtime_error Unconditionally, with an error message formed by
///     the repetition of 'A' as many times as requested.
static int
raise_long_error(lutok::state& state)
{
    const int length = state.to_integer(-1);
    throw std::runtime_error(std::string(length, 'A').c_str());
}


}  // anonymous namespace


ATF_TEST_CASE_WITHOUT_HEAD(close);
ATF_TEST_CASE_BODY(close)
{
    lutok::state state;
    state.close();
    // The destructor for state will run now.  If it does a second close, we may
    // crash, so let's see if we don't.
}


ATF_TEST_CASE_WITHOUT_HEAD(get_global__ok);
ATF_TEST_CASE_BODY(get_global__ok)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "test_variable = 3") == 0);
    state.get_global("test_variable");
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_global__undefined);
ATF_TEST_CASE_BODY(get_global__undefined)
{
    lutok::state state;
    state.get_global("test_variable");
    ATF_REQUIRE(lua_isnil(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_global_table);
ATF_TEST_CASE_BODY(get_global_table)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "global_variable = 'hello'") == 0);
    state.get_global_table();
    lua_pushstring(raw(state), "global_variable");
    lua_gettable(raw(state), -2);
    ATF_REQUIRE(lua_isstring(raw(state), -1));
    ATF_REQUIRE(std::strcmp("hello", lua_tostring(raw(state), -1)) == 0);
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_metafield__ok);
ATF_TEST_CASE_BODY(get_metafield__ok)
{
    lutok::state state;
    luaL_openlibs(raw(state));
    ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; "
                              "t = {}; setmetatable(t, meta)") == 0);
    lua_getglobal(raw(state), "t");
    ATF_REQUIRE(state.get_metafield(-1, "foo"));
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(567, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_metafield__undefined);
ATF_TEST_CASE_BODY(get_metafield__undefined)
{
    lutok::state state;
    luaL_openlibs(raw(state));
    ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; "
                              "t = {}; setmetatable(t, meta)") == 0);
    lua_getglobal(raw(state), "t");
    ATF_REQUIRE(!state.get_metafield(-1, "bar"));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__ok);
ATF_TEST_CASE_BODY(get_metatable__ok)
{
    lutok::state state;
    luaL_openlibs(raw(state));
    ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; "
                              "t = {}; setmetatable(t, meta)") == 0);
    lua_getglobal(raw(state), "t");
    lua_pushinteger(raw(state), 5555);
    ATF_REQUIRE(state.get_metatable(-2));
    ATF_REQUIRE(lua_istable(raw(state), -1));
    lua_pushstring(raw(state), "foo");
    lua_gettable(raw(state), -2);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(567, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 4);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__undefined);
ATF_TEST_CASE_BODY(get_metatable__undefined)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "t = {}") == 0);
    lua_getglobal(raw(state), "t");
    ATF_REQUIRE(!state.get_metatable(-1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_table__ok);
ATF_TEST_CASE_BODY(get_table__ok)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "t = { a = 1, bar = 234 }") == 0);
    lua_getglobal(raw(state), "t");
    lua_pushstring(raw(state), "bar");
    state.get_table(-2);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(234, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_table__nil);
ATF_TEST_CASE_BODY(get_table__nil)
{
    lutok::state state;
    lua_pushnil(raw(state));
    lua_pushinteger(raw(state), 1);
    REQUIRE_API_ERROR("lua_gettable", state.get_table(-2));
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_table__unknown_index);
ATF_TEST_CASE_BODY(get_table__unknown_index)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state),
                              "the_table = { foo = 1, bar = 2 }") == 0);
    lua_getglobal(raw(state), "the_table");
    lua_pushstring(raw(state), "baz");
    state.get_table(-2);
    ATF_REQUIRE(lua_isnil(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(get_top);
ATF_TEST_CASE_BODY(get_top)
{
    lutok::state state;
    ATF_REQUIRE_EQ(0, state.get_top());
    lua_pushinteger(raw(state), 3);
    ATF_REQUIRE_EQ(1, state.get_top());
    lua_pushinteger(raw(state), 3);
    ATF_REQUIRE_EQ(2, state.get_top());
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(insert);
ATF_TEST_CASE_BODY(insert)
{
    lutok::state state;
    lua_pushinteger(raw(state), 1);
    lua_pushinteger(raw(state), 2);
    lua_pushinteger(raw(state), 3);
    lua_pushinteger(raw(state), 4);
    state.insert(-3);
    ATF_REQUIRE_EQ(3, lua_tointeger(raw(state), -1));
    ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -2));
    ATF_REQUIRE_EQ(4, lua_tointeger(raw(state), -3));
    ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -4));
    lua_pop(raw(state), 4);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__empty);
ATF_TEST_CASE_BODY(is_boolean__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_boolean(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__ok);
ATF_TEST_CASE_BODY(is_boolean__ok)
{
    lutok::state state;
    lua_pushboolean(raw(state), 1);
    ATF_REQUIRE(state.is_boolean(-1));
    lua_pushinteger(raw(state), 5);
    ATF_REQUIRE(!state.is_boolean(-1));
    ATF_REQUIRE(state.is_boolean(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_function__empty);
ATF_TEST_CASE_BODY(is_function__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_function(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_function__ok);
ATF_TEST_CASE_BODY(is_function__ok)
{
    lutok::state state;
    luaL_dostring(raw(state), "function my_func(a, b) return a + b; end");

    lua_getglobal(raw(state), "my_func");
    ATF_REQUIRE(state.is_function(-1));
    lua_pushinteger(raw(state), 5);
    ATF_REQUIRE(!state.is_function(-1));
    ATF_REQUIRE(state.is_function(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_nil__empty);
ATF_TEST_CASE_BODY(is_nil__empty)
{
    lutok::state state;
    ATF_REQUIRE(state.is_nil(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_nil__ok);
ATF_TEST_CASE_BODY(is_nil__ok)
{
    lutok::state state;
    lua_pushnil(raw(state));
    ATF_REQUIRE(state.is_nil(-1));
    lua_pushinteger(raw(state), 5);
    ATF_REQUIRE(!state.is_nil(-1));
    ATF_REQUIRE(state.is_nil(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_number__empty);
ATF_TEST_CASE_BODY(is_number__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_number(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_number__ok);
ATF_TEST_CASE_BODY(is_number__ok)
{
    lutok::state state;
    lua_pushnil(raw(state));
    ATF_REQUIRE(!state.is_number(-1));
    lua_pushinteger(raw(state), 5);
    ATF_REQUIRE(state.is_number(-1));
    ATF_REQUIRE(!state.is_number(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_string__empty);
ATF_TEST_CASE_BODY(is_string__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_string(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_string__ok);
ATF_TEST_CASE_BODY(is_string__ok)
{
    lutok::state state;
    lua_pushinteger(raw(state), 3);
    ATF_REQUIRE(state.is_string(-1));
    lua_pushnil(raw(state));
    ATF_REQUIRE(!state.is_string(-1));
    ATF_REQUIRE(state.is_string(-2));
    lua_pushstring(raw(state), "foo");
    ATF_REQUIRE(state.is_string(-1));
    ATF_REQUIRE(!state.is_string(-2));
    ATF_REQUIRE(state.is_string(-3));
    lua_pop(raw(state), 3);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_table__empty);
ATF_TEST_CASE_BODY(is_table__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_table(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_table__ok);
ATF_TEST_CASE_BODY(is_table__ok)
{
    lutok::state state;
    luaL_dostring(raw(state), "t = {3, 4, 5}");

    lua_pushstring(raw(state), "foo");
    ATF_REQUIRE(!state.is_table(-1));
    lua_getglobal(raw(state), "t");
    ATF_REQUIRE(state.is_table(-1));
    ATF_REQUIRE(!state.is_table(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__empty);
ATF_TEST_CASE_BODY(is_userdata__empty)
{
    lutok::state state;
    ATF_REQUIRE(!state.is_userdata(-1));
}


ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__ok);
ATF_TEST_CASE_BODY(is_userdata__ok)
{
    lutok::state state;

    lua_pushstring(raw(state), "foo");
    ATF_REQUIRE(!state.is_userdata(-1));
    lua_newuserdata(raw(state), 543);
    ATF_REQUIRE(state.is_userdata(-1));
    ATF_REQUIRE(!state.is_userdata(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(load_file__ok);
ATF_TEST_CASE_BODY(load_file__ok)
{
    std::ofstream output("test.lua");
    output << "in_the_file = \"oh yes\"\n";
    output.close();

    lutok::state state;
    state.load_file("test.lua");
    ATF_REQUIRE(lua_pcall(raw(state), 0, 0, 0) == 0);
    lua_getglobal(raw(state), "in_the_file");
    ATF_REQUIRE(std::strcmp("oh yes", lua_tostring(raw(state), -1)) == 0);
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(load_file__api_error);
ATF_TEST_CASE_BODY(load_file__api_error)
{
    std::ofstream output("test.lua");
    output << "I have a bad syntax!  Wohoo!\n";
    output.close();

    lutok::state state;
    REQUIRE_API_ERROR("luaL_loadfile", state.load_file("test.lua"));
}


ATF_TEST_CASE_WITHOUT_HEAD(load_file__file_not_found_error);
ATF_TEST_CASE_BODY(load_file__file_not_found_error)
{
    lutok::state state;
    ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua",
                         state.load_file("missing.lua"));
}


ATF_TEST_CASE_WITHOUT_HEAD(load_string__ok);
ATF_TEST_CASE_BODY(load_string__ok)
{
    lutok::state state;
    state.load_string("return 2 + 3");
    ATF_REQUIRE(lua_pcall(raw(state), 0, 1, 0) == 0);
    ATF_REQUIRE_EQ(5, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(load_string__fail);
ATF_TEST_CASE_BODY(load_string__fail)
{
    lutok::state state;
    REQUIRE_API_ERROR("luaL_loadstring", state.load_string("-"));
}


ATF_TEST_CASE_WITHOUT_HEAD(new_table);
ATF_TEST_CASE_BODY(new_table)
{
    lutok::state state;
    state.new_table();
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_istable(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(new_userdata);
ATF_TEST_CASE_BODY(new_userdata)
{
    lutok::state state;
    int* pointer = state.new_userdata< int >();
    *pointer = 1234;
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_isuserdata(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(next__empty);
ATF_TEST_CASE_BODY(next__empty)
{
    lutok::state state;
    luaL_dostring(raw(state), "t = {}");

    lua_getglobal(raw(state), "t");
    lua_pushstring(raw(state), "this is a dummy value");
    lua_pushnil(raw(state));
    ATF_REQUIRE(!state.next(-3));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(next__many);
ATF_TEST_CASE_BODY(next__many)
{
    lutok::state state;
    luaL_dostring(raw(state), "t = {}; t[1] = 100; t[2] = 200");

    lua_getglobal(raw(state), "t");
    lua_pushnil(raw(state));

    ATF_REQUIRE(state.next(-2));
    ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_isnumber(raw(state), -2));
    ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -2));
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(100, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);

    ATF_REQUIRE(state.next(-2));
    ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_isnumber(raw(state), -2));
    ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -2));
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(200, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);

    ATF_REQUIRE(!state.next(-2));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(open_base);
ATF_TEST_CASE_BODY(open_base)
{
    lutok::state state;
    check_modules(state, "");
    state.open_base();
    check_modules(state, "base");
}


ATF_TEST_CASE_WITHOUT_HEAD(open_all);
ATF_TEST_CASE_BODY(open_all)
{
    lutok::state state;
    check_modules(state, "");
    state.open_all();
    // Best-effort attempt at looking for a bunch of possible modules.
    ATF_REQUIRE(is_available(state, "assert"));
    ATF_REQUIRE(is_available(state, "debug.getinfo"));
    ATF_REQUIRE(is_available(state, "package.path"));
    ATF_REQUIRE(is_available(state, "string.byte"));
    ATF_REQUIRE(is_available(state, "table.concat"));
}


ATF_TEST_CASE_WITHOUT_HEAD(open_string);
ATF_TEST_CASE_BODY(open_string)
{
    lutok::state state;
    check_modules(state, "");
    state.open_string();
    check_modules(state, "string");
}


ATF_TEST_CASE_WITHOUT_HEAD(open_table);
ATF_TEST_CASE_BODY(open_table)
{
    lutok::state state;
    check_modules(state, "");
    state.open_table();
    check_modules(state, "table");
}


ATF_TEST_CASE_WITHOUT_HEAD(pcall__ok);
ATF_TEST_CASE_BODY(pcall__ok)
{
    lutok::state state;
    luaL_loadstring(raw(state), "function mul(a, b) return a * b; end");
    state.pcall(0, 0, 0);
    state.get_global_table();
    lua_pushstring(raw(state), "mul");
    lua_gettable(raw(state), -2);
    lua_pushinteger(raw(state), 3);
    lua_pushinteger(raw(state), 5);
    state.pcall(2, 1, 0);
    ATF_REQUIRE_EQ(15, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(pcall__fail);
ATF_TEST_CASE_BODY(pcall__fail)
{
    lutok::state state;
    lua_pushnil(raw(state));
    REQUIRE_API_ERROR("lua_pcall", state.pcall(0, 0, 0));
}


ATF_TEST_CASE_WITHOUT_HEAD(pop__one);
ATF_TEST_CASE_BODY(pop__one)
{
    lutok::state state;
    lua_pushinteger(raw(state), 10);
    lua_pushinteger(raw(state), 20);
    lua_pushinteger(raw(state), 30);
    state.pop(1);
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(pop__many);
ATF_TEST_CASE_BODY(pop__many)
{
    lutok::state state;
    lua_pushinteger(raw(state), 10);
    lua_pushinteger(raw(state), 20);
    lua_pushinteger(raw(state), 30);
    state.pop(2);
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_boolean);
ATF_TEST_CASE_BODY(push_boolean)
{
    lutok::state state;
    state.push_boolean(true);
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_toboolean(raw(state), -1));
    state.push_boolean(false);
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    ATF_REQUIRE(!lua_toboolean(raw(state), -1));
    ATF_REQUIRE(lua_toboolean(raw(state), -2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_closure);
ATF_TEST_CASE_BODY(push_cxx_closure)
{
    lutok::state state;
    state.push_integer(15);
    state.push_cxx_closure(cxx_multiply_closure, 1);
    lua_setglobal(raw(state), "cxx_multiply_closure");

    ATF_REQUIRE(luaL_dostring(raw(state),
                              "return cxx_multiply_closure(10)") == 0);
    ATF_REQUIRE_EQ(150, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__ok);
ATF_TEST_CASE_BODY(push_cxx_function__ok)
{
    lutok::state state;
    state.push_cxx_function(cxx_divide);
    lua_setglobal(raw(state), "cxx_divide");

    ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(17, 3)") == 0);
    ATF_REQUIRE_EQ(5, lua_tointeger(raw(state), -2));
    ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_exception);
ATF_TEST_CASE_BODY(push_cxx_function__fail_exception)
{
    lutok::state state;
    state.push_cxx_function(cxx_divide);
    lua_setglobal(raw(state), "cxx_divide");

    ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(15, 0)") != 0);
    ATF_REQUIRE_MATCH("Divisor is 0", lua_tostring(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_anything);
ATF_TEST_CASE_BODY(push_cxx_function__fail_anything)
{
    lutok::state state;
    state.push_cxx_function(cxx_divide);
    lua_setglobal(raw(state), "cxx_divide");

    ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(-3, -1)") != 0);
    ATF_REQUIRE_MATCH("Unhandled exception", lua_tostring(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_overflow);
ATF_TEST_CASE_BODY(push_cxx_function__fail_overflow)
{
    lutok::state state;
    state.push_cxx_function(raise_long_error);
    lua_setglobal(raw(state), "fail");

    ATF_REQUIRE(luaL_dostring(raw(state), "return fail(900)") != 0);
    ATF_REQUIRE_MATCH(std::string(900, 'A'), lua_tostring(raw(state), -1));
    lua_pop(raw(state), 1);

    ATF_REQUIRE(luaL_dostring(raw(state), "return fail(8192)") != 0);
    ATF_REQUIRE_MATCH(std::string(900, 'A'), lua_tostring(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_integer);
ATF_TEST_CASE_BODY(push_integer)
{
    lutok::state state;
    state.push_integer(12);
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(12, lua_tointeger(raw(state), -1));
    state.push_integer(34);
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(34, lua_tointeger(raw(state), -1));
    ATF_REQUIRE_EQ(12, lua_tointeger(raw(state), -2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_nil);
ATF_TEST_CASE_BODY(push_nil)
{
    lutok::state state;
    state.push_nil();
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
    ATF_REQUIRE(lua_isnil(raw(state), -1));
    state.push_integer(34);
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    ATF_REQUIRE(!lua_isnil(raw(state), -1));
    ATF_REQUIRE(lua_isnil(raw(state), -2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_string);
ATF_TEST_CASE_BODY(push_string)
{
    lutok::state state;

    {
        std::string str = "first";
        state.push_string(str);
        ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));
        ATF_REQUIRE_EQ(std::string("first"), lua_tostring(raw(state), -1));
        str = "second";
        state.push_string(str);
    }
    ATF_REQUIRE_EQ(2, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(std::string("second"), lua_tostring(raw(state), -1));
    ATF_REQUIRE_EQ(std::string("first"), lua_tostring(raw(state), -2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(push_value);
ATF_TEST_CASE_BODY(push_value)
{
    lutok::state state;

    lua_pushinteger(raw(state), 10);
    lua_pushinteger(raw(state), 20);
    state.push_value(-2);
    ATF_REQUIRE_EQ(3, lua_gettop(raw(state)));
    ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -1));
    ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -2));
    ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -3));
    lua_pop(raw(state), 3);
}


ATF_TEST_CASE_WITHOUT_HEAD(raw_get);
ATF_TEST_CASE_BODY(raw_get)
{
    lutok::state state;

    luaL_openlibs(raw(state));
    ATF_REQUIRE(luaL_dostring(
        raw(state), "t = {foo=123} ; setmetatable(t, {__index=1})") == 0);
    lua_getglobal(raw(state), "t");
    lua_pushinteger(raw(state), 9876);
    lua_pushstring(raw(state), "foo");
    state.raw_get(-3);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(123, lua_tointeger(raw(state), -1));
    ATF_REQUIRE_EQ(9876, lua_tointeger(raw(state), -2));
    lua_pop(raw(state), 3);
}


ATF_TEST_CASE_WITHOUT_HEAD(raw_set);
ATF_TEST_CASE_BODY(raw_set)
{
    lutok::state state;

    luaL_openlibs(raw(state));
    ATF_REQUIRE(luaL_dostring(
        raw(state), "t = {} ; setmetatable(t, {__newindex=1})") == 0);
    lua_getglobal(raw(state), "t");
    lua_pushinteger(raw(state), 876);
    lua_pushstring(raw(state), "foo");
    lua_pushinteger(raw(state), 345);
    state.raw_set(-4);
    ATF_REQUIRE(luaL_dostring(raw(state), "return t.foo") == 0);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(345, lua_tointeger(raw(state), -1));
    ATF_REQUIRE_EQ(876, lua_tointeger(raw(state), -2));
    lua_pop(raw(state), 3);
}


ATF_TEST_CASE_WITHOUT_HEAD(registry_index);
ATF_TEST_CASE_BODY(registry_index)
{
    lutok::state state;
    lua_pushvalue(raw(state), lutok::registry_index);
    lua_pushstring(raw(state), "custom_variable");
    lua_pushstring(raw(state), "custom value");
    lua_settable(raw(state), -3);
    lua_pop(raw(state), 1);
    ATF_REQUIRE(luaL_dostring(raw(state),
                              "return custom_variable == nil") == 0);
    ATF_REQUIRE(lua_isboolean(raw(state), -1));
    ATF_REQUIRE(lua_toboolean(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(set_global);
ATF_TEST_CASE_BODY(set_global)
{
    lutok::state state;
    lua_pushinteger(raw(state), 3);
    state.set_global("test_variable");
    ATF_REQUIRE(luaL_dostring(raw(state), "return test_variable + 1") == 0);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(4, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(set_metatable);
ATF_TEST_CASE_BODY(set_metatable)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(
        raw(state),
        "mt = {}\n"
        "mt.__add = function(a, b) return a[1] + b end\n"
        "numbers = {}\n"
        "numbers[1] = 5\n") == 0);

    lua_getglobal(raw(state), "numbers");
    lua_pushinteger(raw(state), 1234);
    lua_getglobal(raw(state), "mt");
    state.set_metatable(-3);
    lua_pop(raw(state), 2);

    ATF_REQUIRE(luaL_dostring(raw(state), "return numbers + 2") == 0);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(7, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(set_table__ok);
ATF_TEST_CASE_BODY(set_table__ok)
{
    lutok::state state;
    ATF_REQUIRE(luaL_dostring(raw(state), "t = { a = 1, bar = 234 }") == 0);
    lua_getglobal(raw(state), "t");

    lua_pushstring(raw(state), "bar");
    lua_pushstring(raw(state), "baz");
    state.set_table(-3);
    ATF_REQUIRE_EQ(1, lua_gettop(raw(state)));

    lua_pushstring(raw(state), "a");
    lua_gettable(raw(state), -2);
    ATF_REQUIRE(lua_isnumber(raw(state), -1));
    ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 1);

    lua_pushstring(raw(state), "bar");
    lua_gettable(raw(state), -2);
    ATF_REQUIRE(lua_isstring(raw(state), -1));
    ATF_REQUIRE_EQ(std::string("baz"), lua_tostring(raw(state), -1));
    lua_pop(raw(state), 1);

    lua_pop(raw(state), 1);
}


ATF_TEST_CASE_WITHOUT_HEAD(set_table__nil);
ATF_TEST_CASE_BODY(set_table__nil)
{
    lutok::state state;
    lua_pushnil(raw(state));
    lua_pushinteger(raw(state), 1);
    lua_pushinteger(raw(state), 2);
    REQUIRE_API_ERROR("lua_settable", state.set_table(-3));
    lua_pop(raw(state), 3);
}


ATF_TEST_CASE_WITHOUT_HEAD(to_boolean);
ATF_TEST_CASE_BODY(to_boolean)
{
    lutok::state state;
    lua_pushboolean(raw(state), 0);
    lua_pushboolean(raw(state), 1);
    ATF_REQUIRE(!state.to_boolean(-2));
    ATF_REQUIRE(state.to_boolean(-1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(to_integer);
ATF_TEST_CASE_BODY(to_integer)
{
    lutok::state state;
    lua_pushinteger(raw(state), 12);
    lua_pushstring(raw(state), "foobar");
    ATF_REQUIRE_EQ(12, state.to_integer(-2));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(to_string);
ATF_TEST_CASE_BODY(to_string)
{
    lutok::state state;
    lua_pushstring(raw(state), "foobar");
    lua_pushinteger(raw(state), 12);
    ATF_REQUIRE_EQ("foobar", state.to_string(-2));
    ATF_REQUIRE_EQ("12", state.to_string(-1));
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(to_userdata);
ATF_TEST_CASE_BODY(to_userdata)
{
    lutok::state state;
    {
        int* pointer = static_cast< int* >(
            lua_newuserdata(raw(state), sizeof(int)));
        *pointer = 987;
    }

    lua_pushinteger(raw(state), 3);
    int* pointer = state.to_userdata< int >(-2);
    ATF_REQUIRE_EQ(987, *pointer);
    lua_pop(raw(state), 2);
}


ATF_TEST_CASE_WITHOUT_HEAD(upvalue_index);
ATF_TEST_CASE_BODY(upvalue_index)
{
    lutok::state state;
    lua_pushinteger(raw(state), 25);
    lua_pushinteger(raw(state), 30);
    lua_pushcclosure(raw(state), c_get_upvalues, 2);
    lua_setglobal(raw(state), "c_get_upvalues");

    ATF_REQUIRE(luaL_dostring(raw(state),
                              "return c_get_upvalues()") == 0);
    ATF_REQUIRE_EQ(25, lua_tointeger(raw(state), -2));
    ATF_REQUIRE_EQ(30, lua_tointeger(raw(state), -1));
    lua_pop(raw(state), 2);
}


ATF_INIT_TEST_CASES(tcs)
{
    ATF_ADD_TEST_CASE(tcs, close);
    ATF_ADD_TEST_CASE(tcs, get_global__ok);
    ATF_ADD_TEST_CASE(tcs, get_global__undefined);
    ATF_ADD_TEST_CASE(tcs, get_global_table);
    ATF_ADD_TEST_CASE(tcs, get_metafield__ok);
    ATF_ADD_TEST_CASE(tcs, get_metafield__undefined);
    ATF_ADD_TEST_CASE(tcs, get_metatable__ok);
    ATF_ADD_TEST_CASE(tcs, get_metatable__undefined);
    ATF_ADD_TEST_CASE(tcs, get_table__ok);
    ATF_ADD_TEST_CASE(tcs, get_table__nil);
    ATF_ADD_TEST_CASE(tcs, get_table__unknown_index);
    ATF_ADD_TEST_CASE(tcs, get_top);
    ATF_ADD_TEST_CASE(tcs, insert);
    ATF_ADD_TEST_CASE(tcs, is_boolean__empty);
    ATF_ADD_TEST_CASE(tcs, is_boolean__ok);
    ATF_ADD_TEST_CASE(tcs, is_function__empty);
    ATF_ADD_TEST_CASE(tcs, is_function__ok);
    ATF_ADD_TEST_CASE(tcs, is_nil__empty);
    ATF_ADD_TEST_CASE(tcs, is_nil__ok);
    ATF_ADD_TEST_CASE(tcs, is_number__empty);
    ATF_ADD_TEST_CASE(tcs, is_number__ok);
    ATF_ADD_TEST_CASE(tcs, is_string__empty);
    ATF_ADD_TEST_CASE(tcs, is_string__ok);
    ATF_ADD_TEST_CASE(tcs, is_table__empty);
    ATF_ADD_TEST_CASE(tcs, is_table__ok);
    ATF_ADD_TEST_CASE(tcs, is_userdata__empty);
    ATF_ADD_TEST_CASE(tcs, is_userdata__ok);
    ATF_ADD_TEST_CASE(tcs, load_file__ok);
    ATF_ADD_TEST_CASE(tcs, load_file__api_error);
    ATF_ADD_TEST_CASE(tcs, load_file__file_not_found_error);
    ATF_ADD_TEST_CASE(tcs, load_string__ok);
    ATF_ADD_TEST_CASE(tcs, load_string__fail);
    ATF_ADD_TEST_CASE(tcs, new_table);
    ATF_ADD_TEST_CASE(tcs, new_userdata);
    ATF_ADD_TEST_CASE(tcs, next__empty);
    ATF_ADD_TEST_CASE(tcs, next__many);
    ATF_ADD_TEST_CASE(tcs, open_all);
    ATF_ADD_TEST_CASE(tcs, open_base);
    ATF_ADD_TEST_CASE(tcs, open_string);
    ATF_ADD_TEST_CASE(tcs, open_table);
    ATF_ADD_TEST_CASE(tcs, pcall__ok);
    ATF_ADD_TEST_CASE(tcs, pcall__fail);
    ATF_ADD_TEST_CASE(tcs, pop__one);
    ATF_ADD_TEST_CASE(tcs, pop__many);
    ATF_ADD_TEST_CASE(tcs, push_boolean);
    ATF_ADD_TEST_CASE(tcs, push_cxx_closure);
    ATF_ADD_TEST_CASE(tcs, push_cxx_function__ok);
    ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_exception);
    ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_anything);
    ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_overflow);
    ATF_ADD_TEST_CASE(tcs, push_integer);
    ATF_ADD_TEST_CASE(tcs, push_nil);
    ATF_ADD_TEST_CASE(tcs, push_string);
    ATF_ADD_TEST_CASE(tcs, push_value);
    ATF_ADD_TEST_CASE(tcs, raw_get);
    ATF_ADD_TEST_CASE(tcs, raw_set);
    ATF_ADD_TEST_CASE(tcs, registry_index);
    ATF_ADD_TEST_CASE(tcs, set_global);
    ATF_ADD_TEST_CASE(tcs, set_metatable);
    ATF_ADD_TEST_CASE(tcs, set_table__ok);
    ATF_ADD_TEST_CASE(tcs, set_table__nil);
    ATF_ADD_TEST_CASE(tcs, to_boolean);
    ATF_ADD_TEST_CASE(tcs, to_integer);
    ATF_ADD_TEST_CASE(tcs, to_string);
    ATF_ADD_TEST_CASE(tcs, to_userdata);
    ATF_ADD_TEST_CASE(tcs, upvalue_index);
}