* [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite
@ 2021-04-13 13:27 Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 01/29] test: add " Sergey Kaplun via Tarantool-patches
` (29 more replies)
0 siblings, 30 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
Branch: https://github.com/tarantool/luajit/tree/skaplun/gh-5845-adapt-puc-rio-test-suite-v2
Test branch: https://github.com/tarantool/tarantool/tree/skaplun/gh-5845-adapt-puc-rio-test-suite-v2
Side note: CI is red due to
https://github.com/tarantool/tarantool/issues/5986.
Issues:
* https://github.com/tarantool/tarantool/issues/5845
* https://github.com/tarantool/tarantool/issues/4473
Suite is taken intact exept trailing whitespaces.
Command to check:
| $ diff -ruZ --color ../test/PUC-Lua-5.1-tests/ ~/Downloads/lua5.1-tests/
| Only in ../test/PUC-Lua-5.1-tests/: CMakeLists.txt
| Only in ../test/PUC-Lua-5.1-tests/libs: CMakeLists.txt
| Only in ~/Downloads/lua5.1-tests/libs: makefile
| Only in ~/Downloads/lua5.1-tests/libs: P1
Changes in the v2:
* split commits to atomic changes
* more verbose comments for some tests
* some test fixed instead commenting
Changes in the v3:
* more verbose comments and commit messages
* PUC-Lua-5.1-tests -> PUC-Rio-Lua-5.1-tests
* squash commits for vararg functions
* move "LuaJIT:" tag to the top of comments
* introduce _dofile and _loadfile functions for PUC-Rio-Lua-5.1 suite
and create <luajit-tests-init.lua> test prerunner to set up them
correctly for out-of-source build.
Sergey Kaplun (29):
test: add PUC-Rio Lua 5.1 test suite
test: build auxiliary C libs from PUC-Rio Lua 5.1
test: adapt PUC-Rio suite for out-of-source build
test: remove quotes in progname from PUC-Rio
test: adapt PUC-Rio test for arg presence
test: disable PUC-Rio tests confused by -v output
test: disable PUC-Rio tests for bytecode header
test: adapt PUC-Rio tests counting GC steps
test: disable PUC-Rio suite tests for line hook
test: adapt PUC-Rio tests with vararg functions
test: adapt PUC-Rio test for debug in vararg func
test: adapt PUC-Rio test with count hooks
test: disable PUC-Rio test for tail call info
test: adapt PUC-Rio test with activeline check
test: disable PUC-Rio test for per-coroutine hooks
test: adapt PUC-Rio test for %q in string.format
test: disable locale-dependent PUC-Rio tests
test: use math.fmod in PUC-Rio tests
test: remove string.gfind assert in PUC-Rio test
test: disable PUC-Rio test for getfenv in tailcall
test: disable PUC-Rio test for variables in error
test: disable PUC-Rio test for fast function name
test: disable PUC-Rio test for non-asci identifier
test: disable PUC-Rio test for syntax level error
test: disable PUC-RIO tests for several -l options
test: disable PUC-Rio test for checking arg layout
test: disable PUC-Rio test checking -h option
test: disable PUC-Rio hanging GC test
test: disable too deep recursive PUC-Rio test
.luacheckrc | 5 +-
CMakeLists.txt | 4 +-
test/CMakeLists.txt | 2 +
test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt | 46 +
test/PUC-Rio-Lua-5.1-tests/README | 41 +
test/PUC-Rio-Lua-5.1-tests/all.lua | 144 +++
test/PUC-Rio-Lua-5.1-tests/api.lua | 711 ++++++++++
test/PUC-Rio-Lua-5.1-tests/attrib.lua | 339 +++++
test/PUC-Rio-Lua-5.1-tests/big.lua | 381 ++++++
test/PUC-Rio-Lua-5.1-tests/calls.lua | 294 +++++
test/PUC-Rio-Lua-5.1-tests/checktable.lua | 77 ++
test/PUC-Rio-Lua-5.1-tests/closure.lua | 432 +++++++
test/PUC-Rio-Lua-5.1-tests/code.lua | 143 ++
test/PUC-Rio-Lua-5.1-tests/constructs.lua | 242 ++++
test/PUC-Rio-Lua-5.1-tests/db.lua | 581 +++++++++
test/PUC-Rio-Lua-5.1-tests/errors.lua | 276 ++++
test/PUC-Rio-Lua-5.1-tests/etc/ltests.c | 1147 +++++++++++++++++
test/PUC-Rio-Lua-5.1-tests/etc/ltests.h | 92 ++
test/PUC-Rio-Lua-5.1-tests/events.lua | 360 ++++++
test/PUC-Rio-Lua-5.1-tests/files.lua | 324 +++++
test/PUC-Rio-Lua-5.1-tests/gc.lua | 325 +++++
.../PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt | 65 +
test/PUC-Rio-Lua-5.1-tests/libs/lib1.c | 40 +
test/PUC-Rio-Lua-5.1-tests/libs/lib11.c | 18 +
test/PUC-Rio-Lua-5.1-tests/libs/lib2.c | 28 +
test/PUC-Rio-Lua-5.1-tests/libs/lib21.c | 18 +
test/PUC-Rio-Lua-5.1-tests/literals.lua | 181 +++
test/PUC-Rio-Lua-5.1-tests/locals.lua | 127 ++
test/PUC-Rio-Lua-5.1-tests/main.lua | 212 +++
test/PUC-Rio-Lua-5.1-tests/math.lua | 209 +++
test/PUC-Rio-Lua-5.1-tests/nextvar.lua | 397 ++++++
test/PUC-Rio-Lua-5.1-tests/pm.lua | 276 ++++
test/PUC-Rio-Lua-5.1-tests/sort.lua | 74 ++
test/PUC-Rio-Lua-5.1-tests/strings.lua | 217 ++++
test/PUC-Rio-Lua-5.1-tests/vararg.lua | 135 ++
test/PUC-Rio-Lua-5.1-tests/verybig.lua | 100 ++
test/luajit-test-init.lua | 18 +
37 files changed, 8077 insertions(+), 4 deletions(-)
create mode 100644 test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt
create mode 100644 test/PUC-Rio-Lua-5.1-tests/README
create mode 100755 test/PUC-Rio-Lua-5.1-tests/all.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/api.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/attrib.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/big.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/calls.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/checktable.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/closure.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/code.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/constructs.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/db.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/errors.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/etc/ltests.c
create mode 100644 test/PUC-Rio-Lua-5.1-tests/etc/ltests.h
create mode 100644 test/PUC-Rio-Lua-5.1-tests/events.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/files.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/gc.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt
create mode 100644 test/PUC-Rio-Lua-5.1-tests/libs/lib1.c
create mode 100644 test/PUC-Rio-Lua-5.1-tests/libs/lib11.c
create mode 100644 test/PUC-Rio-Lua-5.1-tests/libs/lib2.c
create mode 100644 test/PUC-Rio-Lua-5.1-tests/libs/lib21.c
create mode 100644 test/PUC-Rio-Lua-5.1-tests/literals.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/locals.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/main.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/math.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/nextvar.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/pm.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/sort.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/strings.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/vararg.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/verybig.lua
create mode 100644 test/luajit-test-init.lua
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 01/29] test: add PUC-Rio Lua 5.1 test suite
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 20:31 ` Igor Munkin via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 02/29] test: build auxiliary C libs from PUC-Rio Lua 5.1 Sergey Kaplun via Tarantool-patches
` (28 subsequent siblings)
29 siblings, 1 reply; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 210926 bytes --]
This patch adds PUC-Rio Lua 5.1 test suite as a part of the LuaJIT test
suite. Source code is taken verbatim (except trailing whitespace) from
https://www.lua.org/tests/lua5.1-tests.tar.gz.
Some tests may fail after this commit. They will be disabled
or adapted in the next patches.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
.luacheckrc | 5 +-
test/CMakeLists.txt | 2 +
test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt | 45 +
test/PUC-Rio-Lua-5.1-tests/README | 41 +
test/PUC-Rio-Lua-5.1-tests/all.lua | 137 ++
test/PUC-Rio-Lua-5.1-tests/api.lua | 711 ++++++++++
test/PUC-Rio-Lua-5.1-tests/attrib.lua | 339 +++++
test/PUC-Rio-Lua-5.1-tests/big.lua | 381 ++++++
test/PUC-Rio-Lua-5.1-tests/calls.lua | 294 +++++
test/PUC-Rio-Lua-5.1-tests/checktable.lua | 77 ++
test/PUC-Rio-Lua-5.1-tests/closure.lua | 422 ++++++
test/PUC-Rio-Lua-5.1-tests/code.lua | 143 ++
test/PUC-Rio-Lua-5.1-tests/constructs.lua | 240 ++++
test/PUC-Rio-Lua-5.1-tests/db.lua | 499 +++++++
test/PUC-Rio-Lua-5.1-tests/errors.lua | 250 ++++
test/PUC-Rio-Lua-5.1-tests/etc/ltests.c | 1147 +++++++++++++++++
test/PUC-Rio-Lua-5.1-tests/etc/ltests.h | 92 ++
test/PUC-Rio-Lua-5.1-tests/events.lua | 360 ++++++
test/PUC-Rio-Lua-5.1-tests/files.lua | 324 +++++
test/PUC-Rio-Lua-5.1-tests/gc.lua | 312 +++++
.../PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt | 18 +
test/PUC-Rio-Lua-5.1-tests/libs/lib1.c | 40 +
test/PUC-Rio-Lua-5.1-tests/libs/lib11.c | 18 +
test/PUC-Rio-Lua-5.1-tests/libs/lib2.c | 28 +
test/PUC-Rio-Lua-5.1-tests/libs/lib21.c | 18 +
test/PUC-Rio-Lua-5.1-tests/literals.lua | 176 +++
test/PUC-Rio-Lua-5.1-tests/locals.lua | 127 ++
test/PUC-Rio-Lua-5.1-tests/main.lua | 159 +++
test/PUC-Rio-Lua-5.1-tests/math.lua | 208 +++
test/PUC-Rio-Lua-5.1-tests/nextvar.lua | 396 ++++++
test/PUC-Rio-Lua-5.1-tests/pm.lua | 273 ++++
test/PUC-Rio-Lua-5.1-tests/sort.lua | 74 ++
test/PUC-Rio-Lua-5.1-tests/strings.lua | 176 +++
test/PUC-Rio-Lua-5.1-tests/vararg.lua | 126 ++
test/PUC-Rio-Lua-5.1-tests/verybig.lua | 100 ++
35 files changed, 7756 insertions(+), 2 deletions(-)
create mode 100644 test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt
create mode 100644 test/PUC-Rio-Lua-5.1-tests/README
create mode 100755 test/PUC-Rio-Lua-5.1-tests/all.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/api.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/attrib.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/big.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/calls.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/checktable.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/closure.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/code.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/constructs.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/db.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/errors.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/etc/ltests.c
create mode 100644 test/PUC-Rio-Lua-5.1-tests/etc/ltests.h
create mode 100644 test/PUC-Rio-Lua-5.1-tests/events.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/files.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/gc.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt
create mode 100644 test/PUC-Rio-Lua-5.1-tests/libs/lib1.c
create mode 100644 test/PUC-Rio-Lua-5.1-tests/libs/lib11.c
create mode 100644 test/PUC-Rio-Lua-5.1-tests/libs/lib2.c
create mode 100644 test/PUC-Rio-Lua-5.1-tests/libs/lib21.c
create mode 100644 test/PUC-Rio-Lua-5.1-tests/literals.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/locals.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/main.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/math.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/nextvar.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/pm.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/sort.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/strings.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/vararg.lua
create mode 100644 test/PUC-Rio-Lua-5.1-tests/verybig.lua
diff --git a/.luacheckrc b/.luacheckrc
index 4e5dbdf6..a32012ca 100644
--- a/.luacheckrc
+++ b/.luacheckrc
@@ -3,11 +3,12 @@ std = 'luajit'
-- This fork also introduces a new global for misc API namespace.
read_globals = { 'misc' }
--- These files are inherited from the vanilla LuaJIT and need to
--- be coherent with the upstream.
+-- These files are inherited from the vanilla LuaJIT or different
+-- test suites and need to be coherent with the upstream.
exclude_files = {
'dynasm/',
'src/',
'test/LuaJIT-tests/',
+ 'test/PUC-Rio-Lua-5.1-tests/',
'test/lua-Harness-tests/',
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 02fb2edc..ba25af54 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -44,11 +44,13 @@ set(LUAJIT_TEST_COMMAND "${LUAJIT_TEST_BINARY} -e dofile[[${LUAJIT_TEST_INIT}]]"
separate_arguments(LUAJIT_TEST_COMMAND)
add_subdirectory(LuaJIT-tests)
+add_subdirectory(PUC-Rio-Lua-5.1-tests)
add_subdirectory(lua-Harness-tests)
add_subdirectory(tarantool-tests)
add_custom_target(${PROJECT_NAME}-test DEPENDS
LuaJIT-tests
+ PUC-Rio-Lua-5.1-tests
lua-Harness-tests
tarantool-tests
)
diff --git a/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt
new file mode 100644
index 00000000..e3bbc9de
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt
@@ -0,0 +1,45 @@
+# Test suite that has been added from PUC-Rio Lua 5.1 test archive
+# in scope of https://github.com/tarantool/tarantool/issues/5845.
+
+# See the rationale in the root CMakeLists.txt.
+cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
+
+# XXX: There are two ways to set up the proper environment
+# described in the suite's README:
+# * set LUA_PATH to "?;./?.lua"
+# * or, better yet, set LUA_PATH to "./?.lua;;" and LUA_INIT to
+# "package.path = '?;'..package.path"
+# Unfortunately, Tarantool doesn't support LUA_INIT and most
+# likely it never will. For more info, see
+# https://github.com/tarantool/tarantool/issues/5744
+# Hence, there is no way other than set LUA_PATH environment
+# variable as proposed in the first case.
+set(LUA_PATH "?\;${CMAKE_CURRENT_SOURCE_DIR}/?.lua")
+
+# Establish PUC-Lua-5.1-tests-prepare target that creates <libs/P1>
+# subdirectory.
+add_subdirectory(libs)
+
+# TODO: PUC-Rio Lua 5.1 test suite also has special header
+# <ltests.h> and <ltests.c> translation unit to check some
+# internal behaviour of the Lua implementation (see etc/
+# directory). It modifies realloc function to check memory
+# consistency and also contains tests for yield in hooks
+# and for the Lua C API.
+# But, unfortunately, <ltests.c> depends on specific PUC-Rio
+# Lua 5.1 internal headers and should be adapted for LuaJIT.
+
+add_custom_target(PUC-Rio-Lua-5.1-tests
+ DEPENDS ${LUAJIT_TEST_BINARY} PUC-Lua-5.1-tests-prepare
+)
+
+add_custom_command(TARGET PUC-Rio-Lua-5.1-tests
+ COMMENT "Running PUC-Rio Lua 5.1 tests"
+ COMMAND
+ env
+ LUA_PATH="${LUA_PATH}\;\;"
+ ${LUAJIT_TEST_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR}/all.lua
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+# vim: expandtab tabstop=2 shiftwidth=2
diff --git a/test/PUC-Rio-Lua-5.1-tests/README b/test/PUC-Rio-Lua-5.1-tests/README
new file mode 100644
index 00000000..e2d4b285
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/README
@@ -0,0 +1,41 @@
+This tarball contains the official test scripts for Lua 5.1.
+Unlike Lua itself, these tests do not aim portability, small footprint,
+or easy of use. (Their main goal is to try to crash Lua.) They are not
+intended for general use. You are wellcome to use them, but expect to
+have to "dirt your hands".
+
+The tarball should expand in the following contents:
+ - several .lua scripts with the tests
+ - a main "all.lua" Lua script that invokes all the other scripts
+ - a subdirectory "libs" with an empty subdirectory "libs/P1",
+ to be used by the scripts
+ - a subdirectory "etc" with some extra files
+
+To run the tests, do as follows:
+
+- go to the test directory
+
+- set LUA_PATH to "?;./?.lua" (or, better yet, set LUA_PATH to "./?.lua;;"
+ and LUA_INIT to "package.path = '?;'..package.path")
+
+- run "lua all.lua"
+
+
+--------------------------------------------
+Internal tests
+--------------------------------------------
+
+Some tests need a special library, "testC", that gives access to
+several internal structures in Lua.
+This library is only available when Lua is compiled in debug mode.
+The scripts automatically detect its absence and skip those tests.
+
+If you want to run these tests, move etc/ltests.c and etc/ltests.h to
+the directory with the source Lua files, and recompile Lua with
+the option -DLUA_USER_H='"ltests.h"' (or its equivalent to define
+LUA_USER_H as the string "ltests.h", including the quotes). This
+option not only adds the testC library, but it adds several other
+internal tests as well. After the recompilation, run the tests
+as before.
+
+
diff --git a/test/PUC-Rio-Lua-5.1-tests/all.lua b/test/PUC-Rio-Lua-5.1-tests/all.lua
new file mode 100755
index 00000000..8c4aface
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/all.lua
@@ -0,0 +1,137 @@
+#!../lua
+
+math.randomseed(0)
+
+collectgarbage("setstepmul", 180)
+collectgarbage("setpause", 190)
+
+
+--[=[
+ example of a long [comment],
+ [[spanning several [lines]]]
+
+]=]
+
+print("current path:\n " .. string.gsub(package.path, ";", "\n "))
+
+
+local msgs = {}
+function Message (m)
+ print(m)
+ msgs[#msgs+1] = string.sub(m, 3, -3)
+end
+
+
+local c = os.clock()
+
+assert(os.setlocale"C")
+
+local T,print,gcinfo,format,write,assert,type =
+ T,print,gcinfo,string.format,io.write,assert,type
+
+local function formatmem (m)
+ if m < 1024 then return m
+ else
+ m = m/1024 - m/1024%1
+ if m < 1024 then return m.."K"
+ else
+ m = m/1024 - m/1024%1
+ return m.."M"
+ end
+ end
+end
+
+local showmem = function ()
+ if not T then
+ print(format(" ---- total memory: %s ----\n", formatmem(gcinfo())))
+ else
+ T.checkmemory()
+ local a,b,c = T.totalmem()
+ local d,e = gcinfo()
+ print(format(
+ "\n ---- total memory: %s (%dK), max use: %s, blocks: %d\n",
+ formatmem(a), d, formatmem(c), b))
+ end
+end
+
+
+--
+-- redefine dofile to run files through dump/undump
+--
+dofile = function (n)
+ showmem()
+ local f = assert(loadfile(n))
+ local b = string.dump(f)
+ f = assert(loadstring(b))
+ return f()
+end
+
+dofile('main.lua')
+
+do
+ local u = newproxy(true)
+ local newproxy, stderr = newproxy, io.stderr
+ getmetatable(u).__gc = function (o)
+ stderr:write'.'
+ newproxy(o)
+ end
+end
+
+local f = assert(loadfile('gc.lua'))
+f()
+dofile('db.lua')
+assert(dofile('calls.lua') == deep and deep)
+dofile('strings.lua')
+dofile('literals.lua')
+assert(dofile('attrib.lua') == 27)
+assert(dofile('locals.lua') == 5)
+dofile('constructs.lua')
+dofile('code.lua')
+do
+ local f = coroutine.wrap(assert(loadfile('big.lua')))
+ assert(f() == 'b')
+ assert(f() == 'a')
+end
+dofile('nextvar.lua')
+dofile('pm.lua')
+dofile('api.lua')
+assert(dofile('events.lua') == 12)
+dofile('vararg.lua')
+dofile('closure.lua')
+dofile('errors.lua')
+dofile('math.lua')
+dofile('sort.lua')
+assert(dofile('verybig.lua') == 10); collectgarbage()
+dofile('files.lua')
+
+if #msgs > 0 then
+ print("\ntests not performed:")
+ for i=1,#msgs do
+ print(msgs[i])
+ end
+ print()
+end
+
+print("final OK !!!")
+print('cleaning all!!!!')
+
+debug.sethook(function (a) assert(type(a) == 'string') end, "cr")
+
+local _G, collectgarbage, showmem, print, format, clock =
+ _G, collectgarbage, showmem, print, format, os.clock
+
+local a={}
+for n in pairs(_G) do a[n] = 1 end
+a.tostring = nil
+a.___Glob = nil
+for n in pairs(a) do _G[n] = nil end
+
+a = nil
+collectgarbage()
+collectgarbage()
+collectgarbage()
+collectgarbage()
+collectgarbage()
+collectgarbage();showmem()
+
+print(format("\n\ntotal time: %.2f\n", clock()-c))
diff --git a/test/PUC-Rio-Lua-5.1-tests/api.lua b/test/PUC-Rio-Lua-5.1-tests/api.lua
new file mode 100644
index 00000000..c955ebf9
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/api.lua
@@ -0,0 +1,711 @@
+
+if T==nil then
+ (Message or print)('\a\n >>> testC not active: skipping API tests <<<\n\a')
+ return
+end
+
+
+
+function tcheck (t1, t2)
+ table.remove(t1, 1) -- remove code
+ assert(table.getn(t1) == table.getn(t2))
+ for i=1,table.getn(t1) do assert(t1[i] == t2[i]) end
+end
+
+function pack(...) return arg end
+
+
+print('testing C API')
+
+-- testing allignment
+a = T.d2s(12458954321123)
+assert(string.len(a) == 8) -- sizeof(double)
+assert(T.s2d(a) == 12458954321123)
+
+a,b,c = T.testC("pushnum 1; pushnum 2; pushnum 3; return 2")
+assert(a == 2 and b == 3 and not c)
+
+-- test that all trues are equal
+a,b,c = T.testC("pushbool 1; pushbool 2; pushbool 0; return 3")
+assert(a == b and a == true and c == false)
+a,b,c = T.testC"pushbool 0; pushbool 10; pushnil;\
+ tobool -3; tobool -3; tobool -3; return 3"
+assert(a==0 and b==1 and c==0)
+
+
+a,b,c = T.testC("gettop; return 2", 10, 20, 30, 40)
+assert(a == 40 and b == 5 and not c)
+
+t = pack(T.testC("settop 5; gettop; return .", 2, 3))
+tcheck(t, {n=4,2,3})
+
+t = pack(T.testC("settop 0; settop 15; return 10", 3, 1, 23))
+assert(t.n == 10 and t[1] == nil and t[10] == nil)
+
+t = pack(T.testC("remove -2; gettop; return .", 2, 3, 4))
+tcheck(t, {n=2,2,4})
+
+t = pack(T.testC("insert -1; gettop; return .", 2, 3))
+tcheck(t, {n=2,2,3})
+
+t = pack(T.testC("insert 3; gettop; return .", 2, 3, 4, 5))
+tcheck(t, {n=4,2,5,3,4})
+
+t = pack(T.testC("replace 2; gettop; return .", 2, 3, 4, 5))
+tcheck(t, {n=3,5,3,4})
+
+t = pack(T.testC("replace -2; gettop; return .", 2, 3, 4, 5))
+tcheck(t, {n=3,2,3,5})
+
+t = pack(T.testC("remove 3; gettop; return .", 2, 3, 4, 5))
+tcheck(t, {n=3,2,4,5})
+
+t = pack(T.testC("insert 3; pushvalue 3; remove 3; pushvalue 2; remove 2; \
+ insert 2; pushvalue 1; remove 1; insert 1; \
+ insert -2; pushvalue -2; remove -3; gettop; return .",
+ 2, 3, 4, 5, 10, 40, 90))
+tcheck(t, {n=7,2,3,4,5,10,40,90})
+
+t = pack(T.testC("concat 5; gettop; return .", "alo", 2, 3, "joao", 12))
+tcheck(t, {n=1,"alo23joao12"})
+
+-- testing MULTRET
+t = pack(T.testC("rawcall 2,-1; gettop; return .",
+ function (a,b) return 1,2,3,4,a,b end, "alo", "joao"))
+tcheck(t, {n=6,1,2,3,4,"alo", "joao"})
+
+do -- test returning more results than fit in the caller stack
+ local a = {}
+ for i=1,1000 do a[i] = true end; a[999] = 10
+ local b = T.testC([[call 1 -1; pop 1; tostring -1; return 1]], unpack, a)
+ assert(b == "10")
+end
+
+
+-- testing lessthan
+assert(T.testC("lessthan 2 5, return 1", 3, 2, 2, 4, 2, 2))
+assert(T.testC("lessthan 5 2, return 1", 4, 2, 2, 3, 2, 2))
+assert(not T.testC("lessthan 2 -3, return 1", "4", "2", "2", "3", "2", "2"))
+assert(not T.testC("lessthan -3 2, return 1", "3", "2", "2", "4", "2", "2"))
+
+local b = {__lt = function (a,b) return a[1] < b[1] end}
+local a1,a3,a4 = setmetatable({1}, b),
+ setmetatable({3}, b),
+ setmetatable({4}, b)
+assert(T.testC("lessthan 2 5, return 1", a3, 2, 2, a4, 2, 2))
+assert(T.testC("lessthan 5 -6, return 1", a4, 2, 2, a3, 2, 2))
+a,b = T.testC("lessthan 5 -6, return 2", a1, 2, 2, a3, 2, 20)
+assert(a == 20 and b == false)
+
+
+-- testing lua_is
+
+function count (x, n)
+ n = n or 2
+ local prog = [[
+ isnumber %d;
+ isstring %d;
+ isfunction %d;
+ iscfunction %d;
+ istable %d;
+ isuserdata %d;
+ isnil %d;
+ isnull %d;
+ return 8
+ ]]
+ prog = string.format(prog, n, n, n, n, n, n, n, n)
+ local a,b,c,d,e,f,g,h = T.testC(prog, x)
+ return a+b+c+d+e+f+g+(100*h)
+end
+
+assert(count(3) == 2)
+assert(count('alo') == 1)
+assert(count('32') == 2)
+assert(count({}) == 1)
+assert(count(print) == 2)
+assert(count(function () end) == 1)
+assert(count(nil) == 1)
+assert(count(io.stdin) == 1)
+assert(count(nil, 15) == 100)
+
+-- testing lua_to...
+
+function to (s, x, n)
+ n = n or 2
+ return T.testC(string.format("%s %d; return 1", s, n), x)
+end
+
+assert(to("tostring", {}) == nil)
+assert(to("tostring", "alo") == "alo")
+assert(to("tostring", 12) == "12")
+assert(to("tostring", 12, 3) == nil)
+assert(to("objsize", {}) == 0)
+assert(to("objsize", "alo\0\0a") == 6)
+assert(to("objsize", T.newuserdata(0)) == 0)
+assert(to("objsize", T.newuserdata(101)) == 101)
+assert(to("objsize", 12) == 2)
+assert(to("objsize", 12, 3) == 0)
+assert(to("tonumber", {}) == 0)
+assert(to("tonumber", "12") == 12)
+assert(to("tonumber", "s2") == 0)
+assert(to("tonumber", 1, 20) == 0)
+a = to("tocfunction", math.deg)
+assert(a(3) == math.deg(3) and a ~= math.deg)
+
+
+-- testing errors
+
+a = T.testC([[
+ loadstring 2; call 0,1;
+ pushvalue 3; insert -2; call 1, 1;
+ call 0, 0;
+ return 1
+]], "x=150", function (a) assert(a==nil); return 3 end)
+
+assert(type(a) == 'string' and x == 150)
+
+function check3(p, ...)
+ assert(arg.n == 3)
+ assert(string.find(arg[3], p))
+end
+check3(":1:", T.testC("loadstring 2; gettop; return .", "x="))
+check3("cannot read", T.testC("loadfile 2; gettop; return .", "."))
+check3("cannot open xxxx", T.testC("loadfile 2; gettop; return .", "xxxx"))
+
+-- testing table access
+
+a = {x=0, y=12}
+x, y = T.testC("gettable 2; pushvalue 4; gettable 2; return 2",
+ a, 3, "y", 4, "x")
+assert(x == 0 and y == 12)
+T.testC("settable -5", a, 3, 4, "x", 15)
+assert(a.x == 15)
+a[a] = print
+x = T.testC("gettable 2; return 1", a) -- table and key are the same object!
+assert(x == print)
+T.testC("settable 2", a, "x") -- table and key are the same object!
+assert(a[a] == "x")
+
+b = setmetatable({p = a}, {})
+getmetatable(b).__index = function (t, i) return t.p[i] end
+k, x = T.testC("gettable 3, return 2", 4, b, 20, 35, "x")
+assert(x == 15 and k == 35)
+getmetatable(b).__index = function (t, i) return a[i] end
+getmetatable(b).__newindex = function (t, i,v ) a[i] = v end
+y = T.testC("insert 2; gettable -5; return 1", 2, 3, 4, "y", b)
+assert(y == 12)
+k = T.testC("settable -5, return 1", b, 3, 4, "x", 16)
+assert(a.x == 16 and k == 4)
+a[b] = 'xuxu'
+y = T.testC("gettable 2, return 1", b)
+assert(y == 'xuxu')
+T.testC("settable 2", b, 19)
+assert(a[b] == 19)
+
+-- testing next
+a = {}
+t = pack(T.testC("next; gettop; return .", a, nil))
+tcheck(t, {n=1,a})
+a = {a=3}
+t = pack(T.testC("next; gettop; return .", a, nil))
+tcheck(t, {n=3,a,'a',3})
+t = pack(T.testC("next; pop 1; next; gettop; return .", a, nil))
+tcheck(t, {n=1,a})
+
+
+
+-- testing upvalues
+
+do
+ local A = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
+ t, b, c = A([[pushvalue U0; pushvalue U1; pushvalue U2; return 3]])
+ assert(b == 10 and c == 20 and type(t) == 'table')
+ a, b = A([[tostring U3; tonumber U4; return 2]])
+ assert(a == nil and b == 0)
+ A([[pushnum 100; pushnum 200; replace U2; replace U1]])
+ b, c = A([[pushvalue U1; pushvalue U2; return 2]])
+ assert(b == 100 and c == 200)
+ A([[replace U2; replace U1]], {x=1}, {x=2})
+ b, c = A([[pushvalue U1; pushvalue U2; return 2]])
+ assert(b.x == 1 and c.x == 2)
+ T.checkmemory()
+end
+
+local f = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
+assert(T.upvalue(f, 1) == 10 and
+ T.upvalue(f, 2) == 20 and
+ T.upvalue(f, 3) == nil)
+T.upvalue(f, 2, "xuxu")
+assert(T.upvalue(f, 2) == "xuxu")
+
+
+-- testing environments
+
+assert(T.testC"pushvalue G; return 1" == _G)
+assert(T.testC"pushvalue E; return 1" == _G)
+local a = {}
+T.testC("replace E; return 1", a)
+assert(T.testC"pushvalue G; return 1" == _G)
+assert(T.testC"pushvalue E; return 1" == a)
+assert(debug.getfenv(T.testC) == a)
+assert(debug.getfenv(T.upvalue) == _G)
+-- userdata inherit environment
+local u = T.testC"newuserdata 0; return 1"
+assert(debug.getfenv(u) == a)
+-- functions inherit environment
+u = T.testC"pushcclosure 0; return 1"
+assert(debug.getfenv(u) == a)
+debug.setfenv(T.testC, _G)
+assert(T.testC"pushvalue E; return 1" == _G)
+
+local b = newproxy()
+assert(debug.getfenv(b) == _G)
+assert(debug.setfenv(b, a))
+assert(debug.getfenv(b) == a)
+
+
+
+-- testing locks (refs)
+
+-- reuse of references
+local i = T.ref{}
+T.unref(i)
+assert(T.ref{} == i)
+
+Arr = {}
+Lim = 100
+for i=1,Lim do -- lock many objects
+ Arr[i] = T.ref({})
+end
+
+assert(T.ref(nil) == -1 and T.getref(-1) == nil)
+T.unref(-1); T.unref(-1)
+
+for i=1,Lim do -- unlock all them
+ T.unref(Arr[i])
+end
+
+function printlocks ()
+ local n = T.testC("gettable R; return 1", "n")
+ print("n", n)
+ for i=0,n do
+ print(i, T.testC("gettable R; return 1", i))
+ end
+end
+
+
+for i=1,Lim do -- lock many objects
+ Arr[i] = T.ref({})
+end
+
+for i=1,Lim,2 do -- unlock half of them
+ T.unref(Arr[i])
+end
+
+assert(type(T.getref(Arr[2])) == 'table')
+
+
+assert(T.getref(-1) == nil)
+
+
+a = T.ref({})
+
+collectgarbage()
+
+assert(type(T.getref(a)) == 'table')
+
+
+-- colect in cl the `val' of all collected userdata
+tt = {}
+cl = {n=0}
+A = nil; B = nil
+local F
+F = function (x)
+ local udval = T.udataval(x)
+ table.insert(cl, udval)
+ local d = T.newuserdata(100) -- cria lixo
+ d = nil
+ assert(debug.getmetatable(x).__gc == F)
+ loadstring("table.insert({}, {})")() -- cria mais lixo
+ collectgarbage() -- forca coleta de lixo durante coleta!
+ assert(debug.getmetatable(x).__gc == F) -- coleta anterior nao melou isso?
+ local dummy = {} -- cria lixo durante coleta
+ if A ~= nil then
+ assert(type(A) == "userdata")
+ assert(T.udataval(A) == B)
+ debug.getmetatable(A) -- just acess it
+ end
+ A = x -- ressucita userdata
+ B = udval
+ return 1,2,3
+end
+tt.__gc = F
+
+-- test whether udate collection frees memory in the right time
+do
+ collectgarbage();
+ collectgarbage();
+ local x = collectgarbage("count");
+ local a = T.newuserdata(5001)
+ assert(T.testC("objsize 2; return 1", a) == 5001)
+ assert(collectgarbage("count") >= x+4)
+ a = nil
+ collectgarbage();
+ assert(collectgarbage("count") <= x+1)
+ -- udata without finalizer
+ x = collectgarbage("count")
+ collectgarbage("stop")
+ for i=1,1000 do newproxy(false) end
+ assert(collectgarbage("count") > x+10)
+ collectgarbage()
+ assert(collectgarbage("count") <= x+1)
+ -- udata with finalizer
+ x = collectgarbage("count")
+ collectgarbage()
+ collectgarbage("stop")
+ a = newproxy(true)
+ getmetatable(a).__gc = function () end
+ for i=1,1000 do newproxy(a) end
+ assert(collectgarbage("count") >= x+10)
+ collectgarbage() -- this collection only calls TM, without freeing memory
+ assert(collectgarbage("count") >= x+10)
+ collectgarbage() -- now frees memory
+ assert(collectgarbage("count") <= x+1)
+end
+
+
+collectgarbage("stop")
+
+-- create 3 userdatas with tag `tt'
+a = T.newuserdata(0); debug.setmetatable(a, tt); na = T.udataval(a)
+b = T.newuserdata(0); debug.setmetatable(b, tt); nb = T.udataval(b)
+c = T.newuserdata(0); debug.setmetatable(c, tt); nc = T.udataval(c)
+
+-- create userdata without meta table
+x = T.newuserdata(4)
+y = T.newuserdata(0)
+
+assert(debug.getmetatable(x) == nil and debug.getmetatable(y) == nil)
+
+d=T.ref(a);
+e=T.ref(b);
+f=T.ref(c);
+t = {T.getref(d), T.getref(e), T.getref(f)}
+assert(t[1] == a and t[2] == b and t[3] == c)
+
+t=nil; a=nil; c=nil;
+T.unref(e); T.unref(f)
+
+collectgarbage()
+
+-- check that unref objects have been collected
+assert(table.getn(cl) == 1 and cl[1] == nc)
+
+x = T.getref(d)
+assert(type(x) == 'userdata' and debug.getmetatable(x) == tt)
+x =nil
+tt.b = b -- create cycle
+tt=nil -- frees tt for GC
+A = nil
+b = nil
+T.unref(d);
+n5 = T.newuserdata(0)
+debug.setmetatable(n5, {__gc=F})
+n5 = T.udataval(n5)
+collectgarbage()
+assert(table.getn(cl) == 4)
+-- check order of collection
+assert(cl[2] == n5 and cl[3] == nb and cl[4] == na)
+
+
+a, na = {}, {}
+for i=30,1,-1 do
+ a[i] = T.newuserdata(0)
+ debug.setmetatable(a[i], {__gc=F})
+ na[i] = T.udataval(a[i])
+end
+cl = {}
+a = nil; collectgarbage()
+assert(table.getn(cl) == 30)
+for i=1,30 do assert(cl[i] == na[i]) end
+na = nil
+
+
+for i=2,Lim,2 do -- unlock the other half
+ T.unref(Arr[i])
+end
+
+x = T.newuserdata(41); debug.setmetatable(x, {__gc=F})
+assert(T.testC("objsize 2; return 1", x) == 41)
+cl = {}
+a = {[x] = 1}
+x = T.udataval(x)
+collectgarbage()
+-- old `x' cannot be collected (`a' still uses it)
+assert(table.getn(cl) == 0)
+for n in pairs(a) do a[n] = nil end
+collectgarbage()
+assert(table.getn(cl) == 1 and cl[1] == x) -- old `x' must be collected
+
+-- testing lua_equal
+assert(T.testC("equal 2 4; return 1", print, 1, print, 20))
+assert(T.testC("equal 3 2; return 1", 'alo', "alo"))
+assert(T.testC("equal 2 3; return 1", nil, nil))
+assert(not T.testC("equal 2 3; return 1", {}, {}))
+assert(not T.testC("equal 2 3; return 1"))
+assert(not T.testC("equal 2 3; return 1", 3))
+
+-- testing lua_equal with fallbacks
+do
+ local map = {}
+ local t = {__eq = function (a,b) return map[a] == map[b] end}
+ local function f(x)
+ local u = T.newuserdata(0)
+ debug.setmetatable(u, t)
+ map[u] = x
+ return u
+ end
+ assert(f(10) == f(10))
+ assert(f(10) ~= f(11))
+ assert(T.testC("equal 2 3; return 1", f(10), f(10)))
+ assert(not T.testC("equal 2 3; return 1", f(10), f(20)))
+ t.__eq = nil
+ assert(f(10) ~= f(10))
+end
+
+print'+'
+
+
+
+-------------------------------------------------------------------------
+do -- testing errors during GC
+ local a = {}
+ for i=1,20 do
+ a[i] = T.newuserdata(i) -- creates several udata
+ end
+ for i=1,20,2 do -- mark half of them to raise error during GC
+ debug.setmetatable(a[i], {__gc = function (x) error("error inside gc") end})
+ end
+ for i=2,20,2 do -- mark the other half to count and to create more garbage
+ debug.setmetatable(a[i], {__gc = function (x) loadstring("A=A+1")() end})
+ end
+ _G.A = 0
+ a = 0
+ while 1 do
+ if xpcall(collectgarbage, function (s) a=a+1 end) then
+ break -- stop if no more errors
+ end
+ end
+ assert(a == 10) -- number of errors
+ assert(A == 10) -- number of normal collections
+end
+-------------------------------------------------------------------------
+-- test for userdata vals
+do
+ local a = {}; local lim = 30
+ for i=0,lim do a[i] = T.pushuserdata(i) end
+ for i=0,lim do assert(T.udataval(a[i]) == i) end
+ for i=0,lim do assert(T.pushuserdata(i) == a[i]) end
+ for i=0,lim do a[a[i]] = i end
+ for i=0,lim do a[T.pushuserdata(i)] = i end
+ assert(type(tostring(a[1])) == "string")
+end
+
+
+-------------------------------------------------------------------------
+-- testing multiple states
+T.closestate(T.newstate());
+L1 = T.newstate()
+assert(L1)
+assert(pack(T.doremote(L1, "function f () return 'alo', 3 end; f()")).n == 0)
+
+a, b = T.doremote(L1, "return f()")
+assert(a == 'alo' and b == '3')
+
+T.doremote(L1, "_ERRORMESSAGE = nil")
+-- error: `sin' is not defined
+a, b = T.doremote(L1, "return sin(1)")
+assert(a == nil and b == 2) -- 2 == run-time error
+
+-- error: syntax error
+a, b, c = T.doremote(L1, "return a+")
+assert(a == nil and b == 3 and type(c) == "string") -- 3 == syntax error
+
+T.loadlib(L1)
+a, b = T.doremote(L1, [[
+ a = strlibopen()
+ a = packageopen()
+ a = baselibopen(); assert(a == _G and require("_G") == a)
+ a = iolibopen(); assert(type(a.read) == "function")
+ assert(require("io") == a)
+ a = tablibopen(); assert(type(a.insert) == "function")
+ a = dblibopen(); assert(type(a.getlocal) == "function")
+ a = mathlibopen(); assert(type(a.sin) == "function")
+ return string.sub('okinama', 1, 2)
+]])
+assert(a == "ok")
+
+T.closestate(L1);
+
+L1 = T.newstate()
+T.loadlib(L1)
+T.doremote(L1, "a = {}")
+T.testC(L1, [[pushstring a; gettable G; pushstring x; pushnum 1;
+ settable -3]])
+assert(T.doremote(L1, "return a.x") == "1")
+
+T.closestate(L1)
+
+L1 = nil
+
+print('+')
+
+-------------------------------------------------------------------------
+-- testing memory limits
+-------------------------------------------------------------------------
+collectgarbage()
+T.totalmem(T.totalmem()+5000) -- set low memory limit (+5k)
+assert(not pcall(loadstring"local a={}; for i=1,100000 do a[i]=i end"))
+T.totalmem(1000000000) -- restore high limit
+
+
+local function stack(x) if x>0 then stack(x-1) end end
+
+-- test memory errors; increase memory limit in small steps, so that
+-- we get memory errors in different parts of a given task, up to there
+-- is enough memory to complete the task without errors
+function testamem (s, f)
+ collectgarbage()
+ stack(10) -- ensure minimum stack size
+ local M = T.totalmem()
+ local oldM = M
+ local a,b = nil
+ while 1 do
+ M = M+3 -- increase memory limit in small steps
+ T.totalmem(M)
+ a, b = pcall(f)
+ if a and b then break end -- stop when no more errors
+ collectgarbage()
+ if not a and not string.find(b, "memory") then -- `real' error?
+ T.totalmem(1000000000) -- restore high limit
+ error(b, 0)
+ end
+ end
+ T.totalmem(1000000000) -- restore high limit
+ print("\nlimit for " .. s .. ": " .. M-oldM)
+ return b
+end
+
+
+-- testing memory errors when creating a new state
+
+b = testamem("state creation", T.newstate)
+T.closestate(b); -- close new state
+
+
+-- testing threads
+
+function expand (n,s)
+ if n==0 then return "" end
+ local e = string.rep("=", n)
+ return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n",
+ e, s, expand(n-1,s), e)
+end
+
+G=0; collectgarbage(); a =collectgarbage("count")
+loadstring(expand(20,"G=G+1"))()
+assert(G==20); collectgarbage(); -- assert(gcinfo() <= a+1)
+
+testamem("thread creation", function ()
+ return T.doonnewstack("x=1") == 0 -- try to create thread
+end)
+
+
+-- testing memory x compiler
+
+testamem("loadstring", function ()
+ return loadstring("x=1") -- try to do a loadstring
+end)
+
+
+local testprog = [[
+local function foo () return end
+local t = {"x"}
+a = "aaa"
+for _, v in ipairs(t) do a=a..v end
+return true
+]]
+
+-- testing memory x dofile
+_G.a = nil
+local t =os.tmpname()
+local f = assert(io.open(t, "w"))
+f:write(testprog)
+f:close()
+testamem("dofile", function ()
+ local a = loadfile(t)
+ return a and a()
+end)
+assert(os.remove(t))
+assert(_G.a == "aaax")
+
+
+-- other generic tests
+
+testamem("string creation", function ()
+ local a, b = string.gsub("alo alo", "(a)", function (x) return x..'b' end)
+ return (a == 'ablo ablo')
+end)
+
+testamem("dump/undump", function ()
+ local a = loadstring(testprog)
+ local b = a and string.dump(a)
+ a = b and loadstring(b)
+ return a and a()
+end)
+
+local t = os.tmpname()
+testamem("file creation", function ()
+ local f = assert(io.open(t, 'w'))
+ assert (not io.open"nomenaoexistente")
+ io.close(f);
+ return not loadfile'nomenaoexistente'
+end)
+assert(os.remove(t))
+
+testamem("table creation", function ()
+ local a, lim = {}, 10
+ for i=1,lim do a[i] = i; a[i..'a'] = {} end
+ return (type(a[lim..'a']) == 'table' and a[lim] == lim)
+end)
+
+local a = 1
+close = nil
+testamem("closure creation", function ()
+ function close (b,c)
+ return function (x) return a+b+c+x end
+ end
+ return (close(2,3)(4) == 10)
+end)
+
+testamem("coroutines", function ()
+ local a = coroutine.wrap(function ()
+ coroutine.yield(string.rep("a", 10))
+ return {}
+ end)
+ assert(string.len(a()) == 10)
+ return a()
+end)
+
+print'+'
+
+-- testing some auxlib functions
+assert(T.gsub("alo.alo.uhuh.", ".", "//") == "alo//alo//uhuh//")
+assert(T.gsub("alo.alo.uhuh.", "alo", "//") == "//.//.uhuh.")
+assert(T.gsub("", "alo", "//") == "")
+assert(T.gsub("...", ".", "/.") == "/././.")
+assert(T.gsub("...", "...", "") == "")
+
+
+print'OK'
+
diff --git a/test/PUC-Rio-Lua-5.1-tests/attrib.lua b/test/PUC-Rio-Lua-5.1-tests/attrib.lua
new file mode 100644
index 00000000..655669bd
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/attrib.lua
@@ -0,0 +1,339 @@
+do --[
+
+print "testing require"
+
+assert(require"string" == string)
+assert(require"math" == math)
+assert(require"table" == table)
+assert(require"io" == io)
+assert(require"os" == os)
+assert(require"debug" == debug)
+assert(require"coroutine" == coroutine)
+
+assert(type(package.path) == "string")
+assert(type(package.cpath) == "string")
+assert(type(package.loaded) == "table")
+assert(type(package.preload) == "table")
+
+
+local DIR = "libs/"
+
+local function createfiles (files, preextras, posextras)
+ for n,c in pairs(files) do
+ io.output(DIR..n)
+ io.write(string.format(preextras, n))
+ io.write(c)
+ io.write(string.format(posextras, n))
+ io.close(io.output())
+ end
+end
+
+function removefiles (files)
+ for n in pairs(files) do
+ os.remove(DIR..n)
+ end
+end
+
+local files = {
+ ["A.lua"] = "",
+ ["B.lua"] = "assert(...=='B');require 'A'",
+ ["A.lc"] = "",
+ ["A"] = "",
+ ["L"] = "",
+ ["XXxX"] = "",
+ ["C.lua"] = "package.loaded[...] = 25; require'C'"
+}
+
+AA = nil
+local extras = [[
+NAME = '%s'
+REQUIRED = ...
+return AA]]
+
+createfiles(files, "", extras)
+
+
+local oldpath = package.path
+
+package.path = string.gsub("D/?.lua;D/?.lc;D/?;D/??x?;D/L", "D/", DIR)
+
+local try = function (p, n, r)
+ NAME = nil
+ local rr = require(p)
+ assert(NAME == n)
+ assert(REQUIRED == p)
+ assert(rr == r)
+end
+
+assert(require"C" == 25)
+assert(require"C" == 25)
+AA = nil
+try('B', 'B.lua', true)
+assert(package.loaded.B)
+assert(require"B" == true)
+assert(package.loaded.A)
+package.loaded.A = nil
+try('B', nil, true) -- should not reload package
+try('A', 'A.lua', true)
+package.loaded.A = nil
+os.remove(DIR..'A.lua')
+AA = {}
+try('A', 'A.lc', AA) -- now must find second option
+assert(require("A") == AA)
+AA = false
+try('K', 'L', false) -- default option
+try('K', 'L', false) -- default option (should reload it)
+assert(rawget(_G, "_REQUIREDNAME") == nil)
+
+AA = "x"
+try("X", "XXxX", AA)
+
+
+removefiles(files)
+
+
+-- testing require of sub-packages
+
+package.path = string.gsub("D/?.lua;D/?/init.lua", "D/", DIR)
+
+files = {
+ ["P1/init.lua"] = "AA = 10",
+ ["P1/xuxu.lua"] = "AA = 20",
+}
+
+createfiles(files, "module(..., package.seeall)\n", "")
+AA = 0
+
+local m = assert(require"P1")
+assert(m == P1 and m._NAME == "P1" and AA == 0 and m.AA == 10)
+assert(require"P1" == P1 and P1 == m)
+assert(require"P1" == P1)
+assert(P1._PACKAGE == "")
+
+local m = assert(require"P1.xuxu")
+assert(m == P1.xuxu and m._NAME == "P1.xuxu" and AA == 0 and m.AA == 20)
+assert(require"P1.xuxu" == P1.xuxu and P1.xuxu == m)
+assert(require"P1.xuxu" == P1.xuxu)
+assert(require"P1" == P1)
+assert(P1.xuxu._PACKAGE == "P1.")
+assert(P1.AA == 10 and P1._PACKAGE == "")
+assert(P1._G == _G and P1.xuxu._G == _G)
+
+
+
+removefiles(files)
+
+
+package.path = ""
+assert(not pcall(require, "file_does_not_exist"))
+package.path = "??\0?"
+assert(not pcall(require, "file_does_not_exist1"))
+
+package.path = oldpath
+
+-- check 'require' error message
+local fname = "file_does_not_exist2"
+local m, err = pcall(require, fname)
+for t in string.gmatch(package.path..";"..package.cpath, "[^;]+") do
+ t = string.gsub(t, "?", fname)
+ assert(string.find(err, t, 1, true))
+end
+
+
+local function import(...)
+ local f = {...}
+ return function (m)
+ for i=1, #f do m[f[i]] = _G[f[i]] end
+ end
+end
+
+local assert, module, package = assert, module, package
+X = nil; x = 0; assert(_G.x == 0) -- `x' must be a global variable
+module"X"; x = 1; assert(_M.x == 1)
+module"X.a.b.c"; x = 2; assert(_M.x == 2)
+module("X.a.b", package.seeall); x = 3
+assert(X._NAME == "X" and X.a.b.c._NAME == "X.a.b.c" and X.a.b._NAME == "X.a.b")
+assert(X._M == X and X.a.b.c._M == X.a.b.c and X.a.b._M == X.a.b)
+assert(X.x == 1 and X.a.b.c.x == 2 and X.a.b.x == 3)
+assert(X._PACKAGE == "" and X.a.b.c._PACKAGE == "X.a.b." and
+ X.a.b._PACKAGE == "X.a.")
+assert(_PACKAGE.."c" == "X.a.c")
+assert(X.a._NAME == nil and X.a._M == nil)
+module("X.a", import("X")) ; x = 4
+assert(X.a._NAME == "X.a" and X.a.x == 4 and X.a._M == X.a)
+module("X.a.b", package.seeall); assert(x == 3); x = 5
+assert(_NAME == "X.a.b" and X.a.b.x == 5)
+
+assert(X._G == nil and X.a._G == nil and X.a.b._G == _G and X.a.b.c._G == nil)
+
+setfenv(1, _G)
+assert(x == 0)
+
+assert(not pcall(module, "x"))
+assert(not pcall(module, "math.sin"))
+
+
+-- testing C libraries
+
+
+local p = "" -- On Mac OS X, redefine this to "_"
+
+-- assert(loadlib == package.loadlib) -- only for compatibility
+local f, err, when = package.loadlib("libs/lib1.so", p.."luaopen_lib1")
+if not f then
+ (Message or print)('\a\n >>> cannot load dynamic library <<<\n\a')
+ print(err, when)
+else
+ f() -- open library
+ assert(require("lib1") == lib1)
+ collectgarbage()
+ assert(lib1.id("x") == "x")
+ f = assert(package.loadlib("libs/lib1.so", p.."anotherfunc"))
+ assert(f(10, 20) == "1020\n")
+ f, err, when = package.loadlib("libs/lib1.so", p.."xuxu")
+ assert(not f and type(err) == "string" and when == "init")
+ package.cpath = "libs/?.so"
+ require"lib2"
+ assert(lib2.id("x") == "x")
+ local fs = require"lib1.sub"
+ assert(fs == lib1.sub and next(lib1.sub) == nil)
+ module("lib2", package.seeall)
+ f = require"-lib2"
+ assert(f.id("x") == "x" and _M == f and _NAME == "lib2")
+ module("lib1.sub", package.seeall)
+ assert(_M == fs)
+ setfenv(1, _G)
+
+end
+f, err, when = package.loadlib("donotexist", p.."xuxu")
+assert(not f and type(err) == "string" and (when == "open" or when == "absent"))
+
+
+-- testing preload
+
+do
+ local p = package
+ package = {}
+ p.preload.pl = function (...)
+ module(...)
+ function xuxu (x) return x+20 end
+ end
+
+ require"pl"
+ assert(require"pl" == pl)
+ assert(pl.xuxu(10) == 30)
+
+ package = p
+ assert(type(package.path) == "string")
+end
+
+
+
+end --]
+
+print('+')
+
+print("testing assignments, logical operators, and constructors")
+
+local res, res2 = 27
+
+a, b = 1, 2+3
+assert(a==1 and b==5)
+a={}
+function f() return 10, 11, 12 end
+a.x, b, a[1] = 1, 2, f()
+assert(a.x==1 and b==2 and a[1]==10)
+a[f()], b, a[f()+3] = f(), a, 'x'
+assert(a[10] == 10 and b == a and a[13] == 'x')
+
+do
+ local f = function (n) local x = {}; for i=1,n do x[i]=i end;
+ return unpack(x) end;
+ local a,b,c
+ a,b = 0, f(1)
+ assert(a == 0 and b == 1)
+ A,b = 0, f(1)
+ assert(A == 0 and b == 1)
+ a,b,c = 0,5,f(4)
+ assert(a==0 and b==5 and c==1)
+ a,b,c = 0,5,f(0)
+ assert(a==0 and b==5 and c==nil)
+end
+
+
+a, b, c, d = 1 and nil, 1 or nil, (1 and (nil or 1)), 6
+assert(not a and b and c and d==6)
+
+d = 20
+a, b, c, d = f()
+assert(a==10 and b==11 and c==12 and d==nil)
+a,b = f(), 1, 2, 3, f()
+assert(a==10 and b==1)
+
+assert(a<b == false and a>b == true)
+assert((10 and 2) == 2)
+assert((10 or 2) == 10)
+assert((10 or assert(nil)) == 10)
+assert(not (nil and assert(nil)))
+assert((nil or "alo") == "alo")
+assert((nil and 10) == nil)
+assert((false and 10) == false)
+assert((true or 10) == true)
+assert((false or 10) == 10)
+assert(false ~= nil)
+assert(nil ~= false)
+assert(not nil == true)
+assert(not not nil == false)
+assert(not not 1 == true)
+assert(not not a == true)
+assert(not not (6 or nil) == true)
+assert(not not (nil and 56) == false)
+assert(not not (nil and true) == false)
+print('+')
+
+a = {}
+a[true] = 20
+a[false] = 10
+assert(a[1<2] == 20 and a[1>2] == 10)
+
+function f(a) return a end
+
+local a = {}
+for i=3000,-3000,-1 do a[i] = i; end
+a[10e30] = "alo"; a[true] = 10; a[false] = 20
+assert(a[10e30] == 'alo' and a[not 1] == 20 and a[10<20] == 10)
+for i=3000,-3000,-1 do assert(a[i] == i); end
+a[print] = assert
+a[f] = print
+a[a] = a
+assert(a[a][a][a][a][print] == assert)
+a[print](a[a[f]] == a[print])
+a = nil
+
+a = {10,9,8,7,6,5,4,3,2; [-3]='a', [f]=print, a='a', b='ab'}
+a, a.x, a.y = a, a[-3]
+assert(a[1]==10 and a[-3]==a.a and a[f]==print and a.x=='a' and not a.y)
+a[1], f(a)[2], b, c = {['alo']=assert}, 10, a[1], a[f], 6, 10, 23, f(a), 2
+a[1].alo(a[2]==10 and b==10 and c==print)
+
+a[2^31] = 10; a[2^31+1] = 11; a[-2^31] = 12;
+a[2^32] = 13; a[-2^32] = 14; a[2^32+1] = 15; a[10^33] = 16;
+
+assert(a[2^31] == 10 and a[2^31+1] == 11 and a[-2^31] == 12 and
+ a[2^32] == 13 and a[-2^32] == 14 and a[2^32+1] == 15 and
+ a[10^33] == 16)
+
+a = nil
+
+
+do
+ local a,i,j,b
+ a = {'a', 'b'}; i=1; j=2; b=a
+ i, a[i], a, j, a[j], a[i+j] = j, i, i, b, j, i
+ assert(i == 2 and b[1] == 1 and a == 1 and j == b and b[2] == 2 and
+ b[3] == 1)
+end
+
+print('OK')
+
+return res
diff --git a/test/PUC-Rio-Lua-5.1-tests/big.lua b/test/PUC-Rio-Lua-5.1-tests/big.lua
new file mode 100644
index 00000000..92612880
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/big.lua
@@ -0,0 +1,381 @@
+print "testing string length overflow"
+
+local longs = string.rep("\0", 2^25)
+local function catter (i)
+ return assert(loadstring(
+ string.format("return function(a) return a%s end",
+ string.rep("..a", i-1))))()
+end
+rep129 = catter(129)
+local a, b = pcall(rep129, longs)
+assert(not a and string.find(b, "overflow"))
+print('+')
+
+
+require "checktable"
+
+--[[ lots of empty lines (to force SETLINEW)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+--]]
+
+
+a,b = nil,nil
+while not b do
+if a then
+b = { -- lots of strings (to force JMPW and PUSHCONSTANTW)
+"n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9", "n10",
+"n11", "n12", "j301", "j302", "j303", "j304", "j305", "j306", "j307", "j308",
+"j309", "a310", "n311", "n312", "n313", "n314", "n315", "n316", "n317", "n318",
+"n319", "n320", "n321", "n322", "n323", "n324", "n325", "n326", "n327", "n328",
+"a329", "n330", "n331", "n332", "n333", "n334", "n335", "n336", "n337", "n338",
+"n339", "n340", "n341", "z342", "n343", "n344", "n345", "n346", "n347", "n348",
+"n349", "n350", "n351", "n352", "r353", "n354", "n355", "n356", "n357", "n358",
+"n359", "n360", "n361", "n362", "n363", "n364", "n365", "n366", "z367", "n368",
+"n369", "n370", "n371", "n372", "n373", "n374", "n375", "a376", "n377", "n378",
+"n379", "n380", "n381", "n382", "n383", "n384", "n385", "n386", "n387", "n388",
+"n389", "n390", "n391", "n392", "n393", "n394", "n395", "n396", "n397", "n398",
+"n399", "n400", "n13", "n14", "n15", "n16", "n17", "n18", "n19", "n20",
+"n21", "n22", "n23", "a24", "n25", "n26", "n27", "n28", "n29", "j30",
+"n31", "n32", "n33", "n34", "n35", "n36", "n37", "n38", "n39", "n40",
+"n41", "n42", "n43", "n44", "n45", "n46", "n47", "n48", "n49", "n50",
+"n51", "n52", "n53", "n54", "n55", "n56", "n57", "n58", "n59", "n60",
+"n61", "n62", "n63", "n64", "n65", "a66", "z67", "n68", "n69", "n70",
+"n71", "n72", "n73", "n74", "n75", "n76", "n77", "n78", "n79", "n80",
+"n81", "n82", "n83", "n84", "n85", "n86", "n87", "n88", "n89", "n90",
+"n91", "n92", "n93", "n94", "n95", "n96", "n97", "n98", "n99", "n100",
+"n201", "n202", "n203", "n204", "n205", "n206", "n207", "n208", "n209", "n210",
+"n211", "n212", "n213", "n214", "n215", "n216", "n217", "n218", "n219", "n220",
+"n221", "n222", "n223", "n224", "n225", "n226", "n227", "n228", "n229", "n230",
+"n231", "n232", "n233", "n234", "n235", "n236", "n237", "n238", "n239", "a240",
+"a241", "a242", "a243", "a244", "a245", "a246", "a247", "a248", "a249", "n250",
+"n251", "n252", "n253", "n254", "n255", "n256", "n257", "n258", "n259", "n260",
+"n261", "n262", "n263", "n264", "n265", "n266", "n267", "n268", "n269", "n270",
+"n271", "n272", "n273", "n274", "n275", "n276", "n277", "n278", "n279", "n280",
+"n281", "n282", "n283", "n284", "n285", "n286", "n287", "n288", "n289", "n290",
+"n291", "n292", "n293", "n294", "n295", "n296", "n297", "n298", "n299"
+; x=23}
+else a = 1 end
+
+
+end
+
+assert(b.x == 23)
+print('+')
+
+stat(b)
+
+repeat
+a = {
+n1 = 1.5, n2 = 2.5, n3 = 3.5, n4 = 4.5, n5 = 5.5, n6 = 6.5, n7 = 7.5,
+n8 = 8.5, n9 = 9.5, n10 = 10.5, n11 = 11.5, n12 = 12.5,
+j301 = 301.5, j302 = 302.5, j303 = 303.5, j304 = 304.5, j305 = 305.5,
+j306 = 306.5, j307 = 307.5, j308 = 308.5, j309 = 309.5, a310 = 310.5,
+n311 = 311.5, n312 = 312.5, n313 = 313.5, n314 = 314.5, n315 = 315.5,
+n316 = 316.5, n317 = 317.5, n318 = 318.5, n319 = 319.5, n320 = 320.5,
+n321 = 321.5, n322 = 322.5, n323 = 323.5, n324 = 324.5, n325 = 325.5,
+n326 = 326.5, n327 = 327.5, n328 = 328.5, a329 = 329.5, n330 = 330.5,
+n331 = 331.5, n332 = 332.5, n333 = 333.5, n334 = 334.5, n335 = 335.5,
+n336 = 336.5, n337 = 337.5, n338 = 338.5, n339 = 339.5, n340 = 340.5,
+n341 = 341.5, z342 = 342.5, n343 = 343.5, n344 = 344.5, n345 = 345.5,
+n346 = 346.5, n347 = 347.5, n348 = 348.5, n349 = 349.5, n350 = 350.5,
+n351 = 351.5, n352 = 352.5, r353 = 353.5, n354 = 354.5, n355 = 355.5,
+n356 = 356.5, n357 = 357.5, n358 = 358.5, n359 = 359.5, n360 = 360.5,
+n361 = 361.5, n362 = 362.5, n363 = 363.5, n364 = 364.5, n365 = 365.5,
+n366 = 366.5, z367 = 367.5, n368 = 368.5, n369 = 369.5, n370 = 370.5,
+n371 = 371.5, n372 = 372.5, n373 = 373.5, n374 = 374.5, n375 = 375.5,
+a376 = 376.5, n377 = 377.5, n378 = 378.5, n379 = 379.5, n380 = 380.5,
+n381 = 381.5, n382 = 382.5, n383 = 383.5, n384 = 384.5, n385 = 385.5,
+n386 = 386.5, n387 = 387.5, n388 = 388.5, n389 = 389.5, n390 = 390.5,
+n391 = 391.5, n392 = 392.5, n393 = 393.5, n394 = 394.5, n395 = 395.5,
+n396 = 396.5, n397 = 397.5, n398 = 398.5, n399 = 399.5, n400 = 400.5,
+n13 = 13.5, n14 = 14.5, n15 = 15.5, n16 = 16.5, n17 = 17.5,
+n18 = 18.5, n19 = 19.5, n20 = 20.5, n21 = 21.5, n22 = 22.5,
+n23 = 23.5, a24 = 24.5, n25 = 25.5, n26 = 26.5, n27 = 27.5,
+n28 = 28.5, n29 = 29.5, j30 = 30.5, n31 = 31.5, n32 = 32.5,
+n33 = 33.5, n34 = 34.5, n35 = 35.5, n36 = 36.5, n37 = 37.5,
+n38 = 38.5, n39 = 39.5, n40 = 40.5, n41 = 41.5, n42 = 42.5,
+n43 = 43.5, n44 = 44.5, n45 = 45.5, n46 = 46.5, n47 = 47.5,
+n48 = 48.5, n49 = 49.5, n50 = 50.5, n51 = 51.5, n52 = 52.5,
+n53 = 53.5, n54 = 54.5, n55 = 55.5, n56 = 56.5, n57 = 57.5,
+n58 = 58.5, n59 = 59.5, n60 = 60.5, n61 = 61.5, n62 = 62.5,
+n63 = 63.5, n64 = 64.5, n65 = 65.5, a66 = 66.5, z67 = 67.5,
+n68 = 68.5, n69 = 69.5, n70 = 70.5, n71 = 71.5, n72 = 72.5,
+n73 = 73.5, n74 = 74.5, n75 = 75.5, n76 = 76.5, n77 = 77.5,
+n78 = 78.5, n79 = 79.5, n80 = 80.5, n81 = 81.5, n82 = 82.5,
+n83 = 83.5, n84 = 84.5, n85 = 85.5, n86 = 86.5, n87 = 87.5,
+n88 = 88.5, n89 = 89.5, n90 = 90.5, n91 = 91.5, n92 = 92.5,
+n93 = 93.5, n94 = 94.5, n95 = 95.5, n96 = 96.5, n97 = 97.5,
+n98 = 98.5, n99 = 99.5, n100 = 100.5, n201 = 201.5, n202 = 202.5,
+n203 = 203.5, n204 = 204.5, n205 = 205.5, n206 = 206.5, n207 = 207.5,
+n208 = 208.5, n209 = 209.5, n210 = 210.5, n211 = 211.5, n212 = 212.5,
+n213 = 213.5, n214 = 214.5, n215 = 215.5, n216 = 216.5, n217 = 217.5,
+n218 = 218.5, n219 = 219.5, n220 = 220.5, n221 = 221.5, n222 = 222.5,
+n223 = 223.5, n224 = 224.5, n225 = 225.5, n226 = 226.5, n227 = 227.5,
+n228 = 228.5, n229 = 229.5, n230 = 230.5, n231 = 231.5, n232 = 232.5,
+n233 = 233.5, n234 = 234.5, n235 = 235.5, n236 = 236.5, n237 = 237.5,
+n238 = 238.5, n239 = 239.5, a240 = 240.5, a241 = 241.5, a242 = 242.5,
+a243 = 243.5, a244 = 244.5, a245 = 245.5, a246 = 246.5, a247 = 247.5,
+a248 = 248.5, a249 = 249.5, n250 = 250.5, n251 = 251.5, n252 = 252.5,
+n253 = 253.5, n254 = 254.5, n255 = 255.5, n256 = 256.5, n257 = 257.5,
+n258 = 258.5, n259 = 259.5, n260 = 260.5, n261 = 261.5, n262 = 262.5,
+n263 = 263.5, n264 = 264.5, n265 = 265.5, n266 = 266.5, n267 = 267.5,
+n268 = 268.5, n269 = 269.5, n270 = 270.5, n271 = 271.5, n272 = 272.5,
+n273 = 273.5, n274 = 274.5, n275 = 275.5, n276 = 276.5, n277 = 277.5,
+n278 = 278.5, n279 = 279.5, n280 = 280.5, n281 = 281.5, n282 = 282.5,
+n283 = 283.5, n284 = 284.5, n285 = 285.5, n286 = 286.5, n287 = 287.5,
+n288 = 288.5, n289 = 289.5, n290 = 290.5, n291 = 291.5, n292 = 292.5,
+n293 = 293.5, n294 = 294.5, n295 = 295.5, n296 = 296.5, n297 = 297.5,
+n298 = 298.5, n299 = 299.5, j300 = 300} or 1
+until 1
+
+assert(a.n299 == 299.5)
+xxx = 1
+assert(xxx == 1)
+
+stat(a)
+
+function a:findfield (f)
+ local i,v = next(self, nil)
+ while i ~= f do
+ if not i then return end
+ i,v = next(self, i)
+ end
+ return v
+end
+
+local ii = 0
+i = 1
+while b[i] do
+ local r = a:findfield(b[i]);
+ assert(a[b[i]] == r)
+ ii = math.max(ii,i)
+ i = i+1
+end
+
+assert(ii == 299)
+
+function xxxx (x) coroutine.yield('b'); return ii+x end
+
+assert(xxxx(10) == 309)
+
+a = nil
+b = nil
+a1 = nil
+
+print("tables with table indices:")
+i = 1; a={}
+while i <= 1023 do a[{}] = i; i=i+1 end
+stat(a)
+a = nil
+
+print("tables with function indices:")
+a={}
+for i=1,511 do local x; a[function () return x end] = i end
+stat(a)
+a = nil
+
+print'OK'
+
+return 'a'
diff --git a/test/PUC-Rio-Lua-5.1-tests/calls.lua b/test/PUC-Rio-Lua-5.1-tests/calls.lua
new file mode 100644
index 00000000..788f9a1c
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/calls.lua
@@ -0,0 +1,294 @@
+print("testing functions and calls")
+
+-- get the opportunity to test 'type' too ;)
+
+assert(type(1<2) == 'boolean')
+assert(type(true) == 'boolean' and type(false) == 'boolean')
+assert(type(nil) == 'nil' and type(-3) == 'number' and type'x' == 'string' and
+ type{} == 'table' and type(type) == 'function')
+
+assert(type(assert) == type(print))
+f = nil
+function f (x) return a:x (x) end
+assert(type(f) == 'function')
+
+
+-- testing local-function recursion
+fact = false
+do
+ local res = 1
+ local function fact (n)
+ if n==0 then return res
+ else return n*fact(n-1)
+ end
+ end
+ assert(fact(5) == 120)
+end
+assert(fact == false)
+
+-- testing declarations
+a = {i = 10}
+self = 20
+function a:x (x) return x+self.i end
+function a.y (x) return x+self end
+
+assert(a:x(1)+10 == a.y(1))
+
+a.t = {i=-100}
+a["t"].x = function (self, a,b) return self.i+a+b end
+
+assert(a.t:x(2,3) == -95)
+
+do
+ local a = {x=0}
+ function a:add (x) self.x, a.y = self.x+x, 20; return self end
+ assert(a:add(10):add(20):add(30).x == 60 and a.y == 20)
+end
+
+local a = {b={c={}}}
+
+function a.b.c.f1 (x) return x+1 end
+function a.b.c:f2 (x,y) self[x] = y end
+assert(a.b.c.f1(4) == 5)
+a.b.c:f2('k', 12); assert(a.b.c.k == 12)
+
+print('+')
+
+t = nil -- 'declare' t
+function f(a,b,c) local d = 'a'; t={a,b,c,d} end
+
+f( -- this line change must be valid
+ 1,2)
+assert(t[1] == 1 and t[2] == 2 and t[3] == nil and t[4] == 'a')
+f(1,2, -- this one too
+ 3,4)
+assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 'a')
+
+function fat(x)
+ if x <= 1 then return 1
+ else return x*loadstring("return fat(" .. x-1 .. ")")()
+ end
+end
+
+assert(loadstring "loadstring 'assert(fat(6)==720)' () ")()
+a = loadstring('return fat(5), 3')
+a,b = a()
+assert(a == 120 and b == 3)
+print('+')
+
+function err_on_n (n)
+ if n==0 then error(); exit(1);
+ else err_on_n (n-1); exit(1);
+ end
+end
+
+do
+ function dummy (n)
+ if n > 0 then
+ assert(not pcall(err_on_n, n))
+ dummy(n-1)
+ end
+ end
+end
+
+dummy(10)
+
+function deep (n)
+ if n>0 then deep(n-1) end
+end
+deep(10)
+deep(200)
+
+-- testing tail call
+function deep (n) if n>0 then return deep(n-1) else return 101 end end
+assert(deep(30000) == 101)
+a = {}
+function a:deep (n) if n>0 then return self:deep(n-1) else return 101 end end
+assert(a:deep(30000) == 101)
+
+print('+')
+
+
+a = nil
+(function (x) a=x end)(23)
+assert(a == 23 and (function (x) return x*2 end)(20) == 40)
+
+
+local x,y,z,a
+a = {}; lim = 2000
+for i=1, lim do a[i]=i end
+assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim)
+x = unpack(a)
+assert(x == 1)
+x = {unpack(a)}
+assert(table.getn(x) == lim and x[1] == 1 and x[lim] == lim)
+x = {unpack(a, lim-2)}
+assert(table.getn(x) == 3 and x[1] == lim-2 and x[3] == lim)
+x = {unpack(a, 10, 6)}
+assert(next(x) == nil) -- no elements
+x = {unpack(a, 11, 10)}
+assert(next(x) == nil) -- no elements
+x,y = unpack(a, 10, 10)
+assert(x == 10 and y == nil)
+x,y,z = unpack(a, 10, 11)
+assert(x == 10 and y == 11 and z == nil)
+a,x = unpack{1}
+assert(a==1 and x==nil)
+a,x = unpack({1,2}, 1, 1)
+assert(a==1 and x==nil)
+
+
+-- testing closures
+
+-- fixed-point operator
+Y = function (le)
+ local function a (f)
+ return le(function (x) return f(f)(x) end)
+ end
+ return a(a)
+ end
+
+
+-- non-recursive factorial
+
+F = function (f)
+ return function (n)
+ if n == 0 then return 1
+ else return n*f(n-1) end
+ end
+ end
+
+fat = Y(F)
+
+assert(fat(0) == 1 and fat(4) == 24 and Y(F)(5)==5*Y(F)(4))
+
+local function g (z)
+ local function f (a,b,c,d)
+ return function (x,y) return a+b+c+d+a+x+y+z end
+ end
+ return f(z,z+1,z+2,z+3)
+end
+
+f = g(10)
+assert(f(9, 16) == 10+11+12+13+10+9+16+10)
+
+Y, F, f = nil
+print('+')
+
+-- testing multiple returns
+
+function unlpack (t, i)
+ i = i or 1
+ if (i <= table.getn(t)) then
+ return t[i], unlpack(t, i+1)
+ end
+end
+
+function equaltab (t1, t2)
+ assert(table.getn(t1) == table.getn(t2))
+ for i,v1 in ipairs(t1) do
+ assert(v1 == t2[i])
+ end
+end
+
+local function pack (...)
+ local x = {...}
+ x.n = select('#', ...)
+ return x
+end
+
+function f() return 1,2,30,4 end
+function ret2 (a,b) return a,b end
+
+local a,b,c,d = unlpack{1,2,3}
+assert(a==1 and b==2 and c==3 and d==nil)
+a = {1,2,3,4,false,10,'alo',false,assert}
+equaltab(pack(unlpack(a)), a)
+equaltab(pack(unlpack(a), -1), {1,-1})
+a,b,c,d = ret2(f()), ret2(f())
+assert(a==1 and b==1 and c==2 and d==nil)
+a,b,c,d = unlpack(pack(ret2(f()), ret2(f())))
+assert(a==1 and b==1 and c==2 and d==nil)
+a,b,c,d = unlpack(pack(ret2(f()), (ret2(f()))))
+assert(a==1 and b==1 and c==nil and d==nil)
+
+a = ret2{ unlpack{1,2,3}, unlpack{3,2,1}, unlpack{"a", "b"}}
+assert(a[1] == 1 and a[2] == 3 and a[3] == "a" and a[4] == "b")
+
+
+-- testing calls with 'incorrect' arguments
+rawget({}, "x", 1)
+rawset({}, "x", 1, 2)
+assert(math.sin(1,2) == math.sin(1))
+table.sort({10,9,8,4,19,23,0,0}, function (a,b) return a<b end, "extra arg")
+
+
+-- test for generic load
+x = "-- a comment\0\0\0\n x = 10 + \n23; \
+ local a = function () x = 'hi' end; \
+ return '\0'"
+local i = 0
+function read1 (x)
+ return function ()
+ collectgarbage()
+ i=i+1
+ return string.sub(x, i, i)
+ end
+end
+
+a = assert(load(read1(x), "modname"))
+assert(a() == "\0" and _G.x == 33)
+assert(debug.getinfo(a).source == "modname")
+
+x = string.dump(loadstring("x = 1; return x"))
+i = 0
+a = assert(load(read1(x)))
+assert(a() == 1 and _G.x == 1)
+
+i = 0
+local a, b = load(read1("*a = 123"))
+assert(not a and type(b) == "string" and i == 2)
+
+a, b = load(function () error("hhi") end)
+assert(not a and string.find(b, "hhi"))
+
+-- test generic load with nested functions
+x = [[
+ return function (x)
+ return function (y)
+ return function (z)
+ return x+y+z
+ end
+ end
+ end
+]]
+
+a = assert(load(read1(x)))
+assert(a()(2)(3)(10) == 15)
+
+
+-- test for dump/undump with upvalues
+local a, b = 20, 30
+x = loadstring(string.dump(function (x)
+ if x == "set" then a = 10+b; b = b+1 else
+ return a
+ end
+end))
+assert(x() == nil)
+assert(debug.setupvalue(x, 1, "hi") == "a")
+assert(x() == "hi")
+assert(debug.setupvalue(x, 2, 13) == "b")
+assert(not debug.setupvalue(x, 3, 10)) -- only 2 upvalues
+x("set")
+assert(x() == 23)
+x("set")
+assert(x() == 24)
+
+
+-- test for bug in parameter adjustment
+assert((function () return nil end)(4) == nil)
+assert((function () local a; return a end)(4) == nil)
+assert((function (a) return a end)() == nil)
+
+print('OK')
+return deep
diff --git a/test/PUC-Rio-Lua-5.1-tests/checktable.lua b/test/PUC-Rio-Lua-5.1-tests/checktable.lua
new file mode 100644
index 00000000..f0938be8
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/checktable.lua
@@ -0,0 +1,77 @@
+
+assert(rawget(_G, "stat") == nil) -- module not loaded before
+
+if T == nil then
+ stat = function () print"`querytab' nao ativo" end
+ return
+end
+
+
+function checktable (t)
+ local asize, hsize, ff = T.querytab(t)
+ local l = {}
+ for i=0,hsize-1 do
+ local key,val,next = T.querytab(t, i + asize)
+ if key == nil then
+ assert(l[i] == nil and val==nil and next==nil)
+ elseif key == "<undef>" then
+ assert(val==nil)
+ else
+ assert(t[key] == val)
+ local mp = T.hash(key, t)
+ if l[i] then
+ assert(l[i] == mp)
+ elseif mp ~= i then
+ l[i] = mp
+ else -- list head
+ l[mp] = {mp} -- first element
+ while next do
+ assert(ff <= next and next < hsize)
+ if l[next] then assert(l[next] == mp) else l[next] = mp end
+ table.insert(l[mp], next)
+ key,val,next = T.querytab(t, next)
+ assert(key)
+ end
+ end
+ end
+ end
+ l.asize = asize; l.hsize = hsize; l.ff = ff
+ return l
+end
+
+function mostra (t)
+ local asize, hsize, ff = T.querytab(t)
+ print(asize, hsize, ff)
+ print'------'
+ for i=0,asize-1 do
+ local _, v = T.querytab(t, i)
+ print(string.format("[%d] -", i), v)
+ end
+ print'------'
+ for i=0,hsize-1 do
+ print(i, T.querytab(t, i+asize))
+ end
+ print'-------------'
+end
+
+function stat (t)
+ t = checktable(t)
+ local nelem, nlist = 0, 0
+ local maxlist = {}
+ for i=0,t.hsize-1 do
+ if type(t[i]) == 'table' then
+ local n = table.getn(t[i])
+ nlist = nlist+1
+ nelem = nelem + n
+ if not maxlist[n] then maxlist[n] = 0 end
+ maxlist[n] = maxlist[n]+1
+ end
+ end
+ print(string.format("hsize=%d elements=%d load=%.2f med.len=%.2f (asize=%d)",
+ t.hsize, nelem, nelem/t.hsize, nelem/nlist, t.asize))
+ for i=1,table.getn(maxlist) do
+ local n = maxlist[i] or 0
+ print(string.format("%5d %10d %.2f%%", i, n, n*100/nlist))
+ end
+end
+
diff --git a/test/PUC-Rio-Lua-5.1-tests/closure.lua b/test/PUC-Rio-Lua-5.1-tests/closure.lua
new file mode 100644
index 00000000..27ca0adf
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/closure.lua
@@ -0,0 +1,422 @@
+print "testing closures and coroutines"
+
+local A,B = 0,{g=10}
+function f(x)
+ local a = {}
+ for i=1,1000 do
+ local y = 0
+ do
+ a[i] = function () B.g = B.g+1; y = y+x; return y+A end
+ end
+ end
+ local dummy = function () return a[A] end
+ collectgarbage()
+ A = 1; assert(dummy() == a[1]); A = 0;
+ assert(a[1]() == x)
+ assert(a[3]() == x)
+ collectgarbage()
+ assert(B.g == 12)
+ return a
+end
+
+a = f(10)
+-- force a GC in this level
+local x = {[1] = {}} -- to detect a GC
+setmetatable(x, {__mode = 'kv'})
+while x[1] do -- repeat until GC
+ local a = A..A..A..A -- create garbage
+ A = A+1
+end
+assert(a[1]() == 20+A)
+assert(a[1]() == 30+A)
+assert(a[2]() == 10+A)
+collectgarbage()
+assert(a[2]() == 20+A)
+assert(a[2]() == 30+A)
+assert(a[3]() == 20+A)
+assert(a[8]() == 10+A)
+assert(getmetatable(x).__mode == 'kv')
+assert(B.g == 19)
+
+-- testing closures with 'for' control variable
+a = {}
+for i=1,10 do
+ a[i] = {set = function(x) i=x end, get = function () return i end}
+ if i == 3 then break end
+end
+assert(a[4] == nil)
+a[1].set(10)
+assert(a[2].get() == 2)
+a[2].set('a')
+assert(a[3].get() == 3)
+assert(a[2].get() == 'a')
+
+a = {}
+for i, k in pairs{'a', 'b'} do
+ a[i] = {set = function(x, y) i=x; k=y end,
+ get = function () return i, k end}
+ if i == 2 then break end
+end
+a[1].set(10, 20)
+local r,s = a[2].get()
+assert(r == 2 and s == 'b')
+r,s = a[1].get()
+assert(r == 10 and s == 20)
+a[2].set('a', 'b')
+r,s = a[2].get()
+assert(r == "a" and s == "b")
+
+
+-- testing closures with 'for' control variable x break
+for i=1,3 do
+ f = function () return i end
+ break
+end
+assert(f() == 1)
+
+for k, v in pairs{"a", "b"} do
+ f = function () return k, v end
+ break
+end
+assert(({f()})[1] == 1)
+assert(({f()})[2] == "a")
+
+
+-- testing closure x break x return x errors
+
+local b
+function f(x)
+ local first = 1
+ while 1 do
+ if x == 3 and not first then return end
+ local a = 'xuxu'
+ b = function (op, y)
+ if op == 'set' then
+ a = x+y
+ else
+ return a
+ end
+ end
+ if x == 1 then do break end
+ elseif x == 2 then return
+ else if x ~= 3 then error() end
+ end
+ first = nil
+ end
+end
+
+for i=1,3 do
+ f(i)
+ assert(b('get') == 'xuxu')
+ b('set', 10); assert(b('get') == 10+i)
+ b = nil
+end
+
+pcall(f, 4);
+assert(b('get') == 'xuxu')
+b('set', 10); assert(b('get') == 14)
+
+
+local w
+-- testing multi-level closure
+function f(x)
+ return function (y)
+ return function (z) return w+x+y+z end
+ end
+end
+
+y = f(10)
+w = 1.345
+assert(y(20)(30) == 60+w)
+
+-- testing closures x repeat-until
+
+local a = {}
+local i = 1
+repeat
+ local x = i
+ a[i] = function () i = x+1; return x end
+until i > 10 or a[i]() ~= x
+assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4)
+
+print'+'
+
+
+-- test for correctly closing upvalues in tail calls of vararg functions
+local function t ()
+ local function c(a,b) assert(a=="test" and b=="OK") end
+ local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end
+ local x = 1
+ return v(function() return x end)
+end
+t()
+
+
+-- coroutine tests
+
+local f
+
+assert(coroutine.running() == nil)
+
+
+-- tests for global environment
+
+local function foo (a)
+ setfenv(0, a)
+ coroutine.yield(getfenv())
+ assert(getfenv(0) == a)
+ assert(getfenv(1) == _G)
+ assert(getfenv(loadstring"") == a)
+ return getfenv()
+end
+
+f = coroutine.wrap(foo)
+local a = {}
+assert(f(a) == _G)
+local a,b = pcall(f)
+assert(a and b == _G)
+
+
+-- tests for multiple yield/resume arguments
+
+local function eqtab (t1, t2)
+ assert(table.getn(t1) == table.getn(t2))
+ for i,v in ipairs(t1) do
+ assert(t2[i] == v)
+ end
+end
+
+_G.x = nil -- declare x
+function foo (a, ...)
+ assert(coroutine.running() == f)
+ assert(coroutine.status(f) == "running")
+ local arg = {...}
+ for i=1,table.getn(arg) do
+ _G.x = {coroutine.yield(unpack(arg[i]))}
+ end
+ return unpack(a)
+end
+
+f = coroutine.create(foo)
+assert(type(f) == "thread" and coroutine.status(f) == "suspended")
+assert(string.find(tostring(f), "thread"))
+local s,a,b,c,d
+s,a,b,c,d = coroutine.resume(f, {1,2,3}, {}, {1}, {'a', 'b', 'c'})
+assert(s and a == nil and coroutine.status(f) == "suspended")
+s,a,b,c,d = coroutine.resume(f)
+eqtab(_G.x, {})
+assert(s and a == 1 and b == nil)
+s,a,b,c,d = coroutine.resume(f, 1, 2, 3)
+eqtab(_G.x, {1, 2, 3})
+assert(s and a == 'a' and b == 'b' and c == 'c' and d == nil)
+s,a,b,c,d = coroutine.resume(f, "xuxu")
+eqtab(_G.x, {"xuxu"})
+assert(s and a == 1 and b == 2 and c == 3 and d == nil)
+assert(coroutine.status(f) == "dead")
+s, a = coroutine.resume(f, "xuxu")
+assert(not s and string.find(a, "dead") and coroutine.status(f) == "dead")
+
+
+-- yields in tail calls
+local function foo (i) return coroutine.yield(i) end
+f = coroutine.wrap(function ()
+ for i=1,10 do
+ assert(foo(i) == _G.x)
+ end
+ return 'a'
+end)
+for i=1,10 do _G.x = i; assert(f(i) == i) end
+_G.x = 'xuxu'; assert(f('xuxu') == 'a')
+
+-- recursive
+function pf (n, i)
+ coroutine.yield(n)
+ pf(n*i, i+1)
+end
+
+f = coroutine.wrap(pf)
+local s=1
+for i=1,10 do
+ assert(f(1, 1) == s)
+ s = s*i
+end
+
+-- sieve
+function gen (n)
+ return coroutine.wrap(function ()
+ for i=2,n do coroutine.yield(i) end
+ end)
+end
+
+
+function filter (p, g)
+ return coroutine.wrap(function ()
+ while 1 do
+ local n = g()
+ if n == nil then return end
+ if math.mod(n, p) ~= 0 then coroutine.yield(n) end
+ end
+ end)
+end
+
+local x = gen(100)
+local a = {}
+while 1 do
+ local n = x()
+ if n == nil then break end
+ table.insert(a, n)
+ x = filter(n, x)
+end
+
+assert(table.getn(a) == 25 and a[table.getn(a)] == 97)
+
+
+-- errors in coroutines
+function foo ()
+ assert(debug.getinfo(1).currentline == debug.getinfo(foo).linedefined + 1)
+ assert(debug.getinfo(2).currentline == debug.getinfo(goo).linedefined)
+ coroutine.yield(3)
+ error(foo)
+end
+
+function goo() foo() end
+x = coroutine.wrap(goo)
+assert(x() == 3)
+local a,b = pcall(x)
+assert(not a and b == foo)
+
+x = coroutine.create(goo)
+a,b = coroutine.resume(x)
+assert(a and b == 3)
+a,b = coroutine.resume(x)
+assert(not a and b == foo and coroutine.status(x) == "dead")
+a,b = coroutine.resume(x)
+assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead")
+
+
+-- co-routines x for loop
+function all (a, n, k)
+ if k == 0 then coroutine.yield(a)
+ else
+ for i=1,n do
+ a[k] = i
+ all(a, n, k-1)
+ end
+ end
+end
+
+local a = 0
+for t in coroutine.wrap(function () all({}, 5, 4) end) do
+ a = a+1
+end
+assert(a == 5^4)
+
+
+-- access to locals of collected corroutines
+local C = {}; setmetatable(C, {__mode = "kv"})
+local x = coroutine.wrap (function ()
+ local a = 10
+ local function f () a = a+10; return a end
+ while true do
+ a = a+1
+ coroutine.yield(f)
+ end
+ end)
+
+C[1] = x;
+
+local f = x()
+assert(f() == 21 and x()() == 32 and x() == f)
+x = nil
+collectgarbage()
+assert(C[1] == nil)
+assert(f() == 43 and f() == 53)
+
+
+-- old bug: attempt to resume itself
+
+function co_func (current_co)
+ assert(coroutine.running() == current_co)
+ assert(coroutine.resume(current_co) == false)
+ assert(coroutine.resume(current_co) == false)
+ return 10
+end
+
+local co = coroutine.create(co_func)
+local a,b = coroutine.resume(co, co)
+assert(a == true and b == 10)
+assert(coroutine.resume(co, co) == false)
+assert(coroutine.resume(co, co) == false)
+
+-- access to locals of erroneous coroutines
+local x = coroutine.create (function ()
+ local a = 10
+ _G.f = function () a=a+1; return a end
+ error('x')
+ end)
+
+assert(not coroutine.resume(x))
+-- overwrite previous position of local `a'
+assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1))
+assert(_G.f() == 11)
+assert(_G.f() == 12)
+
+
+if not T then
+ (Message or print)('\a\n >>> testC not active: skipping yield/hook tests <<<\n\a')
+else
+
+ local turn
+
+ function fact (t, x)
+ assert(turn == t)
+ if x == 0 then return 1
+ else return x*fact(t, x-1)
+ end
+ end
+
+ local A,B,a,b = 0,0,0,0
+
+ local x = coroutine.create(function ()
+ T.setyhook("", 2)
+ A = fact("A", 10)
+ end)
+
+ local y = coroutine.create(function ()
+ T.setyhook("", 3)
+ B = fact("B", 11)
+ end)
+
+ while A==0 or B==0 do
+ if A==0 then turn = "A"; T.resume(x) end
+ if B==0 then turn = "B"; T.resume(y) end
+ end
+
+ assert(B/A == 11)
+end
+
+
+-- leaving a pending coroutine open
+_X = coroutine.wrap(function ()
+ local a = 10
+ local x = function () a = a+1 end
+ coroutine.yield()
+ end)
+
+_X()
+
+
+-- coroutine environments
+co = coroutine.create(function ()
+ coroutine.yield(getfenv(0))
+ return loadstring("return a")()
+ end)
+
+a = {a = 15}
+debug.setfenv(co, a)
+assert(debug.getfenv(co) == a)
+assert(select(2, coroutine.resume(co)) == a)
+assert(select(2, coroutine.resume(co)) == a.a)
+
+
+print'OK'
diff --git a/test/PUC-Rio-Lua-5.1-tests/code.lua b/test/PUC-Rio-Lua-5.1-tests/code.lua
new file mode 100644
index 00000000..875d4885
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/code.lua
@@ -0,0 +1,143 @@
+
+if T==nil then
+ (Message or print)('\a\n >>> testC not active: skipping opcode tests <<<\n\a')
+ return
+end
+print "testing code generation and optimizations"
+
+
+-- this code gave an error for the code checker
+do
+ local function f (a)
+ for k,v,w in a do end
+ end
+end
+
+
+function check (f, ...)
+ local c = T.listcode(f)
+ for i=1, arg.n do
+ -- print(arg[i], c[i])
+ assert(string.find(c[i], '- '..arg[i]..' *%d'))
+ end
+ assert(c[arg.n+2] == nil)
+end
+
+
+function checkequal (a, b)
+ a = T.listcode(a)
+ b = T.listcode(b)
+ for i = 1, table.getn(a) do
+ a[i] = string.gsub(a[i], '%b()', '') -- remove line number
+ b[i] = string.gsub(b[i], '%b()', '') -- remove line number
+ assert(a[i] == b[i])
+ end
+end
+
+
+-- some basic instructions
+check(function ()
+ (function () end){f()}
+end, 'CLOSURE', 'NEWTABLE', 'GETGLOBAL', 'CALL', 'SETLIST', 'CALL', 'RETURN')
+
+
+-- sequence of LOADNILs
+check(function ()
+ local a,b,c
+ local d; local e;
+ a = nil; d=nil
+end, 'RETURN')
+
+
+-- single return
+check (function (a,b,c) return a end, 'RETURN')
+
+
+-- infinite loops
+check(function () while true do local a = -1 end end,
+'LOADK', 'JMP', 'RETURN')
+
+check(function () while 1 do local a = -1 end end,
+'LOADK', 'JMP', 'RETURN')
+
+check(function () repeat local x = 1 until false end,
+'LOADK', 'JMP', 'RETURN')
+
+check(function () repeat local x until nil end,
+'LOADNIL', 'JMP', 'RETURN')
+
+check(function () repeat local x = 1 until true end,
+'LOADK', 'RETURN')
+
+
+-- concat optimization
+check(function (a,b,c,d) return a..b..c..d end,
+ 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN')
+
+-- not
+check(function () return not not nil end, 'LOADBOOL', 'RETURN')
+check(function () return not not false end, 'LOADBOOL', 'RETURN')
+check(function () return not not true end, 'LOADBOOL', 'RETURN')
+check(function () return not not 1 end, 'LOADBOOL', 'RETURN')
+
+-- direct access to locals
+check(function ()
+ local a,b,c,d
+ a = b*2
+ c[4], a[b] = -((a + d/-20.5 - a[b]) ^ a.x), b
+end,
+ 'MUL',
+ 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW',
+ 'UNM', 'SETTABLE', 'SETTABLE', 'RETURN')
+
+
+-- direct access to constants
+check(function ()
+ local a,b
+ a.x = 0
+ a.x = b
+ a[b] = 'y'
+ a = 1 - a
+ b = 1/a
+ b = 5+4
+ a[true] = false
+end,
+ 'SETTABLE', 'SETTABLE', 'SETTABLE', 'SUB', 'DIV', 'LOADK',
+ 'SETTABLE', 'RETURN')
+
+local function f () return -((2^8 + -(-1)) % 8)/2 * 4 - 3 end
+
+check(f, 'LOADK', 'RETURN')
+assert(f() == -5)
+
+check(function ()
+ local a,b,c
+ b[c], a = c, b
+ b[a], a = c, b
+ a, b = c, a
+ a = a
+end,
+ 'MOVE', 'MOVE', 'SETTABLE',
+ 'MOVE', 'MOVE', 'MOVE', 'SETTABLE',
+ 'MOVE', 'MOVE', 'MOVE',
+ -- no code for a = a
+ 'RETURN')
+
+
+-- x == nil , x ~= nil
+checkequal(function () if (a==nil) then a=1 end; if a~=nil then a=1 end end,
+ function () if (a==9) then a=1 end; if a~=9 then a=1 end end)
+
+check(function () if a==nil then a=1 end end,
+'GETGLOBAL', 'EQ', 'JMP', 'LOADK', 'SETGLOBAL', 'RETURN')
+
+-- de morgan
+checkequal(function () local a; if not (a or b) then b=a end end,
+ function () local a; if (not a and not b) then b=a end end)
+
+checkequal(function (l) local a; return 0 <= a and a <= l end,
+ function (l) local a; return not (not(a >= 0) or not(a <= l)) end)
+
+
+print 'OK'
+
diff --git a/test/PUC-Rio-Lua-5.1-tests/constructs.lua b/test/PUC-Rio-Lua-5.1-tests/constructs.lua
new file mode 100644
index 00000000..5fb37986
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/constructs.lua
@@ -0,0 +1,240 @@
+print "testing syntax"
+
+-- testing priorities
+
+assert(2^3^2 == 2^(3^2));
+assert(2^3*4 == (2^3)*4);
+assert(2^-2 == 1/4 and -2^- -2 == - - -4);
+assert(not nil and 2 and not(2>3 or 3<2));
+assert(-3-1-5 == 0+0-9);
+assert(-2^2 == -4 and (-2)^2 == 4 and 2*2-3-1 == 0);
+assert(2*1+3/3 == 3 and 1+2 .. 3*1 == "33");
+assert(not(2+1 > 3*1) and "a".."b" > "a");
+
+assert(not ((true or false) and nil))
+assert( true or false and nil)
+
+local a,b = 1,nil;
+assert(-(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75);
+x = ((b or a)+1 == 2 and (10 or a)+1 == 11); assert(x);
+x = (((2<3) or 1) == true and (2<3 and 4) == 4); assert(x);
+
+x,y=1,2;
+assert((x>y) and x or y == 2);
+x,y=2,1;
+assert((x>y) and x or y == 2);
+
+assert(1234567890 == tonumber('1234567890') and 1234567890+1 == 1234567891)
+
+
+-- silly loops
+repeat until 1; repeat until true;
+while false do end; while nil do end;
+
+do -- test old bug (first name could not be an `upvalue')
+ local a; function f(x) x={a=1}; x={x=1}; x={G=1} end
+end
+
+function f (i)
+ if type(i) ~= 'number' then return i,'jojo'; end;
+ if i > 0 then return i, f(i-1); end;
+end
+
+x = {f(3), f(5), f(10);};
+assert(x[1] == 3 and x[2] == 5 and x[3] == 10 and x[4] == 9 and x[12] == 1);
+assert(x[nil] == nil)
+x = {f'alo', f'xixi', nil};
+assert(x[1] == 'alo' and x[2] == 'xixi' and x[3] == nil);
+x = {f'alo'..'xixi'};
+assert(x[1] == 'aloxixi')
+x = {f{}}
+assert(x[2] == 'jojo' and type(x[1]) == 'table')
+
+
+local f = function (i)
+ if i < 10 then return 'a';
+ elseif i < 20 then return 'b';
+ elseif i < 30 then return 'c';
+ end;
+end
+
+assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == nil)
+
+for i=1,1000 do break; end;
+n=100;
+i=3;
+t = {};
+a=nil
+while not a do
+ a=0; for i=1,n do for i=i,1,-1 do a=a+1; t[i]=1; end; end;
+end
+assert(a == n*(n+1)/2 and i==3);
+assert(t[1] and t[n] and not t[0] and not t[n+1])
+
+function f(b)
+ local x = 1;
+ repeat
+ local a;
+ if b==1 then local b=1; x=10; break
+ elseif b==2 then x=20; break;
+ elseif b==3 then x=30;
+ else local a,b,c,d=math.sin(1); x=x+1;
+ end
+ until x>=12;
+ return x;
+end;
+
+assert(f(1) == 10 and f(2) == 20 and f(3) == 30 and f(4)==12)
+
+
+local f = function (i)
+ if i < 10 then return 'a'
+ elseif i < 20 then return 'b'
+ elseif i < 30 then return 'c'
+ else return 8
+ end
+end
+
+assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == 8)
+
+local a, b = nil, 23
+x = {f(100)*2+3 or a, a or b+2}
+assert(x[1] == 19 and x[2] == 25)
+x = {f=2+3 or a, a = b+2}
+assert(x.f == 5 and x.a == 25)
+
+a={y=1}
+x = {a.y}
+assert(x[1] == 1)
+
+function f(i)
+ while 1 do
+ if i>0 then i=i-1;
+ else return; end;
+ end;
+end;
+
+function g(i)
+ while 1 do
+ if i>0 then i=i-1
+ else return end
+ end
+end
+
+f(10); g(10);
+
+do
+ function f () return 1,2,3; end
+ local a, b, c = f();
+ assert(a==1 and b==2 and c==3)
+ a, b, c = (f());
+ assert(a==1 and b==nil and c==nil)
+end
+
+local a,b = 3 and f();
+assert(a==1 and b==nil)
+
+function g() f(); return; end;
+assert(g() == nil)
+function g() return nil or f() end
+a,b = g()
+assert(a==1 and b==nil)
+
+print'+';
+
+
+f = [[
+return function ( a , b , c , d , e )
+ local x = a >= b or c or ( d and e ) or nil
+ return x
+end , { a = 1 , b = 2 >= 1 , } or { 1 };
+]]
+f = string.gsub(f, "%s+", "\n"); -- force a SETLINE between opcodes
+f,a = loadstring(f)();
+assert(a.a == 1 and a.b)
+
+function g (a,b,c,d,e)
+ if not (a>=b or c or d and e or nil) then return 0; else return 1; end;
+end
+
+function h (a,b,c,d,e)
+ while (a>=b or c or (d and e) or nil) do return 1; end;
+ return 0;
+end;
+
+assert(f(2,1) == true and g(2,1) == 1 and h(2,1) == 1)
+assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
+assert(f(1,2,'a')
+~= -- force SETLINE before nil
+nil, "")
+assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
+assert(f(1,2,nil,1,'x') == 'x' and g(1,2,nil,1,'x') == 1 and
+ h(1,2,nil,1,'x') == 1)
+assert(f(1,2,nil,nil,'x') == nil and g(1,2,nil,nil,'x') == 0 and
+ h(1,2,nil,nil,'x') == 0)
+assert(f(1,2,nil,1,nil) == nil and g(1,2,nil,1,nil) == 0 and
+ h(1,2,nil,1,nil) == 0)
+
+assert(1 and 2<3 == true and 2<3 and 'a'<'b' == true)
+x = 2<3 and not 3; assert(x==false)
+x = 2<1 or (2>1 and 'a'); assert(x=='a')
+
+
+do
+ local a; if nil then a=1; else a=2; end; -- this nil comes as PUSHNIL 2
+ assert(a==2)
+end
+
+function F(a)
+ assert(debug.getinfo(1, "n").name == 'F')
+ return a,2,3
+end
+
+a,b = F(1)~=nil; assert(a == true and b == nil);
+a,b = F(nil)==nil; assert(a == true and b == nil)
+
+----------------------------------------------------------------
+-- creates all combinations of
+-- [not] ([not] arg op [not] (arg op [not] arg ))
+-- and tests each one
+
+function ID(x) return x end
+
+function f(t, i)
+ local b = t.n
+ local res = math.mod(math.floor(i/c), b)+1
+ c = c*b
+ return t[res]
+end
+
+local arg = {" ( 1 < 2 ) ", " ( 1 >= 2 ) ", " F ( ) ", " nil "; n=4}
+
+local op = {" and ", " or ", " == ", " ~= "; n=4}
+
+local neg = {" ", " not "; n=2}
+
+local i = 0
+repeat
+ c = 1
+ local s = f(neg, i)..'ID('..f(neg, i)..f(arg, i)..f(op, i)..
+ f(neg, i)..'ID('..f(arg, i)..f(op, i)..f(neg, i)..f(arg, i)..'))'
+ local s1 = string.gsub(s, 'ID', '')
+ K,X,NX,WX1,WX2 = nil
+ s = string.format([[
+ local a = %s
+ local b = not %s
+ K = b
+ local xxx;
+ if %s then X = a else X = b end
+ if %s then NX = b else NX = a end
+ while %s do WX1 = a; break end
+ while %s do WX2 = a; break end
+ repeat if (%s) then break end; assert(b) until not(%s)
+ ]], s1, s, s1, s, s1, s, s1, s, s)
+ assert(loadstring(s))()
+ assert(X and not NX and not WX1 == K and not WX2 == K)
+ if math.mod(i,4000) == 0 then print('+') end
+ i = i+1
+until i==c
+
+print'OK'
diff --git a/test/PUC-Rio-Lua-5.1-tests/db.lua b/test/PUC-Rio-Lua-5.1-tests/db.lua
new file mode 100644
index 00000000..9d2c86f0
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/db.lua
@@ -0,0 +1,499 @@
+-- testing debug library
+
+local function dostring(s) return assert(loadstring(s))() end
+
+print"testing debug library and debug information"
+
+do
+local a=1
+end
+
+function test (s, l, p)
+ collectgarbage() -- avoid gc during trace
+ local function f (event, line)
+ assert(event == 'line')
+ local l = table.remove(l, 1)
+ if p then print(l, line) end
+ assert(l == line, "wrong trace!!")
+ end
+ debug.sethook(f,"l"); loadstring(s)(); debug.sethook()
+ assert(table.getn(l) == 0)
+end
+
+
+do
+ local a = debug.getinfo(print)
+ assert(a.what == "C" and a.short_src == "[C]")
+ local b = debug.getinfo(test, "SfL")
+ assert(b.name == nil and b.what == "Lua" and b.linedefined == 11 and
+ b.lastlinedefined == b.linedefined + 10 and
+ b.func == test and not string.find(b.short_src, "%["))
+ assert(b.activelines[b.linedefined + 1] and
+ b.activelines[b.lastlinedefined])
+ assert(not b.activelines[b.linedefined] and
+ not b.activelines[b.lastlinedefined + 1])
+end
+
+
+-- test file and string names truncation
+a = "function f () end"
+local function dostring (s, x) return loadstring(s, x)() end
+dostring(a)
+assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a))
+dostring(a..string.format("; %s\n=1", string.rep('p', 400)))
+assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
+dostring("\n"..a)
+assert(debug.getinfo(f).short_src == '[string "..."]')
+dostring(a, "")
+assert(debug.getinfo(f).short_src == '[string ""]')
+dostring(a, "@xuxu")
+assert(debug.getinfo(f).short_src == "xuxu")
+dostring(a, "@"..string.rep('p', 1000)..'t')
+assert(string.find(debug.getinfo(f).short_src, "^%.%.%.p*t$"))
+dostring(a, "=xuxu")
+assert(debug.getinfo(f).short_src == "xuxu")
+dostring(a, string.format("=%s", string.rep('x', 500)))
+assert(string.find(debug.getinfo(f).short_src, "^x*"))
+dostring(a, "=")
+assert(debug.getinfo(f).short_src == "")
+a = nil; f = nil;
+
+
+repeat
+ local g = {x = function ()
+ local a = debug.getinfo(2)
+ assert(a.name == 'f' and a.namewhat == 'local')
+ a = debug.getinfo(1)
+ assert(a.name == 'x' and a.namewhat == 'field')
+ return 'xixi'
+ end}
+ local f = function () return 1+1 and (not 1 or g.x()) end
+ assert(f() == 'xixi')
+ g = debug.getinfo(f)
+ assert(g.what == "Lua" and g.func == f and g.namewhat == "" and not g.name)
+
+ function f (x, name) -- local!
+ name = name or 'f'
+ local a = debug.getinfo(1)
+ assert(a.name == name and a.namewhat == 'local')
+ return x
+ end
+
+ -- breaks in different conditions
+ if 3>4 then break end; f()
+ if 3<4 then a=1 else break end; f()
+ while 1 do local x=10; break end; f()
+ local b = 1
+ if 3>4 then return math.sin(1) end; f()
+ a = 3<4; f()
+ a = 3<4 or 1; f()
+ repeat local x=20; if 4>3 then f() else break end; f() until 1
+ g = {}
+ f(g).x = f(2) and f(10)+f(9)
+ assert(g.x == f(19))
+ function g(x) if not x then return 3 end return (x('a', 'x')) end
+ assert(g(f) == 'a')
+until 1
+
+test([[if
+math.sin(1)
+then
+ a=1
+else
+ a=2
+end
+]], {2,4,7})
+
+test([[--
+if nil then
+ a=1
+else
+ a=2
+end
+]], {2,5,6})
+
+test([[a=1
+repeat
+ a=a+1
+until a==3
+]], {1,3,4,3,4})
+
+test([[ do
+ return
+end
+]], {2})
+
+test([[local a
+a=1
+while a<=3 do
+ a=a+1
+end
+]], {2,3,4,3,4,3,4,3,5})
+
+test([[while math.sin(1) do
+ if math.sin(1)
+ then
+ break
+ end
+end
+a=1]], {1,2,4,7})
+
+test([[for i=1,3 do
+ a=i
+end
+]], {1,2,1,2,1,2,1,3})
+
+test([[for i,v in pairs{'a','b'} do
+ a=i..v
+end
+]], {1,2,1,2,1,3})
+
+test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
+
+
+
+print'+'
+
+a = {}; L = nil
+local glob = 1
+local oldglob = glob
+debug.sethook(function (e,l)
+ collectgarbage() -- force GC during a hook
+ local f, m, c = debug.gethook()
+ assert(m == 'crl' and c == 0)
+ if e == "line" then
+ if glob ~= oldglob then
+ L = l-1 -- get the first line where "glob" has changed
+ oldglob = glob
+ end
+ elseif e == "call" then
+ local f = debug.getinfo(2, "f").func
+ a[f] = 1
+ else assert(e == "return")
+ end
+end, "crl")
+
+function f(a,b)
+ collectgarbage()
+ local _, x = debug.getlocal(1, 1)
+ local _, y = debug.getlocal(1, 2)
+ assert(x == a and y == b)
+ assert(debug.setlocal(2, 3, "pera") == "AA".."AA")
+ assert(debug.setlocal(2, 4, "maçã") == "B")
+ x = debug.getinfo(2)
+ assert(x.func == g and x.what == "Lua" and x.name == 'g' and
+ x.nups == 0 and string.find(x.source, "^@.*db%.lua"))
+ glob = glob+1
+ assert(debug.getinfo(1, "l").currentline == L+1)
+ assert(debug.getinfo(1, "l").currentline == L+2)
+end
+
+function foo()
+ glob = glob+1
+ assert(debug.getinfo(1, "l").currentline == L+1)
+end; foo() -- set L
+-- check line counting inside strings and empty lines
+
+_ = 'alo\
+alo' .. [[
+
+]]
+--[[
+]]
+assert(debug.getinfo(1, "l").currentline == L+11) -- check count of lines
+
+
+function g(...)
+ do local a,b,c; a=math.sin(40); end
+ local feijao
+ local AAAA,B = "xuxu", "mamão"
+ f(AAAA,B)
+ assert(AAAA == "pera" and B == "maçã")
+ do
+ local B = 13
+ local x,y = debug.getlocal(1,5)
+ assert(x == 'B' and y == 13)
+ end
+end
+
+g()
+
+
+assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print])
+
+
+-- tests for manipulating non-registered locals (C and Lua temporaries)
+
+local n, v = debug.getlocal(0, 1)
+assert(v == 0 and n == "(*temporary)")
+local n, v = debug.getlocal(0, 2)
+assert(v == 2 and n == "(*temporary)")
+assert(not debug.getlocal(0, 3))
+assert(not debug.getlocal(0, 0))
+
+function f()
+ assert(select(2, debug.getlocal(2,3)) == 1)
+ assert(not debug.getlocal(2,4))
+ debug.setlocal(2, 3, 10)
+ return 20
+end
+
+function g(a,b) return (a+1) + f() end
+
+assert(g(0,0) == 30)
+
+
+debug.sethook(nil);
+assert(debug.gethook() == nil)
+
+
+-- testing access to function arguments
+
+X = nil
+a = {}
+function a:f (a, b, ...) local c = 13 end
+debug.sethook(function (e)
+ assert(e == "call")
+ dostring("XX = 12") -- test dostring inside hooks
+ -- testing errors inside hooks
+ assert(not pcall(loadstring("a='joao'+1")))
+ debug.sethook(function (e, l)
+ assert(debug.getinfo(2, "l").currentline == l)
+ local f,m,c = debug.gethook()
+ assert(e == "line")
+ assert(m == 'l' and c == 0)
+ debug.sethook(nil) -- hook is called only once
+ assert(not X) -- check that
+ X = {}; local i = 1
+ local x,y
+ while 1 do
+ x,y = debug.getlocal(2, i)
+ if x==nil then break end
+ X[x] = y
+ i = i+1
+ end
+ end, "l")
+end, "c")
+
+a:f(1,2,3,4,5)
+assert(X.self == a and X.a == 1 and X.b == 2 and X.arg.n == 3 and X.c == nil)
+assert(XX == 12)
+assert(debug.gethook() == nil)
+
+
+-- testing upvalue access
+local function getupvalues (f)
+ local t = {}
+ local i = 1
+ while true do
+ local name, value = debug.getupvalue(f, i)
+ if not name then break end
+ assert(not t[name])
+ t[name] = value
+ i = i + 1
+ end
+ return t
+end
+
+local a,b,c = 1,2,3
+local function foo1 (a) b = a; return c end
+local function foo2 (x) a = x; return c+b end
+assert(debug.getupvalue(foo1, 3) == nil)
+assert(debug.getupvalue(foo1, 0) == nil)
+assert(debug.setupvalue(foo1, 3, "xuxu") == nil)
+local t = getupvalues(foo1)
+assert(t.a == nil and t.b == 2 and t.c == 3)
+t = getupvalues(foo2)
+assert(t.a == 1 and t.b == 2 and t.c == 3)
+assert(debug.setupvalue(foo1, 1, "xuxu") == "b")
+assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu")
+-- cannot manipulate C upvalues from Lua
+assert(debug.getupvalue(io.read, 1) == nil)
+assert(debug.setupvalue(io.read, 1, 10) == nil)
+
+
+-- testing count hooks
+local a=0
+debug.sethook(function (e) a=a+1 end, "", 1)
+a=0; for i=1,1000 do end; assert(1000 < a and a < 1012)
+debug.sethook(function (e) a=a+1 end, "", 4)
+a=0; for i=1,1000 do end; assert(250 < a and a < 255)
+local f,m,c = debug.gethook()
+assert(m == "" and c == 4)
+debug.sethook(function (e) a=a+1 end, "", 4000)
+a=0; for i=1,1000 do end; assert(a == 0)
+debug.sethook(print, "", 2^24 - 1) -- count upperbound
+local f,m,c = debug.gethook()
+assert(({debug.gethook()})[3] == 2^24 - 1)
+debug.sethook()
+
+
+-- tests for tail calls
+local function f (x)
+ if x then
+ assert(debug.getinfo(1, "S").what == "Lua")
+ local tail = debug.getinfo(2)
+ assert(not pcall(getfenv, 3))
+ assert(tail.what == "tail" and tail.short_src == "(tail call)" and
+ tail.linedefined == -1 and tail.func == nil)
+ assert(debug.getinfo(3, "f").func == g1)
+ assert(getfenv(3))
+ assert(debug.getinfo(4, "S").what == "tail")
+ assert(not pcall(getfenv, 5))
+ assert(debug.getinfo(5, "S").what == "main")
+ assert(getfenv(5))
+ print"+"
+ end
+end
+
+function g(x) return f(x) end
+
+function g1(x) g(x) end
+
+local function h (x) local f=g1; return f(x) end
+
+h(true)
+
+local b = {}
+debug.sethook(function (e) table.insert(b, e) end, "cr")
+h(false)
+debug.sethook()
+local res = {"return", -- first return (from sethook)
+ "call", "call", "call", "call",
+ "return", "tail return", "return", "tail return",
+ "call", -- last call (to sethook)
+}
+for _, k in ipairs(res) do assert(k == table.remove(b, 1)) end
+
+
+lim = 30000
+local function foo (x)
+ if x==0 then
+ assert(debug.getinfo(lim+2).what == "main")
+ for i=2,lim do assert(debug.getinfo(i, "S").what == "tail") end
+ else return foo(x-1)
+ end
+end
+
+foo(lim)
+
+
+print"+"
+
+
+-- testing traceback
+
+assert(debug.traceback(print) == print)
+assert(debug.traceback(print, 4) == print)
+assert(string.find(debug.traceback("hi", 4), "^hi\n"))
+assert(string.find(debug.traceback("hi"), "^hi\n"))
+assert(not string.find(debug.traceback("hi"), "'traceback'"))
+assert(string.find(debug.traceback("hi", 0), "'traceback'"))
+assert(string.find(debug.traceback(), "^stack traceback:\n"))
+
+-- testing debugging of coroutines
+
+local function checktraceback (co, p)
+ local tb = debug.traceback(co)
+ local i = 0
+ for l in string.gmatch(tb, "[^\n]+\n?") do
+ assert(i == 0 or string.find(l, p[i]))
+ i = i+1
+ end
+ assert(p[i] == nil)
+end
+
+
+local function f (n)
+ if n > 0 then return f(n-1)
+ else coroutine.yield() end
+end
+
+local co = coroutine.create(f)
+coroutine.resume(co, 3)
+checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
+
+
+co = coroutine.create(function (x)
+ local a = 1
+ coroutine.yield(debug.getinfo(1, "l"))
+ coroutine.yield(debug.getinfo(1, "l").currentline)
+ return a
+ end)
+
+local tr = {}
+local foo = function (e, l) table.insert(tr, l) end
+debug.sethook(co, foo, "l")
+
+local _, l = coroutine.resume(co, 10)
+local x = debug.getinfo(co, 1, "lfLS")
+assert(x.currentline == l.currentline and x.activelines[x.currentline])
+assert(type(x.func) == "function")
+for i=x.linedefined + 1, x.lastlinedefined do
+ assert(x.activelines[i])
+ x.activelines[i] = nil
+end
+assert(next(x.activelines) == nil) -- no 'extra' elements
+assert(debug.getinfo(co, 2) == nil)
+local a,b = debug.getlocal(co, 1, 1)
+assert(a == "x" and b == 10)
+a,b = debug.getlocal(co, 1, 2)
+assert(a == "a" and b == 1)
+debug.setlocal(co, 1, 2, "hi")
+assert(debug.gethook(co) == foo)
+assert(table.getn(tr) == 2 and
+ tr[1] == l.currentline-1 and tr[2] == l.currentline)
+
+a,b,c = pcall(coroutine.resume, co)
+assert(a and b and c == l.currentline+1)
+checktraceback(co, {"yield", "in function <"})
+
+a,b = coroutine.resume(co)
+assert(a and b == "hi")
+assert(table.getn(tr) == 4 and tr[4] == l.currentline+2)
+assert(debug.gethook(co) == foo)
+assert(debug.gethook() == nil)
+checktraceback(co, {})
+
+
+-- check traceback of suspended (or dead with error) coroutines
+
+function f(i) if i==0 then error(i) else coroutine.yield(); f(i-1) end end
+
+co = coroutine.create(function (x) f(x) end)
+a, b = coroutine.resume(co, 3)
+t = {"'yield'", "'f'", "in function <"}
+while coroutine.status(co) == "suspended" do
+ checktraceback(co, t)
+ a, b = coroutine.resume(co)
+ table.insert(t, 2, "'f'") -- one more recursive call to 'f'
+end
+t[1] = "'error'"
+checktraceback(co, t)
+
+
+-- test acessing line numbers of a coroutine from a resume inside
+-- a C function (this is a known bug in Lua 5.0)
+
+local function g(x)
+ coroutine.yield(x)
+end
+
+local function f (i)
+ debug.sethook(function () end, "l")
+ for j=1,1000 do
+ g(i+j)
+ end
+end
+
+local co = coroutine.wrap(f)
+co(10)
+pcall(co)
+pcall(co)
+
+
+assert(type(debug.getregistry()) == "table")
+
+
+print"OK"
+
diff --git a/test/PUC-Rio-Lua-5.1-tests/errors.lua b/test/PUC-Rio-Lua-5.1-tests/errors.lua
new file mode 100644
index 00000000..e8812117
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/errors.lua
@@ -0,0 +1,250 @@
+print("testing errors")
+
+function doit (s)
+ local f, msg = loadstring(s)
+ if f == nil then return msg end
+ local cond, msg = pcall(f)
+ return (not cond) and msg
+end
+
+
+function checkmessage (prog, msg)
+ assert(string.find(doit(prog), msg, 1, true))
+end
+
+function checksyntax (prog, extra, token, line)
+ local msg = doit(prog)
+ token = string.gsub(token, "(%p)", "%%%1")
+ local pt = string.format([[^%%[string ".*"%%]:%d: .- near '%s'$]],
+ line, token)
+ assert(string.find(msg, pt))
+ assert(string.find(msg, msg, 1, true))
+end
+
+
+-- test error message with no extra info
+assert(doit("error('hi', 0)") == 'hi')
+
+-- test error message with no info
+assert(doit("error()") == nil)
+
+
+-- test common errors/errors that crashed in the past
+assert(doit("unpack({}, 1, n=2^30)"))
+assert(doit("a=math.sin()"))
+assert(not doit("tostring(1)") and doit("tostring()"))
+assert(doit"tonumber()")
+assert(doit"repeat until 1; a")
+checksyntax("break label", "", "label", 1)
+assert(doit";")
+assert(doit"a=1;;")
+assert(doit"return;;")
+assert(doit"assert(false)")
+assert(doit"assert(nil)")
+assert(doit"a=math.sin\n(3)")
+assert(doit("function a (... , ...) end"))
+assert(doit("function a (, ...) end"))
+
+checksyntax([[
+ local a = {4
+
+]], "'}' expected (to close '{' at line 1)", "<eof>", 3)
+
+
+-- tests for better error messages
+
+checkmessage("a=1; bbbb=2; a=math.sin(3)+bbbb(3)", "global 'bbbb'")
+checkmessage("a=1; local a,bbbb=2,3; a = math.sin(1) and bbbb(3)",
+ "local 'bbbb'")
+checkmessage("a={}; do local a=1 end a:bbbb(3)", "method 'bbbb'")
+checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'")
+assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'"))
+checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number")
+
+aaa = nil
+checkmessage("aaa.bbb:ddd(9)", "global 'aaa'")
+checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'")
+checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'")
+checkmessage("local a,b,c; (function () a = b+1 end)()", "upvalue 'b'")
+assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)")
+
+checkmessage("b=1; local aaa='a'; x=aaa+b", "local 'aaa'")
+checkmessage("aaa={}; x=3/aaa", "global 'aaa'")
+checkmessage("aaa='2'; b=nil;x=aaa*b", "global 'b'")
+checkmessage("aaa={}; x=-aaa", "global 'aaa'")
+assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
+assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'"))
+
+checkmessage([[aaa=9
+repeat until 3==3
+local x=math.sin(math.cos(3))
+if math.sin(1) == x then return math.sin(1) end -- tail call
+local a,b = 1, {
+ {x='a'..'b'..'c', y='b', z=x},
+ {1,2,3,4,5} or 3+3<=3+3,
+ 3+1>3+1,
+ {d = x and aaa[x or y]}}
+]], "global 'aaa'")
+
+checkmessage([[
+local x,y = {},1
+if math.sin(1) == 0 then return 3 end -- return
+x.a()]], "field 'a'")
+
+checkmessage([[
+prefix = nil
+insert = nil
+while 1 do
+ local a
+ if nil then break end
+ insert(prefix, a)
+end]], "global 'insert'")
+
+checkmessage([[ -- tail call
+ return math.sin("a")
+]], "'sin'")
+
+checkmessage([[collectgarbage("nooption")]], "invalid option")
+
+checkmessage([[x = print .. "a"]], "concatenate")
+
+checkmessage("getmetatable(io.stdin).__gc()", "no value")
+
+print'+'
+
+
+-- testing line error
+
+function lineerror (s)
+ local err,msg = pcall(loadstring(s))
+ local line = string.match(msg, ":(%d+):")
+ return line and line+0
+end
+
+assert(lineerror"local a\n for i=1,'a' do \n print(i) \n end" == 2)
+assert(lineerror"\n local a \n for k,v in 3 \n do \n print(k) \n end" == 3)
+assert(lineerror"\n\n for k,v in \n 3 \n do \n print(k) \n end" == 4)
+assert(lineerror"function a.x.y ()\na=a+1\nend" == 1)
+
+local p = [[
+function g() f() end
+function f(x) error('a', X) end
+g()
+]]
+X=3;assert(lineerror(p) == 3)
+X=0;assert(lineerror(p) == nil)
+X=1;assert(lineerror(p) == 2)
+X=2;assert(lineerror(p) == 1)
+
+lineerror = nil
+
+C = 0
+local l = debug.getinfo(1, "l").currentline; function y () C=C+1; y() end
+
+local function checkstackmessage (m)
+ return (string.find(m, "^.-:%d+: stack overflow"))
+end
+assert(checkstackmessage(doit('y()')))
+assert(checkstackmessage(doit('y()')))
+assert(checkstackmessage(doit('y()')))
+-- teste de linhas em erro
+C = 0
+local l1
+local function g()
+ l1 = debug.getinfo(1, "l").currentline; y()
+end
+local _, stackmsg = xpcall(g, debug.traceback)
+local stack = {}
+for line in string.gmatch(stackmsg, "[^\n]*") do
+ local curr = string.match(line, ":(%d+):")
+ if curr then table.insert(stack, tonumber(curr)) end
+end
+local i=1
+while stack[i] ~= l1 do
+ assert(stack[i] == l)
+ i = i+1
+end
+assert(i > 15)
+
+
+-- error in error handling
+local res, msg = xpcall(error, error)
+assert(not res and type(msg) == 'string')
+
+local function f (x)
+ if x==0 then error('a\n')
+ else
+ local aux = function () return f(x-1) end
+ local a,b = xpcall(aux, aux)
+ return a,b
+ end
+end
+f(3)
+
+-- non string messages
+function f() error{msg='x'} end
+res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end)
+assert(msg.msg == 'xy')
+
+print('+')
+checksyntax("syntax error", "", "error", 1)
+checksyntax("1.000", "", "1.000", 1)
+checksyntax("[[a]]", "", "[[a]]", 1)
+checksyntax("'aa'", "", "'aa'", 1)
+
+-- test 255 as first char in a chunk
+checksyntax("\255a = 1", "", "\255", 1)
+
+doit('I = loadstring("a=9+"); a=3')
+assert(a==3 and I == nil)
+print('+')
+
+lim = 1000
+if rawget(_G, "_soft") then lim = 100 end
+for i=1,lim do
+ doit('a = ')
+ doit('a = 4+nil')
+end
+
+
+-- testing syntax limits
+local function testrep (init, rep)
+ local s = "local a; "..init .. string.rep(rep, 400)
+ local a,b = loadstring(s)
+ assert(not a and string.find(b, "syntax levels"))
+end
+testrep("a=", "{")
+testrep("a=", "(")
+testrep("", "a(")
+testrep("", "do ")
+testrep("", "while a do ")
+testrep("", "if a then else ")
+testrep("", "function foo () ")
+testrep("a=", "a..")
+testrep("a=", "a^")
+
+
+-- testing other limits
+-- upvalues
+local s = "function foo ()\n local "
+for j = 1,70 do
+ s = s.."a"..j..", "
+end
+s = s.."b\n"
+for j = 1,70 do
+ s = s.."function foo"..j.." ()\n a"..j.."=3\n"
+end
+local a,b = loadstring(s)
+assert(string.find(b, "line 3"))
+
+-- local variables
+s = "\nfunction foo ()\n local "
+for j = 1,300 do
+ s = s.."a"..j..", "
+end
+s = s.."b\n"
+local a,b = loadstring(s)
+assert(string.find(b, "line 2"))
+
+
+print('OK')
diff --git a/test/PUC-Rio-Lua-5.1-tests/etc/ltests.c b/test/PUC-Rio-Lua-5.1-tests/etc/ltests.c
new file mode 100644
index 00000000..be949e59
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/etc/ltests.c
@@ -0,0 +1,1147 @@
+/*
+** $Id: ltests.c,v 2.36 2006/01/10 13:13:06 roberto Exp $
+** Internal Module for Debugging of the Lua Implementation
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ltests_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lapi.h"
+#include "lauxlib.h"
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "lualib.h"
+
+
+
+/*
+** The whole module only makes sense with LUA_DEBUG on
+*/
+#if defined(LUA_DEBUG)
+
+
+int Trick = 0;
+
+
+static lua_State *lua_state = NULL;
+
+int islocked = 0;
+
+
+#define obj_at(L,k) (L->ci->base+(k) - 1)
+
+
+static void setnameval (lua_State *L, const char *name, int val) {
+ lua_pushstring(L, name);
+ lua_pushinteger(L, val);
+ lua_settable(L, -3);
+}
+
+
+/*
+** {======================================================================
+** Controlled version for realloc.
+** =======================================================================
+*/
+
+#define MARK 0x55 /* 01010101 (a nice pattern) */
+
+#ifndef EXTERNMEMCHECK
+/* full memory check */
+#define HEADER (sizeof(L_Umaxalign)) /* ensures maximum alignment for HEADER */
+#define MARKSIZE 16 /* size of marks after each block */
+#define blockhead(b) (cast(char *, b) - HEADER)
+#define setsize(newblock, size) (*cast(size_t *, newblock) = size)
+#define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b))))
+#define fillmem(mem,size) memset(mem, -MARK, size)
+#else
+/* external memory check: don't do it twice */
+#define HEADER 0
+#define MARKSIZE 0
+#define blockhead(b) (b)
+#define setsize(newblock, size) /* empty */
+#define checkblocksize(b,size) (1)
+#define fillmem(mem,size) /* empty */
+#endif
+
+
+Memcontrol memcontrol = {0L, 0L, 0L, ULONG_MAX};
+
+
+static void *checkblock (void *block, size_t size) {
+ void *b = blockhead(block);
+ int i;
+ for (i=0;i<MARKSIZE;i++)
+ lua_assert(*(cast(char *, b)+HEADER+size+i) == MARK+i); /* corrupted block? */
+ return b;
+}
+
+
+static void freeblock (Memcontrol *mc, void *block, size_t size) {
+ if (block) {
+ lua_assert(checkblocksize(block, size));
+ block = checkblock(block, size);
+ fillmem(block, size+HEADER+MARKSIZE); /* erase block */
+ free(block); /* free original block */
+ mc->numblocks--;
+ mc->total -= size;
+ }
+}
+
+
+void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
+ Memcontrol *mc = cast(Memcontrol *, ud);
+ lua_assert(oldsize == 0 || checkblocksize(block, oldsize));
+ if (size == 0) {
+ freeblock(mc, block, oldsize);
+ return NULL;
+ }
+ else if (size > oldsize && mc->total+size-oldsize > mc->memlimit)
+ return NULL; /* to test memory allocation errors */
+ else {
+ void *newblock;
+ int i;
+ size_t realsize = HEADER+size+MARKSIZE;
+ size_t commonsize = (oldsize < size) ? oldsize : size;
+ if (realsize < size) return NULL; /* overflow! */
+ newblock = malloc(realsize); /* alloc a new block */
+ if (newblock == NULL) return NULL;
+ if (block) {
+ memcpy(cast(char *, newblock)+HEADER, block, commonsize);
+ freeblock(mc, block, oldsize); /* erase (and check) old copy */
+ }
+ /* initialize new part of the block with something `weird' */
+ fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize);
+ mc->total += size;
+ if (mc->total > mc->maxmem)
+ mc->maxmem = mc->total;
+ mc->numblocks++;
+ setsize(newblock, size);
+ for (i=0;i<MARKSIZE;i++)
+ *(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i);
+ return cast(char *, newblock)+HEADER;
+ }
+}
+
+
+/* }====================================================================== */
+
+
+
+/*
+** {======================================================
+** Functions to check memory consistency
+** =======================================================
+*/
+
+static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
+ if (isdead(g,t)) return 0;
+ if (g->gcstate == GCSpropagate)
+ return !isblack(f) || !iswhite(t);
+ else if (g->gcstate == GCSfinalize)
+ return iswhite(f);
+ else
+ return 1;
+}
+
+
+static void printobj (global_State *g, GCObject *o) {
+ int i = 0;
+ GCObject *p;
+ for (p = g->rootgc; p != o && p != NULL; p = p->gch.next) i++;
+ if (p == NULL) i = -1;
+ printf("%d:%s(%p)-%c(%02X)", i, luaT_typenames[o->gch.tt], (void *)o,
+ isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', o->gch.marked);
+}
+
+
+static int testobjref (global_State *g, GCObject *f, GCObject *t) {
+ int r = testobjref1(g,f,t);
+ if (!r) {
+ printf("%d(%02X) - ", g->gcstate, g->currentwhite);
+ printobj(g, f);
+ printf("\t-> ");
+ printobj(g, t);
+ printf("\n");
+ }
+ return r;
+}
+
+#define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t)))
+
+#define checkvalref(g,f,t) lua_assert(!iscollectable(t) || \
+ ((ttype(t) == (t)->value.gc->gch.tt) && testobjref(g,f,gcvalue(t))))
+
+
+
+static void checktable (global_State *g, Table *h) {
+ int i;
+ int weakkey = 0;
+ int weakvalue = 0;
+ const TValue *mode;
+ GCObject *hgc = obj2gco(h);
+ if (h->metatable)
+ checkobjref(g, hgc, h->metatable);
+ mode = gfasttm(g, h->metatable, TM_MODE);
+ if (mode && ttisstring(mode)) { /* is there a weak mode? */
+ weakkey = (strchr(svalue(mode), 'k') != NULL);
+ weakvalue = (strchr(svalue(mode), 'v') != NULL);
+ }
+ i = h->sizearray;
+ while (i--)
+ checkvalref(g, hgc, &h->array[i]);
+ i = sizenode(h);
+ while (i--) {
+ Node *n = gnode(h, i);
+ if (!ttisnil(gval(n))) {
+ lua_assert(!ttisnil(gkey(n)));
+ checkvalref(g, hgc, gkey(n));
+ checkvalref(g, hgc, gval(n));
+ }
+ }
+}
+
+
+/*
+** All marks are conditional because a GC may happen while the
+** prototype is still being created
+*/
+static void checkproto (global_State *g, Proto *f) {
+ int i;
+ GCObject *fgc = obj2gco(f);
+ if (f->source) checkobjref(g, fgc, f->source);
+ for (i=0; i<f->sizek; i++) {
+ if (ttisstring(f->k+i))
+ checkobjref(g, fgc, rawtsvalue(f->k+i));
+ }
+ for (i=0; i<f->sizeupvalues; i++) {
+ if (f->upvalues[i])
+ checkobjref(g, fgc, f->upvalues[i]);
+ }
+ for (i=0; i<f->sizep; i++) {
+ if (f->p[i])
+ checkobjref(g, fgc, f->p[i]);
+ }
+ for (i=0; i<f->sizelocvars; i++) {
+ if (f->locvars[i].varname)
+ checkobjref(g, fgc, f->locvars[i].varname);
+ }
+}
+
+
+
+static void checkclosure (global_State *g, Closure *cl) {
+ GCObject *clgc = obj2gco(cl);
+ checkobjref(g, clgc, cl->l.env);
+ if (cl->c.isC) {
+ int i;
+ for (i=0; i<cl->c.nupvalues; i++)
+ checkvalref(g, clgc, &cl->c.upvalue[i]);
+ }
+ else {
+ int i;
+ lua_assert(cl->l.nupvalues == cl->l.p->nups);
+ checkobjref(g, clgc, cl->l.p);
+ for (i=0; i<cl->l.nupvalues; i++) {
+ if (cl->l.upvals[i]) {
+ lua_assert(cl->l.upvals[i]->tt == LUA_TUPVAL);
+ checkobjref(g, clgc, cl->l.upvals[i]);
+ }
+ }
+ }
+}
+
+
+static void checkstack (global_State *g, lua_State *L1) {
+ StkId o;
+ CallInfo *ci;
+ GCObject *uvo;
+ lua_assert(!isdead(g, obj2gco(L1)));
+ for (uvo = L1->openupval; uvo != NULL; uvo = uvo->gch.next) {
+ UpVal *uv = gco2uv(uvo);
+ lua_assert(uv->v != &uv->u.value); /* must be open */
+ lua_assert(!isblack(uvo)); /* open upvalues cannot be black */
+ }
+ checkliveness(g, gt(L1));
+ if (L1->base_ci) {
+ for (ci = L1->base_ci; ci <= L1->ci; ci++) {
+ lua_assert(ci->top <= L1->stack_last);
+ lua_assert(lua_checkpc(L1, ci));
+ }
+ }
+ else lua_assert(L1->size_ci == 0);
+ if (L1->stack) {
+ for (o = L1->stack; o < L1->top; o++)
+ checkliveness(g, o);
+ }
+ else lua_assert(L1->stacksize == 0);
+}
+
+
+static void checkobject (global_State *g, GCObject *o) {
+ if (isdead(g, o))
+/* lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);*/
+{ if (!(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep))
+printf(">>> %d %s %02x\n", g->gcstate, luaT_typenames[o->gch.tt], o->gch.marked);
+}
+ else {
+ if (g->gcstate == GCSfinalize)
+ lua_assert(iswhite(o));
+ switch (o->gch.tt) {
+ case LUA_TUPVAL: {
+ UpVal *uv = gco2uv(o);
+ lua_assert(uv->v == &uv->u.value); /* must be closed */
+ lua_assert(!isgray(o)); /* closed upvalues are never gray */
+ checkvalref(g, o, uv->v);
+ break;
+ }
+ case LUA_TUSERDATA: {
+ Table *mt = gco2u(o)->metatable;
+ if (mt) checkobjref(g, o, mt);
+ break;
+ }
+ case LUA_TTABLE: {
+ checktable(g, gco2h(o));
+ break;
+ }
+ case LUA_TTHREAD: {
+ checkstack(g, gco2th(o));
+ break;
+ }
+ case LUA_TFUNCTION: {
+ checkclosure(g, gco2cl(o));
+ break;
+ }
+ case LUA_TPROTO: {
+ checkproto(g, gco2p(o));
+ break;
+ }
+ default: lua_assert(0);
+ }
+ }
+}
+
+
+int lua_checkpc (lua_State *L, pCallInfo ci) {
+ if (ci == L->base_ci || !f_isLua(ci)) return 1;
+ else {
+ Proto *p = ci_func(ci)->l.p;
+ if (ci < L->ci)
+ return p->code <= ci->savedpc && ci->savedpc <= p->code + p->sizecode;
+ else
+ return p->code <= L->savedpc && L->savedpc <= p->code + p->sizecode;
+ }
+}
+
+
+int lua_checkmemory (lua_State *L) {
+ global_State *g = G(L);
+ GCObject *o;
+ UpVal *uv;
+ checkstack(g, g->mainthread);
+ for (o = g->rootgc; o != obj2gco(g->mainthread); o = o->gch.next)
+ checkobject(g, o);
+ for (o = o->gch.next; o != NULL; o = o->gch.next) {
+ lua_assert(o->gch.tt == LUA_TUSERDATA);
+ checkobject(g, o);
+ }
+ for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ lua_assert(uv->v != &uv->u.value); /* must be open */
+ lua_assert(!isblack(obj2gco(uv))); /* open upvalues are never black */
+ checkvalref(g, obj2gco(uv), uv->v);
+ }
+ return 0;
+}
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** Disassembler
+** =======================================================
+*/
+
+
+static char *buildop (Proto *p, int pc, char *buff) {
+ Instruction i = p->code[pc];
+ OpCode o = GET_OPCODE(i);
+ const char *name = luaP_opnames[o];
+ int line = getline(p, pc);
+ sprintf(buff, "(%4d) %4d - ", line, pc);
+ switch (getOpMode(o)) {
+ case iABC:
+ sprintf(buff+strlen(buff), "%-12s%4d %4d %4d", name,
+ GETARG_A(i), GETARG_B(i), GETARG_C(i));
+ break;
+ case iABx:
+ sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i));
+ break;
+ case iAsBx:
+ sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i));
+ break;
+ }
+ return buff;
+}
+
+
+#if 0
+void luaI_printcode (Proto *pt, int size) {
+ int pc;
+ for (pc=0; pc<size; pc++) {
+ char buff[100];
+ printf("%s\n", buildop(pt, pc, buff));
+ }
+ printf("-------\n");
+}
+#endif
+
+
+static int listcode (lua_State *L) {
+ int pc;
+ Proto *p;
+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
+ 1, "Lua function expected");
+ p = clvalue(obj_at(L, 1))->l.p;
+ lua_newtable(L);
+ setnameval(L, "maxstack", p->maxstacksize);
+ setnameval(L, "numparams", p->numparams);
+ for (pc=0; pc<p->sizecode; pc++) {
+ char buff[100];
+ lua_pushinteger(L, pc+1);
+ lua_pushstring(L, buildop(p, pc, buff));
+ lua_settable(L, -3);
+ }
+ return 1;
+}
+
+
+static int listk (lua_State *L) {
+ Proto *p;
+ int i;
+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
+ 1, "Lua function expected");
+ p = clvalue(obj_at(L, 1))->l.p;
+ lua_createtable(L, p->sizek, 0);
+ for (i=0; i<p->sizek; i++) {
+ luaA_pushobject(L, p->k+i);
+ lua_rawseti(L, -2, i+1);
+ }
+ return 1;
+}
+
+
+static int listlocals (lua_State *L) {
+ Proto *p;
+ int pc = luaL_checkint(L, 2) - 1;
+ int i = 0;
+ const char *name;
+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
+ 1, "Lua function expected");
+ p = clvalue(obj_at(L, 1))->l.p;
+ while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
+ lua_pushstring(L, name);
+ return i-1;
+}
+
+/* }====================================================== */
+
+
+
+
+static int get_limits (lua_State *L) {
+ lua_createtable(L, 0, 5);
+ setnameval(L, "BITS_INT", LUAI_BITSINT);
+ setnameval(L, "LFPF", LFIELDS_PER_FLUSH);
+ setnameval(L, "MAXVARS", LUAI_MAXVARS);
+ setnameval(L, "MAXSTACK", MAXSTACK);
+ setnameval(L, "MAXUPVALUES", LUAI_MAXUPVALUES);
+ setnameval(L, "NUM_OPCODES", NUM_OPCODES);
+ return 1;
+}
+
+
+static int mem_query (lua_State *L) {
+ if (lua_isnone(L, 1)) {
+ lua_pushinteger(L, memcontrol.total);
+ lua_pushinteger(L, memcontrol.numblocks);
+ lua_pushinteger(L, memcontrol.maxmem);
+ return 3;
+ }
+ else {
+ memcontrol.memlimit = luaL_checkint(L, 1);
+ return 0;
+ }
+}
+
+
+static int settrick (lua_State *L) {
+ Trick = lua_tointeger(L, 1);
+ return 0;
+}
+
+
+/*static int set_gcstate (lua_State *L) {
+ static const char *const state[] = {"propagate", "sweep", "finalize"};
+ return 0;
+}*/
+
+
+static int get_gccolor (lua_State *L) {
+ TValue *o;
+ luaL_checkany(L, 1);
+ o = obj_at(L, 1);
+ if (!iscollectable(o))
+ lua_pushstring(L, "no collectable");
+ else
+ lua_pushstring(L, iswhite(gcvalue(o)) ? "white" :
+ isblack(gcvalue(o)) ? "black" : "grey");
+ return 1;
+}
+
+
+static int gcstate (lua_State *L) {
+ switch(G(L)->gcstate) {
+ case GCSpropagate: lua_pushstring(L, "propagate"); break;
+ case GCSsweepstring: lua_pushstring(L, "sweep strings"); break;
+ case GCSsweep: lua_pushstring(L, "sweep"); break;
+ case GCSfinalize: lua_pushstring(L, "finalize"); break;
+ }
+ return 1;
+}
+
+
+static int hash_query (lua_State *L) {
+ if (lua_isnone(L, 2)) {
+ luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
+ lua_pushinteger(L, tsvalue(obj_at(L, 1))->hash);
+ }
+ else {
+ TValue *o = obj_at(L, 1);
+ Table *t;
+ luaL_checktype(L, 2, LUA_TTABLE);
+ t = hvalue(obj_at(L, 2));
+ lua_pushinteger(L, luaH_mainposition(t, o) - t->node);
+ }
+ return 1;
+}
+
+
+static int stacklevel (lua_State *L) {
+ unsigned long a = 0;
+ lua_pushinteger(L, (L->top - L->stack));
+ lua_pushinteger(L, (L->stack_last - L->stack));
+ lua_pushinteger(L, (L->ci - L->base_ci));
+ lua_pushinteger(L, (L->end_ci - L->base_ci));
+ lua_pushinteger(L, (unsigned long)&a);
+ return 5;
+}
+
+
+static int table_query (lua_State *L) {
+ const Table *t;
+ int i = luaL_optint(L, 2, -1);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ t = hvalue(obj_at(L, 1));
+ if (i == -1) {
+ lua_pushinteger(L, t->sizearray);
+ lua_pushinteger(L, luaH_isdummy(t->node) ? 0 : sizenode(t));
+ lua_pushinteger(L, t->lastfree - t->node);
+ }
+ else if (i < t->sizearray) {
+ lua_pushinteger(L, i);
+ luaA_pushobject(L, &t->array[i]);
+ lua_pushnil(L);
+ }
+ else if ((i -= t->sizearray) < sizenode(t)) {
+ if (!ttisnil(gval(gnode(t, i))) ||
+ ttisnil(gkey(gnode(t, i))) ||
+ ttisnumber(gkey(gnode(t, i)))) {
+ luaA_pushobject(L, key2tval(gnode(t, i)));
+ }
+ else
+ lua_pushliteral(L, "<undef>");
+ luaA_pushobject(L, gval(gnode(t, i)));
+ if (gnext(&t->node[i]))
+ lua_pushinteger(L, gnext(&t->node[i]) - t->node);
+ else
+ lua_pushnil(L);
+ }
+ return 3;
+}
+
+
+static int string_query (lua_State *L) {
+ stringtable *tb = &G(L)->strt;
+ int s = luaL_optint(L, 2, 0) - 1;
+ if (s==-1) {
+ lua_pushinteger(L ,tb->nuse);
+ lua_pushinteger(L ,tb->size);
+ return 2;
+ }
+ else if (s < tb->size) {
+ GCObject *ts;
+ int n = 0;
+ for (ts = tb->hash[s]; ts; ts = ts->gch.next) {
+ setsvalue2s(L, L->top, gco2ts(ts));
+ incr_top(L);
+ n++;
+ }
+ return n;
+ }
+ return 0;
+}
+
+
+static int tref (lua_State *L) {
+ int level = lua_gettop(L);
+ int lock = luaL_optint(L, 2, 1);
+ luaL_checkany(L, 1);
+ lua_pushvalue(L, 1);
+ lua_pushinteger(L, lua_ref(L, lock));
+ lua_assert(lua_gettop(L) == level+1); /* +1 for result */
+ return 1;
+}
+
+static int getref (lua_State *L) {
+ int level = lua_gettop(L);
+ lua_getref(L, luaL_checkint(L, 1));
+ lua_assert(lua_gettop(L) == level+1);
+ return 1;
+}
+
+static int unref (lua_State *L) {
+ int level = lua_gettop(L);
+ lua_unref(L, luaL_checkint(L, 1));
+ lua_assert(lua_gettop(L) == level);
+ return 0;
+}
+
+
+static int upvalue (lua_State *L) {
+ int n = luaL_checkint(L, 2);
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ if (lua_isnone(L, 3)) {
+ const char *name = lua_getupvalue(L, 1, n);
+ if (name == NULL) return 0;
+ lua_pushstring(L, name);
+ return 2;
+ }
+ else {
+ const char *name = lua_setupvalue(L, 1, n);
+ lua_pushstring(L, name);
+ return 1;
+ }
+}
+
+
+static int newuserdata (lua_State *L) {
+ size_t size = luaL_checkint(L, 1);
+ char *p = cast(char *, lua_newuserdata(L, size));
+ while (size--) *p++ = '\0';
+ return 1;
+}
+
+
+static int pushuserdata (lua_State *L) {
+ lua_pushlightuserdata(L, cast(void *, luaL_checkint(L, 1)));
+ return 1;
+}
+
+
+static int udataval (lua_State *L) {
+ lua_pushinteger(L, cast(long, lua_touserdata(L, 1)));
+ return 1;
+}
+
+
+static int doonnewstack (lua_State *L) {
+ lua_State *L1 = lua_newthread(L);
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ int status = luaL_loadbuffer(L1, s, l, s);
+ if (status == 0)
+ status = lua_pcall(L1, 0, 0, 0);
+ lua_pushinteger(L, status);
+ return 1;
+}
+
+
+static int s2d (lua_State *L) {
+ lua_pushnumber(L, *cast(const double *, luaL_checkstring(L, 1)));
+ return 1;
+}
+
+
+static int d2s (lua_State *L) {
+ double d = luaL_checknumber(L, 1);
+ lua_pushlstring(L, cast(char *, &d), sizeof(d));
+ return 1;
+}
+
+
+static int num2int (lua_State *L) {
+ lua_pushinteger(L, lua_tointeger(L, 1));
+ return 1;
+}
+
+
+static int newstate (lua_State *L) {
+ void *ud;
+ lua_Alloc f = lua_getallocf(L, &ud);
+ lua_State *L1 = lua_newstate(f, ud);
+ if (L1)
+ lua_pushinteger(L, (unsigned long)L1);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+
+static int loadlib (lua_State *L) {
+ static const luaL_Reg libs[] = {
+ {"baselibopen", luaopen_base},
+ {"dblibopen", luaopen_debug},
+ {"iolibopen", luaopen_io},
+ {"mathlibopen", luaopen_math},
+ {"strlibopen", luaopen_string},
+ {"tablibopen", luaopen_table},
+ {"packageopen", luaopen_package},
+ {NULL, NULL}
+ };
+ lua_State *L1 = cast(lua_State *,
+ cast(unsigned long, luaL_checknumber(L, 1)));
+ lua_pushvalue(L1, LUA_GLOBALSINDEX);
+ luaL_register(L1, NULL, libs);
+ return 0;
+}
+
+static int closestate (lua_State *L) {
+ lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1)));
+ lua_close(L1);
+ return 0;
+}
+
+static int doremote (lua_State *L) {
+ lua_State *L1 = cast(lua_State *,cast(unsigned long,luaL_checknumber(L, 1)));
+ size_t lcode;
+ const char *code = luaL_checklstring(L, 2, &lcode);
+ int status;
+ lua_settop(L1, 0);
+ status = luaL_loadbuffer(L1, code, lcode, code);
+ if (status == 0)
+ status = lua_pcall(L1, 0, LUA_MULTRET, 0);
+ if (status != 0) {
+ lua_pushnil(L);
+ lua_pushinteger(L, status);
+ lua_pushstring(L, lua_tostring(L1, -1));
+ return 3;
+ }
+ else {
+ int i = 0;
+ while (!lua_isnone(L1, ++i))
+ lua_pushstring(L, lua_tostring(L1, i));
+ lua_pop(L1, i-1);
+ return i-1;
+ }
+}
+
+
+static int log2_aux (lua_State *L) {
+ lua_pushinteger(L, luaO_log2(luaL_checkint(L, 1)));
+ return 1;
+}
+
+static int int2fb_aux (lua_State *L) {
+ int b = luaO_int2fb(luaL_checkint(L, 1));
+ lua_pushinteger(L, b);
+ lua_pushinteger(L, luaO_fb2int(b));
+ return 2;
+}
+
+
+
+/*
+** {======================================================
+** function to test the API with C. It interprets a kind of assembler
+** language with calls to the API, so the test can be driven by Lua code
+** =======================================================
+*/
+
+static const char *const delimits = " \t\n,;";
+
+static void skip (const char **pc) {
+ while (**pc != '\0' && strchr(delimits, **pc)) (*pc)++;
+}
+
+static int getnum_aux (lua_State *L, const char **pc) {
+ int res = 0;
+ int sig = 1;
+ skip(pc);
+ if (**pc == '.') {
+ res = cast_int(lua_tonumber(L, -1));
+ lua_pop(L, 1);
+ (*pc)++;
+ return res;
+ }
+ else if (**pc == '-') {
+ sig = -1;
+ (*pc)++;
+ }
+ while (isdigit(cast_int(**pc))) res = res*10 + (*(*pc)++) - '0';
+ return sig*res;
+}
+
+static const char *getname_aux (char *buff, const char **pc) {
+ int i = 0;
+ skip(pc);
+ while (**pc != '\0' && !strchr(delimits, **pc))
+ buff[i++] = *(*pc)++;
+ buff[i] = '\0';
+ return buff;
+}
+
+
+static int getindex_aux (lua_State *L, const char **pc) {
+ skip(pc);
+ switch (*(*pc)++) {
+ case 'R': return LUA_REGISTRYINDEX;
+ case 'G': return LUA_GLOBALSINDEX;
+ case 'E': return LUA_ENVIRONINDEX;
+ case 'U': return lua_upvalueindex(getnum_aux(L, pc));
+ default: (*pc)--; return getnum_aux(L, pc);
+ }
+}
+
+#define EQ(s1) (strcmp(s1, inst) == 0)
+
+#define getnum (getnum_aux(L, &pc))
+#define getname (getname_aux(buff, &pc))
+#define getindex (getindex_aux(L, &pc))
+
+
+static int testC (lua_State *L) {
+ char buff[30];
+ lua_State *L1;
+ const char *pc;
+ if (lua_isnumber(L, 1)) {
+ L1 = cast(lua_State *,cast(unsigned long,luaL_checknumber(L, 1)));
+ pc = luaL_checkstring(L, 2);
+ }
+ else {
+ L1 = L;
+ pc = luaL_checkstring(L, 1);
+ }
+ for (;;) {
+ const char *inst = getname;
+ if EQ("") return 0;
+ else if EQ("isnumber") {
+ lua_pushinteger(L1, lua_isnumber(L1, getindex));
+ }
+ else if EQ("isstring") {
+ lua_pushinteger(L1, lua_isstring(L1, getindex));
+ }
+ else if EQ("istable") {
+ lua_pushinteger(L1, lua_istable(L1, getindex));
+ }
+ else if EQ("iscfunction") {
+ lua_pushinteger(L1, lua_iscfunction(L1, getindex));
+ }
+ else if EQ("isfunction") {
+ lua_pushinteger(L1, lua_isfunction(L1, getindex));
+ }
+ else if EQ("isuserdata") {
+ lua_pushinteger(L1, lua_isuserdata(L1, getindex));
+ }
+ else if EQ("isudataval") {
+ lua_pushinteger(L1, lua_islightuserdata(L1, getindex));
+ }
+ else if EQ("isnil") {
+ lua_pushinteger(L1, lua_isnil(L1, getindex));
+ }
+ else if EQ("isnull") {
+ lua_pushinteger(L1, lua_isnone(L1, getindex));
+ }
+ else if EQ("tonumber") {
+ lua_pushnumber(L1, lua_tonumber(L1, getindex));
+ }
+ else if EQ("tostring") {
+ const char *s = lua_tostring(L1, getindex);
+ lua_pushstring(L1, s);
+ }
+ else if EQ("objsize") {
+ lua_pushinteger(L1, lua_objlen(L1, getindex));
+ }
+ else if EQ("tocfunction") {
+ lua_pushcfunction(L1, lua_tocfunction(L1, getindex));
+ }
+ else if EQ("return") {
+ return getnum;
+ }
+ else if EQ("gettop") {
+ lua_pushinteger(L1, lua_gettop(L1));
+ }
+ else if EQ("settop") {
+ lua_settop(L1, getnum);
+ }
+ else if EQ("pop") {
+ lua_pop(L1, getnum);
+ }
+ else if EQ("pushnum") {
+ lua_pushinteger(L1, getnum);
+ }
+ else if EQ("pushstring") {
+ lua_pushstring(L1, getname);
+ }
+ else if EQ("pushnil") {
+ lua_pushnil(L1);
+ }
+ else if EQ("pushbool") {
+ lua_pushboolean(L1, getnum);
+ }
+ else if EQ("newuserdata") {
+ lua_newuserdata(L1, getnum);
+ }
+ else if EQ("tobool") {
+ lua_pushinteger(L1, lua_toboolean(L1, getindex));
+ }
+ else if EQ("pushvalue") {
+ lua_pushvalue(L1, getindex);
+ }
+ else if EQ("pushcclosure") {
+ lua_pushcclosure(L1, testC, getnum);
+ }
+ else if EQ("remove") {
+ lua_remove(L1, getnum);
+ }
+ else if EQ("insert") {
+ lua_insert(L1, getnum);
+ }
+ else if EQ("replace") {
+ lua_replace(L1, getindex);
+ }
+ else if EQ("gettable") {
+ lua_gettable(L1, getindex);
+ }
+ else if EQ("settable") {
+ lua_settable(L1, getindex);
+ }
+ else if EQ("next") {
+ lua_next(L1, -2);
+ }
+ else if EQ("concat") {
+ lua_concat(L1, getnum);
+ }
+ else if EQ("lessthan") {
+ int a = getindex;
+ lua_pushboolean(L1, lua_lessthan(L1, a, getindex));
+ }
+ else if EQ("equal") {
+ int a = getindex;
+ lua_pushboolean(L1, lua_equal(L1, a, getindex));
+ }
+ else if EQ("rawcall") {
+ int narg = getnum;
+ int nres = getnum;
+ lua_call(L1, narg, nres);
+ }
+ else if EQ("call") {
+ int narg = getnum;
+ int nres = getnum;
+ lua_pcall(L1, narg, nres, 0);
+ }
+ else if EQ("loadstring") {
+ size_t sl;
+ const char *s = luaL_checklstring(L1, getnum, &sl);
+ luaL_loadbuffer(L1, s, sl, s);
+ }
+ else if EQ("loadfile") {
+ luaL_loadfile(L1, luaL_checkstring(L1, getnum));
+ }
+ else if EQ("setmetatable") {
+ lua_setmetatable(L1, getindex);
+ }
+ else if EQ("getmetatable") {
+ if (lua_getmetatable(L1, getindex) == 0)
+ lua_pushnil(L1);
+ }
+ else if EQ("type") {
+ lua_pushstring(L1, luaL_typename(L1, getnum));
+ }
+ else if EQ("getn") {
+ int i = getindex;
+ lua_pushinteger(L1, luaL_getn(L1, i));
+ }
+#ifndef luaL_setn
+ else if EQ("setn") {
+ int i = getindex;
+ int n = cast_int(lua_tonumber(L1, -1));
+ luaL_setn(L1, i, n);
+ lua_pop(L1, 1);
+ }
+#endif
+ else if EQ("throw") {
+#if defined(__cplusplus)
+static struct X { int x; } x;
+ throw x;
+#else
+ luaL_error(L1, "C++");
+#endif
+ break;
+ }
+ else luaL_error(L, "unknown instruction %s", buff);
+ }
+ return 0;
+}
+
+/* }====================================================== */
+
+
+/*
+** {======================================================
+** tests for yield inside hooks
+** =======================================================
+*/
+
+static void yieldf (lua_State *L, lua_Debug *ar) {
+ lua_yield(L, 0);
+}
+
+static int setyhook (lua_State *L) {
+ if (lua_isnoneornil(L, 1))
+ lua_sethook(L, NULL, 0, 0); /* turn off hooks */
+ else {
+ const char *smask = luaL_checkstring(L, 1);
+ int count = luaL_optint(L, 2, 0);
+ int mask = 0;
+ if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
+ if (count > 0) mask |= LUA_MASKCOUNT;
+ lua_sethook(L, yieldf, mask, count);
+ }
+ return 0;
+}
+
+
+static int coresume (lua_State *L) {
+ int status;
+ lua_State *co = lua_tothread(L, 1);
+ luaL_argcheck(L, co, 1, "coroutine expected");
+ status = lua_resume(co, 0);
+ if (status != 0) {
+ lua_pushboolean(L, 0);
+ lua_insert(L, -2);
+ return 2; /* return false + error message */
+ }
+ else {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+}
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** tests auxlib functions
+** =======================================================
+*/
+
+static int auxgsub (lua_State *L) {
+ const char *s1 = luaL_checkstring(L, 1);
+ const char *s2 = luaL_checkstring(L, 2);
+ const char *s3 = luaL_checkstring(L, 3);
+ lua_settop(L, 3);
+ luaL_gsub(L, s1, s2, s3);
+ lua_assert(lua_gettop(L) == 4);
+ return 1;
+}
+
+
+/* }====================================================== */
+
+
+
+static const struct luaL_Reg tests_funcs[] = {
+ {"checkmemory", lua_checkmemory},
+ {"closestate", closestate},
+ {"d2s", d2s},
+ {"doonnewstack", doonnewstack},
+ {"doremote", doremote},
+ {"gccolor", get_gccolor},
+ {"gcstate", gcstate},
+ {"getref", getref},
+ {"gsub", auxgsub},
+ {"hash", hash_query},
+ {"int2fb", int2fb_aux},
+ {"limits", get_limits},
+ {"listcode", listcode},
+ {"listk", listk},
+ {"listlocals", listlocals},
+ {"loadlib", loadlib},
+ {"log2", log2_aux},
+ {"newstate", newstate},
+ {"newuserdata", newuserdata},
+ {"num2int", num2int},
+ {"pushuserdata", pushuserdata},
+ {"querystr", string_query},
+ {"querytab", table_query},
+ {"ref", tref},
+ {"resume", coresume},
+ {"s2d", s2d},
+ {"setyhook", setyhook},
+ {"stacklevel", stacklevel},
+ {"testC", testC},
+ {"totalmem", mem_query},
+ {"trick", settrick},
+ {"udataval", udataval},
+ {"unref", unref},
+ {"upvalue", upvalue},
+ {NULL, NULL}
+};
+
+
+int luaB_opentests (lua_State *L) {
+ void *ud;
+ lua_assert(lua_getallocf(L, &ud) == debug_realloc);
+ lua_assert(ud == cast(void *, &memcontrol));
+ lua_setallocf(L, lua_getallocf(L, NULL), ud);
+ lua_state = L; /* keep first state to be opened */
+ luaL_register(L, "T", tests_funcs);
+ return 0;
+}
+
+
+#undef main
+int main (int argc, char *argv[]) {
+ int ret;
+ char *limit = getenv("MEMLIMIT");
+ if (limit)
+ memcontrol.memlimit = strtoul(limit, NULL, 10);
+ ret = l_main(argc, argv);
+ lua_assert(memcontrol.numblocks == 0);
+ lua_assert(memcontrol.total == 0);
+ return ret;
+}
+
+#endif
diff --git a/test/PUC-Rio-Lua-5.1-tests/etc/ltests.h b/test/PUC-Rio-Lua-5.1-tests/etc/ltests.h
new file mode 100644
index 00000000..e5702127
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/etc/ltests.h
@@ -0,0 +1,92 @@
+/*
+** $Id: ltests.h,v 2.17 2005/12/27 17:12:00 roberto Exp $
+** Internal Header for Debugging of the Lua Implementation
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ltests_h
+#define ltests_h
+
+
+#include <stdlib.h>
+
+
+#define LUA_DEBUG
+
+#undef NDEBUG
+#include <assert.h>
+#define lua_assert(c) assert(c)
+
+
+/* to avoid warnings, and to make sure value is really unused */
+#define UNUSED(x) (x=0, (void)(x))
+
+
+/* memory allocator control variables */
+typedef struct Memcontrol {
+ unsigned long numblocks;
+ unsigned long total;
+ unsigned long maxmem;
+ unsigned long memlimit;
+} Memcontrol;
+
+LUAI_DATA Memcontrol memcontrol;
+
+
+/*
+** generic variable for debug tricks
+*/
+LUAI_DATA int Trick;
+
+
+void *debug_realloc (void *ud, void *block, size_t osize, size_t nsize);
+
+#ifdef lua_c
+#define luaL_newstate() lua_newstate(debug_realloc, &memcontrol)
+#endif
+
+
+typedef struct CallInfo *pCallInfo;
+
+int lua_checkmemory (lua_State *L);
+int lua_checkpc (lua_State *L, pCallInfo ci);
+
+
+/* test for lock/unlock */
+#undef luai_userstateopen
+#undef luai_userstatethread
+#undef lua_lock
+#undef lua_unlock
+#undef LUAI_EXTRASPACE
+
+struct L_EXTRA { int lock; int *plock; };
+#define LUAI_EXTRASPACE sizeof(struct L_EXTRA)
+#define getlock(l) (cast(struct L_EXTRA *, l) - 1)
+#define luai_userstateopen(l) \
+ (getlock(l)->lock = 0, getlock(l)->plock = &(getlock(l)->lock))
+#define luai_userstatethread(l,l1) (getlock(l1)->plock = getlock(l)->plock)
+#define lua_lock(l) lua_assert((*getlock(l)->plock)++ == 0)
+#define lua_unlock(l) lua_assert(--(*getlock(l)->plock) == 0)
+
+
+int luaB_opentests (lua_State *L);
+
+#ifdef lua_c
+#define luaL_openlibs(L) { (luaL_openlibs)(L); luaB_opentests(L); }
+#endif
+
+
+
+/* real main will be defined at `ltests.c' */
+int l_main (int argc, char *argv[]);
+#define main l_main
+
+
+
+/* change some sizes to give some bugs a chance */
+
+#undef LUAL_BUFFERSIZE
+#define LUAL_BUFFERSIZE 27
+#define MINSTRTABSIZE 2
+
+#endif
diff --git a/test/PUC-Rio-Lua-5.1-tests/events.lua b/test/PUC-Rio-Lua-5.1-tests/events.lua
new file mode 100644
index 00000000..5234b007
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/events.lua
@@ -0,0 +1,360 @@
+print('testing metatables')
+
+X = 20; B = 30
+
+setfenv(1, setmetatable({}, {__index=_G}))
+
+collectgarbage()
+
+X = X+10
+assert(X == 30 and _G.X == 20)
+B = false
+assert(B == false)
+B = nil
+assert(B == 30)
+
+assert(getmetatable{} == nil)
+assert(getmetatable(4) == nil)
+assert(getmetatable(nil) == nil)
+a={}; setmetatable(a, {__metatable = "xuxu",
+ __tostring=function(x) return x.name end})
+assert(getmetatable(a) == "xuxu")
+assert(tostring(a) == nil)
+-- cannot change a protected metatable
+assert(pcall(setmetatable, a, {}) == false)
+a.name = "gororoba"
+assert(tostring(a) == "gororoba")
+
+local a, t = {10,20,30; x="10", y="20"}, {}
+assert(setmetatable(a,t) == a)
+assert(getmetatable(a) == t)
+assert(setmetatable(a,nil) == a)
+assert(getmetatable(a) == nil)
+assert(setmetatable(a,t) == a)
+
+
+function f (t, i, e)
+ assert(not e)
+ local p = rawget(t, "parent")
+ return (p and p[i]+3), "dummy return"
+end
+
+t.__index = f
+
+a.parent = {z=25, x=12, [4] = 24}
+assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10")
+
+collectgarbage()
+
+a = setmetatable({}, t)
+function f(t, i, v) rawset(t, i, v-3) end
+t.__newindex = f
+a[1] = 30; a.x = "101"; a[5] = 200
+assert(a[1] == 27 and a.x == 98 and a[5] == 197)
+
+
+local c = {}
+a = setmetatable({}, t)
+t.__newindex = c
+a[1] = 10; a[2] = 20; a[3] = 90
+assert(c[1] == 10 and c[2] == 20 and c[3] == 90)
+
+
+do
+ local a;
+ a = setmetatable({}, {__index = setmetatable({},
+ {__index = setmetatable({},
+ {__index = function (_,n) return a[n-3]+4, "lixo" end})})})
+ a[0] = 20
+ for i=0,10 do
+ assert(a[i*3] == 20 + i*4)
+ end
+end
+
+
+do -- newindex
+ local foi
+ local a = {}
+ for i=1,10 do a[i] = 0; a['a'..i] = 0; end
+ setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end})
+ foi = false; a[1]=0; assert(not foi)
+ foi = false; a['a1']=0; assert(not foi)
+ foi = false; a['a11']=0; assert(foi)
+ foi = false; a[11]=0; assert(foi)
+ foi = false; a[1]=nil; assert(not foi)
+ foi = false; a[1]=nil; assert(foi)
+end
+
+
+function f (t, ...) return t, {...} end
+t.__call = f
+
+do
+ local x,y = a(unpack{'a', 1})
+ assert(x==a and y[1]=='a' and y[2]==1 and y[3]==nil)
+ x,y = a()
+ assert(x==a and y[1]==nil)
+end
+
+
+local b = setmetatable({}, t)
+setmetatable(b,t)
+
+function f(op)
+ return function (...) cap = {[0] = op, ...} ; return (...) end
+end
+t.__add = f("add")
+t.__sub = f("sub")
+t.__mul = f("mul")
+t.__div = f("div")
+t.__mod = f("mod")
+t.__unm = f("unm")
+t.__pow = f("pow")
+
+assert(b+5 == b)
+assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==nil)
+assert(b+'5' == b)
+assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==nil)
+assert(5+b == 5)
+assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==nil)
+assert('5'+b == '5')
+assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==nil)
+b=b-3; assert(getmetatable(b) == t)
+assert(5-a == 5)
+assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==nil)
+assert('5'-a == '5')
+assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==nil)
+assert(a*a == a)
+assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==nil)
+assert(a/0 == a)
+assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==nil)
+assert(a%2 == a)
+assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==nil)
+assert(-a == a)
+assert(cap[0] == "unm" and cap[1] == a)
+assert(a^4 == a)
+assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==nil)
+assert(a^'4' == a)
+assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==nil)
+assert(4^a == 4)
+assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==nil)
+assert('4'^a == '4')
+assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==nil)
+
+
+t = {}
+t.__lt = function (a,b,c)
+ collectgarbage()
+ assert(c == nil)
+ if type(a) == 'table' then a = a.x end
+ if type(b) == 'table' then b = b.x end
+ return a<b, "dummy"
+end
+
+function Op(x) return setmetatable({x=x}, t) end
+
+local function test ()
+ assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1)))
+ assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a')))
+ assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1)))
+ assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a')))
+ assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1)))
+ assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a')))
+ assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1)))
+ assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a')))
+end
+
+test()
+
+t.__le = function (a,b,c)
+ assert(c == nil)
+ if type(a) == 'table' then a = a.x end
+ if type(b) == 'table' then b = b.x end
+ return a<=b, "dummy"
+end
+
+test() -- retest comparisons, now using both `lt' and `le'
+
+
+-- test `partial order'
+
+local function Set(x)
+ local y = {}
+ for _,k in pairs(x) do y[k] = 1 end
+ return setmetatable(y, t)
+end
+
+t.__lt = function (a,b)
+ for k in pairs(a) do
+ if not b[k] then return false end
+ b[k] = nil
+ end
+ return next(b) ~= nil
+end
+
+t.__le = nil
+
+assert(Set{1,2,3} < Set{1,2,3,4})
+assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
+assert((Set{1,2,3,4} <= Set{1,2,3,4}))
+assert((Set{1,2,3,4} >= Set{1,2,3,4}))
+assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-)
+
+t.__le = function (a,b)
+ for k in pairs(a) do
+ if not b[k] then return false end
+ end
+ return true
+end
+
+assert(not (Set{1,3} <= Set{3,5})) -- now its OK!
+assert(not(Set{1,3} <= Set{3,5}))
+assert(not(Set{1,3} >= Set{3,5}))
+
+t.__eq = function (a,b)
+ for k in pairs(a) do
+ if not b[k] then return false end
+ b[k] = nil
+ end
+ return next(b) == nil
+end
+
+local s = Set{1,3,5}
+assert(s == Set{3,5,1})
+assert(not rawequal(s, Set{3,5,1}))
+assert(rawequal(s, s))
+assert(Set{1,3,5,1} == Set{3,5,1})
+assert(Set{1,3,5} ~= Set{3,5,1,6})
+t[Set{1,3,5}] = 1
+assert(t[Set{1,3,5}] == nil) -- `__eq' is not valid for table accesses
+
+
+t.__concat = function (a,b,c)
+ assert(c == nil)
+ if type(a) == 'table' then a = a.val end
+ if type(b) == 'table' then b = b.val end
+ if A then return a..b
+ else
+ return setmetatable({val=a..b}, t)
+ end
+end
+
+c = {val="c"}; setmetatable(c, t)
+d = {val="d"}; setmetatable(d, t)
+
+A = true
+assert(c..d == 'cd')
+assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g")
+
+A = false
+x = c..d
+assert(getmetatable(x) == t and x.val == 'cd')
+x = 0 .."a".."b"..c..d.."e".."f".."g"
+assert(x.val == "0abcdefg")
+
+
+-- test comparison compatibilities
+local t1, t2, c, d
+t1 = {}; c = {}; setmetatable(c, t1)
+d = {}
+t1.__eq = function () return true end
+t1.__lt = function () return true end
+assert(c ~= d and not pcall(function () return c < d end))
+setmetatable(d, t1)
+assert(c == d and c < d and not(d <= c))
+t2 = {}
+t2.__eq = t1.__eq
+t2.__lt = t1.__lt
+setmetatable(d, t2)
+assert(c == d and c < d and not(d <= c))
+
+
+
+-- test for several levels of calls
+local i
+local tt = {
+ __call = function (t, ...)
+ i = i+1
+ if t.f then return t.f(...)
+ else return {...}
+ end
+ end
+}
+
+local a = setmetatable({}, tt)
+local b = setmetatable({f=a}, tt)
+local c = setmetatable({f=b}, tt)
+
+i = 0
+x = c(3,4,5)
+assert(i == 3 and x[1] == 3 and x[3] == 5)
+
+
+assert(_G.X == 20)
+assert(_G == getfenv(0))
+
+print'+'
+
+local _g = _G
+setfenv(1, setmetatable({}, {__index=function (_,k) return _g[k] end}))
+
+-- testing proxies
+assert(getmetatable(newproxy()) == nil)
+assert(getmetatable(newproxy(false)) == nil)
+
+local u = newproxy(true)
+
+getmetatable(u).__newindex = function (u,k,v)
+ getmetatable(u)[k] = v
+end
+
+getmetatable(u).__index = function (u,k)
+ return getmetatable(u)[k]
+end
+
+for i=1,10 do u[i] = i end
+for i=1,10 do assert(u[i] == i) end
+
+local k = newproxy(u)
+assert(getmetatable(k) == getmetatable(u))
+
+
+a = {}
+rawset(a, "x", 1, 2, 3)
+assert(a.x == 1 and rawget(a, "x", 3) == 1)
+
+print '+'
+
+-- testing metatables for basic types
+mt = {}
+debug.setmetatable(10, mt)
+assert(getmetatable(-2) == mt)
+mt.__index = function (a,b) return a+b end
+assert((10)[3] == 13)
+assert((10)["3"] == 13)
+debug.setmetatable(23, nil)
+assert(getmetatable(-2) == nil)
+
+debug.setmetatable(true, mt)
+assert(getmetatable(false) == mt)
+mt.__index = function (a,b) return a or b end
+assert((true)[false] == true)
+assert((false)[false] == false)
+debug.setmetatable(false, nil)
+assert(getmetatable(true) == nil)
+
+debug.setmetatable(nil, mt)
+assert(getmetatable(nil) == mt)
+mt.__add = function (a,b) return (a or 0) + (b or 0) end
+assert(10 + nil == 10)
+assert(nil + 23 == 23)
+assert(nil + nil == 0)
+debug.setmetatable(nil, nil)
+assert(getmetatable(nil) == nil)
+
+debug.setmetatable(nil, {})
+
+
+print 'OK'
+
+return 12
diff --git a/test/PUC-Rio-Lua-5.1-tests/files.lua b/test/PUC-Rio-Lua-5.1-tests/files.lua
new file mode 100644
index 00000000..903488ce
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/files.lua
@@ -0,0 +1,324 @@
+
+print('testing i/o')
+
+assert(io.input(io.stdin) == io.stdin)
+assert(io.output(io.stdout) == io.stdout)
+
+
+assert(type(io.input()) == "userdata" and io.type(io.output()) == "file")
+assert(io.type(8) == nil)
+local a = {}; setmetatable(a, {})
+assert(io.type(a) == nil)
+
+local a,b,c = io.open('xuxu_nao_existe')
+assert(not a and type(b) == "string" and type(c) == "number")
+
+a,b,c = io.open('/a/b/c/d', 'w')
+assert(not a and type(b) == "string" and type(c) == "number")
+
+local file = os.tmpname()
+local otherfile = os.tmpname()
+
+assert(os.setlocale('C', 'all'))
+
+io.input(io.stdin); io.output(io.stdout);
+
+os.remove(file)
+assert(loadfile(file) == nil)
+assert(io.open(file) == nil)
+io.output(file)
+assert(io.output() ~= io.stdout)
+
+assert(io.output():seek() == 0)
+assert(io.write("alo alo"))
+assert(io.output():seek() == string.len("alo alo"))
+assert(io.output():seek("cur", -3) == string.len("alo alo")-3)
+assert(io.write("joao"))
+assert(io.output():seek("end") == string.len("alo joao"))
+
+assert(io.output():seek("set") == 0)
+
+assert(io.write('"álo"', "{a}\n", "second line\n", "third line \n"))
+assert(io.write('çfourth_line'))
+io.output(io.stdout)
+collectgarbage() -- file should be closed by GC
+assert(io.input() == io.stdin and rawequal(io.output(), io.stdout))
+print('+')
+
+-- test GC for files
+collectgarbage()
+for i=1,120 do
+ for i=1,5 do
+ io.input(file)
+ assert(io.open(file, 'r'))
+ io.lines(file)
+ end
+ collectgarbage()
+end
+
+assert(os.rename(file, otherfile))
+assert(os.rename(file, otherfile) == nil)
+
+io.output(io.open(otherfile, "a"))
+assert(io.write("\n\n\t\t 3450\n"));
+io.close()
+
+-- test line generators
+assert(os.rename(otherfile, file))
+io.output(otherfile)
+local f = io.lines(file)
+while f() do end;
+assert(not pcall(f)) -- read lines after EOF
+assert(not pcall(f)) -- read lines after EOF
+-- copy from file to otherfile
+for l in io.lines(file) do io.write(l, "\n") end
+io.close()
+-- copy from otherfile back to file
+local f = assert(io.open(otherfile))
+assert(io.type(f) == "file")
+io.output(file)
+assert(io.output():read() == nil)
+for l in f:lines() do io.write(l, "\n") end
+assert(f:close()); io.close()
+assert(not pcall(io.close, f)) -- error trying to close again
+assert(tostring(f) == "file (closed)")
+assert(io.type(f) == "closed file")
+io.input(file)
+f = io.open(otherfile):lines()
+for l in io.lines() do assert(l == f()) end
+assert(os.remove(otherfile))
+
+io.input(file)
+do -- test error returns
+ local a,b,c = io.input():write("xuxu")
+ assert(not a and type(b) == "string" and type(c) == "number")
+end
+assert(io.read(0) == "") -- not eof
+assert(io.read(5, '*l') == '"álo"')
+assert(io.read(0) == "")
+assert(io.read() == "second line")
+local x = io.input():seek()
+assert(io.read() == "third line ")
+assert(io.input():seek("set", x))
+assert(io.read('*l') == "third line ")
+assert(io.read(1) == "ç")
+assert(io.read(string.len"fourth_line") == "fourth_line")
+assert(io.input():seek("cur", -string.len"fourth_line"))
+assert(io.read() == "fourth_line")
+assert(io.read() == "") -- empty line
+assert(io.read('*n') == 3450)
+assert(io.read(1) == '\n')
+assert(io.read(0) == nil) -- end of file
+assert(io.read(1) == nil) -- end of file
+assert(({io.read(1)})[2] == nil)
+assert(io.read() == nil) -- end of file
+assert(({io.read()})[2] == nil)
+assert(io.read('*n') == nil) -- end of file
+assert(({io.read('*n')})[2] == nil)
+assert(io.read('*a') == '') -- end of file (OK for `*a')
+assert(io.read('*a') == '') -- end of file (OK for `*a')
+collectgarbage()
+print('+')
+io.close(io.input())
+assert(not pcall(io.read))
+
+assert(os.remove(file))
+
+local t = '0123456789'
+for i=1,12 do t = t..t; end
+assert(string.len(t) == 10*2^12)
+
+io.output(file)
+io.write("alo\n")
+io.close()
+assert(not pcall(io.write))
+local f = io.open(file, "a")
+io.output(f)
+collectgarbage()
+
+assert(io.write(' ' .. t .. ' '))
+assert(io.write(';', 'end of file\n'))
+f:flush(); io.flush()
+f:close()
+print('+')
+
+io.input(file)
+assert(io.read() == "alo")
+assert(io.read(1) == ' ')
+assert(io.read(string.len(t)) == t)
+assert(io.read(1) == ' ')
+assert(io.read(0))
+assert(io.read('*a') == ';end of file\n')
+assert(io.read(0) == nil)
+assert(io.close(io.input()))
+
+assert(os.remove(file))
+print('+')
+
+local x1 = "string\n\n\\com \"\"''coisas [[estranhas]] ]]'"
+io.output(file)
+assert(io.write(string.format("x2 = %q\n-- comment without ending EOS", x1)))
+io.close()
+assert(loadfile(file))()
+assert(x1 == x2)
+print('+')
+assert(os.remove(file))
+assert(os.remove(file) == nil)
+assert(os.remove(otherfile) == nil)
+
+io.output(file)
+assert(io.write("qualquer coisa\n"))
+assert(io.write("mais qualquer coisa"))
+io.close()
+io.output(assert(io.open(otherfile, 'wb')))
+assert(io.write("outra coisa\0\1\3\0\0\0\0\255\0"))
+io.close()
+
+local filehandle = assert(io.open(file, 'r'))
+local otherfilehandle = assert(io.open(otherfile, 'rb'))
+assert(filehandle ~= otherfilehandle)
+assert(type(filehandle) == "userdata")
+assert(filehandle:read('*l') == "qualquer coisa")
+io.input(otherfilehandle)
+assert(io.read(string.len"outra coisa") == "outra coisa")
+assert(filehandle:read('*l') == "mais qualquer coisa")
+filehandle:close();
+assert(type(filehandle) == "userdata")
+io.input(otherfilehandle)
+assert(io.read(4) == "\0\1\3\0")
+assert(io.read(3) == "\0\0\0")
+assert(io.read(0) == "") -- 255 is not eof
+assert(io.read(1) == "\255")
+assert(io.read('*a') == "\0")
+assert(not io.read(0))
+assert(otherfilehandle == io.input())
+otherfilehandle:close()
+assert(os.remove(file))
+assert(os.remove(otherfile))
+collectgarbage()
+
+io.output(file)
+io.write[[
+ 123.4 -56e-2 not a number
+second line
+third line
+
+and the rest of the file
+]]
+io.close()
+io.input(file)
+local _,a,b,c,d,e,h,__ = io.read(1, '*n', '*n', '*l', '*l', '*l', '*a', 10)
+assert(io.close(io.input()))
+assert(_ == ' ' and __ == nil)
+assert(type(a) == 'number' and a==123.4 and b==-56e-2)
+assert(d=='second line' and e=='third line')
+assert(h==[[
+
+and the rest of the file
+]])
+assert(os.remove(file))
+collectgarbage()
+
+-- testing buffers
+do
+ local f = assert(io.open(file, "w"))
+ local fr = assert(io.open(file, "r"))
+ assert(f:setvbuf("full", 2000))
+ f:write("x")
+ assert(fr:read("*all") == "") -- full buffer; output not written yet
+ f:close()
+ fr:seek("set")
+ assert(fr:read("*all") == "x") -- `close' flushes it
+ f = assert(io.open(file), "w")
+ assert(f:setvbuf("no"))
+ f:write("x")
+ fr:seek("set")
+ assert(fr:read("*all") == "x") -- no buffer; output is ready
+ f:close()
+ f = assert(io.open(file, "a"))
+ assert(f:setvbuf("line"))
+ f:write("x")
+ fr:seek("set", 1)
+ assert(fr:read("*all") == "") -- line buffer; no output without `\n'
+ f:write("a\n")
+ fr:seek("set", 1)
+ assert(fr:read("*all") == "xa\n") -- now we have a whole line
+ f:close(); fr:close()
+end
+
+
+-- testing large files (> BUFSIZ)
+io.output(file)
+for i=1,5001 do io.write('0123456789123') end
+io.write('\n12346')
+io.close()
+io.input(file)
+local x = io.read('*a')
+io.input():seek('set', 0)
+local y = io.read(30001)..io.read(1005)..io.read(0)..io.read(1)..io.read(100003)
+assert(x == y and string.len(x) == 5001*13 + 6)
+io.input():seek('set', 0)
+y = io.read() -- huge line
+assert(x == y..'\n'..io.read())
+assert(io.read() == nil)
+io.close(io.input())
+assert(os.remove(file))
+x = nil; y = nil
+
+x, y = pcall(io.popen, "ls")
+if x then
+ assert(y:read("*a"))
+ assert(y:close())
+else
+ (Message or print)('\a\n >>> popen not available<<<\n\a')
+end
+
+print'+'
+
+local t = os.time()
+T = os.date("*t", t)
+loadstring(os.date([[assert(T.year==%Y and T.month==%m and T.day==%d and
+ T.hour==%H and T.min==%M and T.sec==%S and
+ T.wday==%w+1 and T.yday==%j and type(T.isdst) == 'boolean')]], t))()
+
+assert(os.time(T) == t)
+
+T = os.date("!*t", t)
+loadstring(os.date([[!assert(T.year==%Y and T.month==%m and T.day==%d and
+ T.hour==%H and T.min==%M and T.sec==%S and
+ T.wday==%w+1 and T.yday==%j and type(T.isdst) == 'boolean')]], t))()
+
+do
+ local T = os.date("*t")
+ local t = os.time(T)
+ assert(type(T.isdst) == 'boolean')
+ T.isdst = nil
+ local t1 = os.time(T)
+ assert(t == t1) -- if isdst is absent uses correct default
+end
+
+t = os.time(T)
+T.year = T.year-1;
+local t1 = os.time(T)
+-- allow for leap years
+assert(math.abs(os.difftime(t,t1)/(24*3600) - 365) < 2)
+
+t = os.time()
+t1 = os.time(os.date("*t"))
+assert(os.difftime(t1,t) <= 2)
+
+local t1 = os.time{year=2000, month=10, day=1, hour=23, min=12, sec=17}
+local t2 = os.time{year=2000, month=10, day=1, hour=23, min=10, sec=19}
+assert(os.difftime(t1,t2) == 60*2-2)
+
+io.output(io.stdout)
+local d = os.date('%d')
+local m = os.date('%m')
+local a = os.date('%Y')
+local ds = os.date('%w') + 1
+local h = os.date('%H')
+local min = os.date('%M')
+local s = os.date('%S')
+io.write(string.format('test done on %2.2d/%2.2d/%d', d, m, a))
+io.write(string.format(', at %2.2d:%2.2d:%2.2d\n', h, min, s))
+io.write(string.format('%s\n', _VERSION))
diff --git a/test/PUC-Rio-Lua-5.1-tests/gc.lua b/test/PUC-Rio-Lua-5.1-tests/gc.lua
new file mode 100644
index 00000000..86a9f758
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/gc.lua
@@ -0,0 +1,312 @@
+print('testing garbage collection')
+
+collectgarbage()
+
+_G["while"] = 234
+
+limit = 5000
+
+
+
+contCreate = 0
+
+print('tables')
+while contCreate <= limit do
+ local a = {}; a = nil
+ contCreate = contCreate+1
+end
+
+a = "a"
+
+contCreate = 0
+print('strings')
+while contCreate <= limit do
+ a = contCreate .. "b";
+ a = string.gsub(a, '(%d%d*)', string.upper)
+ a = "a"
+ contCreate = contCreate+1
+end
+
+
+contCreate = 0
+
+a = {}
+
+print('functions')
+function a:test ()
+ while contCreate <= limit do
+ loadstring(string.format("function temp(a) return 'a%d' end", contCreate))()
+ assert(temp() == string.format('a%d', contCreate))
+ contCreate = contCreate+1
+ end
+end
+
+a:test()
+
+-- collection of functions without locals, globals, etc.
+do local f = function () end end
+
+
+print("functions with errors")
+prog = [[
+do
+ a = 10;
+ function foo(x,y)
+ a = sin(a+0.456-0.23e-12);
+ return function (z) return sin(%x+z) end
+ end
+ local x = function (w) a=a+w; end
+end
+]]
+do
+ local step = 1
+ if rawget(_G, "_soft") then step = 13 end
+ for i=1, string.len(prog), step do
+ for j=i, string.len(prog), step do
+ pcall(loadstring(string.sub(prog, i, j)))
+ end
+ end
+end
+
+print('long strings')
+x = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"
+assert(string.len(x)==80)
+s = ''
+n = 0
+k = 300
+while n < k do s = s..x; n=n+1; j=tostring(n) end
+assert(string.len(s) == k*80)
+s = string.sub(s, 1, 20000)
+s, i = string.gsub(s, '(%d%d%d%d)', math.sin)
+assert(i==20000/4)
+s = nil
+x = nil
+
+assert(_G["while"] == 234)
+
+
+local bytes = gcinfo()
+while 1 do
+ local nbytes = gcinfo()
+ if nbytes < bytes then break end -- run until gc
+ bytes = nbytes
+ a = {}
+end
+
+
+local function dosteps (siz)
+ collectgarbage()
+ collectgarbage"stop"
+ local a = {}
+ for i=1,100 do a[i] = {{}}; local b = {} end
+ local x = gcinfo()
+ local i = 0
+ repeat
+ i = i+1
+ until collectgarbage("step", siz)
+ assert(gcinfo() < x)
+ return i
+end
+
+assert(dosteps(0) > 10)
+assert(dosteps(6) < dosteps(2))
+assert(dosteps(10000) == 1)
+assert(collectgarbage("step", 1000000) == true)
+assert(collectgarbage("step", 1000000))
+
+
+do
+ local x = gcinfo()
+ collectgarbage()
+ collectgarbage"stop"
+ repeat
+ local a = {}
+ until gcinfo() > 1000
+ collectgarbage"restart"
+ repeat
+ local a = {}
+ until gcinfo() < 1000
+end
+
+lim = 15
+a = {}
+-- fill a with `collectable' indices
+for i=1,lim do a[{}] = i end
+b = {}
+for k,v in pairs(a) do b[k]=v end
+-- remove all indices and collect them
+for n in pairs(b) do
+ a[n] = nil
+ assert(type(n) == 'table' and next(n) == nil)
+ collectgarbage()
+end
+b = nil
+collectgarbage()
+for n in pairs(a) do error'cannot be here' end
+for i=1,lim do a[i] = i end
+for i=1,lim do assert(a[i] == i) end
+
+
+print('weak tables')
+a = {}; setmetatable(a, {__mode = 'k'});
+-- fill a with some `collectable' indices
+for i=1,lim do a[{}] = i end
+-- and some non-collectable ones
+for i=1,lim do local t={}; a[t]=t end
+for i=1,lim do a[i] = i end
+for i=1,lim do local s=string.rep('@', i); a[s] = s..'#' end
+collectgarbage()
+local i = 0
+for k,v in pairs(a) do assert(k==v or k..'#'==v); i=i+1 end
+assert(i == 3*lim)
+
+a = {}; setmetatable(a, {__mode = 'v'});
+a[1] = string.rep('b', 21)
+collectgarbage()
+assert(a[1]) -- strings are *values*
+a[1] = nil
+-- fill a with some `collectable' values (in both parts of the table)
+for i=1,lim do a[i] = {} end
+for i=1,lim do a[i..'x'] = {} end
+-- and some non-collectable ones
+for i=1,lim do local t={}; a[t]=t end
+for i=1,lim do a[i+lim]=i..'x' end
+collectgarbage()
+local i = 0
+for k,v in pairs(a) do assert(k==v or k-lim..'x' == v); i=i+1 end
+assert(i == 2*lim)
+
+a = {}; setmetatable(a, {__mode = 'vk'});
+local x, y, z = {}, {}, {}
+-- keep only some items
+a[1], a[2], a[3] = x, y, z
+a[string.rep('$', 11)] = string.rep('$', 11)
+-- fill a with some `collectable' values
+for i=4,lim do a[i] = {} end
+for i=1,lim do a[{}] = i end
+for i=1,lim do local t={}; a[t]=t end
+collectgarbage()
+assert(next(a) ~= nil)
+local i = 0
+for k,v in pairs(a) do
+ assert((k == 1 and v == x) or
+ (k == 2 and v == y) or
+ (k == 3 and v == z) or k==v);
+ i = i+1
+end
+assert(i == 4)
+x,y,z=nil
+collectgarbage()
+assert(next(a) == string.rep('$', 11))
+
+
+-- testing userdata
+collectgarbage("stop") -- stop collection
+local u = newproxy(true)
+local s = 0
+local a = {[u] = 0}; setmetatable(a, {__mode = 'vk'})
+for i=1,10 do a[newproxy(u)] = i end
+for k in pairs(a) do assert(getmetatable(k) == getmetatable(u)) end
+local a1 = {}; for k,v in pairs(a) do a1[k] = v end
+for k,v in pairs(a1) do a[v] = k end
+for i =1,10 do assert(a[i]) end
+getmetatable(u).a = a1
+getmetatable(u).u = u
+do
+ local u = u
+ getmetatable(u).__gc = function (o)
+ assert(a[o] == 10-s)
+ assert(a[10-s] == nil) -- udata already removed from weak table
+ assert(getmetatable(o) == getmetatable(u))
+ assert(getmetatable(o).a[o] == 10-s)
+ s=s+1
+ end
+end
+a1, u = nil
+assert(next(a) ~= nil)
+collectgarbage()
+assert(s==11)
+collectgarbage()
+assert(next(a) == nil) -- finalized keys are removed in two cycles
+
+
+-- __gc x weak tables
+local u = newproxy(true)
+setmetatable(getmetatable(u), {__mode = "v"})
+getmetatable(u).__gc = function (o) os.exit(1) end -- cannot happen
+collectgarbage()
+
+local u = newproxy(true)
+local m = getmetatable(u)
+m.x = {[{0}] = 1; [0] = {1}}; setmetatable(m.x, {__mode = "kv"});
+m.__gc = function (o)
+ assert(next(getmetatable(o).x) == nil)
+ m = 10
+end
+u, m = nil
+collectgarbage()
+assert(m==10)
+
+
+-- errors during collection
+u = newproxy(true)
+getmetatable(u).__gc = function () error "!!!" end
+u = nil
+assert(not pcall(collectgarbage))
+
+
+if not rawget(_G, "_soft") then
+ print("deep structures")
+ local a = {}
+ for i = 1,200000 do
+ a = {next = a}
+ end
+ collectgarbage()
+end
+
+-- create many threads with self-references and open upvalues
+local thread_id = 0
+local threads = {}
+
+function fn(thread)
+ local x = {}
+ threads[thread_id] = function()
+ thread = x
+ end
+ coroutine.yield()
+end
+
+while thread_id < 1000 do
+ local thread = coroutine.create(fn)
+ coroutine.resume(thread, thread)
+ thread_id = thread_id + 1
+end
+
+
+
+-- create a userdata to be collected when state is closed
+do
+ local newproxy,assert,type,print,getmetatable =
+ newproxy,assert,type,print,getmetatable
+ local u = newproxy(true)
+ local tt = getmetatable(u)
+ ___Glob = {u} -- avoid udata being collected before program end
+ tt.__gc = function (o)
+ assert(getmetatable(o) == tt)
+ -- create new objects during GC
+ local a = 'xuxu'..(10+3)..'joao', {}
+ ___Glob = o -- ressurect object!
+ newproxy(o) -- creates a new one with same metatable
+ print(">>> closing state " .. "<<<\n")
+ end
+end
+
+-- create several udata to raise errors when collected while closing state
+do
+ local u = newproxy(true)
+ getmetatable(u).__gc = function (o) return o + 1 end
+ table.insert(___Glob, u) -- preserve udata until the end
+ for i = 1,10 do table.insert(___Glob, newproxy(u)) end
+end
+
+print('OK')
diff --git a/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt b/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt
new file mode 100644
index 00000000..f24e7f30
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Test suite that has been added from PUC-Rio Lua 5.1 test archive
+# in scope of https://github.com/tarantool/tarantool/issues/5845.
+
+# See the rationale in the root CMakeLists.txt.
+cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
+
+# The original tarball contains subdirectory "libs" with an empty
+# subdirectory "libs/P1", to be used by tests.
+# Instead of tracking empty directory with some anchor-file for
+# git, create this directory via CMake.
+add_custom_target(PUC-Lua-5.1-tests-prepare)
+add_custom_command(TARGET PUC-Lua-5.1-tests-prepare
+ COMMENT "Create directory for PUC-Rio Lua 5.1 tests"
+ COMMAND ${CMAKE_COMMAND} -E make_directory P1
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+# vim: expandtab tabstop=2 shiftwidth=2
diff --git a/test/PUC-Rio-Lua-5.1-tests/libs/lib1.c b/test/PUC-Rio-Lua-5.1-tests/libs/lib1.c
new file mode 100644
index 00000000..812bb9ac
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/libs/lib1.c
@@ -0,0 +1,40 @@
+/*
+** compile with
+** Linux: gcc -Wall -O2 -I.. -ansi -shared -o lib1.so lib1.c
+** Mac OS X: export MACOSX_DEPLOYMENT_TARGET=10.3
+** gcc -bundle -undefined dynamic_lookup -Wall -O2 -o lib1.so lib1.c
+*/
+
+
+#include "lua.h"
+#include "lauxlib.h"
+
+static int id (lua_State *L) {
+ return lua_gettop(L);
+}
+
+
+static const struct luaL_reg funcs[] = {
+ {"id", id},
+ {NULL, NULL}
+};
+
+
+int anotherfunc (lua_State *L) {
+ lua_pushfstring(L, "%f%f\n", lua_tonumber(L, 1), lua_tonumber(L, 2));
+ return 1;
+}
+
+
+int luaopen_lib1_sub (lua_State *L) {
+ luaL_register(L, "lib1.sub", funcs + 1);
+ return 1;
+}
+
+
+int luaopen_lib1 (lua_State *L) {
+ luaL_register(L, "lib1", funcs);
+ return 1;
+}
+
+
diff --git a/test/PUC-Rio-Lua-5.1-tests/libs/lib11.c b/test/PUC-Rio-Lua-5.1-tests/libs/lib11.c
new file mode 100644
index 00000000..3efa3d3e
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/libs/lib11.c
@@ -0,0 +1,18 @@
+/*
+** compile with
+** Linux: gcc -Wall -O2 -I.. -ansi -shared -o lib1.so lib1.c
+** Mac OS X: export MACOSX_DEPLOYMENT_TARGET=10.3
+** gcc -bundle -undefined dynamic_lookup -Wall -O2 -o lib1.so lib1.c
+*/
+
+
+#include "lua.h"
+
+
+int luaopen_lib1 (lua_State *L);
+
+int luaopen_lib11 (lua_State *L) {
+ return luaopen_lib1(L);
+}
+
+
diff --git a/test/PUC-Rio-Lua-5.1-tests/libs/lib2.c b/test/PUC-Rio-Lua-5.1-tests/libs/lib2.c
new file mode 100644
index 00000000..9972cbe4
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/libs/lib2.c
@@ -0,0 +1,28 @@
+/*
+** compile with
+** gcc -Wall -O2 -I.. -ansi -shared -o lib1.so lib1.c
+*/
+
+
+#include "lua.h"
+#include "lauxlib.h"
+
+static int id (lua_State *L) {
+ return lua_gettop(L);
+}
+
+
+static const struct luaL_reg funcs[] = {
+ {"id", id},
+ {NULL, NULL}
+};
+
+
+int luaopen_lib2 (lua_State *L) {
+ luaL_register(L, "lib2", funcs);
+ lua_pushnumber(L, 0.5);
+ lua_setglobal(L, "x");
+ return 1;
+}
+
+
diff --git a/test/PUC-Rio-Lua-5.1-tests/libs/lib21.c b/test/PUC-Rio-Lua-5.1-tests/libs/lib21.c
new file mode 100644
index 00000000..167507f9
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/libs/lib21.c
@@ -0,0 +1,18 @@
+/*
+** compile with
+** Linux: gcc -Wall -O2 -I.. -ansi -shared -o lib1.so lib1.c
+** Mac OS X: export MACOSX_DEPLOYMENT_TARGET=10.3
+** gcc -bundle -undefined dynamic_lookup -Wall -O2 -o lib1.so lib1.c
+*/
+
+
+#include "lua.h"
+
+
+int luaopen_lib2 (lua_State *L);
+
+int luaopen_lib21 (lua_State *L) {
+ return luaopen_lib2(L);
+}
+
+
diff --git a/test/PUC-Rio-Lua-5.1-tests/literals.lua b/test/PUC-Rio-Lua-5.1-tests/literals.lua
new file mode 100644
index 00000000..01d84d5a
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/literals.lua
@@ -0,0 +1,176 @@
+print('testing scanner')
+
+local function dostring (x) return assert(loadstring(x))() end
+
+dostring("x = 'a\0a'")
+assert(x == 'a\0a' and string.len(x) == 3)
+
+-- escape sequences
+assert('\n\"\'\\' == [[
+
+"'\]])
+
+assert(string.find("\a\b\f\n\r\t\v", "^%c%c%c%c%c%c%c$"))
+
+-- assume ASCII just for tests:
+assert("\09912" == 'c12')
+assert("\99ab" == 'cab')
+assert("\099" == '\99')
+assert("\099\n" == 'c\10')
+assert('\0\0\0alo' == '\0' .. '\0\0' .. 'alo')
+
+assert(010 .. 020 .. -030 == "1020-30")
+
+-- long variable names
+
+var = string.rep('a', 15000)
+prog = string.format("%s = 5", var)
+dostring(prog)
+assert(_G[var] == 5)
+var = nil
+print('+')
+
+-- escapes --
+assert("\n\t" == [[
+
+ ]])
+assert([[
+
+ $debug]] == "\n $debug")
+assert([[ [ ]] ~= [[ ] ]])
+-- long strings --
+b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
+assert(string.len(b) == 960)
+prog = [=[
+print('+')
+
+a1 = [["isto e' um string com várias 'aspas'"]]
+a2 = "'aspas'"
+
+assert(string.find(a1, a2) == 31)
+print('+')
+
+a1 = [==[temp = [[um valor qualquer]]; ]==]
+assert(loadstring(a1))()
+assert(temp == 'um valor qualquer')
+-- long strings --
+b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
+assert(string.len(b) == 960)
+print('+')
+
+a = [[00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+]]
+assert(string.len(a) == 1863)
+assert(string.sub(a, 1, 40) == string.sub(b, 1, 40))
+x = 1
+]=]
+
+print('+')
+x = nil
+dostring(prog)
+assert(x)
+
+prog = nil
+a = nil
+b = nil
+
+
+-- testing line ends
+prog = [[
+a = 1 -- a comment
+b = 2
+
+
+x = [=[
+hi
+]=]
+y = "\
+hello\r\n\
+"
+return debug.getinfo(1).currentline
+]]
+
+for _, n in pairs{"\n", "\r", "\n\r", "\r\n"} do
+ local prog, nn = string.gsub(prog, "\n", n)
+ assert(dostring(prog) == nn)
+ assert(_G.x == "hi\n" and _G.y == "\nhello\r\n\n")
+end
+
+
+-- testing comments and strings with long brackets
+a = [==[]=]==]
+assert(a == "]=")
+
+a = [==[[===[[=[]]=][====[]]===]===]==]
+assert(a == "[===[[=[]]=][====[]]===]===")
+
+a = [====[[===[[=[]]=][====[]]===]===]====]
+assert(a == "[===[[=[]]=][====[]]===]===")
+
+a = [=[]]]]]]]]]=]
+assert(a == "]]]]]]]]")
+
+
+--[===[
+x y z [==[ blu foo
+]==
+]
+]=]==]
+error error]=]===]
+
+-- generate all strings of four of these chars
+local x = {"=", "[", "]", "\n"}
+local len = 4
+local function gen (c, n)
+ if n==0 then coroutine.yield(c)
+ else
+ for _, a in pairs(x) do
+ gen(c..a, n-1)
+ end
+ end
+end
+
+for s in coroutine.wrap(function () gen("", len) end) do
+ assert(s == loadstring("return [====[\n"..s.."]====]")())
+end
+
+
+-- testing decimal point locale
+if os.setlocale("pt_BR") or os.setlocale("ptb") then
+ assert(tonumber("3,4") == 3.4 and tonumber"3.4" == nil)
+ assert(assert(loadstring("return 3.4"))() == 3.4)
+ assert(assert(loadstring("return .4,3"))() == .4)
+ assert(assert(loadstring("return 4."))() == 4.)
+ assert(assert(loadstring("return 4.+.5"))() == 4.5)
+ local a,b = loadstring("return 4.5.")
+ assert(string.find(b, "'4%.5%.'"))
+ assert(os.setlocale("C"))
+else
+ (Message or print)(
+ '\a\n >>> pt_BR locale not available: skipping decimal point tests <<<\n\a')
+end
+
+
+print('OK')
diff --git a/test/PUC-Rio-Lua-5.1-tests/locals.lua b/test/PUC-Rio-Lua-5.1-tests/locals.lua
new file mode 100644
index 00000000..011645af
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/locals.lua
@@ -0,0 +1,127 @@
+print('testing local variables plus some extra stuff')
+
+do
+ local i = 10
+ do local i = 100; assert(i==100) end
+ do local i = 1000; assert(i==1000) end
+ assert(i == 10)
+ if i ~= 10 then
+ local i = 20
+ else
+ local i = 30
+ assert(i == 30)
+ end
+end
+
+
+
+f = nil
+
+local f
+x = 1
+
+a = nil
+loadstring('local a = {}')()
+assert(type(a) ~= 'table')
+
+function f (a)
+ local _1, _2, _3, _4, _5
+ local _6, _7, _8, _9, _10
+ local x = 3
+ local b = a
+ local c,d = a,b
+ if (d == b) then
+ local x = 'q'
+ x = b
+ assert(x == 2)
+ else
+ assert(nil)
+ end
+ assert(x == 3)
+ local f = 10
+end
+
+local b=10
+local a; repeat local b; a,b=1,2; assert(a+1==b); until a+b==3
+
+
+assert(x == 1)
+
+f(2)
+assert(type(f) == 'function')
+
+
+-- testing globals ;-)
+do
+ local f = {}
+ local _G = _G
+ for i=1,10 do f[i] = function (x) A=A+1; return A, _G.getfenv(x) end end
+ A=10; assert(f[1]() == 11)
+ for i=1,10 do assert(setfenv(f[i], {A=i}) == f[i]) end
+ assert(f[3]() == 4 and A == 11)
+ local a,b = f[8](1)
+ assert(b.A == 9)
+ a,b = f[8](0)
+ assert(b.A == 11) -- `real' global
+ local g
+ local function f () assert(setfenv(2, {a='10'}) == g) end
+ g = function () f(); _G.assert(_G.getfenv(1).a == '10') end
+ g(); assert(getfenv(g).a == '10')
+end
+
+-- test for global table of loaded chunks
+local function foo (s)
+ return loadstring(s)
+end
+
+assert(getfenv(foo("")) == _G)
+local a = {loadstring = loadstring}
+setfenv(foo, a)
+assert(getfenv(foo("")) == _G)
+setfenv(0, a) -- change global environment
+assert(getfenv(foo("")) == a)
+setfenv(0, _G)
+
+
+-- testing limits for special instructions
+
+local a
+local p = 4
+for i=2,31 do
+ for j=-3,3 do
+ assert(loadstring(string.format([[local a=%s;a=a+
+ %s;
+ assert(a
+ ==2^%s)]], j, p-j, i))) ()
+ assert(loadstring(string.format([[local a=%s;
+ a=a-%s;
+ assert(a==-2^%s)]], -j, p-j, i))) ()
+ assert(loadstring(string.format([[local a,b=0,%s;
+ a=b-%s;
+ assert(a==-2^%s)]], -j, p-j, i))) ()
+ end
+ p =2*p
+end
+
+print'+'
+
+
+if rawget(_G, "querytab") then
+ -- testing clearing of dead elements from tables
+ collectgarbage("stop") -- stop GC
+ local a = {[{}] = 4, [3] = 0, alo = 1,
+ a1234567890123456789012345678901234567890 = 10}
+
+ local t = querytab(a)
+
+ for k,_ in pairs(a) do a[k] = nil end
+ collectgarbage() -- restore GC and collect dead fiels in `a'
+ for i=0,t-1 do
+ local k = querytab(a, i)
+ assert(k == nil or type(k) == 'number' or k == 'alo')
+ end
+end
+
+print('OK')
+
+return 5,f
diff --git a/test/PUC-Rio-Lua-5.1-tests/main.lua b/test/PUC-Rio-Lua-5.1-tests/main.lua
new file mode 100644
index 00000000..f520896a
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/main.lua
@@ -0,0 +1,159 @@
+# testing special comment on first line
+
+print ("testing lua.c options")
+
+assert(os.execute() ~= 0) -- machine has a system command
+
+prog = os.tmpname()
+otherprog = os.tmpname()
+out = os.tmpname()
+
+do
+ local i = 0
+ while arg[i] do i=i-1 end
+ progname = '"'..arg[i+1]..'"'
+end
+print(progname)
+
+local prepfile = function (s, p)
+ p = p or prog
+ io.output(p)
+ io.write(s)
+ assert(io.close())
+end
+
+function checkout (s)
+ io.input(out)
+ local t = io.read("*a")
+ io.input():close()
+ assert(os.remove(out))
+ if s ~= t then print(string.format("'%s' - '%s'\n", s, t)) end
+ assert(s == t)
+ return t
+end
+
+function auxrun (...)
+ local s = string.format(...)
+ s = string.gsub(s, "lua", progname, 1)
+ return os.execute(s)
+end
+
+function RUN (...)
+ assert(auxrun(...) == 0)
+end
+
+function NoRun (...)
+ print("\n(the next error is expected by the test)")
+ assert(auxrun(...) ~= 0)
+end
+
+-- test 2 files
+prepfile("print(1); a=2")
+prepfile("print(a)", otherprog)
+RUN("lua -l %s -l%s -lstring -l io %s > %s", prog, otherprog, otherprog, out)
+checkout("1\n2\n2\n")
+
+local a = [[
+ assert(table.getn(arg) == 3 and arg[1] == 'a' and
+ arg[2] == 'b' and arg[3] == 'c')
+ assert(arg[-1] == '--' and arg[-2] == "-e " and arg[-3] == %s)
+ assert(arg[4] == nil and arg[-4] == nil)
+ local a, b, c = ...
+ assert(... == 'a' and a == 'a' and b == 'b' and c == 'c')
+]]
+a = string.format(a, progname)
+prepfile(a)
+RUN('lua "-e " -- %s a b c', prog)
+
+prepfile"assert(arg==nil)"
+prepfile("assert(arg)", otherprog)
+RUN("lua -l%s - < %s", prog, otherprog)
+
+prepfile""
+RUN("lua - < %s > %s", prog, out)
+checkout("")
+
+-- test many arguments
+prepfile[[print(({...})[30])]]
+RUN("lua %s %s > %s", prog, string.rep(" a", 30), out)
+checkout("a\n")
+
+RUN([[lua "-eprint(1)" -ea=3 -e "print(a)" > %s]], out)
+checkout("1\n3\n")
+
+prepfile[[
+ print(
+1, a
+)
+]]
+RUN("lua - < %s > %s", prog, out)
+checkout("1\tnil\n")
+
+prepfile[[
+= (6*2-6) -- ===
+a
+= 10
+print(a)
+= a]]
+RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
+checkout("6\n10\n10\n\n")
+
+prepfile("a = [[b\nc\nd\ne]]\n=a")
+print(prog)
+RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
+checkout("b\nc\nd\ne\n\n")
+
+prompt = "alo"
+prepfile[[ --
+a = 2
+]]
+RUN([[lua "-e_PROMPT='%s'" -i < %s > %s]], prompt, prog, out)
+checkout(string.rep(prompt, 3).."\n")
+
+s = [=[ --
+function f ( x )
+ local a = [[
+xuxu
+]]
+ local b = "\
+xuxu\n"
+ if x == 11 then return 1 , 2 end --[[ test multiple returns ]]
+ return x + 1
+ --\\
+end
+=( f( 10 ) )
+assert( a == b )
+=f( 11 ) ]=]
+s = string.gsub(s, ' ', '\n\n')
+prepfile(s)
+RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
+checkout("11\n1\t2\n\n")
+
+prepfile[[#comment in 1st line without \n at the end]]
+RUN("lua %s", prog)
+
+prepfile("#comment with a binary file\n"..string.dump(loadstring("print(1)")))
+RUN("lua %s > %s", prog, out)
+checkout("1\n")
+
+prepfile("#comment with a binary file\r\n"..string.dump(loadstring("print(1)")))
+RUN("lua %s > %s", prog, out)
+checkout("1\n")
+
+-- close Lua with an open file
+prepfile(string.format([[io.output(%q); io.write('alo')]], out))
+RUN("lua %s", prog)
+checkout('alo')
+
+assert(os.remove(prog))
+assert(os.remove(otherprog))
+assert(not os.remove(out))
+
+RUN("lua -v")
+
+NoRun("lua -h")
+NoRun("lua -e")
+NoRun("lua -e a")
+NoRun("lua -f")
+
+print("OK")
diff --git a/test/PUC-Rio-Lua-5.1-tests/math.lua b/test/PUC-Rio-Lua-5.1-tests/math.lua
new file mode 100644
index 00000000..5076f38d
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/math.lua
@@ -0,0 +1,208 @@
+print("testing numbers and math lib")
+
+do
+ local a,b,c = "2", " 3e0 ", " 10 "
+ assert(a+b == 5 and -b == -3 and b+"2" == 5 and "10"-c == 0)
+ assert(type(a) == 'string' and type(b) == 'string' and type(c) == 'string')
+ assert(a == "2" and b == " 3e0 " and c == " 10 " and -c == -" 10 ")
+ assert(c%a == 0 and a^b == 8)
+end
+
+
+do
+ local a,b = math.modf(3.5)
+ assert(a == 3 and b == 0.5)
+ assert(math.huge > 10e30)
+ assert(-math.huge < -10e30)
+end
+
+function f(...)
+ if select('#', ...) == 1 then
+ return (...)
+ else
+ return "***"
+ end
+end
+
+assert(tonumber{} == nil)
+assert(tonumber'+0.01' == 1/100 and tonumber'+.01' == 0.01 and
+ tonumber'.01' == 0.01 and tonumber'-1.' == -1 and
+ tonumber'+1.' == 1)
+assert(tonumber'+ 0.01' == nil and tonumber'+.e1' == nil and
+ tonumber'1e' == nil and tonumber'1.0e+' == nil and
+ tonumber'.' == nil)
+assert(tonumber('-12') == -10-2)
+assert(tonumber('-1.2e2') == - - -120)
+assert(f(tonumber('1 a')) == nil)
+assert(f(tonumber('e1')) == nil)
+assert(f(tonumber('e 1')) == nil)
+assert(f(tonumber(' 3.4.5 ')) == nil)
+assert(f(tonumber('')) == nil)
+assert(f(tonumber('', 8)) == nil)
+assert(f(tonumber(' ')) == nil)
+assert(f(tonumber(' ', 9)) == nil)
+assert(f(tonumber('99', 8)) == nil)
+assert(tonumber(' 1010 ', 2) == 10)
+assert(tonumber('10', 36) == 36)
+--assert(tonumber('\n -10 \n', 36) == -36)
+--assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15)))))))
+assert(tonumber('fFfa', 15) == nil)
+--assert(tonumber(string.rep('1', 42), 2) + 1 == 2^42)
+assert(tonumber(string.rep('1', 32), 2) + 1 == 2^32)
+--assert(tonumber('-fffffFFFFF', 16)-1 == -2^40)
+assert(tonumber('ffffFFFF', 16)+1 == 2^32)
+
+assert(1.1 == 1.+.1)
+assert(100.0 == 1E2 and .01 == 1e-2)
+assert(1111111111111111-1111111111111110== 1000.00e-03)
+-- 1234567890123456
+assert(1.1 == '1.'+'.1')
+assert('1111111111111111'-'1111111111111110' == tonumber" +0.001e+3 \n\t")
+
+function eq (a,b,limit)
+ if not limit then limit = 10E-10 end
+ return math.abs(a-b) <= limit
+end
+
+assert(0.1e-30 > 0.9E-31 and 0.9E30 < 0.1e31)
+
+assert(0.123456 > 0.123455)
+
+assert(tonumber('+1.23E30') == 1.23*10^30)
+
+-- testing order operators
+assert(not(1<1) and (1<2) and not(2<1))
+assert(not('a'<'a') and ('a'<'b') and not('b'<'a'))
+assert((1<=1) and (1<=2) and not(2<=1))
+assert(('a'<='a') and ('a'<='b') and not('b'<='a'))
+assert(not(1>1) and not(1>2) and (2>1))
+assert(not('a'>'a') and not('a'>'b') and ('b'>'a'))
+assert((1>=1) and not(1>=2) and (2>=1))
+assert(('a'>='a') and not('a'>='b') and ('b'>='a'))
+
+-- testing mod operator
+assert(-4%3 == 2)
+assert(4%-3 == -2)
+assert(math.pi - math.pi % 1 == 3)
+assert(math.pi - math.pi % 0.001 == 3.141)
+
+local function testbit(a, n)
+ return a/2^n % 2 >= 1
+end
+
+assert(eq(math.sin(-9.8)^2 + math.cos(-9.8)^2, 1))
+assert(eq(math.tan(math.pi/4), 1))
+assert(eq(math.sin(math.pi/2), 1) and eq(math.cos(math.pi/2), 0))
+assert(eq(math.atan(1), math.pi/4) and eq(math.acos(0), math.pi/2) and
+ eq(math.asin(1), math.pi/2))
+assert(eq(math.deg(math.pi/2), 90) and eq(math.rad(90), math.pi/2))
+assert(math.abs(-10) == 10)
+assert(eq(math.atan2(1,0), math.pi/2))
+assert(math.ceil(4.5) == 5.0)
+assert(math.floor(4.5) == 4.0)
+assert(math.mod(10,3) == 1)
+assert(eq(math.sqrt(10)^2, 10))
+assert(eq(math.log10(2), math.log(2)/math.log(10)))
+assert(eq(math.exp(0), 1))
+assert(eq(math.sin(10), math.sin(10%(2*math.pi))))
+local v,e = math.frexp(math.pi)
+assert(eq(math.ldexp(v,e), math.pi))
+
+assert(eq(math.tanh(3.5), math.sinh(3.5)/math.cosh(3.5)))
+
+assert(tonumber(' 1.3e-2 ') == 1.3e-2)
+assert(tonumber(' -1.00000000000001 ') == -1.00000000000001)
+
+-- testing constant limits
+-- 2^23 = 8388608
+assert(8388609 + -8388609 == 0)
+assert(8388608 + -8388608 == 0)
+assert(8388607 + -8388607 == 0)
+
+if rawget(_G, "_soft") then return end
+
+f = io.tmpfile()
+assert(f)
+f:write("a = {")
+i = 1
+repeat
+ f:write("{", math.sin(i), ", ", math.cos(i), ", ", i/3, "},\n")
+ i=i+1
+until i > 1000
+f:write("}")
+f:seek("set", 0)
+assert(loadstring(f:read('*a')))()
+assert(f:close())
+
+assert(eq(a[300][1], math.sin(300)))
+assert(eq(a[600][1], math.sin(600)))
+assert(eq(a[500][2], math.cos(500)))
+assert(eq(a[800][2], math.cos(800)))
+assert(eq(a[200][3], 200/3))
+assert(eq(a[1000][3], 1000/3, 0.001))
+print('+')
+
+do -- testing NaN
+ local NaN = 10e500 - 10e400
+ assert(NaN ~= NaN)
+ assert(not (NaN < NaN))
+ assert(not (NaN <= NaN))
+ assert(not (NaN > NaN))
+ assert(not (NaN >= NaN))
+ assert(not (0 < NaN))
+ assert(not (NaN < 0))
+ local a = {}
+ assert(not pcall(function () a[NaN] = 1 end))
+ assert(a[NaN] == nil)
+ a[1] = 1
+ assert(not pcall(function () a[NaN] = 1 end))
+ assert(a[NaN] == nil)
+end
+
+require "checktable"
+stat(a)
+
+a = nil
+
+-- testing implicit convertions
+
+local a,b = '10', '20'
+assert(a*b == 200 and a+b == 30 and a-b == -10 and a/b == 0.5 and -b == -20)
+assert(a == '10' and b == '20')
+
+
+math.randomseed(0)
+
+local i = 0
+local Max = 0
+local Min = 2
+repeat
+ local t = math.random()
+ Max = math.max(Max, t)
+ Min = math.min(Min, t)
+ i=i+1
+ flag = eq(Max, 1, 0.001) and eq(Min, 0, 0.001)
+until flag or i>10000
+assert(0 <= Min and Max<1)
+assert(flag);
+
+for i=1,10 do
+ local t = math.random(5)
+ assert(1 <= t and t <= 5)
+end
+
+i = 0
+Max = -200
+Min = 200
+repeat
+ local t = math.random(-10,0)
+ Max = math.max(Max, t)
+ Min = math.min(Min, t)
+ i=i+1
+ flag = (Max == 0 and Min == -10)
+until flag or i>10000
+assert(-10 <= Min and Max<=0)
+assert(flag);
+
+
+print('OK')
diff --git a/test/PUC-Rio-Lua-5.1-tests/nextvar.lua b/test/PUC-Rio-Lua-5.1-tests/nextvar.lua
new file mode 100644
index 00000000..7ceaa75a
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/nextvar.lua
@@ -0,0 +1,396 @@
+print('testing tables, next, and for')
+
+local a = {}
+
+-- make sure table has lots of space in hash part
+for i=1,100 do a[i.."+"] = true end
+for i=1,100 do a[i.."+"] = nil end
+-- fill hash part with numeric indices testing size operator
+for i=1,100 do
+ a[i] = true
+ assert(#a == i)
+end
+
+
+if T then
+-- testing table sizes
+
+local l2 = math.log(2)
+local function log2 (x) return math.log(x)/l2 end
+
+local function mp2 (n) -- minimum power of 2 >= n
+ local mp = 2^math.ceil(log2(n))
+ assert(n == 0 or (mp/2 < n and n <= mp))
+ return mp
+end
+
+local function fb (n)
+ local r, nn = T.int2fb(n)
+ assert(r < 256)
+ return nn
+end
+
+-- test fb function
+local a = 1
+local lim = 2^30
+while a < lim do
+ local n = fb(a)
+ assert(a <= n and n <= a*1.125)
+ a = math.ceil(a*1.3)
+end
+
+
+local function check (t, na, nh)
+ local a, h = T.querytab(t)
+ if a ~= na or h ~= nh then
+ print(na, nh, a, h)
+ assert(nil)
+ end
+end
+
+-- testing constructor sizes
+local lim = 40
+local s = 'return {'
+for i=1,lim do
+ s = s..i..','
+ local s = s
+ for k=0,lim do
+ local t = loadstring(s..'}')()
+ assert(#t == i)
+ check(t, fb(i), mp2(k))
+ s = string.format('%sa%d=%d,', s, k, k)
+ end
+end
+
+
+-- tests with unknown number of elements
+local a = {}
+for i=1,lim do a[i] = i end -- build auxiliary table
+for k=0,lim do
+ local a = {unpack(a,1,k)}
+ assert(#a == k)
+ check(a, k, 0)
+ a = {1,2,3,unpack(a,1,k)}
+ check(a, k+3, 0)
+ assert(#a == k + 3)
+end
+
+
+print'+'
+
+-- testing tables dynamically built
+local lim = 130
+local a = {}; a[2] = 1; check(a, 0, 1)
+a = {}; a[0] = 1; check(a, 0, 1); a[2] = 1; check(a, 0, 2)
+a = {}; a[0] = 1; a[1] = 1; check(a, 1, 1)
+a = {}
+for i = 1,lim do
+ a[i] = 1
+ assert(#a == i)
+ check(a, mp2(i), 0)
+end
+
+a = {}
+for i = 1,lim do
+ a['a'..i] = 1
+ assert(#a == 0)
+ check(a, 0, mp2(i))
+end
+
+a = {}
+for i=1,16 do a[i] = i end
+check(a, 16, 0)
+for i=1,11 do a[i] = nil end
+for i=30,40 do a[i] = nil end -- force a rehash (?)
+check(a, 0, 8)
+a[10] = 1
+for i=30,40 do a[i] = nil end -- force a rehash (?)
+check(a, 0, 8)
+for i=1,14 do a[i] = nil end
+for i=30,50 do a[i] = nil end -- force a rehash (?)
+check(a, 0, 4)
+
+-- reverse filling
+for i=1,lim do
+ local a = {}
+ for i=i,1,-1 do a[i] = i end -- fill in reverse
+ check(a, mp2(i), 0)
+end
+
+-- size tests for vararg
+lim = 35
+function foo (n, ...)
+ local arg = {...}
+ check(arg, n, 0)
+ assert(select('#', ...) == n)
+ arg[n+1] = true
+ check(arg, mp2(n+1), 0)
+ arg.x = true
+ check(arg, mp2(n+1), 1)
+end
+local a = {}
+for i=1,lim do a[i] = true; foo(i, unpack(a)) end
+
+end
+
+
+-- test size operation on empty tables
+assert(#{} == 0)
+assert(#{nil} == 0)
+assert(#{nil, nil} == 0)
+assert(#{nil, nil, nil} == 0)
+assert(#{nil, nil, nil, nil} == 0)
+print'+'
+
+
+local nofind = {}
+
+a,b,c = 1,2,3
+a,b,c = nil
+
+local function find (name)
+ local n,v
+ while 1 do
+ n,v = next(_G, n)
+ if not n then return nofind end
+ assert(v ~= nil)
+ if n == name then return v end
+ end
+end
+
+local function find1 (name)
+ for n,v in pairs(_G) do
+ if n==name then return v end
+ end
+ return nil -- not found
+end
+
+do -- create 10000 new global variables
+ for i=1,10000 do _G[i] = i end
+end
+
+
+a = {x=90, y=8, z=23}
+assert(table.foreach(a, function(i,v) if i=='x' then return v end end) == 90)
+assert(table.foreach(a, function(i,v) if i=='a' then return v end end) == nil)
+table.foreach({}, error)
+
+table.foreachi({x=10, y=20}, error)
+local a = {n = 1}
+table.foreachi({n=3}, function (i, v)
+ assert(a.n == i and not v)
+ a.n=a.n+1
+end)
+a = {10,20,30,nil,50}
+table.foreachi(a, function (i,v) assert(a[i] == v) end)
+assert(table.foreachi({'a', 'b', 'c'}, function (i,v)
+ if i==2 then return v end
+ end) == 'b')
+
+
+assert(print==find("print") and print == find1("print"))
+assert(_G["print"]==find("print"))
+assert(assert==find1("assert"))
+assert(nofind==find("return"))
+assert(not find1("return"))
+_G["ret" .. "urn"] = nil
+assert(nofind==find("return"))
+_G["xxx"] = 1
+assert(xxx==find("xxx"))
+print('+')
+
+a = {}
+for i=0,10000 do
+ if math.mod(i,10) ~= 0 then
+ a['x'..i] = i
+ end
+end
+
+n = {n=0}
+for i,v in pairs(a) do
+ n.n = n.n+1
+ assert(i and v and a[i] == v)
+end
+assert(n.n == 9000)
+a = nil
+
+-- remove those 10000 new global variables
+for i=1,10000 do _G[i] = nil end
+
+do -- clear global table
+ local a = {}
+ local preserve = {io = 1, string = 1, debug = 1, os = 1,
+ coroutine = 1, table = 1, math = 1}
+ for n,v in pairs(_G) do a[n]=v end
+ for n,v in pairs(a) do
+ if not preserve[n] and type(v) ~= "function" and
+ not string.find(n, "^[%u_]") then
+ _G[n] = nil
+ end
+ collectgarbage()
+ end
+end
+
+local function foo ()
+ local getfenv, setfenv, assert, next =
+ getfenv, setfenv, assert, next
+ local n = {gl1=3}
+ setfenv(foo, n)
+ assert(getfenv(foo) == getfenv(1))
+ assert(getfenv(foo) == n)
+ assert(print == nil and gl1 == 3)
+ gl1 = nil
+ gl = 1
+ assert(n.gl == 1 and next(n, 'gl') == nil)
+end
+foo()
+
+print'+'
+
+local function checknext (a)
+ local b = {}
+ table.foreach(a, function (k,v) b[k] = v end)
+ for k,v in pairs(b) do assert(a[k] == v) end
+ for k,v in pairs(a) do assert(b[k] == v) end
+ b = {}
+ do local k,v = next(a); while k do b[k] = v; k,v = next(a,k) end end
+ for k,v in pairs(b) do assert(a[k] == v) end
+ for k,v in pairs(a) do assert(b[k] == v) end
+end
+
+checknext{1,x=1,y=2,z=3}
+checknext{1,2,x=1,y=2,z=3}
+checknext{1,2,3,x=1,y=2,z=3}
+checknext{1,2,3,4,x=1,y=2,z=3}
+checknext{1,2,3,4,5,x=1,y=2,z=3}
+
+assert(table.getn{} == 0)
+assert(table.getn{[-1] = 2} == 0)
+assert(table.getn{1,2,3,nil,nil} == 3)
+for i=0,40 do
+ local a = {}
+ for j=1,i do a[j]=j end
+ assert(table.getn(a) == i)
+end
+
+
+assert(table.maxn{} == 0)
+assert(table.maxn{["1000"] = true} == 0)
+assert(table.maxn{["1000"] = true, [24.5] = 3} == 24.5)
+assert(table.maxn{[1000] = true} == 1000)
+assert(table.maxn{[10] = true, [100*math.pi] = print} == 100*math.pi)
+
+
+-- int overflow
+a = {}
+for i=0,50 do a[math.pow(2,i)] = true end
+assert(a[table.getn(a)])
+
+print("+")
+
+
+-- erasing values
+local t = {[{1}] = 1, [{2}] = 2, [string.rep("x ", 4)] = 3,
+ [100.3] = 4, [4] = 5}
+
+local n = 0
+for k, v in pairs( t ) do
+ n = n+1
+ assert(t[k] == v)
+ t[k] = nil
+ collectgarbage()
+ assert(t[k] == nil)
+end
+assert(n == 5)
+
+
+local function test (a)
+ table.insert(a, 10); table.insert(a, 2, 20);
+ table.insert(a, 1, -1); table.insert(a, 40);
+ table.insert(a, table.getn(a)+1, 50)
+ table.insert(a, 2, -2)
+ assert(table.remove(a,1) == -1)
+ assert(table.remove(a,1) == -2)
+ assert(table.remove(a,1) == 10)
+ assert(table.remove(a,1) == 20)
+ assert(table.remove(a,1) == 40)
+ assert(table.remove(a,1) == 50)
+ assert(table.remove(a,1) == nil)
+end
+
+a = {n=0, [-7] = "ban"}
+test(a)
+assert(a.n == 0 and a[-7] == "ban")
+
+a = {[-7] = "ban"};
+test(a)
+assert(a.n == nil and table.getn(a) == 0 and a[-7] == "ban")
+
+
+table.insert(a, 1, 10); table.insert(a, 1, 20); table.insert(a, 1, -1)
+assert(table.remove(a) == 10)
+assert(table.remove(a) == 20)
+assert(table.remove(a) == -1)
+
+a = {'c', 'd'}
+table.insert(a, 3, 'a')
+table.insert(a, 'b')
+assert(table.remove(a, 1) == 'c')
+assert(table.remove(a, 1) == 'd')
+assert(table.remove(a, 1) == 'a')
+assert(table.remove(a, 1) == 'b')
+assert(table.getn(a) == 0 and a.n == nil)
+print("+")
+
+a = {}
+for i=1,1000 do
+ a[i] = i; a[i-1] = nil
+end
+assert(next(a,nil) == 1000 and next(a,1000) == nil)
+
+assert(next({}) == nil)
+assert(next({}, nil) == nil)
+
+for a,b in pairs{} do error"not here" end
+for i=1,0 do error'not here' end
+for i=0,1,-1 do error'not here' end
+a = nil; for i=1,1 do assert(not a); a=1 end; assert(a)
+a = nil; for i=1,1,-1 do assert(not a); a=1 end; assert(a)
+
+a = 0; for i=0, 1, 0.1 do a=a+1 end; assert(a==11)
+-- precision problems
+--a = 0; for i=1, 0, -0.01 do a=a+1 end; assert(a==101)
+a = 0; for i=0, 0.999999999, 0.1 do a=a+1 end; assert(a==10)
+a = 0; for i=1, 1, 1 do a=a+1 end; assert(a==1)
+a = 0; for i=1e10, 1e10, -1 do a=a+1 end; assert(a==1)
+a = 0; for i=1, 0.99999, 1 do a=a+1 end; assert(a==0)
+a = 0; for i=99999, 1e5, -1 do a=a+1 end; assert(a==0)
+a = 0; for i=1, 0.99999, -1 do a=a+1 end; assert(a==1)
+
+-- conversion
+a = 0; for i="10","1","-2" do a=a+1 end; assert(a==5)
+
+
+collectgarbage()
+
+
+-- testing generic 'for'
+
+local function f (n, p)
+ local t = {}; for i=1,p do t[i] = i*10 end
+ return function (_,n)
+ if n > 0 then
+ n = n-1
+ return n, unpack(t)
+ end
+ end, nil, n
+end
+
+local x = 0
+for n,a,b,c,d in f(5,3) do
+ x = x+1
+ assert(a == 10 and b == 20 and c == 30 and d == nil)
+end
+assert(x == 5)
+
+print"OK"
diff --git a/test/PUC-Rio-Lua-5.1-tests/pm.lua b/test/PUC-Rio-Lua-5.1-tests/pm.lua
new file mode 100644
index 00000000..fa125dc9
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/pm.lua
@@ -0,0 +1,273 @@
+print('testing pattern matching')
+
+function f(s, p)
+ local i,e = string.find(s, p)
+ if i then return string.sub(s, i, e) end
+end
+
+function f1(s, p)
+ p = string.gsub(p, "%%([0-9])", function (s) return "%" .. (s+1) end)
+ p = string.gsub(p, "^(^?)", "%1()", 1)
+ p = string.gsub(p, "($?)$", "()%1", 1)
+ local t = {string.match(s, p)}
+ return string.sub(s, t[1], t[#t] - 1)
+end
+
+a,b = string.find('', '') -- empty patterns are tricky
+assert(a == 1 and b == 0);
+a,b = string.find('alo', '')
+assert(a == 1 and b == 0)
+a,b = string.find('a\0o a\0o a\0o', 'a', 1) -- first position
+assert(a == 1 and b == 1)
+a,b = string.find('a\0o a\0o a\0o', 'a\0o', 2) -- starts in the midle
+assert(a == 5 and b == 7)
+a,b = string.find('a\0o a\0o a\0o', 'a\0o', 9) -- starts in the midle
+assert(a == 9 and b == 11)
+a,b = string.find('a\0a\0a\0a\0\0ab', '\0ab', 2); -- finds at the end
+assert(a == 9 and b == 11);
+a,b = string.find('a\0a\0a\0a\0\0ab', 'b') -- last position
+assert(a == 11 and b == 11)
+assert(string.find('a\0a\0a\0a\0\0ab', 'b\0') == nil) -- check ending
+assert(string.find('', '\0') == nil)
+assert(string.find('alo123alo', '12') == 4)
+assert(string.find('alo123alo', '^12') == nil)
+
+assert(f('aloALO', '%l*') == 'alo')
+assert(f('aLo_ALO', '%a*') == 'aLo')
+
+assert(f('aaab', 'a*') == 'aaa');
+assert(f('aaa', '^.*$') == 'aaa');
+assert(f('aaa', 'b*') == '');
+assert(f('aaa', 'ab*a') == 'aa')
+assert(f('aba', 'ab*a') == 'aba')
+assert(f('aaab', 'a+') == 'aaa')
+assert(f('aaa', '^.+$') == 'aaa')
+assert(f('aaa', 'b+') == nil)
+assert(f('aaa', 'ab+a') == nil)
+assert(f('aba', 'ab+a') == 'aba')
+assert(f('a$a', '.$') == 'a')
+assert(f('a$a', '.%$') == 'a$')
+assert(f('a$a', '.$.') == 'a$a')
+assert(f('a$a', '$$') == nil)
+assert(f('a$b', 'a$') == nil)
+assert(f('a$a', '$') == '')
+assert(f('', 'b*') == '')
+assert(f('aaa', 'bb*') == nil)
+assert(f('aaab', 'a-') == '')
+assert(f('aaa', '^.-$') == 'aaa')
+assert(f('aabaaabaaabaaaba', 'b.*b') == 'baaabaaabaaab')
+assert(f('aabaaabaaabaaaba', 'b.-b') == 'baaab')
+assert(f('alo xo', '.o$') == 'xo')
+assert(f(' \n isto é assim', '%S%S*') == 'isto')
+assert(f(' \n isto é assim', '%S*$') == 'assim')
+assert(f(' \n isto é assim', '[a-z]*$') == 'assim')
+assert(f('um caracter ? extra', '[^%sa-z]') == '?')
+assert(f('', 'a?') == '')
+assert(f('á', 'á?') == 'á')
+assert(f('ábl', 'á?b?l?') == 'ábl')
+assert(f(' ábl', 'á?b?l?') == '')
+assert(f('aa', '^aa?a?a') == 'aa')
+assert(f(']]]áb', '[^]]') == 'á')
+assert(f("0alo alo", "%x*") == "0a")
+assert(f("alo alo", "%C+") == "alo alo")
+print('+')
+
+assert(f1('alo alx 123 b\0o b\0o', '(..*) %1') == "b\0o b\0o")
+assert(f1('axz123= 4= 4 34', '(.+)=(.*)=%2 %1') == '3= 4= 4 3')
+assert(f1('=======', '^(=*)=%1$') == '=======')
+assert(string.match('==========', '^([=]*)=%1$') == nil)
+
+local function range (i, j)
+ if i <= j then
+ return i, range(i+1, j)
+ end
+end
+
+local abc = string.char(range(0, 255));
+
+assert(string.len(abc) == 256)
+
+function strset (p)
+ local res = {s=''}
+ string.gsub(abc, p, function (c) res.s = res.s .. c end)
+ return res.s
+end;
+
+assert(string.len(strset('[\200-\210]')) == 11)
+
+assert(strset('[a-z]') == "abcdefghijklmnopqrstuvwxyz")
+assert(strset('[a-z%d]') == strset('[%da-uu-z]'))
+assert(strset('[a-]') == "-a")
+assert(strset('[^%W]') == strset('[%w]'))
+assert(strset('[]%%]') == '%]')
+assert(strset('[a%-z]') == '-az')
+assert(strset('[%^%[%-a%]%-b]') == '-[]^ab')
+assert(strset('%Z') == strset('[\1-\255]'))
+assert(strset('.') == strset('[\1-\255%z]'))
+print('+');
+
+assert(string.match("alo xyzK", "(%w+)K") == "xyz")
+assert(string.match("254 K", "(%d*)K") == "")
+assert(string.match("alo ", "(%w*)$") == "")
+assert(string.match("alo ", "(%w+)$") == nil)
+assert(string.find("(álo)", "%(á") == 1)
+local a, b, c, d, e = string.match("âlo alo", "^(((.).).* (%w*))$")
+assert(a == 'âlo alo' and b == 'âl' and c == 'â' and d == 'alo' and e == nil)
+a, b, c, d = string.match('0123456789', '(.+(.?)())')
+assert(a == '0123456789' and b == '' and c == 11 and d == nil)
+print('+')
+
+assert(string.gsub('ülo ülo', 'ü', 'x') == 'xlo xlo')
+assert(string.gsub('alo úlo ', ' +$', '') == 'alo úlo') -- trim
+assert(string.gsub(' alo alo ', '^%s*(.-)%s*$', '%1') == 'alo alo') -- double trim
+assert(string.gsub('alo alo \n 123\n ', '%s+', ' ') == 'alo alo 123 ')
+t = "abç d"
+a, b = string.gsub(t, '(.)', '%1@')
+assert('@'..a == string.gsub(t, '', '@') and b == 5)
+a, b = string.gsub('abçd', '(.)', '%0@', 2)
+assert(a == 'a@b@çd' and b == 2)
+assert(string.gsub('alo alo', '()[al]', '%1') == '12o 56o')
+assert(string.gsub("abc=xyz", "(%w*)(%p)(%w+)", "%3%2%1-%0") ==
+ "xyz=abc-abc=xyz")
+assert(string.gsub("abc", "%w", "%1%0") == "aabbcc")
+assert(string.gsub("abc", "%w+", "%0%1") == "abcabc")
+assert(string.gsub('áéí', '$', '\0óú') == 'áéí\0óú')
+assert(string.gsub('', '^', 'r') == 'r')
+assert(string.gsub('', '$', 'r') == 'r')
+print('+')
+
+assert(string.gsub("um (dois) tres (quatro)", "(%(%w+%))", string.upper) ==
+ "um (DOIS) tres (QUATRO)")
+
+do
+ local function setglobal (n,v) rawset(_G, n, v) end
+ string.gsub("a=roberto,roberto=a", "(%w+)=(%w%w*)", setglobal)
+ assert(_G.a=="roberto" and _G.roberto=="a")
+end
+
+function f(a,b) return string.gsub(a,'.',b) end
+assert(string.gsub("trocar tudo em |teste|b| é |beleza|al|", "|([^|]*)|([^|]*)|", f) ==
+ "trocar tudo em bbbbb é alalalalalal")
+
+local function dostring (s) return loadstring(s)() or "" end
+assert(string.gsub("alo $a=1$ novamente $return a$", "$([^$]*)%$", dostring) ==
+ "alo novamente 1")
+
+x = string.gsub("$x=string.gsub('alo', '.', string.upper)$ assim vai para $return x$",
+ "$([^$]*)%$", dostring)
+assert(x == ' assim vai para ALO')
+
+t = {}
+s = 'a alo jose joao'
+r = string.gsub(s, '()(%w+)()', function (a,w,b)
+ assert(string.len(w) == b-a);
+ t[a] = b-a;
+ end)
+assert(s == r and t[1] == 1 and t[3] == 3 and t[7] == 4 and t[13] == 4)
+
+
+function isbalanced (s)
+ return string.find(string.gsub(s, "%b()", ""), "[()]") == nil
+end
+
+assert(isbalanced("(9 ((8))(\0) 7) \0\0 a b ()(c)() a"))
+assert(not isbalanced("(9 ((8) 7) a b (\0 c) a"))
+assert(string.gsub("alo 'oi' alo", "%b''", '"') == 'alo " alo')
+
+
+local t = {"apple", "orange", "lime"; n=0}
+assert(string.gsub("x and x and x", "x", function () t.n=t.n+1; return t[t.n] end)
+ == "apple and orange and lime")
+
+t = {n=0}
+string.gsub("first second word", "%w%w*", function (w) t.n=t.n+1; t[t.n] = w end)
+assert(t[1] == "first" and t[2] == "second" and t[3] == "word" and t.n == 3)
+
+t = {n=0}
+assert(string.gsub("first second word", "%w+",
+ function (w) t.n=t.n+1; t[t.n] = w end, 2) == "first second word")
+assert(t[1] == "first" and t[2] == "second" and t[3] == nil)
+
+assert(not pcall(string.gsub, "alo", "(.", print))
+assert(not pcall(string.gsub, "alo", ".)", print))
+assert(not pcall(string.gsub, "alo", "(.", {}))
+assert(not pcall(string.gsub, "alo", "(.)", "%2"))
+assert(not pcall(string.gsub, "alo", "(%1)", "a"))
+assert(not pcall(string.gsub, "alo", "(%0)", "a"))
+
+-- big strings
+local a = string.rep('a', 300000)
+assert(string.find(a, '^a*.?$'))
+assert(not string.find(a, '^a*.?b$'))
+assert(string.find(a, '^a-.?$'))
+
+-- deep nest of gsubs
+function rev (s)
+ return string.gsub(s, "(.)(.+)", function (c,s1) return rev(s1)..c end)
+end
+
+local x = string.rep('012345', 10)
+assert(rev(rev(x)) == x)
+
+
+-- gsub with tables
+assert(string.gsub("alo alo", ".", {}) == "alo alo")
+assert(string.gsub("alo alo", "(.)", {a="AA", l=""}) == "AAo AAo")
+assert(string.gsub("alo alo", "(.).", {a="AA", l="K"}) == "AAo AAo")
+assert(string.gsub("alo alo", "((.)(.?))", {al="AA", o=false}) == "AAo AAo")
+
+assert(string.gsub("alo alo", "().", {2,5,6}) == "256 alo")
+
+t = {}; setmetatable(t, {__index = function (t,s) return string.upper(s) end})
+assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI")
+
+
+-- tests for gmatch
+assert(string.gfind == string.gmatch)
+local a = 0
+for i in string.gmatch('abcde', '()') do assert(i == a+1); a=i end
+assert(a==6)
+
+t = {n=0}
+for w in string.gmatch("first second word", "%w+") do
+ t.n=t.n+1; t[t.n] = w
+end
+assert(t[1] == "first" and t[2] == "second" and t[3] == "word")
+
+t = {3, 6, 9}
+for i in string.gmatch ("xuxx uu ppar r", "()(.)%2") do
+ assert(i == table.remove(t, 1))
+end
+assert(table.getn(t) == 0)
+
+t = {}
+for i,j in string.gmatch("13 14 10 = 11, 15= 16, 22=23", "(%d+)%s*=%s*(%d+)") do
+ t[i] = j
+end
+a = 0
+for k,v in pairs(t) do assert(k+1 == v+0); a=a+1 end
+assert(a == 3)
+
+
+-- tests for `%f' (`frontiers')
+
+assert(string.gsub("aaa aa a aaa a", "%f[%w]a", "x") == "xaa xa x xaa x")
+assert(string.gsub("[[]] [][] [[[[", "%f[[].", "x") == "x[]] x]x] x[[[")
+assert(string.gsub("01abc45de3", "%f[%d]", ".") == ".01abc.45de.3")
+assert(string.gsub("01abc45 de3x", "%f[%D]%w", ".") == "01.bc45 de3.")
+assert(string.gsub("function", "%f[\1-\255]%w", ".") == ".unction")
+assert(string.gsub("function", "%f[^\1-\255]", ".") == "function.")
+
+local i, e = string.find(" alo aalo allo", "%f[%S].-%f[%s].-%f[%S]")
+assert(i == 2 and e == 5)
+local k = string.match(" alo aalo allo", "%f[%S](.-%f[%s].-%f[%S])")
+assert(k == 'alo ')
+
+local a = {1, 5, 9, 14, 17,}
+for k in string.gmatch("alo alo th02 is 1hat", "()%f[%w%d]") do
+ assert(table.remove(a, 1) == k)
+end
+assert(table.getn(a) == 0)
+
+
+print('OK')
diff --git a/test/PUC-Rio-Lua-5.1-tests/sort.lua b/test/PUC-Rio-Lua-5.1-tests/sort.lua
new file mode 100644
index 00000000..6fccd49e
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/sort.lua
@@ -0,0 +1,74 @@
+print"testing sort"
+
+
+function check (a, f)
+ f = f or function (x,y) return x<y end;
+ for n=table.getn(a),2,-1 do
+ assert(not f(a[n], a[n-1]))
+ end
+end
+
+a = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
+ "Oct", "Nov", "Dec"}
+
+table.sort(a)
+check(a)
+
+limit = 30000
+if rawget(_G, "_soft") then limit = 5000 end
+
+a = {}
+for i=1,limit do
+ a[i] = math.random()
+end
+
+local x = os.clock()
+table.sort(a)
+print(string.format("Sorting %d elements in %.2f sec.", limit, os.clock()-x))
+check(a)
+
+x = os.clock()
+table.sort(a)
+print(string.format("Re-sorting %d elements in %.2f sec.", limit, os.clock()-x))
+check(a)
+
+a = {}
+for i=1,limit do
+ a[i] = math.random()
+end
+
+x = os.clock(); i=0
+table.sort(a, function(x,y) i=i+1; return y<x end)
+print(string.format("Invert-sorting other %d elements in %.2f sec., with %i comparisons",
+ limit, os.clock()-x, i))
+check(a, function(x,y) return y<x end)
+
+
+table.sort{} -- empty array
+
+for i=1,limit do a[i] = false end
+x = os.clock();
+table.sort(a, function(x,y) return nil end)
+print(string.format("Sorting %d equal elements in %.2f sec.", limit, os.clock()-x))
+check(a, function(x,y) return nil end)
+for i,v in pairs(a) do assert(not v or i=='n' and v==limit) end
+
+a = {"álo", "\0first :-)", "alo", "then this one", "45", "and a new"}
+table.sort(a)
+check(a)
+
+table.sort(a, function (x, y)
+ loadstring(string.format("a[%q] = ''", x))()
+ collectgarbage()
+ return x<y
+ end)
+
+
+tt = {__lt = function (a,b) return a.val < b.val end}
+a = {}
+for i=1,10 do a[i] = {val=math.random(100)}; setmetatable(a[i], tt); end
+table.sort(a)
+check(a, tt.__lt)
+check(a)
+
+print"OK"
diff --git a/test/PUC-Rio-Lua-5.1-tests/strings.lua b/test/PUC-Rio-Lua-5.1-tests/strings.lua
new file mode 100644
index 00000000..237dbad3
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/strings.lua
@@ -0,0 +1,176 @@
+print('testing strings and string library')
+
+assert('alo' < 'alo1')
+assert('' < 'a')
+assert('alo\0alo' < 'alo\0b')
+assert('alo\0alo\0\0' > 'alo\0alo\0')
+assert('alo' < 'alo\0')
+assert('alo\0' > 'alo')
+assert('\0' < '\1')
+assert('\0\0' < '\0\1')
+assert('\1\0a\0a' <= '\1\0a\0a')
+assert(not ('\1\0a\0b' <= '\1\0a\0a'))
+assert('\0\0\0' < '\0\0\0\0')
+assert(not('\0\0\0\0' < '\0\0\0'))
+assert('\0\0\0' <= '\0\0\0\0')
+assert(not('\0\0\0\0' <= '\0\0\0'))
+assert('\0\0\0' <= '\0\0\0')
+assert('\0\0\0' >= '\0\0\0')
+assert(not ('\0\0b' < '\0\0a\0'))
+print('+')
+
+assert(string.sub("123456789",2,4) == "234")
+assert(string.sub("123456789",7) == "789")
+assert(string.sub("123456789",7,6) == "")
+assert(string.sub("123456789",7,7) == "7")
+assert(string.sub("123456789",0,0) == "")
+assert(string.sub("123456789",-10,10) == "123456789")
+assert(string.sub("123456789",1,9) == "123456789")
+assert(string.sub("123456789",-10,-20) == "")
+assert(string.sub("123456789",-1) == "9")
+assert(string.sub("123456789",-4) == "6789")
+assert(string.sub("123456789",-6, -4) == "456")
+assert(string.sub("\000123456789",3,5) == "234")
+assert(("\000123456789"):sub(8) == "789")
+print('+')
+
+assert(string.find("123456789", "345") == 3)
+a,b = string.find("123456789", "345")
+assert(string.sub("123456789", a, b) == "345")
+assert(string.find("1234567890123456789", "345", 3) == 3)
+assert(string.find("1234567890123456789", "345", 4) == 13)
+assert(string.find("1234567890123456789", "346", 4) == nil)
+assert(string.find("1234567890123456789", ".45", -9) == 13)
+assert(string.find("abcdefg", "\0", 5, 1) == nil)
+assert(string.find("", "") == 1)
+assert(string.find('', 'aaa', 1) == nil)
+assert(('alo(.)alo'):find('(.)', 1, 1) == 4)
+print('+')
+
+assert(string.len("") == 0)
+assert(string.len("\0\0\0") == 3)
+assert(string.len("1234567890") == 10)
+
+assert(#"" == 0)
+assert(#"\0\0\0" == 3)
+assert(#"1234567890" == 10)
+
+assert(string.byte("a") == 97)
+assert(string.byte("á") > 127)
+assert(string.byte(string.char(255)) == 255)
+assert(string.byte(string.char(0)) == 0)
+assert(string.byte("\0") == 0)
+assert(string.byte("\0\0alo\0x", -1) == string.byte('x'))
+assert(string.byte("ba", 2) == 97)
+assert(string.byte("\n\n", 2, -1) == 10)
+assert(string.byte("\n\n", 2, 2) == 10)
+assert(string.byte("") == nil)
+assert(string.byte("hi", -3) == nil)
+assert(string.byte("hi", 3) == nil)
+assert(string.byte("hi", 9, 10) == nil)
+assert(string.byte("hi", 2, 1) == nil)
+assert(string.char() == "")
+assert(string.char(0, 255, 0) == "\0\255\0")
+assert(string.char(0, string.byte("á"), 0) == "\0á\0")
+assert(string.char(string.byte("ál\0óu", 1, -1)) == "ál\0óu")
+assert(string.char(string.byte("ál\0óu", 1, 0)) == "")
+assert(string.char(string.byte("ál\0óu", -10, 100)) == "ál\0óu")
+print('+')
+
+assert(string.upper("ab\0c") == "AB\0C")
+assert(string.lower("\0ABCc%$") == "\0abcc%$")
+assert(string.rep('teste', 0) == '')
+assert(string.rep('tés\00tê', 2) == 'tés\0têtés\000tê')
+assert(string.rep('', 10) == '')
+
+assert(string.reverse"" == "")
+assert(string.reverse"\0\1\2\3" == "\3\2\1\0")
+assert(string.reverse"\0001234" == "4321\0")
+
+for i=0,30 do assert(string.len(string.rep('a', i)) == i) end
+
+assert(type(tostring(nil)) == 'string')
+assert(type(tostring(12)) == 'string')
+assert(''..12 == '12' and type(12 .. '') == 'string')
+assert(string.find(tostring{}, 'table:'))
+assert(string.find(tostring(print), 'function:'))
+assert(tostring(1234567890123) == '1234567890123')
+assert(#tostring('\0') == 1)
+assert(tostring(true) == "true")
+assert(tostring(false) == "false")
+print('+')
+
+x = '"ílo"\n\\'
+assert(string.format('%q%s', x, x) == '"\\"ílo\\"\\\n\\\\""ílo"\n\\')
+assert(string.format('%q', "\0") == [["\000"]])
+assert(string.format("\0%c\0%c%x\0", string.byte("á"), string.byte("b"), 140) ==
+ "\0á\0b8c\0")
+assert(string.format('') == "")
+assert(string.format("%c",34)..string.format("%c",48)..string.format("%c",90)..string.format("%c",100) ==
+ string.format("%c%c%c%c", 34, 48, 90, 100))
+assert(string.format("%s\0 is not \0%s", 'not be', 'be') == 'not be\0 is not \0be')
+assert(string.format("%%%d %010d", 10, 23) == "%10 0000000023")
+assert(tonumber(string.format("%f", 10.3)) == 10.3)
+x = string.format('"%-50s"', 'a')
+assert(#x == 52)
+assert(string.sub(x, 1, 4) == '"a ')
+
+assert(string.format("-%.20s.20s", string.rep("%", 2000)) == "-"..string.rep("%", 20)..".20s")
+assert(string.format('"-%20s.20s"', string.rep("%", 2000)) ==
+ string.format("%q", "-"..string.rep("%", 2000)..".20s"))
+
+
+-- longest number that can be formated
+assert(string.len(string.format('%99.99f', -1e308)) >= 100)
+
+assert(loadstring("return 1\n--comentário sem EOL no final")() == 1)
+
+
+assert(table.concat{} == "")
+assert(table.concat({}, 'x') == "")
+assert(table.concat({'\0', '\0\1', '\0\1\2'}, '.\0.') == "\0.\0.\0\1.\0.\0\1\2")
+local a = {}; for i=1,3000 do a[i] = "xuxu" end
+assert(table.concat(a, "123").."123" == string.rep("xuxu123", 3000))
+assert(table.concat(a, "b", 20, 20) == "xuxu")
+assert(table.concat(a, "", 20, 21) == "xuxuxuxu")
+assert(table.concat(a, "", 22, 21) == "")
+assert(table.concat(a, "3", 2999) == "xuxu3xuxu")
+
+a = {"a","b","c"}
+assert(table.concat(a, ",", 1, 0) == "")
+assert(table.concat(a, ",", 1, 1) == "a")
+assert(table.concat(a, ",", 1, 2) == "a,b")
+assert(table.concat(a, ",", 2) == "b,c")
+assert(table.concat(a, ",", 3) == "c")
+assert(table.concat(a, ",", 4) == "")
+
+local locales = { "ptb", "ISO-8859-1", "pt_BR" }
+local function trylocale (w)
+ for _, l in ipairs(locales) do
+ if os.setlocale(l, w) then return true end
+ end
+ return false
+end
+
+if not trylocale("collate") then
+ print("locale not supported")
+else
+ assert("alo" < "álo" and "álo" < "amo")
+end
+
+if not trylocale("ctype") then
+ print("locale not supported")
+else
+ assert(string.gsub("áéíóú", "%a", "x") == "xxxxx")
+ assert(string.gsub("áÁéÉ", "%l", "x") == "xÁxÉ")
+ assert(string.gsub("áÁéÉ", "%u", "x") == "áxéx")
+ assert(string.upper"áÁé{xuxu}ção" == "ÁÁÉ{XUXU}ÇÃO")
+end
+
+os.setlocale("C")
+assert(os.setlocale() == 'C')
+assert(os.setlocale(nil, "numeric") == 'C')
+
+print('OK')
+
+
diff --git a/test/PUC-Rio-Lua-5.1-tests/vararg.lua b/test/PUC-Rio-Lua-5.1-tests/vararg.lua
new file mode 100644
index 00000000..ae068fac
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/vararg.lua
@@ -0,0 +1,126 @@
+print('testing vararg')
+
+_G.arg = nil
+
+function f(a, ...)
+ assert(type(arg) == 'table')
+ assert(type(arg.n) == 'number')
+ for i=1,arg.n do assert(a[i]==arg[i]) end
+ return arg.n
+end
+
+function c12 (...)
+ assert(arg == nil)
+ local x = {...}; x.n = table.getn(x)
+ local res = (x.n==2 and x[1] == 1 and x[2] == 2)
+ if res then res = 55 end
+ return res, 2
+end
+
+function vararg (...) return arg end
+
+local call = function (f, args) return f(unpack(args, 1, args.n)) end
+
+assert(f() == 0)
+assert(f({1,2,3}, 1, 2, 3) == 3)
+assert(f({"alo", nil, 45, f, nil}, "alo", nil, 45, f, nil) == 5)
+
+assert(c12(1,2)==55)
+a,b = assert(call(c12, {1,2}))
+assert(a == 55 and b == 2)
+a = call(c12, {1,2;n=2})
+assert(a == 55 and b == 2)
+a = call(c12, {1,2;n=1})
+assert(not a)
+assert(c12(1,2,3) == false)
+local a = vararg(call(next, {_G,nil;n=2}))
+local b,c = next(_G)
+assert(a[1] == b and a[2] == c and a.n == 2)
+a = vararg(call(call, {c12, {1,2}}))
+assert(a.n == 2 and a[1] == 55 and a[2] == 2)
+a = call(print, {'+'})
+assert(a == nil)
+
+local t = {1, 10}
+function t:f (...) return self[arg[1]]+arg.n end
+assert(t:f(1,4) == 3 and t:f(2) == 11)
+print('+')
+
+lim = 20
+local i, a = 1, {}
+while i <= lim do a[i] = i+0.3; i=i+1 end
+
+function f(a, b, c, d, ...)
+ local more = {...}
+ assert(a == 1.3 and more[1] == 5.3 and
+ more[lim-4] == lim+0.3 and not more[lim-3])
+end
+
+function g(a,b,c)
+ assert(a == 1.3 and b == 2.3 and c == 3.3)
+end
+
+call(f, a)
+call(g, a)
+
+a = {}
+i = 1
+while i <= lim do a[i] = i; i=i+1 end
+assert(call(math.max, a) == lim)
+
+print("+")
+
+
+-- new-style varargs
+
+function oneless (a, ...) return ... end
+
+function f (n, a, ...)
+ local b
+ assert(arg == nil)
+ if n == 0 then
+ local b, c, d = ...
+ return a, b, c, d, oneless(oneless(oneless(...)))
+ else
+ n, b, a = n-1, ..., a
+ assert(b == ...)
+ return f(n, a, ...)
+ end
+end
+
+a,b,c,d,e = assert(f(10,5,4,3,2,1))
+assert(a==5 and b==4 and c==3 and d==2 and e==1)
+
+a,b,c,d,e = f(4)
+assert(a==nil and b==nil and c==nil and d==nil and e==nil)
+
+
+-- varargs for main chunks
+f = loadstring[[ return {...} ]]
+x = f(2,3)
+assert(x[1] == 2 and x[2] == 3 and x[3] == nil)
+
+
+f = loadstring[[
+ local x = {...}
+ for i=1,select('#', ...) do assert(x[i] == select(i, ...)) end
+ assert(x[select('#', ...)+1] == nil)
+ return true
+]]
+
+assert(f("a", "b", nil, {}, assert))
+assert(f())
+
+a = {select(3, unpack{10,20,30,40})}
+assert(table.getn(a) == 2 and a[1] == 30 and a[2] == 40)
+a = {select(1)}
+assert(next(a) == nil)
+a = {select(-1, 3, 5, 7)}
+assert(a[1] == 7 and a[2] == nil)
+a = {select(-2, 3, 5, 7)}
+assert(a[1] == 5 and a[2] == 7 and a[3] == nil)
+pcall(select, 10000)
+pcall(select, -10000)
+
+print('OK')
+
diff --git a/test/PUC-Rio-Lua-5.1-tests/verybig.lua b/test/PUC-Rio-Lua-5.1-tests/verybig.lua
new file mode 100644
index 00000000..59e0142a
--- /dev/null
+++ b/test/PUC-Rio-Lua-5.1-tests/verybig.lua
@@ -0,0 +1,100 @@
+if rawget(_G, "_soft") then return 10 end
+
+print "testing large programs (>64k)"
+
+-- template to create a very big test file
+prog = [[$
+
+local a,b
+
+b = {$1$
+ b30009 = 65534,
+ b30010 = 65535,
+ b30011 = 65536,
+ b30012 = 65537,
+ b30013 = 16777214,
+ b30014 = 16777215,
+ b30015 = 16777216,
+ b30016 = 16777217,
+ b30017 = 4294967294,
+ b30018 = 4294967295,
+ b30019 = 4294967296,
+ b30020 = 4294967297,
+ b30021 = -65534,
+ b30022 = -65535,
+ b30023 = -65536,
+ b30024 = -4294967297,
+ b30025 = 15012.5,
+ $2$
+};
+
+assert(b.a50008 == 25004 and b["a11"] == 5.5)
+assert(b.a33007 == 16503.5 and b.a50009 == 25004.5)
+assert(b["b"..30024] == -4294967297)
+
+function b:xxx (a,b) return a+b end
+assert(b:xxx(10, 12) == 22) -- pushself with non-constant index
+b.xxx = nil
+
+s = 0; n=0
+for a,b in pairs(b) do s=s+b; n=n+1 end
+assert(s==13977183656.5 and n==70001)
+
+require "checktable"
+stat(b)
+
+a = nil; b = nil
+print'+'
+
+function f(x) b=x end
+
+a = f{$3$} or 10
+
+assert(a==10)
+assert(b[1] == "a10" and b[2] == 5 and b[table.getn(b)-1] == "a50009")
+
+
+function xxxx (x) return b[x] end
+
+assert(xxxx(3) == "a11")
+
+a = nil; b=nil
+xxxx = nil
+
+return 10
+
+]]
+
+-- functions to fill in the $n$
+F = {
+function () -- $1$
+ for i=10,50009 do
+ io.write('a', i, ' = ', 5+((i-10)/2), ',\n')
+ end
+end,
+
+function () -- $2$
+ for i=30026,50009 do
+ io.write('b', i, ' = ', 15013+((i-30026)/2), ',\n')
+ end
+end,
+
+function () -- $3$
+ for i=10,50009 do
+ io.write('"a', i, '", ', 5+((i-10)/2), ',\n')
+ end
+end,
+}
+
+file = os.tmpname()
+io.output(file)
+for s in string.gmatch(prog, "$([^$]+)") do
+ local n = tonumber(s)
+ if not n then io.write(s) else F[n]() end
+end
+io.close()
+result = dofile(file)
+assert(os.remove(file))
+print'OK'
+return result
+
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 02/29] test: build auxiliary C libs from PUC-Rio Lua 5.1
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 01/29] test: add " Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 03/29] test: adapt PUC-Rio suite for out-of-source build Sergey Kaplun via Tarantool-patches
` (27 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
This patch adds rules to create additional LuaC libraries for tests
in <attrib.lua>. Also, it renames `luaL_reg` to `luaL_Reg` in <lib1.c>
and <lib2.c> to be consistent with the current LuaJIT's LuaC API.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt | 3 +-
.../PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt | 49 ++++++++++++++++++-
test/PUC-Rio-Lua-5.1-tests/libs/lib1.c | 2 +-
test/PUC-Rio-Lua-5.1-tests/libs/lib2.c | 2 +-
4 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt
index e3bbc9de..aab2d2fc 100644
--- a/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt
+++ b/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt
@@ -16,7 +16,8 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
# variable as proposed in the first case.
set(LUA_PATH "?\;${CMAKE_CURRENT_SOURCE_DIR}/?.lua")
-# Establish PUC-Lua-5.1-tests-prepare target that creates <libs/P1>
+# Establish PUC-Lua-5.1-tests-prepare target that contains rules
+# for <libs/*> libraries compilation and creates <libs/P1>
# subdirectory.
add_subdirectory(libs)
diff --git a/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt b/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt
index f24e7f30..b31ba130 100644
--- a/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt
+++ b/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt
@@ -4,11 +4,58 @@
# See the rationale in the root CMakeLists.txt.
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
+# Build additional C libraries for tests.
+macro(BuildTestCLib lib sources)
+ add_library(${lib} SHARED EXCLUDE_FROM_ALL ${sources})
+ target_include_directories(${lib} PRIVATE
+ ${LUAJIT_SOURCE_DIR}
+ )
+ set_target_properties(${lib} PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ PREFIX ""
+ )
+ # XXX: The dynamic libraries are loaded with LuaJIT binary and
+ # use symbols from it. So it is totally OK to have unresolved
+ # symbols at build time.
+ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set_target_properties(${lib} PROPERTIES
+ LINK_FLAGS "-undefined dynamic_lookup"
+ )
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ # XXX: This is necessary mostly for openSUSE builds, see also
+ # https://bugzilla.suse.com/show_bug.cgi?id=1012388.
+ # Just strip out the linker flag to suppress this linker
+ # option.
+ string(REPLACE "-Wl,--no-undefined" ""
+ CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}"
+ )
+ endif()
+ list(APPEND TESTLIBS ${lib})
+endmacro()
+
+BuildTestCLib(lib1 lib1.c)
+BuildTestCLib(lib11 lib1.c lib11.c)
+BuildTestCLib(lib2 lib2.c)
+BuildTestCLib(lib21 lib2.c lib21.c)
+
+# Create the exact copy of the lib2 library for tests
+# in <attrib.lua>.
+set(LIB2ORIG "${CMAKE_CURRENT_BINARY_DIR}/lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
+set(LIB2COPY "${CMAKE_CURRENT_BINARY_DIR}/-lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
+add_custom_command(
+ OUTPUT ${LIB2COPY}
+ COMMENT "Copying lib2 to -lib2 for PUC-Rio Lua 5.1 tests"
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIB2ORIG} ${LIB2COPY}
+ DEPENDS ${TESTLIBS}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+list(APPEND TESTLIBS ${LIB2COPY})
+
# The original tarball contains subdirectory "libs" with an empty
# subdirectory "libs/P1", to be used by tests.
# Instead of tracking empty directory with some anchor-file for
# git, create this directory via CMake.
-add_custom_target(PUC-Lua-5.1-tests-prepare)
+add_custom_target(PUC-Lua-5.1-tests-prepare DEPENDS ${TESTLIBS})
add_custom_command(TARGET PUC-Lua-5.1-tests-prepare
COMMENT "Create directory for PUC-Rio Lua 5.1 tests"
COMMAND ${CMAKE_COMMAND} -E make_directory P1
diff --git a/test/PUC-Rio-Lua-5.1-tests/libs/lib1.c b/test/PUC-Rio-Lua-5.1-tests/libs/lib1.c
index 812bb9ac..22fe6dee 100644
--- a/test/PUC-Rio-Lua-5.1-tests/libs/lib1.c
+++ b/test/PUC-Rio-Lua-5.1-tests/libs/lib1.c
@@ -14,7 +14,7 @@ static int id (lua_State *L) {
}
-static const struct luaL_reg funcs[] = {
+static const struct luaL_Reg funcs[] = {
{"id", id},
{NULL, NULL}
};
diff --git a/test/PUC-Rio-Lua-5.1-tests/libs/lib2.c b/test/PUC-Rio-Lua-5.1-tests/libs/lib2.c
index 9972cbe4..876a212f 100644
--- a/test/PUC-Rio-Lua-5.1-tests/libs/lib2.c
+++ b/test/PUC-Rio-Lua-5.1-tests/libs/lib2.c
@@ -12,7 +12,7 @@ static int id (lua_State *L) {
}
-static const struct luaL_reg funcs[] = {
+static const struct luaL_Reg funcs[] = {
{"id", id},
{NULL, NULL}
};
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 03/29] test: adapt PUC-Rio suite for out-of-source build
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 01/29] test: add " Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 02/29] test: build auxiliary C libs from PUC-Rio Lua 5.1 Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 21:05 ` Igor Munkin via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 04/29] test: remove quotes in progname from PUC-Rio Sergey Kaplun via Tarantool-patches
` (26 subsequent siblings)
29 siblings, 1 reply; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
The redefined `dofile()` function failed to find the test file to load,
when tests are run out-of-source. So, fullpath is detected considering
`arg[0]` value. Moreover, some tests use `loadfile()` instead, so their
argument has to be adjusted to the full path to the files.
Usage of functions invoking source test files was changed to
`_loadfile()` and `_dofile()` correspondingly. They equal
`loadfile()` and `dofile()` by default and can be overloaded via running
lua code from LUAJIT_TEST_INIT. This patch introduces the
<test/luajit-test-init.lua> file to be executed before tests and
redefines the functions considering the path from `arg[0]` variable.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
CMakeLists.txt | 4 +--
test/PUC-Rio-Lua-5.1-tests/all.lua | 51 +++++++++++++++++-------------
test/luajit-test-init.lua | 18 +++++++++++
3 files changed, 49 insertions(+), 24 deletions(-)
create mode 100644 test/luajit-test-init.lua
diff --git a/CMakeLists.txt b/CMakeLists.txt
index eb562923..df82d57c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -302,8 +302,8 @@ set(LUAJIT_TEST_BINARY ${LUAJIT_BINARY} CACHE STRING
# tweaked, the introduced option can be used.
# XXX: The default behaviour is nop, so /dev/null is the best
# option for this.
-set(LUAJIT_TEST_INIT "/dev/null" CACHE STRING
- "Lua code need to be run before tests are started. Default is nop."
+set(LUAJIT_TEST_INIT "${PROJECT_SOURCE_DIR}/test/luajit-test-init.lua" CACHE STRING
+ "Lua code need to be run before tests are started."
)
add_subdirectory(test)
diff --git a/test/PUC-Rio-Lua-5.1-tests/all.lua b/test/PUC-Rio-Lua-5.1-tests/all.lua
index 8c4aface..7460a677 100755
--- a/test/PUC-Rio-Lua-5.1-tests/all.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/all.lua
@@ -66,7 +66,12 @@ dofile = function (n)
return f()
end
-dofile('main.lua')
+-- LuaJIT: Adapt tests for testing with out-of-source build.
+-- See the comment in <test/luajit-test-init.lua>.
+local _dofile = _dofile or dofile
+local _loadstring = _loadstring or loadstring
+
+_dofile('main.lua')
do
local u = newproxy(true)
@@ -77,32 +82,34 @@ do
end
end
-local f = assert(loadfile('gc.lua'))
+-- LuaJIT: Adapt tests for testing with out-of-source build.
+-- See the comment in <test/luajit-test-init.lua>.
+local f = assert(_loadfile('gc.lua'))
f()
-dofile('db.lua')
-assert(dofile('calls.lua') == deep and deep)
-dofile('strings.lua')
-dofile('literals.lua')
-assert(dofile('attrib.lua') == 27)
-assert(dofile('locals.lua') == 5)
-dofile('constructs.lua')
-dofile('code.lua')
+_dofile('db.lua')
+assert(_dofile('calls.lua') == deep and deep)
+_dofile('strings.lua')
+_dofile('literals.lua')
+assert(_dofile('attrib.lua') == 27)
+assert(_dofile('locals.lua') == 5)
+_dofile('constructs.lua')
+_dofile('code.lua')
do
- local f = coroutine.wrap(assert(loadfile('big.lua')))
+ local f = coroutine.wrap(assert(_loadfile('big.lua')))
assert(f() == 'b')
assert(f() == 'a')
end
-dofile('nextvar.lua')
-dofile('pm.lua')
-dofile('api.lua')
-assert(dofile('events.lua') == 12)
-dofile('vararg.lua')
-dofile('closure.lua')
-dofile('errors.lua')
-dofile('math.lua')
-dofile('sort.lua')
-assert(dofile('verybig.lua') == 10); collectgarbage()
-dofile('files.lua')
+_dofile('nextvar.lua')
+_dofile('pm.lua')
+_dofile('api.lua')
+assert(_dofile('events.lua') == 12)
+_dofile('vararg.lua')
+_dofile('closure.lua')
+_dofile('errors.lua')
+_dofile('math.lua')
+_dofile('sort.lua')
+assert(_dofile('verybig.lua') == 10); collectgarbage()
+_dofile('files.lua')
if #msgs > 0 then
print("\ntests not performed:")
diff --git a/test/luajit-test-init.lua b/test/luajit-test-init.lua
new file mode 100644
index 00000000..aadd15af
--- /dev/null
+++ b/test/luajit-test-init.lua
@@ -0,0 +1,18 @@
+-- XXX: PUC Rio Lua 5.1 test suite checks that global variable
+-- `_loadfile()` exists and use it for code loading from test
+-- files If the variable is not defined then suite uses
+-- `loadfile()` as default. Same for the `_dofile()`.
+
+-- XXX: Some tests in PUC Rio Lua 5.1 test suite clean `arg`
+-- variable, so evaluate this once and use later.
+local path_to_sources = arg[0]:gsub("[^/]+$", "")
+
+-- luacheck: no global
+function _loadfile(filename)
+ return loadfile(path_to_sources..filename)
+end
+
+-- luacheck: no global
+function _dofile(filename)
+ return dofile(path_to_sources..filename)
+end
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 04/29] test: remove quotes in progname from PUC-Rio
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (2 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 03/29] test: adapt PUC-Rio suite for out-of-source build Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 05/29] test: adapt PUC-Rio test for arg presence Sergey Kaplun via Tarantool-patches
` (25 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
When LUAJIT_TEST_COMMAND extends the least `arg` slot with some string
containing double quotes, <os.execute> failed to exec this command for
child test.
This patch removes framing '"' to be able to run an extended command
containing '"' and run other test suites.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/main.lua | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/main.lua b/test/PUC-Rio-Lua-5.1-tests/main.lua
index f520896a..e72b1896 100644
--- a/test/PUC-Rio-Lua-5.1-tests/main.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/main.lua
@@ -11,7 +11,9 @@ out = os.tmpname()
do
local i = 0
while arg[i] do i=i-1 end
- progname = '"'..arg[i+1]..'"'
+ -- LuaJIT: remove framing '"' to be able to run an extended
+ -- command containing '"' and run other test suites.
+ progname = arg[i+1]
end
print(progname)
@@ -53,10 +55,12 @@ prepfile("print(a)", otherprog)
RUN("lua -l %s -l%s -lstring -l io %s > %s", prog, otherprog, otherprog, out)
checkout("1\n2\n2\n")
+-- LuaJIT: test file is adapted for LuaJIT's test system, see
+-- the comment near `progname` initialization.
local a = [[
assert(table.getn(arg) == 3 and arg[1] == 'a' and
arg[2] == 'b' and arg[3] == 'c')
- assert(arg[-1] == '--' and arg[-2] == "-e " and arg[-3] == %s)
+ assert(arg[-1] == '--' and arg[-2] == "-e " and arg[-3] == '%s')
assert(arg[4] == nil and arg[-4] == nil)
local a, b, c = ...
assert(... == 'a' and a == 'a' and b == 'b' and c == 'c')
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 05/29] test: adapt PUC-Rio test for arg presence
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (3 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 04/29] test: remove quotes in progname from PUC-Rio Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 06/29] test: disable PUC-Rio tests confused by -v output Sergey Kaplun via Tarantool-patches
` (24 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
The argument table `arg` can be read (and modified) by `LUA_INIT` and
`-e` chunks since the commit 92d9ff211ae864777a8580b5a7326d5f408161ce
(Set arg table before evaluating LUA_INIT and -e chunks.).
This behaviour is similar to Lua 5.3, so the test was adapted
considering PUC-Rio Lua 5.3 test suite taken from
https://www.lua.org/tests/lua-5.3.0-tests.tar.gz.
Resolves tarantool/tarantool#5686
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/main.lua | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/main.lua b/test/PUC-Rio-Lua-5.1-tests/main.lua
index e72b1896..606ebacc 100644
--- a/test/PUC-Rio-Lua-5.1-tests/main.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/main.lua
@@ -69,9 +69,19 @@ a = string.format(a, progname)
prepfile(a)
RUN('lua "-e " -- %s a b c', prog)
-prepfile"assert(arg==nil)"
+-- test 'arg' availability in libraries
+-- LuaJIT: LuaJIT v2.1.0-beta3 has extension from Lua 5.3:
+-- The argument table `arg` can be read (and modified)
+-- by `LUA_INIT` and `-e` chunks.
+-- See commit 92d9ff211ae864777a8580b5a7326d5f408161ce
+-- (Set arg table before evaluating LUA_INIT and -e chunks.).
+-- See also https://github.com/tarantool/tarantool/issues/5686.
+-- In Lua 5.3 this feature was introduced via commit
+-- 23f0ff95177eda2e0a80e3a48562cc6837705735.
+-- Test is adapted from PUC-Rio Lua 5.3 test suite.
+prepfile"assert(arg)"
prepfile("assert(arg)", otherprog)
-RUN("lua -l%s - < %s", prog, otherprog)
+RUN('env LUA_PATH="?;;" lua -l%s - < %s', prog, otherprog)
prepfile""
RUN("lua - < %s > %s", prog, out)
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 06/29] test: disable PUC-Rio tests confused by -v output
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (4 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 05/29] test: adapt PUC-Rio test for arg presence Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 07/29] test: disable PUC-Rio tests for bytecode header Sergey Kaplun via Tarantool-patches
` (23 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
Version and status are printed to stdout instead of stderr since
LuaJIT-2.0.0-beta11 (as it is not an error message).
See commit 0bd1a66f2f055211ef55834ccebca3b82d03c735
(Print version and JIT status to stdout, not stderr.).
This behavior is the same as in Lua 5.2.
This patch disables tests confused by unexpected -v output to stdout.
Relates to tarantool/tarantool#5687
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/main.lua | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/main.lua b/test/PUC-Rio-Lua-5.1-tests/main.lua
index 606ebacc..bc862c58 100644
--- a/test/PUC-Rio-Lua-5.1-tests/main.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/main.lua
@@ -103,26 +103,37 @@ prepfile[[
RUN("lua - < %s > %s", prog, out)
checkout("1\tnil\n")
+-- FIXME: Version and status are printed to stdout instead of
+-- stderr since LuaJIT-2.0.0-beta11 (as it is not an error
+-- message). See commit 0bd1a66f2f055211ef55834ccebca3b82d03c735
+-- (Print version and JIT status to stdout, not stderr.).
+-- This behavior is the same as in Lua 5.2.
+-- In Lua 5.2 this feature was introduced via commit
+-- 9e7de9473c65baee1f567852a778f2d33a47ea83.
+-- See also https://github.com/tarantool/tarantool/issues/5687.
prepfile[[
= (6*2-6) -- ===
a
= 10
print(a)
= a]]
-RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
-checkout("6\n10\n10\n\n")
+-- FIXME: Behavior is different for LuaJIT. See the comment above.
+-- RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
+-- checkout("6\n10\n10\n\n")
prepfile("a = [[b\nc\nd\ne]]\n=a")
print(prog)
-RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
-checkout("b\nc\nd\ne\n\n")
+-- FIXME: Behavior is different for LuaJIT. See the comment above.
+-- RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
+-- checkout("b\nc\nd\ne\n\n")
prompt = "alo"
prepfile[[ --
a = 2
]]
-RUN([[lua "-e_PROMPT='%s'" -i < %s > %s]], prompt, prog, out)
-checkout(string.rep(prompt, 3).."\n")
+-- FIXME: Behavior is different for LuaJIT. See the comment above.
+-- RUN([[lua "-e_PROMPT='%s'" -i < %s > %s]], prompt, prog, out)
+-- checkout(string.rep(prompt, 3).."\n")
s = [=[ --
function f ( x )
@@ -140,8 +151,9 @@ assert( a == b )
=f( 11 ) ]=]
s = string.gsub(s, ' ', '\n\n')
prepfile(s)
-RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
-checkout("11\n1\t2\n\n")
+-- FIXME: Behavior is different for LuaJIT. See the comment above.
+-- RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
+-- checkout("11\n1\t2\n\n")
prepfile[[#comment in 1st line without \n at the end]]
RUN("lua %s", prog)
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 07/29] test: disable PUC-Rio tests for bytecode header
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (5 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 06/29] test: disable PUC-Rio tests confused by -v output Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 08/29] test: adapt PUC-Rio tests counting GC steps Sergey Kaplun via Tarantool-patches
` (22 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
Loading bytecode with an extra header (BOM or "#") is disabled
for security reasons since LuaJIT-2.0.0-beta10.
For more information see comment for `lj_lex_setup()`
in <src/lj_lex.c>.
Also see commit 53a285c0c3544ff5dea7c67b741c3c2d06d22b47
(Disable loading bytecode with an extra header (BOM or #!).).
These tests are disabled for LuaJIT.
Relates to tarantool/tarantool#5691
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/main.lua | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/main.lua b/test/PUC-Rio-Lua-5.1-tests/main.lua
index bc862c58..bf9c2805 100644
--- a/test/PUC-Rio-Lua-5.1-tests/main.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/main.lua
@@ -158,13 +158,23 @@ prepfile(s)
prepfile[[#comment in 1st line without \n at the end]]
RUN("lua %s", prog)
+-- FIXME: Loading bytecode with an extra header (BOM or "#")
+-- is disabled for security reasons since LuaJIT-2.0.0-beta10.
+-- For more information see comment for `lj_lex_setup()`
+-- in <src/lj_lex.c>.
+-- Also see commit 53a285c0c3544ff5dea7c67b741c3c2d06d22b47
+-- (Disable loading bytecode with an extra header (BOM or #!).).
+-- See also https://github.com/tarantool/tarantool/issues/5691.
+-- The test is disabled for LuaJIT.
prepfile("#comment with a binary file\n"..string.dump(loadstring("print(1)")))
-RUN("lua %s > %s", prog, out)
-checkout("1\n")
+-- RUN("lua %s > %s", prog, out)
+-- checkout("1\n")
prepfile("#comment with a binary file\r\n"..string.dump(loadstring("print(1)")))
-RUN("lua %s > %s", prog, out)
-checkout("1\n")
+-- FIXME: Behavior is different for LuaJIT. See the comment above.
+-- The test is disabled for LuaJIT.
+-- RUN("lua %s > %s", prog, out)
+-- checkout("1\n")
-- close Lua with an open file
prepfile(string.format([[io.output(%q); io.write('alo')]], out))
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 08/29] test: adapt PUC-Rio tests counting GC steps
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (6 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 07/29] test: disable PUC-Rio tests for bytecode header Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 09/29] test: disable PUC-Rio suite tests for line hook Sergey Kaplun via Tarantool-patches
` (21 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
JIT compilation can unpredictably allocate or reference objects (or
traces itself). So, the amount of GC steps can vary from run to run.
This patch disables JIT machinery, if it is enabled, for stable GC
results.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/gc.lua | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/test/PUC-Rio-Lua-5.1-tests/gc.lua b/test/PUC-Rio-Lua-5.1-tests/gc.lua
index 86a9f758..b6925b69 100644
--- a/test/PUC-Rio-Lua-5.1-tests/gc.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/gc.lua
@@ -108,11 +108,21 @@ local function dosteps (siz)
return i
end
+-- LuaJIT: JIT compilation can unpredictably allocate or reference
+-- objects (or traces itself). Disable it if necessary for
+-- this chunk for stable GC results.
+local jit_is_enabled = jit.status()
+if jit_is_enabled then
+ jit.off()
+end
assert(dosteps(0) > 10)
assert(dosteps(6) < dosteps(2))
assert(dosteps(10000) == 1)
assert(collectgarbage("step", 1000000) == true)
assert(collectgarbage("step", 1000000))
+if jit_is_enabled then
+ jit.on()
+end
do
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 09/29] test: disable PUC-Rio suite tests for line hook
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (7 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 08/29] test: adapt PUC-Rio tests counting GC steps Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 10/29] test: adapt PUC-Rio tests with vararg functions Sergey Kaplun via Tarantool-patches
` (20 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
The LuaJIT's virtual machine interprets the bytecode following the
return from function (i.e. the one succeeding the call made) and located
on the line other than that return bytecode, as a new line trigger for
line hooks, unlike Lua does. This looks like "implementation-defined
behaviour" mentioned in https://luajit.org/status.html.
All tests checking the debug hook for a new line of code are affected
and disabled by this patch.
Relates to tarantool/tarantool#5693
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/db.lua | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/db.lua b/test/PUC-Rio-Lua-5.1-tests/db.lua
index 9d2c86f0..c9741981 100644
--- a/test/PUC-Rio-Lua-5.1-tests/db.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/db.lua
@@ -95,6 +95,26 @@ repeat
assert(g(f) == 'a')
until 1
+-- FIXME: The LuaJIT's virtual machine interprets the bytecode
+-- following the return from function (i.e. the one succeeding
+-- the call made) and located on the line other than that return
+-- bytecode, as a new line trigger for line hooks,
+-- unlike Lua does.
+-- Here is an example (it is joined in one line intend):
+--[[
+debug.sethook(function(_, l) print("LINE: "..l) end, "l") loadstring("\n\ns=nil")() debug.sethook()
+--]]
+-- This chunk prints for LuaJIT:
+--[[
+LINE: 3
+LINE: 1
+--]]
+-- But for Lua 5.1 it is only "LINE: 3" in the output.
+-- See also https://github.com/tarantool/tarantool/issues/5693.
+-- Considering implementation-defined behaviour difference
+-- (see also https://luajit.org/status.html) test is disabled for
+-- LuaJIT.
+--[=[
test([[if
math.sin(1)
then
@@ -149,7 +169,7 @@ end
]], {1,2,1,2,1,3})
test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
-
+--]=]
print'+'
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 10/29] test: adapt PUC-Rio tests with vararg functions
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (8 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 09/29] test: disable PUC-Rio suite tests for line hook Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 11/29] test: adapt PUC-Rio test for debug in vararg func Sergey Kaplun via Tarantool-patches
` (19 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 2922 bytes --]
Lua 5.1 interprets `...` in the vararg functions as an additional
local argument unlike LuaJIT does. This behaviour is extension from
Lua 5.2.
This patch adapted tests considering behaviour of LuaJIT and Lua 5.2.
The tests are adapted like it done in Lua 5.2 test suite taken from
https://www.lua.org/tests/lua-5.2.0-tests.tar.gz.
Tests in the following files are adapted:
* db.lua
* vararg.lua
Resolves tarantool/tarantool#5712
Part of tarantool/tarantool#5694
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/db.lua | 7 +++++++
test/PUC-Rio-Lua-5.1-tests/vararg.lua | 17 +++++++++++++----
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/db.lua b/test/PUC-Rio-Lua-5.1-tests/db.lua
index c9741981..82d1cfa6 100644
--- a/test/PUC-Rio-Lua-5.1-tests/db.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/db.lua
@@ -224,6 +224,13 @@ assert(debug.getinfo(1, "l").currentline == L+11) -- check count of lines
function g(...)
+ -- LuaJIT: Lua 5.1 interprets `...` in the vararg functions like
+ -- an additional local argument unlike LuaJIT does.
+ -- This extension is from Lua 5.2.
+ -- See also https://github.com/tarantool/tarantool/issues/5694.
+ -- Test is adapted from PUC-Rio Lua 5.2 test suite by adding
+ -- additional variable `arg`.
+ local arg = {...}
do local a,b,c; a=math.sin(40); end
local feijao
local AAAA,B = "xuxu", "mamão"
diff --git a/test/PUC-Rio-Lua-5.1-tests/vararg.lua b/test/PUC-Rio-Lua-5.1-tests/vararg.lua
index ae068fac..a9c3a6a2 100644
--- a/test/PUC-Rio-Lua-5.1-tests/vararg.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/vararg.lua
@@ -2,9 +2,14 @@ print('testing vararg')
_G.arg = nil
+-- LuaJIT: Lua 5.1 interprets ... in the vararg functions as an
+-- additional local argument, unlike LuaJIT does. All extra
+-- arguments are set into `arg` variable. This extension
+-- is from Lua 5.2.
+-- See also https://github.com/tarantool/tarantool/issues/5712.
+-- Test is adapted from PUC-Rio Lua 5.2 test suite.
function f(a, ...)
- assert(type(arg) == 'table')
- assert(type(arg.n) == 'number')
+ local arg = {n = select('#', ...), ...}
for i=1,arg.n do assert(a[i]==arg[i]) end
return arg.n
end
@@ -17,7 +22,9 @@ function c12 (...)
return res, 2
end
-function vararg (...) return arg end
+-- LuaJIT: Test chunk is adapted from PUC-Rio Lua 5.2 test suite.
+-- See the comment above.
+function vararg (...) return {n = select('#', ...), ...} end
local call = function (f, args) return f(unpack(args, 1, args.n)) end
@@ -42,7 +49,9 @@ a = call(print, {'+'})
assert(a == nil)
local t = {1, 10}
-function t:f (...) return self[arg[1]]+arg.n end
+-- LuaJIT: Test chunk is adapted from PUC-Rio Lua 5.2 test suite.
+-- See the comment above.
+function t:f (...) local arg = {...}; return self[...]+#arg end
assert(t:f(1,4) == 3 and t:f(2) == 11)
print('+')
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 11/29] test: adapt PUC-Rio test for debug in vararg func
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (9 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 10/29] test: adapt PUC-Rio tests with vararg functions Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 12/29] test: adapt PUC-Rio test with count hooks Sergey Kaplun via Tarantool-patches
` (18 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
Lua 5.1 interprets `...` in the vararg functions as an additional
local argument unlike LuaJIT does. So, `a:f()` function will not set
the corresponding table `arg`, as test expects.
Implicit `arg` parameter for old-style vararg functions was finally
removed in Lua 5.2. The test is adapted from PUC-Rio Lua 5.2 test suite
by removing additional check for amount of arguments via `arg.n`.
Lua 5.2 test suite is taken from
https://www.lua.org/tests/lua-5.2.0-tests.tar.gz.
Resolves tarantool/tarantool#5694
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/db.lua | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/db.lua b/test/PUC-Rio-Lua-5.1-tests/db.lua
index 82d1cfa6..6c412170 100644
--- a/test/PUC-Rio-Lua-5.1-tests/db.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/db.lua
@@ -303,7 +303,16 @@ debug.sethook(function (e)
end, "c")
a:f(1,2,3,4,5)
-assert(X.self == a and X.a == 1 and X.b == 2 and X.arg.n == 3 and X.c == nil)
+
+-- LuaJIT: Lua 5.1 interprets `...` in the vararg functions as
+-- an additional local argument unlike LuaJIT does.
+-- So, `a:f()` function will not set the corresponding table
+-- `arg`, as test expects.
+-- Implicit `arg` parameter for old-style vararg functions was
+-- finally removed in Lua 5.2
+-- The test is adapted from PUC-Rio Lua 5.2 test suite by removing
+-- additional `arg.n == 3` check.
+assert(X.self == a and X.a == 1 and X.b == 2 and X.c == nil)
assert(XX == 12)
assert(debug.gethook() == nil)
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 12/29] test: adapt PUC-Rio test with count hooks
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (10 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 11/29] test: adapt PUC-Rio test for debug in vararg func Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 13/29] test: disable PUC-Rio test for tail call info Sergey Kaplun via Tarantool-patches
` (17 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
LuaJIT does not check hooks at traces without defined
-DLUAJIT_ENABLE_CHECKHOOK. For more information see <src/lj_record.c>
or commit 6bce6b118eeb2bb7f36157de158e5cccf0ea68e5 (Add compile-time
option LUAJIT_ENABLE_CHECKHOOK. Disabled by default.).
This patch adapts these tests for LuaJIT by disabling JIT while testing
count hooks.
Resolves tarantool/tarantool#5701
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/db.lua | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/test/PUC-Rio-Lua-5.1-tests/db.lua b/test/PUC-Rio-Lua-5.1-tests/db.lua
index 6c412170..db69b2df 100644
--- a/test/PUC-Rio-Lua-5.1-tests/db.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/db.lua
@@ -350,6 +350,18 @@ assert(debug.setupvalue(io.read, 1, 10) == nil)
-- testing count hooks
local a=0
+-- LuaJIT: LuaJIT does not check hooks at traces without defined
+-- -DLUAJIT_ENABLE_CHECKHOOK.
+-- For more information see <src/lj_record.c> or commit
+-- 6bce6b118eeb2bb7f36157de158e5cccf0ea68e5 (Add compile-time
+-- option LUAJIT_ENABLE_CHECKHOOK. Disabled by default.).
+-- See also https://github.com/tarantool/tarantool/issues/5701
+-- Test is adapted for LuaJIT by disabling JIT while
+-- testing count hooks.
+local jit_is_enabled = jit.status()
+if jit_is_enabled then
+ jit.off()
+end
debug.sethook(function (e) a=a+1 end, "", 1)
a=0; for i=1,1000 do end; assert(1000 < a and a < 1012)
debug.sethook(function (e) a=a+1 end, "", 4)
@@ -362,6 +374,9 @@ debug.sethook(print, "", 2^24 - 1) -- count upperbound
local f,m,c = debug.gethook()
assert(({debug.gethook()})[3] == 2^24 - 1)
debug.sethook()
+if jit_is_enabled then
+ jit.on()
+end
-- tests for tail calls
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 13/29] test: disable PUC-Rio test for tail call info
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (11 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 12/29] test: adapt PUC-Rio test with count hooks Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 14/29] test: adapt PUC-Rio test with activeline check Sergey Kaplun via Tarantool-patches
` (16 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
LuaJIT does not provide information about tail calls in debug.getinfo(),
unlike Lua does. This missed feature is described in
https://luajit.org/status.html.
This patch disables tests for tail call checks and getfenv() checks,
because tail calls do not provide an additional call frame for LuaJIT
and level number given to getfenv() should be changed.
Relates to tarantool/tarantool#5702
Relates to tarantool/tarantool#5703
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/db.lua | 29 ++++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/db.lua b/test/PUC-Rio-Lua-5.1-tests/db.lua
index db69b2df..f81b86cf 100644
--- a/test/PUC-Rio-Lua-5.1-tests/db.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/db.lua
@@ -403,18 +403,29 @@ function g1(x) g(x) end
local function h (x) local f=g1; return f(x) end
-h(true)
+-- FIXME: LuaJIT does not provide information about tail calls,
+-- unlike Lua does. See also https://luajit.org/status.html.
+-- getfenv() behaviour is also different here, because tail calls
+-- do not provide additional call frame for LuaJIT and level
+-- number should be changed.
+-- Test is disabled for LuaJIT.
+-- See also https://github.com/tarantool/tarantool/issues/5702.
+-- h(true)
local b = {}
-debug.sethook(function (e) table.insert(b, e) end, "cr")
-h(false)
-debug.sethook()
+-- FIXME: Behavior is different for LuaJIT. See the comment above.
+-- Test is disabled for LuaJIT.
+-- debug.sethook(function (e) table.insert(b, e) end, "cr")
+-- h(false)
+-- debug.sethook()
local res = {"return", -- first return (from sethook)
"call", "call", "call", "call",
"return", "tail return", "return", "tail return",
"call", -- last call (to sethook)
}
-for _, k in ipairs(res) do assert(k == table.remove(b, 1)) end
+-- FIXME: Behavior is different for LuaJIT. See the comment above.
+-- Test is disabled for LuaJIT.
+-- for _, k in ipairs(res) do assert(k == table.remove(b, 1)) end
lim = 30000
@@ -426,7 +437,9 @@ local function foo (x)
end
end
-foo(lim)
+-- FIXME: Behavior is different for LuaJIT.
+-- See the comment to `h()` above. Test is disabled for LuaJIT.
+-- foo(lim)
print"+"
@@ -462,7 +475,9 @@ end
local co = coroutine.create(f)
coroutine.resume(co, 3)
-checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
+-- FIXME: Behavior is different for LuaJIT.
+-- See the comment to `h()` above. Test is disabled for LuaJIT.
+-- checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
co = coroutine.create(function (x)
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 14/29] test: adapt PUC-Rio test with activeline check
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (12 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 13/29] test: disable PUC-Rio test for tail call info Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 15/29] test: disable PUC-Rio test for per-coroutine hooks Sergey Kaplun via Tarantool-patches
` (15 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
LuaJIT does not report the line with single "end" statement
(the last line of the function) as an active line in
debug.getinfo(), unlike Lua does. There is no bytecode
related to this line, so it is "unreachable" and
may be considered not active.
This patch excludes the last line of the function from the check,
considering LuaJIT's behaviour.
Resolves tarantool/tarantool#5708
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/db.lua | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/db.lua b/test/PUC-Rio-Lua-5.1-tests/db.lua
index f81b86cf..9ad58264 100644
--- a/test/PUC-Rio-Lua-5.1-tests/db.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/db.lua
@@ -495,7 +495,15 @@ local _, l = coroutine.resume(co, 10)
local x = debug.getinfo(co, 1, "lfLS")
assert(x.currentline == l.currentline and x.activelines[x.currentline])
assert(type(x.func) == "function")
-for i=x.linedefined + 1, x.lastlinedefined do
+-- LuaJIT: LuaJIT does not report the line with single "end"
+-- statement (the last line of the function) as an active line in
+-- debug.getinfo(), unlike Lua does. There is no bytecode
+-- related to this line, so it is "unreachable" and
+-- may be considered not active.
+-- See also https://github.com/tarantool/tarantool/issues/5708.
+-- Test is adapted for LuaJIT's behaviour by avoiding the last
+-- line check.
+for i=x.linedefined + 1, x.lastlinedefined - 1 do
assert(x.activelines[i])
x.activelines[i] = nil
end
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 15/29] test: disable PUC-Rio test for per-coroutine hooks
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (13 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 14/29] test: adapt PUC-Rio test with activeline check Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 16/29] test: adapt PUC-Rio test for %q in string.format Sergey Kaplun via Tarantool-patches
` (14 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
LuaJIT does not support per-coroutine hooks. Hooks are set for the
whole VM. See actual status at https://luajit.org/status.html.
This patch disables tests for per-coroutine hooks in <db.lua>.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/db.lua | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/db.lua b/test/PUC-Rio-Lua-5.1-tests/db.lua
index 9ad58264..954a1d52 100644
--- a/test/PUC-Rio-Lua-5.1-tests/db.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/db.lua
@@ -515,8 +515,12 @@ a,b = debug.getlocal(co, 1, 2)
assert(a == "a" and b == 1)
debug.setlocal(co, 1, 2, "hi")
assert(debug.gethook(co) == foo)
-assert(table.getn(tr) == 2 and
- tr[1] == l.currentline-1 and tr[2] == l.currentline)
+-- LuaJIT: LuaJIT does not support per-coroutine hooks.
+-- Hook is set for the whole VM.
+-- See also https://luajit.org/status.html.
+-- Test is disabled for LuaJIT.
+-- assert(table.getn(tr) == 2 and
+-- tr[1] == l.currentline-1 and tr[2] == l.currentline)
a,b,c = pcall(coroutine.resume, co)
assert(a and b and c == l.currentline+1)
@@ -524,9 +528,13 @@ checktraceback(co, {"yield", "in function <"})
a,b = coroutine.resume(co)
assert(a and b == "hi")
-assert(table.getn(tr) == 4 and tr[4] == l.currentline+2)
+-- LuaJIT: Behavior is different for LuaJIT.
+-- See the comment above. Test is disabled for LuaJIT.
+-- assert(table.getn(tr) == 4 and tr[4] == l.currentline+2)
assert(debug.gethook(co) == foo)
-assert(debug.gethook() == nil)
+-- LuaJIT: Behavior is different for LuaJIT.
+-- See the comment above. Test is disabled for LuaJIT.
+-- assert(debug.gethook() == nil)
checktraceback(co, {})
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 16/29] test: adapt PUC-Rio test for %q in string.format
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (14 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 15/29] test: disable PUC-Rio test for per-coroutine hooks Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 17/29] test: disable locale-dependent PUC-Rio tests Sergey Kaplun via Tarantool-patches
` (13 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 4234 bytes --]
LuaJIT since v2.0.0-beta6 has extension from Lua 5.2:
string.format(): %q reversible.
See also https://luajit.org/extensions.html#lua52.
The q option formats a string in a form suitable to be safely read
back by the Lua interpreter [1].
In Lua 5.1, '\0' was converted to "\000" unconditionally.
In Lua 5.2, control characters are written as \nnn when needed, see
d62a21b9d379a576bae7426c80039ca1a4d2bb07 ("when formatting with '%q',
all control characters are coded as \nnn.") [1]. In this patch, %q
specifier starts writing control characters to a new string in the same
way through \d, instead of their binary representation as it is. If the
control character is followed by a digit, then for the correct work of
the parser, it is necessary to extend the escape sequence to 3
significant characters (otherwise, the transition "\0002" -> "\02"
corrupts string). For this patch, the expansion is performed
unconditionally (the check for the next symbol is not performed) if this
first symbol is a zero byte.
Consistent work with the zero byte processing omitting the custom check
was added in the commit 658ea8752b979102627e2fede7b7ddfbb67ba6c9 ("no
need to handle '\0' differently from other control chars in format
'%q'") [2]. Note, that this patch does not change the semantics of %q
specifier - the new string can still be "safely read back by the Lua
interpreter".
[1]: https://www.lua.org/manual/5.1/manual.html#pdf-string.format
[2]: https://github.com/lua/lua/commit/d62a21b9d379a576bae7426c80039ca1a4d2bb07
[3]: https://github.com/lua/lua/commit/658ea8752b979102627e2fede7b7ddfbb67ba6c9
This patch adapts test for LuaJIT and Lua 5.2 behaviour considering
the test from Lua 5.2 test suite taken from
https://www.lua.org/tests/lua-5.2.0-tests.tar.gz.
Resolves tarantool/tarantool#5710
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/strings.lua | 38 +++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/strings.lua b/test/PUC-Rio-Lua-5.1-tests/strings.lua
index 237dbad3..0eee4c6e 100644
--- a/test/PUC-Rio-Lua-5.1-tests/strings.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/strings.lua
@@ -102,7 +102,43 @@ print('+')
x = '"ílo"\n\\'
assert(string.format('%q%s', x, x) == '"\\"ílo\\"\\\n\\\\""ílo"\n\\')
-assert(string.format('%q', "\0") == [["\000"]])
+--[[
+LuaJIT: LuaJIT since v2.0.0-beta6 has extension from Lua 5.2:
+string.format(): %q reversible.
+
+The q option formats a string in a form suitable to be safely read
+back by the Lua interpreter [1].
+
+In Lua 5.1, '\0' was converted to "\000" unconditionally.
+
+In Lua 5.2, control characters are written as \nnn when needed,
+see d62a21b9d379a576bae7426c80039ca1a4d2bb07 ("when formatting
+with '%q', all control characters are coded as \nnn.") [1].
+In this patch, %q specifier starts writing control characters to
+a new string in the same way through \d, instead of their binary
+representation as it is. If the control character is followed by
+a digit, then for the correct work of the parser, it is necessary
+to extend the escape sequence to 3 significant characters
+(otherwise, the transition "\0002" -> "\02" corrupts string).
+For this patch, the expansion is performed unconditionally
+(the check for the next symbol is not performed) if this first
+symbol is a zero byte.
+
+Consistent work with the zero byte processing omitting the custom
+check was added in the commit
+658ea8752b979102627e2fede7b7ddfbb67ba6c9 ("no need to handle '\0'
+differently from other control chars in format '%q'") [2]. Note,
+that this patch does not change the semantics of %q specifier -
+the new string can still be "safely read back by the Lua
+interpreter".
+
+[1]: https://www.lua.org/manual/5.1/manual.html#pdf-string.format
+[2]: https://github.com/lua/lua/commit/d62a21b9d379a576bae7426c80039ca1a4d2bb07
+[3]: https://github.com/lua/lua/commit/658ea8752b979102627e2fede7b7ddfbb67ba6c9
+
+Test is adapted from PUC-Rio Lua 5.2 test suite.
+--]]
+assert(string.format('%q', "\0") == [["\0"]])
assert(string.format("\0%c\0%c%x\0", string.byte("á"), string.byte("b"), 140) ==
"\0á\0b8c\0")
assert(string.format('') == "")
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 17/29] test: disable locale-dependent PUC-Rio tests
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (15 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 16/29] test: adapt PUC-Rio test for %q in string.format Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 18/29] test: use math.fmod in " Sergey Kaplun via Tarantool-patches
` (12 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 2031 bytes --]
LuaJIT doesn't compare strings by `strcoll()`, like Lua 5.1 does.
So locale-depended tests in <strings.lua> are disabled.
Also, LuaJIT doesn't use `strtod()` dependent on the locale for parsing,
unlike Lua does. See <src/lj_strscan.c> for more info. See also
http://luajit.org/extensions.html#tonumber.
Locale-depended tests in <literals.lua> are disabled.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/literals.lua | 5 +++++
test/PUC-Rio-Lua-5.1-tests/strings.lua | 5 +++++
2 files changed, 10 insertions(+)
diff --git a/test/PUC-Rio-Lua-5.1-tests/literals.lua b/test/PUC-Rio-Lua-5.1-tests/literals.lua
index 01d84d5a..4fc3e88d 100644
--- a/test/PUC-Rio-Lua-5.1-tests/literals.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/literals.lua
@@ -158,6 +158,10 @@ end
-- testing decimal point locale
+-- LuaJIT: LuaJIT doesn't use `strtod()` dependent on the locale,
+-- unlike Lua does. See <src/lj_strscan.c> for more info.
+-- Tests are disabled for LuaJIT.
+--[[
if os.setlocale("pt_BR") or os.setlocale("ptb") then
assert(tonumber("3,4") == 3.4 and tonumber"3.4" == nil)
assert(assert(loadstring("return 3.4"))() == 3.4)
@@ -171,6 +175,7 @@ else
(Message or print)(
'\a\n >>> pt_BR locale not available: skipping decimal point tests <<<\n\a')
end
+--]]
print('OK')
diff --git a/test/PUC-Rio-Lua-5.1-tests/strings.lua b/test/PUC-Rio-Lua-5.1-tests/strings.lua
index 0eee4c6e..67e42cb6 100644
--- a/test/PUC-Rio-Lua-5.1-tests/strings.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/strings.lua
@@ -188,6 +188,10 @@ local function trylocale (w)
return false
end
+-- LuaJIT: LuaJIT doesn't compare strings by `strcoll()`,
+-- like Lua 5.1 does.
+-- Tests are disabled for LuaJIT.
+--[[
if not trylocale("collate") then
print("locale not supported")
else
@@ -202,6 +206,7 @@ else
assert(string.gsub("áÁéÉ", "%u", "x") == "áxéx")
assert(string.upper"áÁé{xuxu}ção" == "ÁÁÉ{XUXU}ÇÃO")
end
+--]]
os.setlocale("C")
assert(os.setlocale() == 'C')
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 18/29] test: use math.fmod in PUC-Rio tests
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (16 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 17/29] test: disable locale-dependent PUC-Rio tests Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 19/29] test: remove string.gfind assert in PUC-Rio test Sergey Kaplun via Tarantool-patches
` (11 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
In Lua 5.1 math.mod() is renamed to math.fmod() if one builds Lua 5.1
without `-DLUA_COMPAT_MOD` flag.
LuaJIT has math.fmod() instead of old-style math.mod() built-in.
This backward compatibility was dropped via commit
de5568e0eaf22d2c7d58c2cbd9060460abc4ff2f
(Remove Lua 5.0 compatibility defines.).
This patch replaces usage of math.mod with new-style math.fmod
in the following files:
* closure.lua
* constructs.lua
* math.lua
* nextvar.lua
Resolves tarantool/tarantool#5711
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/closure.lua | 4 +++-
test/PUC-Rio-Lua-5.1-tests/constructs.lua | 6 ++++--
test/PUC-Rio-Lua-5.1-tests/math.lua | 3 ++-
test/PUC-Rio-Lua-5.1-tests/nextvar.lua | 3 ++-
4 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/closure.lua b/test/PUC-Rio-Lua-5.1-tests/closure.lua
index 27ca0adf..fdcfe934 100644
--- a/test/PUC-Rio-Lua-5.1-tests/closure.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/closure.lua
@@ -254,7 +254,9 @@ function filter (p, g)
while 1 do
local n = g()
if n == nil then return end
- if math.mod(n, p) ~= 0 then coroutine.yield(n) end
+ -- LuaJIT: use `math.fmod()` instead of old-style
+ -- `math.mod()`.
+ if math.fmod(n, p) ~= 0 then coroutine.yield(n) end
end
end)
end
diff --git a/test/PUC-Rio-Lua-5.1-tests/constructs.lua b/test/PUC-Rio-Lua-5.1-tests/constructs.lua
index 5fb37986..970b8c4b 100644
--- a/test/PUC-Rio-Lua-5.1-tests/constructs.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/constructs.lua
@@ -202,7 +202,8 @@ function ID(x) return x end
function f(t, i)
local b = t.n
- local res = math.mod(math.floor(i/c), b)+1
+ -- LuaJIT: use `math.fmod()` instead of old-style `math.mod()`.
+ local res = math.fmod(math.floor(i/c), b)+1
c = c*b
return t[res]
end
@@ -233,7 +234,8 @@ repeat
]], s1, s, s1, s, s1, s, s1, s, s)
assert(loadstring(s))()
assert(X and not NX and not WX1 == K and not WX2 == K)
- if math.mod(i,4000) == 0 then print('+') end
+ -- LuaJIT: use `math.fmod()` instead of old-style `math.mod()`.
+ if math.fmod(i,4000) == 0 then print('+') end
i = i+1
until i==c
diff --git a/test/PUC-Rio-Lua-5.1-tests/math.lua b/test/PUC-Rio-Lua-5.1-tests/math.lua
index 5076f38d..f66ce196 100644
--- a/test/PUC-Rio-Lua-5.1-tests/math.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/math.lua
@@ -100,7 +100,8 @@ assert(math.abs(-10) == 10)
assert(eq(math.atan2(1,0), math.pi/2))
assert(math.ceil(4.5) == 5.0)
assert(math.floor(4.5) == 4.0)
-assert(math.mod(10,3) == 1)
+-- LuaJIT: use `math.fmod()` instead of old-style `math.mod()`.
+assert(math.fmod(10,3) == 1)
assert(eq(math.sqrt(10)^2, 10))
assert(eq(math.log10(2), math.log(2)/math.log(10)))
assert(eq(math.exp(0), 1))
diff --git a/test/PUC-Rio-Lua-5.1-tests/nextvar.lua b/test/PUC-Rio-Lua-5.1-tests/nextvar.lua
index 7ceaa75a..c16bb53a 100644
--- a/test/PUC-Rio-Lua-5.1-tests/nextvar.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/nextvar.lua
@@ -201,7 +201,8 @@ print('+')
a = {}
for i=0,10000 do
- if math.mod(i,10) ~= 0 then
+ -- LuaJIT: use `math.fmod()` instead of old-style `math.mod()`.
+ if math.fmod(i,10) ~= 0 then
a['x'..i] = i
end
end
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 19/29] test: remove string.gfind assert in PUC-Rio test
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (17 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 18/29] test: use math.fmod in " Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 20/29] test: disable PUC-Rio test for getfenv in tailcall Sergey Kaplun via Tarantool-patches
` (10 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
In Lua 5.1 function `string.gfind()` was renamed to `string.gmatch()`.
You can use it if Lua 5.1 is built with compile-time option
`-DLUA_COMPAT_GFIND`.
This built-in is removed from LuaJIT via commit
de5568e0eaf22d2c7d58c2cbd9060460abc4ff2f (Remove Lua 5.0 compatibility
defines.).
This patch removes test checking that `string.gfind()` and
`string.gmatch() is the same function.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/pm.lua | 1 -
1 file changed, 1 deletion(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/pm.lua b/test/PUC-Rio-Lua-5.1-tests/pm.lua
index fa125dc9..b159b6bd 100644
--- a/test/PUC-Rio-Lua-5.1-tests/pm.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/pm.lua
@@ -223,7 +223,6 @@ assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI")
-- tests for gmatch
-assert(string.gfind == string.gmatch)
local a = 0
for i in string.gmatch('abcde', '()') do assert(i == a+1); a=i end
assert(a==6)
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 20/29] test: disable PUC-Rio test for getfenv in tailcall
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (18 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 19/29] test: remove string.gfind assert in PUC-Rio test Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 21/29] test: disable PUC-Rio test for variables in error Sergey Kaplun via Tarantool-patches
` (9 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
Tail calls are not taken into account for call-level counting. So,
`getfenv()` behaviour in LuaJIT is different from Lua 5.1 in tailcalls.
LuaJIT doesn't create an additional frame for tailcalls, just uses
the previous one.
This patch disables test for the return result of `getfenv()` tailcall.
Default value (equals to 1) of `getfenv()` function's argument (function
level) is invalid for this tailcall -- LuaJIT can't provide necessary
debug information for the frame.
Relates to tarantool/tarantool#5713
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/closure.lua | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/closure.lua b/test/PUC-Rio-Lua-5.1-tests/closure.lua
index fdcfe934..551fe70d 100644
--- a/test/PUC-Rio-Lua-5.1-tests/closure.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/closure.lua
@@ -174,7 +174,15 @@ f = coroutine.wrap(foo)
local a = {}
assert(f(a) == _G)
local a,b = pcall(f)
-assert(a and b == _G)
+-- FIXME: LuaJIT doesn't take into account tail calls for
+-- call-level counting, so `getfenv()` behaviour is different
+-- in tail calls. For example, this `pcall()` returns false,
+-- because `getfenv()` default level is 1 which is invalid for
+-- this case when is called from tail call (`lj_debug_frame()`
+-- returns NULL).
+-- See also https://github.com/tarantool/tarantool/issues/5713.
+-- Test is disabled for LuaJIT for now.
+-- assert(a and b == _G)
-- tests for multiple yield/resume arguments
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 21/29] test: disable PUC-Rio test for variables in error
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (19 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 20/29] test: disable PUC-Rio test for getfenv in tailcall Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 22/29] test: disable PUC-Rio test for fast function name Sergey Kaplun via Tarantool-patches
` (8 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
LuaJIT includes the variable name to the error message, when try to
call non-function object without __call metamethod.
Also, LuaJIT includes the variable name to the error message, when try
to perform unacceptable arithmetic operation with the variable.
Lua 5.1 doesn't report the variable name in these errors.
The test checking, that variable name isn't reported, is disabled by
this patch.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/errors.lua | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/errors.lua b/test/PUC-Rio-Lua-5.1-tests/errors.lua
index e8812117..c9d79279 100644
--- a/test/PUC-Rio-Lua-5.1-tests/errors.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/errors.lua
@@ -72,8 +72,13 @@ checkmessage("b=1; local aaa='a'; x=aaa+b", "local 'aaa'")
checkmessage("aaa={}; x=3/aaa", "global 'aaa'")
checkmessage("aaa='2'; b=nil;x=aaa*b", "global 'b'")
checkmessage("aaa={}; x=-aaa", "global 'aaa'")
-assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
-assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'"))
+-- LuaJIT: LuaJIT includes variable name to the error message.
+-- It looks like:
+-- "attempt to perform arithmetic on global 'aaa' (a table value)"
+-- Lua 5.1 doesn't report the variable name here.
+-- Tests are disabled for LuaJIT.
+-- assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
+-- assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'"))
checkmessage([[aaa=9
repeat until 3==3
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 22/29] test: disable PUC-Rio test for fast function name
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (20 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 21/29] test: disable PUC-Rio test for variables in error Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 23/29] test: disable PUC-Rio test for non-asci identifier Sergey Kaplun via Tarantool-patches
` (7 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
When LuaJIT tries to detect function's name for error message, it
determines the bytecode position first, via `debug_framepc()`. For
tailcall there is no creation of additional Lua frame, so the current
frame is a C protected frame (at the moment of the error throwing).
`debug_framepc()` can't determine bytecode position for non-Lua frames,
so the fast function name is not detected.
This patch disables the test that checks the name of built-in functions
reported in error in tail call.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/errors.lua | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/errors.lua b/test/PUC-Rio-Lua-5.1-tests/errors.lua
index c9d79279..1cc01564 100644
--- a/test/PUC-Rio-Lua-5.1-tests/errors.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/errors.lua
@@ -105,9 +105,17 @@ while 1 do
insert(prefix, a)
end]], "global 'insert'")
-checkmessage([[ -- tail call
- return math.sin("a")
-]], "'sin'")
+-- LuaJIT: When LuaJIT tries to detect function's name for error
+-- message, it determines the bytecode position first, via
+-- `debug_framepc()`. For tailcall there is no creation of
+-- additional Lua frame, so the current frame is a C protected
+-- frame (at the moment of the error throwing). `debug_framepc()`
+-- can't determine bytecode position for non-Lua frames, so
+-- the fast function name is not detected.
+-- The test is disabled for LuaJIT.
+-- checkmessage([[ -- tail call
+-- return math.sin("a")
+-- ]], "'sin'")
checkmessage([[collectgarbage("nooption")]], "invalid option")
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 23/29] test: disable PUC-Rio test for non-asci identifier
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (21 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 22/29] test: disable PUC-Rio test for fast function name Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 24/29] test: disable PUC-Rio test for syntax level error Sergey Kaplun via Tarantool-patches
` (6 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
LuaJIT does not forbid using non-alphanumeric symbols as identifiers,
unlike Lua does.
This patch disables the test that expects an error during parsing the
variable name containing octal \255 as the first char in a variable
name.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/errors.lua | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/errors.lua b/test/PUC-Rio-Lua-5.1-tests/errors.lua
index 1cc01564..ee07e14d 100644
--- a/test/PUC-Rio-Lua-5.1-tests/errors.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/errors.lua
@@ -206,7 +206,11 @@ checksyntax("[[a]]", "", "[[a]]", 1)
checksyntax("'aa'", "", "'aa'", 1)
-- test 255 as first char in a chunk
-checksyntax("\255a = 1", "", "\255", 1)
+-- LuaJIT: LuaJIT does not forbid using non-alphanumeric symbols
+-- as identifiers, unlike Lua does.
+-- For more details see <src/lj_char.c> and <src/lj_lex.c>.
+-- Test is disabled for LuaJIT.
+-- checksyntax("\255a = 1", "", "\255", 1)
doit('I = loadstring("a=9+"); a=3')
assert(a==3 and I == nil)
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 24/29] test: disable PUC-Rio test for syntax level error
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (22 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 23/29] test: disable PUC-Rio test for non-asci identifier Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 25/29] test: disable PUC-RIO tests for several -l options Sergey Kaplun via Tarantool-patches
` (5 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
When LuaJIT is compiled with LUAJIT_ENABLE_GC64, LJ_MAX_SLOTS limit is
reached and error LJ_ERR_XSLOTS ("function or expression too complex")
is raised earlier, than LJ_MAX_XLEVEL limit is reached and error
LJ_ERR_XLEVELS ("chunk has too many syntax levels") is raised.
This happens, because, when GC64 support is enabled, every
function's call needs twice more slots on the coroutine stack
(since LJ_FR2 is also set).
This patch disabled the test expecting the LJ_ERR_XLEVEL error, but
failing with the LJ_ERR_XSLOTS error.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/errors.lua | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/errors.lua b/test/PUC-Rio-Lua-5.1-tests/errors.lua
index ee07e14d..440f68cd 100644
--- a/test/PUC-Rio-Lua-5.1-tests/errors.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/errors.lua
@@ -232,7 +232,16 @@ local function testrep (init, rep)
end
testrep("a=", "{")
testrep("a=", "(")
-testrep("", "a(")
+-- LuaJIT: When compiled with LUAJIT_ENABLE_GC64, LJ_MAX_SLOTS
+-- limit is reached and error LJ_ERR_XSLOTS ("function or
+-- expression too complex") is raised earlier, than LJ_MAX_XLEVEL
+-- limit is reached and error LJ_ERR_XLEVELS ("chunk has too many
+-- syntax levels") is raised.
+-- This happens, because, when GC64 support is enabled, every
+-- function's call needs twice more slots on the coroutine stack
+-- (since LJ_FR2 is also set).
+-- Test is disabled for LuaJIT.
+-- testrep("", "a(")
testrep("", "do ")
testrep("", "while a do ")
testrep("", "if a then else ")
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 25/29] test: disable PUC-RIO tests for several -l options
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (23 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 24/29] test: disable PUC-Rio test for syntax level error Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 26/29] test: disable PUC-Rio test for checking arg layout Sergey Kaplun via Tarantool-patches
` (4 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
Tarantool may crash when -e or -l option and their argument are not
separated by space.
This patch disables tests leading to crash.
Relates to tarantool/tarantool#5747
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/main.lua | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/main.lua b/test/PUC-Rio-Lua-5.1-tests/main.lua
index bf9c2805..96006d1b 100644
--- a/test/PUC-Rio-Lua-5.1-tests/main.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/main.lua
@@ -52,8 +52,12 @@ end
-- test 2 files
prepfile("print(1); a=2")
prepfile("print(a)", otherprog)
-RUN("lua -l %s -l%s -lstring -l io %s > %s", prog, otherprog, otherprog, out)
-checkout("1\n2\n2\n")
+-- FIXME: Tarantool may crash when -e or -l option and their
+-- argument are not separated by space.
+-- The test is disabled for the Tarantool binary.
+-- See https://github.com/tarantool/tarantool/issues/5747.
+-- RUN("lua -l %s -l%s -lstring -l io %s > %s", prog, otherprog, otherprog, out)
+-- checkout("1\n2\n2\n")
-- LuaJIT: test file is adapted for LuaJIT's test system, see
-- the comment near `progname` initialization.
@@ -92,8 +96,12 @@ prepfile[[print(({...})[30])]]
RUN("lua %s %s > %s", prog, string.rep(" a", 30), out)
checkout("a\n")
-RUN([[lua "-eprint(1)" -ea=3 -e "print(a)" > %s]], out)
-checkout("1\n3\n")
+-- FIXME: Tarantool may crash when -e or -l option and their
+-- argument are not separated by space.
+-- The test is disabled for the Tarantool binary.
+-- See https://github.com/tarantool/tarantool/issues/5747.
+-- RUN([[lua "-eprint(1)" -ea=3 -e "print(a)" > %s]], out)
+-- checkout("1\n3\n")
prepfile[[
print(
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 26/29] test: disable PUC-Rio test for checking arg layout
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (24 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 25/29] test: disable PUC-RIO tests for several -l options Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 27/29] test: disable PUC-Rio test checking -h option Sergey Kaplun via Tarantool-patches
` (3 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
Unlike LuaJIT, Tarantool doesn't store the given CLI flags in `arg`,
so the table has the following layout:
* arg[-1] -- the binary name
* arg[0] -- the script name
* arg[N] -- the script argument for all N in [1, #arg]
This patch disables the test checking `arg` layout by negative indexes.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/main.lua | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/main.lua b/test/PUC-Rio-Lua-5.1-tests/main.lua
index 96006d1b..79ca0cb4 100644
--- a/test/PUC-Rio-Lua-5.1-tests/main.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/main.lua
@@ -71,7 +71,13 @@ local a = [[
]]
a = string.format(a, progname)
prepfile(a)
-RUN('lua "-e " -- %s a b c', prog)
+-- FIXME: Unlike LuaJIT, Tarantool doesn't store the given
+-- CLI flags in `arg`, so the table has the following layout:
+-- * arg[-1] -- the binary name
+-- * arg[0] -- the script name
+-- * arg[N] -- the script argument for all N in [1, #arg]
+-- Test is disabled for the Tarantool binary.
+-- RUN('lua "-e " -- %s a b c', prog)
-- test 'arg' availability in libraries
-- LuaJIT: LuaJIT v2.1.0-beta3 has extension from Lua 5.3:
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 27/29] test: disable PUC-Rio test checking -h option
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (25 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 26/29] test: disable PUC-Rio test for checking arg layout Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 28/29] test: disable PUC-Rio hanging GC test Sergey Kaplun via Tarantool-patches
` (2 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
Tarantool returns zero status at exit with -h option, unlike Lua or
LuaJIT does.
This patch disables the test checking the exit code, when binary
runs with -h option.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/main.lua | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/main.lua b/test/PUC-Rio-Lua-5.1-tests/main.lua
index 79ca0cb4..07facc4c 100644
--- a/test/PUC-Rio-Lua-5.1-tests/main.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/main.lua
@@ -201,7 +201,10 @@ assert(not os.remove(out))
RUN("lua -v")
-NoRun("lua -h")
+-- FIXME: Tarantool returns zero status at exit with -h option,
+-- unlike Lua or LuaJIT does.
+-- The test is disabled for Tarantool binary.
+-- NoRun("lua -h")
NoRun("lua -e")
NoRun("lua -e a")
NoRun("lua -f")
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 28/29] test: disable PUC-Rio hanging GC test
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (26 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 27/29] test: disable PUC-Rio test checking -h option Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 29/29] test: disable too deep recursive PUC-Rio test Sergey Kaplun via Tarantool-patches
2021-04-14 21:08 ` [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Igor Munkin via Tarantool-patches
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
Tarantool has too many alive objects at start. `gcinfo()` result is
always greater than 1000 expected by the test. It leads to infinite loop
in the test.
This patch disables the GC test leading to Tarantool binary hang.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/gc.lua | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/gc.lua b/test/PUC-Rio-Lua-5.1-tests/gc.lua
index b6925b69..10e1f2dd 100644
--- a/test/PUC-Rio-Lua-5.1-tests/gc.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/gc.lua
@@ -133,9 +133,12 @@ do
local a = {}
until gcinfo() > 1000
collectgarbage"restart"
- repeat
- local a = {}
- until gcinfo() < 1000
+ -- LuaJIT: Tarantool has too many alive objects at start.
+ -- `gcinfo()` result is always greater than 1000.
+ -- The test is disabled for Tarantool binary.
+ -- repeat
+ -- local a = {}
+ -- until gcinfo() < 1000
end
lim = 15
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [Tarantool-patches] [PATCH luajit v3 29/29] test: disable too deep recursive PUC-Rio test
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (27 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 28/29] test: disable PUC-Rio hanging GC test Sergey Kaplun via Tarantool-patches
@ 2021-04-13 13:27 ` Sergey Kaplun via Tarantool-patches
2021-04-14 21:08 ` [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Igor Munkin via Tarantool-patches
29 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-13 13:27 UTC (permalink / raw)
To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches
The first Tarantool's fiber has only 512Kb of stack.
It is not enough for deep recursive call in the test for
`string.gsub()`.
This patch disables the test leads to Tarantool crash.
Relates to tarantool/tarantool#5782
Resolves tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
test/PUC-Rio-Lua-5.1-tests/pm.lua | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/test/PUC-Rio-Lua-5.1-tests/pm.lua b/test/PUC-Rio-Lua-5.1-tests/pm.lua
index b159b6bd..e364ff9d 100644
--- a/test/PUC-Rio-Lua-5.1-tests/pm.lua
+++ b/test/PUC-Rio-Lua-5.1-tests/pm.lua
@@ -207,7 +207,11 @@ function rev (s)
end
local x = string.rep('012345', 10)
-assert(rev(rev(x)) == x)
+-- FIXME: The first Tarantool's fiber has only 512Kb of stack.
+-- It is not enough for this recursive call.
+-- See also https://github.com/tarantool/tarantool/issues/5782.
+-- The test is disabled for Tarantool binary.
+-- assert(rev(rev(x)) == x)
-- gsub with tables
--
2.31.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Tarantool-patches] [PATCH luajit v3 01/29] test: add PUC-Rio Lua 5.1 test suite
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 01/29] test: add " Sergey Kaplun via Tarantool-patches
@ 2021-04-13 20:31 ` Igor Munkin via Tarantool-patches
2021-04-14 13:54 ` Sergey Kaplun via Tarantool-patches
0 siblings, 1 reply; 35+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-04-13 20:31 UTC (permalink / raw)
To: Sergey Kaplun; +Cc: tarantool-patches
Sergey,
Thanks for the patch! LGTM with the following nits: I fixed them on top
of your branch[1] and guess no re-testing is needed.
On 13.04.21, Sergey Kaplun wrote:
> This patch adds PUC-Rio Lua 5.1 test suite as a part of the LuaJIT test
> suite. Source code is taken verbatim (except trailing whitespace) from
> https://www.lua.org/tests/lua5.1-tests.tar.gz.
>
> Some tests may fail after this commit. They will be disabled
> or adapted in the next patches.
>
> Part of tarantool/tarantool#5845
> Part of tarantool/tarantool#4473
> ---
<snipped>
> diff --git a/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt
> new file mode 100644
> index 00000000..e3bbc9de
> --- /dev/null
> +++ b/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt
> @@ -0,0 +1,45 @@
> +# Test suite that has been added from PUC-Rio Lua 5.1 test archive
> +# in scope of https://github.com/tarantool/tarantool/issues/5845.
> +
> +# See the rationale in the root CMakeLists.txt.
> +cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
> +
> +# XXX: There are two ways to set up the proper environment
> +# described in the suite's README:
> +# * set LUA_PATH to "?;./?.lua"
> +# * or, better yet, set LUA_PATH to "./?.lua;;" and LUA_INIT to
> +# "package.path = '?;'..package.path"
> +# Unfortunately, Tarantool doesn't support LUA_INIT and most
> +# likely it never will. For more info, see
> +# https://github.com/tarantool/tarantool/issues/5744
> +# Hence, there is no way other than set LUA_PATH environment
> +# variable as proposed in the first case.
> +set(LUA_PATH "?\;${CMAKE_CURRENT_SOURCE_DIR}/?.lua")
> +
> +# Establish PUC-Lua-5.1-tests-prepare target that creates <libs/P1>
Typo: s/PUC-Lua-5.1-tests-prepare/PUC-Rio-Lua-5.1-tests-prepare/.
> +# subdirectory.
> +add_subdirectory(libs)
> +
> +# TODO: PUC-Rio Lua 5.1 test suite also has special header
> +# <ltests.h> and <ltests.c> translation unit to check some
> +# internal behaviour of the Lua implementation (see etc/
> +# directory). It modifies realloc function to check memory
> +# consistency and also contains tests for yield in hooks
> +# and for the Lua C API.
> +# But, unfortunately, <ltests.c> depends on specific PUC-Rio
> +# Lua 5.1 internal headers and should be adapted for LuaJIT.
> +
> +add_custom_target(PUC-Rio-Lua-5.1-tests
> + DEPENDS ${LUAJIT_TEST_BINARY} PUC-Lua-5.1-tests-prepare
Typo: s/PUC-Lua-5.1-tests-prepare/PUC-Rio-Lua-5.1-tests-prepare/.
> +)
> +
> +add_custom_command(TARGET PUC-Rio-Lua-5.1-tests
> + COMMENT "Running PUC-Rio Lua 5.1 tests"
> + COMMAND
> + env
> + LUA_PATH="${LUA_PATH}\;\;"
> + ${LUAJIT_TEST_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR}/all.lua
> + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> +)
> +
> +# vim: expandtab tabstop=2 shiftwidth=2
<snipped>
> diff --git a/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt b/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt
> new file mode 100644
> index 00000000..f24e7f30
> --- /dev/null
> +++ b/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt
> @@ -0,0 +1,18 @@
> +# Test suite that has been added from PUC-Rio Lua 5.1 test archive
> +# in scope of https://github.com/tarantool/tarantool/issues/5845.
> +
> +# See the rationale in the root CMakeLists.txt.
> +cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
> +
> +# The original tarball contains subdirectory "libs" with an empty
> +# subdirectory "libs/P1", to be used by tests.
> +# Instead of tracking empty directory with some anchor-file for
> +# git, create this directory via CMake.
> +add_custom_target(PUC-Lua-5.1-tests-prepare)
> +add_custom_command(TARGET PUC-Lua-5.1-tests-prepare
Typo: s/PUC-Lua-5.1-tests-prepare/PUC-Rio-Lua-5.1-tests-prepare/g.
> + COMMENT "Create directory for PUC-Rio Lua 5.1 tests"
> + COMMAND ${CMAKE_COMMAND} -E make_directory P1
> + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> +)
> +
> +# vim: expandtab tabstop=2 shiftwidth=2
<snipped>
> --
> 2.31.0
>
[1]: https://github.com/tarantool/luajit/commit/47deba2
--
Best regards,
IM
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Tarantool-patches] [PATCH luajit v3 03/29] test: adapt PUC-Rio suite for out-of-source build
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 03/29] test: adapt PUC-Rio suite for out-of-source build Sergey Kaplun via Tarantool-patches
@ 2021-04-13 21:05 ` Igor Munkin via Tarantool-patches
2021-04-14 13:54 ` Sergey Kaplun via Tarantool-patches
0 siblings, 1 reply; 35+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-04-13 21:05 UTC (permalink / raw)
To: Sergey Kaplun; +Cc: tarantool-patches
Sergey,
Thanks for the patch! LGTM with the following nits: I fixed them on your
branch[1] and guess no re-testing is needed.
On 13.04.21, Sergey Kaplun wrote:
> The redefined `dofile()` function failed to find the test file to load,
> when tests are run out-of-source. So, fullpath is detected considering
> `arg[0]` value. Moreover, some tests use `loadfile()` instead, so their
> argument has to be adjusted to the full path to the files.
>
> Usage of functions invoking source test files was changed to
> `_loadfile()` and `_dofile()` correspondingly. They equal
Typo: s/They equal/They equal to/.
> `loadfile()` and `dofile()` by default and can be overloaded via running
> lua code from LUAJIT_TEST_INIT. This patch introduces the
Typo: s/lua/Lua/.
> <test/luajit-test-init.lua> file to be executed before tests and
> redefines the functions considering the path from `arg[0]` variable.
>
> Part of tarantool/tarantool#5845
> Part of tarantool/tarantool#4473
> ---
> CMakeLists.txt | 4 +--
> test/PUC-Rio-Lua-5.1-tests/all.lua | 51 +++++++++++++++++-------------
> test/luajit-test-init.lua | 18 +++++++++++
> 3 files changed, 49 insertions(+), 24 deletions(-)
> create mode 100644 test/luajit-test-init.lua
>
> diff --git a/CMakeLists.txt b/CMakeLists.txt
> index eb562923..df82d57c 100644
> --- a/CMakeLists.txt
> +++ b/CMakeLists.txt
> @@ -302,8 +302,8 @@ set(LUAJIT_TEST_BINARY ${LUAJIT_BINARY} CACHE STRING
> # tweaked, the introduced option can be used.
> # XXX: The default behaviour is nop, so /dev/null is the best
Comment need to be adjusted.
> # option for this.
> -set(LUAJIT_TEST_INIT "/dev/null" CACHE STRING
> - "Lua code need to be run before tests are started. Default is nop."
> +set(LUAJIT_TEST_INIT "${PROJECT_SOURCE_DIR}/test/luajit-test-init.lua" CACHE STRING
> + "Lua code need to be run before tests are started."
> )
>
> add_subdirectory(test)
<snipped>
> diff --git a/test/luajit-test-init.lua b/test/luajit-test-init.lua
> new file mode 100644
> index 00000000..aadd15af
> --- /dev/null
> +++ b/test/luajit-test-init.lua
> @@ -0,0 +1,18 @@
> +-- XXX: PUC Rio Lua 5.1 test suite checks that global variable
> +-- `_loadfile()` exists and use it for code loading from test
Typo: s/use/uses/.
> +-- files If the variable is not defined then suite uses
Typo: s/files/files./.
> +-- `loadfile()` as default. Same for the `_dofile()`.
> +
> +-- XXX: Some tests in PUC Rio Lua 5.1 test suite clean `arg`
> +-- variable, so evaluate this once and use later.
> +local path_to_sources = arg[0]:gsub("[^/]+$", "")
> +
> +-- luacheck: no global
> +function _loadfile(filename)
> + return loadfile(path_to_sources..filename)
> +end
> +
> +-- luacheck: no global
> +function _dofile(filename)
> + return dofile(path_to_sources..filename)
> +end
> --
> 2.31.0
>
[1]: https://github.com/tarantool/luajit/commit/c28985b
--
Best regards,
IM
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Tarantool-patches] [PATCH luajit v3 01/29] test: add PUC-Rio Lua 5.1 test suite
2021-04-13 20:31 ` Igor Munkin via Tarantool-patches
@ 2021-04-14 13:54 ` Sergey Kaplun via Tarantool-patches
0 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-14 13:54 UTC (permalink / raw)
To: Igor Munkin; +Cc: tarantool-patches
Hi, Igor!
Thanks for the review!
I see fixups on branch and they LGTM.
AFAIU, do you want to squash them by yourself?
On 13.04.21, Igor Munkin wrote:
> Sergey,
>
> Thanks for the patch! LGTM with the following nits: I fixed them on top
> of your branch[1] and guess no re-testing is needed.
>
> On 13.04.21, Sergey Kaplun wrote:
> > This patch adds PUC-Rio Lua 5.1 test suite as a part of the LuaJIT test
> > suite. Source code is taken verbatim (except trailing whitespace) from
> > https://www.lua.org/tests/lua5.1-tests.tar.gz.
> >
> > Some tests may fail after this commit. They will be disabled
> > or adapted in the next patches.
> >
> > Part of tarantool/tarantool#5845
> > Part of tarantool/tarantool#4473
> > ---
>
> <snipped>
>
> > diff --git a/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt
> > new file mode 100644
> > index 00000000..e3bbc9de
> > --- /dev/null
> > +++ b/test/PUC-Rio-Lua-5.1-tests/CMakeLists.txt
> > @@ -0,0 +1,45 @@
> > +# Test suite that has been added from PUC-Rio Lua 5.1 test archive
> > +# in scope of https://github.com/tarantool/tarantool/issues/5845.
> > +
> > +# See the rationale in the root CMakeLists.txt.
> > +cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
> > +
> > +# XXX: There are two ways to set up the proper environment
> > +# described in the suite's README:
> > +# * set LUA_PATH to "?;./?.lua"
> > +# * or, better yet, set LUA_PATH to "./?.lua;;" and LUA_INIT to
> > +# "package.path = '?;'..package.path"
> > +# Unfortunately, Tarantool doesn't support LUA_INIT and most
> > +# likely it never will. For more info, see
> > +# https://github.com/tarantool/tarantool/issues/5744
> > +# Hence, there is no way other than set LUA_PATH environment
> > +# variable as proposed in the first case.
> > +set(LUA_PATH "?\;${CMAKE_CURRENT_SOURCE_DIR}/?.lua")
> > +
> > +# Establish PUC-Lua-5.1-tests-prepare target that creates <libs/P1>
>
> Typo: s/PUC-Lua-5.1-tests-prepare/PUC-Rio-Lua-5.1-tests-prepare/.
>
> > +# subdirectory.
> > +add_subdirectory(libs)
> > +
> > +# TODO: PUC-Rio Lua 5.1 test suite also has special header
> > +# <ltests.h> and <ltests.c> translation unit to check some
> > +# internal behaviour of the Lua implementation (see etc/
> > +# directory). It modifies realloc function to check memory
> > +# consistency and also contains tests for yield in hooks
> > +# and for the Lua C API.
> > +# But, unfortunately, <ltests.c> depends on specific PUC-Rio
> > +# Lua 5.1 internal headers and should be adapted for LuaJIT.
> > +
> > +add_custom_target(PUC-Rio-Lua-5.1-tests
> > + DEPENDS ${LUAJIT_TEST_BINARY} PUC-Lua-5.1-tests-prepare
>
> Typo: s/PUC-Lua-5.1-tests-prepare/PUC-Rio-Lua-5.1-tests-prepare/.
>
> > +)
> > +
> > +add_custom_command(TARGET PUC-Rio-Lua-5.1-tests
> > + COMMENT "Running PUC-Rio Lua 5.1 tests"
> > + COMMAND
> > + env
> > + LUA_PATH="${LUA_PATH}\;\;"
> > + ${LUAJIT_TEST_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR}/all.lua
> > + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> > +)
> > +
> > +# vim: expandtab tabstop=2 shiftwidth=2
>
> <snipped>
>
> > diff --git a/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt b/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt
> > new file mode 100644
> > index 00000000..f24e7f30
> > --- /dev/null
> > +++ b/test/PUC-Rio-Lua-5.1-tests/libs/CMakeLists.txt
> > @@ -0,0 +1,18 @@
> > +# Test suite that has been added from PUC-Rio Lua 5.1 test archive
> > +# in scope of https://github.com/tarantool/tarantool/issues/5845.
> > +
> > +# See the rationale in the root CMakeLists.txt.
> > +cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
> > +
> > +# The original tarball contains subdirectory "libs" with an empty
> > +# subdirectory "libs/P1", to be used by tests.
> > +# Instead of tracking empty directory with some anchor-file for
> > +# git, create this directory via CMake.
> > +add_custom_target(PUC-Lua-5.1-tests-prepare)
> > +add_custom_command(TARGET PUC-Lua-5.1-tests-prepare
>
> Typo: s/PUC-Lua-5.1-tests-prepare/PUC-Rio-Lua-5.1-tests-prepare/g.
>
> > + COMMENT "Create directory for PUC-Rio Lua 5.1 tests"
> > + COMMAND ${CMAKE_COMMAND} -E make_directory P1
> > + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> > +)
> > +
> > +# vim: expandtab tabstop=2 shiftwidth=2
>
> <snipped>
>
> > --
> > 2.31.0
> >
>
> [1]: https://github.com/tarantool/luajit/commit/47deba2
>
> --
> Best regards,
> IM
--
Best regards,
Sergey Kaplun
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Tarantool-patches] [PATCH luajit v3 03/29] test: adapt PUC-Rio suite for out-of-source build
2021-04-13 21:05 ` Igor Munkin via Tarantool-patches
@ 2021-04-14 13:54 ` Sergey Kaplun via Tarantool-patches
0 siblings, 0 replies; 35+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-04-14 13:54 UTC (permalink / raw)
To: Igor Munkin; +Cc: tarantool-patches
Hi, Igor!
Thanks for the review!
I see fixups on branch and they LGTM.
AFAIU, do you want to squash them by yourself?
On 14.04.21, Igor Munkin wrote:
> Sergey,
>
> Thanks for the patch! LGTM with the following nits: I fixed them on your
> branch[1] and guess no re-testing is needed.
>
> On 13.04.21, Sergey Kaplun wrote:
> > The redefined `dofile()` function failed to find the test file to load,
> > when tests are run out-of-source. So, fullpath is detected considering
> > `arg[0]` value. Moreover, some tests use `loadfile()` instead, so their
> > argument has to be adjusted to the full path to the files.
> >
> > Usage of functions invoking source test files was changed to
> > `_loadfile()` and `_dofile()` correspondingly. They equal
>
> Typo: s/They equal/They equal to/.
>
> > `loadfile()` and `dofile()` by default and can be overloaded via running
> > lua code from LUAJIT_TEST_INIT. This patch introduces the
>
> Typo: s/lua/Lua/.
>
> > <test/luajit-test-init.lua> file to be executed before tests and
> > redefines the functions considering the path from `arg[0]` variable.
> >
> > Part of tarantool/tarantool#5845
> > Part of tarantool/tarantool#4473
> > ---
> > CMakeLists.txt | 4 +--
> > test/PUC-Rio-Lua-5.1-tests/all.lua | 51 +++++++++++++++++-------------
> > test/luajit-test-init.lua | 18 +++++++++++
> > 3 files changed, 49 insertions(+), 24 deletions(-)
> > create mode 100644 test/luajit-test-init.lua
> >
> > diff --git a/CMakeLists.txt b/CMakeLists.txt
> > index eb562923..df82d57c 100644
> > --- a/CMakeLists.txt
> > +++ b/CMakeLists.txt
> > @@ -302,8 +302,8 @@ set(LUAJIT_TEST_BINARY ${LUAJIT_BINARY} CACHE STRING
> > # tweaked, the introduced option can be used.
> > # XXX: The default behaviour is nop, so /dev/null is the best
>
> Comment need to be adjusted.
>
> > # option for this.
> > -set(LUAJIT_TEST_INIT "/dev/null" CACHE STRING
> > - "Lua code need to be run before tests are started. Default is nop."
> > +set(LUAJIT_TEST_INIT "${PROJECT_SOURCE_DIR}/test/luajit-test-init.lua" CACHE STRING
> > + "Lua code need to be run before tests are started."
> > )
> >
> > add_subdirectory(test)
>
> <snipped>
>
> > diff --git a/test/luajit-test-init.lua b/test/luajit-test-init.lua
> > new file mode 100644
> > index 00000000..aadd15af
> > --- /dev/null
> > +++ b/test/luajit-test-init.lua
> > @@ -0,0 +1,18 @@
> > +-- XXX: PUC Rio Lua 5.1 test suite checks that global variable
> > +-- `_loadfile()` exists and use it for code loading from test
>
> Typo: s/use/uses/.
>
> > +-- files If the variable is not defined then suite uses
>
> Typo: s/files/files./.
>
> > +-- `loadfile()` as default. Same for the `_dofile()`.
> > +
> > +-- XXX: Some tests in PUC Rio Lua 5.1 test suite clean `arg`
> > +-- variable, so evaluate this once and use later.
> > +local path_to_sources = arg[0]:gsub("[^/]+$", "")
> > +
> > +-- luacheck: no global
> > +function _loadfile(filename)
> > + return loadfile(path_to_sources..filename)
> > +end
> > +
> > +-- luacheck: no global
> > +function _dofile(filename)
> > + return dofile(path_to_sources..filename)
> > +end
> > --
> > 2.31.0
> >
>
> [1]: https://github.com/tarantool/luajit/commit/c28985b
>
> --
> Best regards,
> IM
--
Best regards,
Sergey Kaplun
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
` (28 preceding siblings ...)
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 29/29] test: disable too deep recursive PUC-Rio test Sergey Kaplun via Tarantool-patches
@ 2021-04-14 21:08 ` Igor Munkin via Tarantool-patches
29 siblings, 0 replies; 35+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-04-14 21:08 UTC (permalink / raw)
To: Sergey Kaplun; +Cc: tarantool-patches
Sergey,
Thanks for the new series! Now everything LGTM.
I've checked the patchset into all long-term branches in
tarantool/luajit and bumped a new version in 1.10, 2.6, 2.7 and master.
On 13.04.21, Sergey Kaplun wrote:
> Branch: https://github.com/tarantool/luajit/tree/skaplun/gh-5845-adapt-puc-rio-test-suite-v2
> Test branch: https://github.com/tarantool/tarantool/tree/skaplun/gh-5845-adapt-puc-rio-test-suite-v2
>
> Side note: CI is red due to
> https://github.com/tarantool/tarantool/issues/5986.
>
> Issues:
> * https://github.com/tarantool/tarantool/issues/5845
> * https://github.com/tarantool/tarantool/issues/4473
>
> Suite is taken intact exept trailing whitespaces.
> Command to check:
> | $ diff -ruZ --color ../test/PUC-Lua-5.1-tests/ ~/Downloads/lua5.1-tests/
> | Only in ../test/PUC-Lua-5.1-tests/: CMakeLists.txt
> | Only in ../test/PUC-Lua-5.1-tests/libs: CMakeLists.txt
> | Only in ~/Downloads/lua5.1-tests/libs: makefile
> | Only in ~/Downloads/lua5.1-tests/libs: P1
>
> Changes in the v2:
> * split commits to atomic changes
> * more verbose comments for some tests
> * some test fixed instead commenting
>
> Changes in the v3:
> * more verbose comments and commit messages
> * PUC-Lua-5.1-tests -> PUC-Rio-Lua-5.1-tests
> * squash commits for vararg functions
> * move "LuaJIT:" tag to the top of comments
> * introduce _dofile and _loadfile functions for PUC-Rio-Lua-5.1 suite
> and create <luajit-tests-init.lua> test prerunner to set up them
> correctly for out-of-source build.
>
>
> Sergey Kaplun (29):
> test: add PUC-Rio Lua 5.1 test suite
> test: build auxiliary C libs from PUC-Rio Lua 5.1
> test: adapt PUC-Rio suite for out-of-source build
> test: remove quotes in progname from PUC-Rio
> test: adapt PUC-Rio test for arg presence
> test: disable PUC-Rio tests confused by -v output
> test: disable PUC-Rio tests for bytecode header
> test: adapt PUC-Rio tests counting GC steps
> test: disable PUC-Rio suite tests for line hook
> test: adapt PUC-Rio tests with vararg functions
> test: adapt PUC-Rio test for debug in vararg func
> test: adapt PUC-Rio test with count hooks
> test: disable PUC-Rio test for tail call info
> test: adapt PUC-Rio test with activeline check
> test: disable PUC-Rio test for per-coroutine hooks
> test: adapt PUC-Rio test for %q in string.format
> test: disable locale-dependent PUC-Rio tests
> test: use math.fmod in PUC-Rio tests
> test: remove string.gfind assert in PUC-Rio test
> test: disable PUC-Rio test for getfenv in tailcall
> test: disable PUC-Rio test for variables in error
> test: disable PUC-Rio test for fast function name
> test: disable PUC-Rio test for non-asci identifier
> test: disable PUC-Rio test for syntax level error
> test: disable PUC-RIO tests for several -l options
> test: disable PUC-Rio test for checking arg layout
> test: disable PUC-Rio test checking -h option
> test: disable PUC-Rio hanging GC test
> test: disable too deep recursive PUC-Rio test
>
<snipped>
>
> --
> 2.31.0
>
--
Best regards,
IM
^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2021-04-14 21:09 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-13 13:27 [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 01/29] test: add " Sergey Kaplun via Tarantool-patches
2021-04-13 20:31 ` Igor Munkin via Tarantool-patches
2021-04-14 13:54 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 02/29] test: build auxiliary C libs from PUC-Rio Lua 5.1 Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 03/29] test: adapt PUC-Rio suite for out-of-source build Sergey Kaplun via Tarantool-patches
2021-04-13 21:05 ` Igor Munkin via Tarantool-patches
2021-04-14 13:54 ` Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 04/29] test: remove quotes in progname from PUC-Rio Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 05/29] test: adapt PUC-Rio test for arg presence Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 06/29] test: disable PUC-Rio tests confused by -v output Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 07/29] test: disable PUC-Rio tests for bytecode header Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 08/29] test: adapt PUC-Rio tests counting GC steps Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 09/29] test: disable PUC-Rio suite tests for line hook Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 10/29] test: adapt PUC-Rio tests with vararg functions Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 11/29] test: adapt PUC-Rio test for debug in vararg func Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 12/29] test: adapt PUC-Rio test with count hooks Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 13/29] test: disable PUC-Rio test for tail call info Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 14/29] test: adapt PUC-Rio test with activeline check Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 15/29] test: disable PUC-Rio test for per-coroutine hooks Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 16/29] test: adapt PUC-Rio test for %q in string.format Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 17/29] test: disable locale-dependent PUC-Rio tests Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 18/29] test: use math.fmod in " Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 19/29] test: remove string.gfind assert in PUC-Rio test Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 20/29] test: disable PUC-Rio test for getfenv in tailcall Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 21/29] test: disable PUC-Rio test for variables in error Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 22/29] test: disable PUC-Rio test for fast function name Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 23/29] test: disable PUC-Rio test for non-asci identifier Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 24/29] test: disable PUC-Rio test for syntax level error Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 25/29] test: disable PUC-RIO tests for several -l options Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 26/29] test: disable PUC-Rio test for checking arg layout Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 27/29] test: disable PUC-Rio test checking -h option Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 28/29] test: disable PUC-Rio hanging GC test Sergey Kaplun via Tarantool-patches
2021-04-13 13:27 ` [Tarantool-patches] [PATCH luajit v3 29/29] test: disable too deep recursive PUC-Rio test Sergey Kaplun via Tarantool-patches
2021-04-14 21:08 ` [Tarantool-patches] [PATCH luajit v3 00/29] Adapt PUC-Rio Lua 5.1 test suite Igor Munkin via Tarantool-patches
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox