Tarantool development patches archive
 help / color / mirror / Atom feed
* [Tarantool-patches] [PATCH luajit 0/3] Adapt PUC-Rio Lua 5.1 test suite
@ 2021-03-12  5:36 Sergey Kaplun via Tarantool-patches
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 1/3] test: add " Sergey Kaplun via Tarantool-patches
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-12  5:36 UTC (permalink / raw)
  To: Igor Munkin, Sergey Ostanevich; +Cc: tarantool-patches

In this patchset PUC-Rio Lua 5.1 test suite is adapted for the LuaJIT
fork and Tarantool.

Branch: https://github.com/tarantool/luajit/tree/skaplun/gh-5845-adapt-puc-rio-test-suite
Tarantool's branch for tests:
https://github.com/tarantool/tarantool/tree/skaplun/gh-5845-adapt-puc-rio-test-suite
Issues:
* https://github.com/tarantool/tarantool/issues/5845
* https://github.com/tarantool/tarantool/issues/5473

You can check the accuracy of the first patch with the following command:
| $ diff --color -urZ test/PUC-Lua-5.1-tests/ ~/Downloads/lua5.1-tests/

Trailing whitespaces are stripped from test suites because:
* They have no semantic charge (feel free to prove the opposite)
* Lua 5.1 is not supported by Roberto, so these tests are not supported
  too, and there is no need to keep this suite "as is" so strict

Sergey Kaplun (3):
  test: add PUC-Rio Lua 5.1 test suite
  test: adapt PUC-Rio Lua 5.1 test suite for LuaJIT
  test: adapt Lua 5.1 test suite for Tarantool

 .luacheckrc                           |    5 +-
 test/CMakeLists.txt                   |    4 +-
 test/PUC-Lua-5.1-tests/CMakeLists.txt |   92 ++
 test/PUC-Lua-5.1-tests/README         |   41 +
 test/PUC-Lua-5.1-tests/all.lua        |  145 ++++
 test/PUC-Lua-5.1-tests/api.lua        |  711 +++++++++++++++
 test/PUC-Lua-5.1-tests/attrib.lua     |  339 ++++++++
 test/PUC-Lua-5.1-tests/big.lua        |  381 ++++++++
 test/PUC-Lua-5.1-tests/calls.lua      |  294 +++++++
 test/PUC-Lua-5.1-tests/checktable.lua |   77 ++
 test/PUC-Lua-5.1-tests/closure.lua    |  432 ++++++++++
 test/PUC-Lua-5.1-tests/code.lua       |  143 +++
 test/PUC-Lua-5.1-tests/constructs.lua |  247 ++++++
 test/PUC-Lua-5.1-tests/db.lua         |  538 ++++++++++++
 test/PUC-Lua-5.1-tests/errors.lua     |  264 ++++++
 test/PUC-Lua-5.1-tests/etc/ltests.c   | 1147 +++++++++++++++++++++++++
 test/PUC-Lua-5.1-tests/etc/ltests.h   |   92 ++
 test/PUC-Lua-5.1-tests/events.lua     |  360 ++++++++
 test/PUC-Lua-5.1-tests/files.lua      |  324 +++++++
 test/PUC-Lua-5.1-tests/gc.lua         |  320 +++++++
 test/PUC-Lua-5.1-tests/libs/lib1.c    |   40 +
 test/PUC-Lua-5.1-tests/libs/lib11.c   |   18 +
 test/PUC-Lua-5.1-tests/libs/lib2.c    |   28 +
 test/PUC-Lua-5.1-tests/libs/lib21.c   |   18 +
 test/PUC-Lua-5.1-tests/literals.lua   |  181 ++++
 test/PUC-Lua-5.1-tests/locals.lua     |  127 +++
 test/PUC-Lua-5.1-tests/main.lua       |  195 +++++
 test/PUC-Lua-5.1-tests/math.lua       |  213 +++++
 test/PUC-Lua-5.1-tests/nextvar.lua    |  403 +++++++++
 test/PUC-Lua-5.1-tests/pm.lua         |  281 ++++++
 test/PUC-Lua-5.1-tests/sort.lua       |   74 ++
 test/PUC-Lua-5.1-tests/strings.lua    |  191 ++++
 test/PUC-Lua-5.1-tests/vararg.lua     |  134 +++
 test/PUC-Lua-5.1-tests/verybig.lua    |  102 +++
 34 files changed, 7958 insertions(+), 3 deletions(-)
 create mode 100644 test/PUC-Lua-5.1-tests/CMakeLists.txt
 create mode 100644 test/PUC-Lua-5.1-tests/README
 create mode 100755 test/PUC-Lua-5.1-tests/all.lua
 create mode 100644 test/PUC-Lua-5.1-tests/api.lua
 create mode 100644 test/PUC-Lua-5.1-tests/attrib.lua
 create mode 100644 test/PUC-Lua-5.1-tests/big.lua
 create mode 100644 test/PUC-Lua-5.1-tests/calls.lua
 create mode 100644 test/PUC-Lua-5.1-tests/checktable.lua
 create mode 100644 test/PUC-Lua-5.1-tests/closure.lua
 create mode 100644 test/PUC-Lua-5.1-tests/code.lua
 create mode 100644 test/PUC-Lua-5.1-tests/constructs.lua
 create mode 100644 test/PUC-Lua-5.1-tests/db.lua
 create mode 100644 test/PUC-Lua-5.1-tests/errors.lua
 create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.c
 create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.h
 create mode 100644 test/PUC-Lua-5.1-tests/events.lua
 create mode 100644 test/PUC-Lua-5.1-tests/files.lua
 create mode 100644 test/PUC-Lua-5.1-tests/gc.lua
 create mode 100644 test/PUC-Lua-5.1-tests/libs/lib1.c
 create mode 100644 test/PUC-Lua-5.1-tests/libs/lib11.c
 create mode 100644 test/PUC-Lua-5.1-tests/libs/lib2.c
 create mode 100644 test/PUC-Lua-5.1-tests/libs/lib21.c
 create mode 100644 test/PUC-Lua-5.1-tests/literals.lua
 create mode 100644 test/PUC-Lua-5.1-tests/locals.lua
 create mode 100644 test/PUC-Lua-5.1-tests/main.lua
 create mode 100644 test/PUC-Lua-5.1-tests/math.lua
 create mode 100644 test/PUC-Lua-5.1-tests/nextvar.lua
 create mode 100644 test/PUC-Lua-5.1-tests/pm.lua
 create mode 100644 test/PUC-Lua-5.1-tests/sort.lua
 create mode 100644 test/PUC-Lua-5.1-tests/strings.lua
 create mode 100644 test/PUC-Lua-5.1-tests/vararg.lua
 create mode 100644 test/PUC-Lua-5.1-tests/verybig.lua

-- 
2.28.0


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Tarantool-patches] [PATCH luajit 1/3] test: add PUC-Rio Lua 5.1 test suite
  2021-03-12  5:36 [Tarantool-patches] [PATCH luajit 0/3] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
@ 2021-03-12  5:36 ` Sergey Kaplun via Tarantool-patches
  2021-03-16 13:35   ` Sergey Ostanevich via Tarantool-patches
  2021-03-17 14:55   ` Igor Munkin via Tarantool-patches
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 2/3] test: adapt PUC-Rio Lua 5.1 test suite for LuaJIT Sergey Kaplun via Tarantool-patches
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 3/3] test: adapt Lua 5.1 test suite for Tarantool Sergey Kaplun via Tarantool-patches
  2 siblings, 2 replies; 13+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-12  5:36 UTC (permalink / raw)
  To: Igor Munkin, Sergey Ostanevich; +Cc: tarantool-patches

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 210495 bytes --]

This patch adds PUC-Rio Lua 5.1 test suite as a part of the LuaJIT
test suite. Source code taken verbatim from
https://www.lua.org/tests/lua5.1-tests.tar.gz.

<lib1.c> and <lib2.c> is slightly modified to be consistent with the
current LuaJIT's LuaC API.

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                   |    4 +-
 test/PUC-Lua-5.1-tests/CMakeLists.txt |   89 ++
 test/PUC-Lua-5.1-tests/README         |   41 +
 test/PUC-Lua-5.1-tests/all.lua        |  137 +++
 test/PUC-Lua-5.1-tests/api.lua        |  711 +++++++++++++++
 test/PUC-Lua-5.1-tests/attrib.lua     |  339 ++++++++
 test/PUC-Lua-5.1-tests/big.lua        |  381 ++++++++
 test/PUC-Lua-5.1-tests/calls.lua      |  294 +++++++
 test/PUC-Lua-5.1-tests/checktable.lua |   77 ++
 test/PUC-Lua-5.1-tests/closure.lua    |  422 +++++++++
 test/PUC-Lua-5.1-tests/code.lua       |  143 +++
 test/PUC-Lua-5.1-tests/constructs.lua |  240 ++++++
 test/PUC-Lua-5.1-tests/db.lua         |  499 +++++++++++
 test/PUC-Lua-5.1-tests/errors.lua     |  250 ++++++
 test/PUC-Lua-5.1-tests/etc/ltests.c   | 1147 +++++++++++++++++++++++++
 test/PUC-Lua-5.1-tests/etc/ltests.h   |   92 ++
 test/PUC-Lua-5.1-tests/events.lua     |  360 ++++++++
 test/PUC-Lua-5.1-tests/files.lua      |  324 +++++++
 test/PUC-Lua-5.1-tests/gc.lua         |  312 +++++++
 test/PUC-Lua-5.1-tests/libs/lib1.c    |   40 +
 test/PUC-Lua-5.1-tests/libs/lib11.c   |   18 +
 test/PUC-Lua-5.1-tests/libs/lib2.c    |   28 +
 test/PUC-Lua-5.1-tests/libs/lib21.c   |   18 +
 test/PUC-Lua-5.1-tests/literals.lua   |  176 ++++
 test/PUC-Lua-5.1-tests/locals.lua     |  127 +++
 test/PUC-Lua-5.1-tests/main.lua       |  159 ++++
 test/PUC-Lua-5.1-tests/math.lua       |  208 +++++
 test/PUC-Lua-5.1-tests/nextvar.lua    |  396 +++++++++
 test/PUC-Lua-5.1-tests/pm.lua         |  273 ++++++
 test/PUC-Lua-5.1-tests/sort.lua       |   74 ++
 test/PUC-Lua-5.1-tests/strings.lua    |  176 ++++
 test/PUC-Lua-5.1-tests/vararg.lua     |  126 +++
 test/PUC-Lua-5.1-tests/verybig.lua    |  100 +++
 34 files changed, 7783 insertions(+), 3 deletions(-)
 create mode 100644 test/PUC-Lua-5.1-tests/CMakeLists.txt
 create mode 100644 test/PUC-Lua-5.1-tests/README
 create mode 100755 test/PUC-Lua-5.1-tests/all.lua
 create mode 100644 test/PUC-Lua-5.1-tests/api.lua
 create mode 100644 test/PUC-Lua-5.1-tests/attrib.lua
 create mode 100644 test/PUC-Lua-5.1-tests/big.lua
 create mode 100644 test/PUC-Lua-5.1-tests/calls.lua
 create mode 100644 test/PUC-Lua-5.1-tests/checktable.lua
 create mode 100644 test/PUC-Lua-5.1-tests/closure.lua
 create mode 100644 test/PUC-Lua-5.1-tests/code.lua
 create mode 100644 test/PUC-Lua-5.1-tests/constructs.lua
 create mode 100644 test/PUC-Lua-5.1-tests/db.lua
 create mode 100644 test/PUC-Lua-5.1-tests/errors.lua
 create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.c
 create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.h
 create mode 100644 test/PUC-Lua-5.1-tests/events.lua
 create mode 100644 test/PUC-Lua-5.1-tests/files.lua
 create mode 100644 test/PUC-Lua-5.1-tests/gc.lua
 create mode 100644 test/PUC-Lua-5.1-tests/libs/lib1.c
 create mode 100644 test/PUC-Lua-5.1-tests/libs/lib11.c
 create mode 100644 test/PUC-Lua-5.1-tests/libs/lib2.c
 create mode 100644 test/PUC-Lua-5.1-tests/libs/lib21.c
 create mode 100644 test/PUC-Lua-5.1-tests/literals.lua
 create mode 100644 test/PUC-Lua-5.1-tests/locals.lua
 create mode 100644 test/PUC-Lua-5.1-tests/main.lua
 create mode 100644 test/PUC-Lua-5.1-tests/math.lua
 create mode 100644 test/PUC-Lua-5.1-tests/nextvar.lua
 create mode 100644 test/PUC-Lua-5.1-tests/pm.lua
 create mode 100644 test/PUC-Lua-5.1-tests/sort.lua
 create mode 100644 test/PUC-Lua-5.1-tests/strings.lua
 create mode 100644 test/PUC-Lua-5.1-tests/vararg.lua
 create mode 100644 test/PUC-Lua-5.1-tests/verybig.lua

diff --git a/.luacheckrc b/.luacheckrc
index 1a76108..cbd2912 100644
--- a/.luacheckrc
+++ b/.luacheckrc
@@ -3,10 +3,11 @@ 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-Lua-5.1-tests/',
 }
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 99471db..93c43ea 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -43,11 +43,13 @@ endif()
 set(LUAJIT_TEST_COMMAND "${LUAJIT_TEST_BINARY} -e dofile[[${LUAJIT_TEST_INIT}]]")
 separate_arguments(LUAJIT_TEST_COMMAND)
 
-add_subdirectory(tarantool-tests)
 add_subdirectory(LuaJIT-tests)
+add_subdirectory(PUC-Lua-5.1-tests)
+add_subdirectory(tarantool-tests)
 
 add_custom_target(${PROJECT_NAME}-test DEPENDS
   LuaJIT-tests
+  PUC-Lua-5.1-tests
   tarantool-tests
 )
 
diff --git a/test/PUC-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Lua-5.1-tests/CMakeLists.txt
new file mode 100644
index 0000000..08bee36
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/CMakeLists.txt
@@ -0,0 +1,89 @@
+# Test suite that has been added from PUC-Rio Lua 5.1 test archive
+# in scope of https://github.com/tarantool/tarantool/issues/4473.
+
+# See the rationale in the root CMakeLists.txt.
+cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
+
+set(TEST_RUNNER  ${CMAKE_CURRENT_SOURCE_DIR}/all.lua)
+set(LIB_SOURCES  ${CMAKE_CURRENT_SOURCE_DIR}/libs)
+set(TESTLIB_PATH ${CMAKE_CURRENT_BINARY_DIR}/libs)
+
+# XXX: -fPIC is required to linking with static library.
+if(NOT BUILDMODE STREQUAL "static")
+  # Build additional C libraries for tests.
+  macro(build_lib 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 "${TESTLIB_PATH}"
+      PREFIX ""
+    )
+    if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+      set_target_properties(${lib} PROPERTIES
+        LINK_FLAGS "-undefined dynamic_lookup"
+      )
+    endif()
+    target_link_libraries(${lib} PRIVATE libluajit_shared)
+    list(APPEND TESTLIBS ${lib})
+  endmacro()
+
+  build_lib(lib1  ${LIB_SOURCES}/lib1.c)
+  build_lib(lib11 ${LIB_SOURCES}/lib1.c ${LIB_SOURCES}/lib11.c)
+  build_lib(lib2  ${LIB_SOURCES}/lib2.c)
+  build_lib(lib21 ${LIB_SOURCES}/lib2.c ${LIB_SOURCES}/lib21.c)
+
+  set(LIB2COPY "${TESTLIB_PATH}/lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
+  set(LIB_COPY "${TESTLIB_PATH}/-lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
+
+  add_custom_command(
+    COMMENT "Copping lib2 to -lib2 for PUC-Rio Lua 5.1 tests"
+    OUTPUT  ${LIB_COPY}
+    DEPENDS ${TESTLIBS}
+    COMMAND ${CMAKE_COMMAND} -E copy ${LIB2COPY} ${LIB_COPY}
+    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+  )
+  list(APPEND TESTLIBS ${LIB_COPY})
+endif()
+
+set(CUSTOM_TEST_DIR ${TESTLIB_PATH}/P1)
+add_custom_command(
+  COMMENT "Create directory for PUC-Rio Lua 5.1 tests"
+  OUTPUT  ${CUSTOM_TEST_DIR}
+  COMMAND ${CMAKE_COMMAND} -E make_directory ${CUSTOM_TEST_DIR}
+  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(LUA_PATH "?\;${CMAKE_CURRENT_SOURCE_DIR}/?.lua")
+
+# 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 adopted for LuaJIT.
+
+add_custom_target(PUC-Lua-5.1-tests
+  DEPENDS ${LUAJIT_TEST_BINARY} ${TESTLIBS} ${CUSTOM_TEST_DIR}
+)
+
+add_custom_command(TARGET PUC-Lua-5.1-tests
+  COMMENT "Running PUC-Rio Lua 5.1 tests"
+  COMMAND
+  env
+    # Tarantool doesn't support LUA_INIT and most likely it
+    # never will.
+    # See https://github.com/tarantool/tarantool/issues/5744
+    # for more info.
+    # LUA_PATH="${CMAKE_CURRENT_BINARY_DIR}/?.lua\;\;"
+    # LUA_INIT="package.path='?\;'..package.path"
+    # So use less preferable way for tests.
+    LUA_PATH="${LUA_PATH}\;\;"
+    ${LUAJIT_TEST_COMMAND} ${TEST_RUNNER}
+  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+# vim: expandtab tabstop=2 shiftwidth=2
diff --git a/test/PUC-Lua-5.1-tests/README b/test/PUC-Lua-5.1-tests/README
new file mode 100644
index 0000000..e2d4b28
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/all.lua b/test/PUC-Lua-5.1-tests/all.lua
new file mode 100755
index 0000000..8c4afac
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/api.lua b/test/PUC-Lua-5.1-tests/api.lua
new file mode 100644
index 0000000..c955ebf
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/attrib.lua b/test/PUC-Lua-5.1-tests/attrib.lua
new file mode 100644
index 0000000..655669b
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/big.lua b/test/PUC-Lua-5.1-tests/big.lua
new file mode 100644
index 0000000..9261288
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/calls.lua b/test/PUC-Lua-5.1-tests/calls.lua
new file mode 100644
index 0000000..788f9a1
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/checktable.lua b/test/PUC-Lua-5.1-tests/checktable.lua
new file mode 100644
index 0000000..f0938be
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/closure.lua b/test/PUC-Lua-5.1-tests/closure.lua
new file mode 100644
index 0000000..27ca0ad
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/code.lua b/test/PUC-Lua-5.1-tests/code.lua
new file mode 100644
index 0000000..875d488
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/constructs.lua b/test/PUC-Lua-5.1-tests/constructs.lua
new file mode 100644
index 0000000..5fb3798
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/db.lua b/test/PUC-Lua-5.1-tests/db.lua
new file mode 100644
index 0000000..9d2c86f
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/errors.lua b/test/PUC-Lua-5.1-tests/errors.lua
new file mode 100644
index 0000000..e881211
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/etc/ltests.c b/test/PUC-Lua-5.1-tests/etc/ltests.c
new file mode 100644
index 0000000..be949e5
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/etc/ltests.h b/test/PUC-Lua-5.1-tests/etc/ltests.h
new file mode 100644
index 0000000..e570212
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/events.lua b/test/PUC-Lua-5.1-tests/events.lua
new file mode 100644
index 0000000..5234b00
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/files.lua b/test/PUC-Lua-5.1-tests/files.lua
new file mode 100644
index 0000000..903488c
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/gc.lua b/test/PUC-Lua-5.1-tests/gc.lua
new file mode 100644
index 0000000..86a9f75
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/libs/lib1.c b/test/PUC-Lua-5.1-tests/libs/lib1.c
new file mode 100644
index 0000000..22fe6de
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/libs/lib11.c b/test/PUC-Lua-5.1-tests/libs/lib11.c
new file mode 100644
index 0000000..3efa3d3
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/libs/lib2.c b/test/PUC-Lua-5.1-tests/libs/lib2.c
new file mode 100644
index 0000000..876a212
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/libs/lib21.c b/test/PUC-Lua-5.1-tests/libs/lib21.c
new file mode 100644
index 0000000..167507f
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/literals.lua b/test/PUC-Lua-5.1-tests/literals.lua
new file mode 100644
index 0000000..01d84d5
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/locals.lua b/test/PUC-Lua-5.1-tests/locals.lua
new file mode 100644
index 0000000..011645a
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/main.lua b/test/PUC-Lua-5.1-tests/main.lua
new file mode 100644
index 0000000..f520896
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/math.lua b/test/PUC-Lua-5.1-tests/math.lua
new file mode 100644
index 0000000..5076f38
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/nextvar.lua b/test/PUC-Lua-5.1-tests/nextvar.lua
new file mode 100644
index 0000000..7ceaa75
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/pm.lua b/test/PUC-Lua-5.1-tests/pm.lua
new file mode 100644
index 0000000..fa125dc
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/sort.lua b/test/PUC-Lua-5.1-tests/sort.lua
new file mode 100644
index 0000000..6fccd49
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/strings.lua b/test/PUC-Lua-5.1-tests/strings.lua
new file mode 100644
index 0000000..237dbad
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/vararg.lua b/test/PUC-Lua-5.1-tests/vararg.lua
new file mode 100644
index 0000000..ae068fa
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/verybig.lua b/test/PUC-Lua-5.1-tests/verybig.lua
new file mode 100644
index 0000000..59e0142
--- /dev/null
+++ b/test/PUC-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.28.0


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Tarantool-patches] [PATCH luajit 2/3] test: adapt PUC-Rio Lua 5.1 test suite for LuaJIT
  2021-03-12  5:36 [Tarantool-patches] [PATCH luajit 0/3] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 1/3] test: add " Sergey Kaplun via Tarantool-patches
@ 2021-03-12  5:36 ` Sergey Kaplun via Tarantool-patches
  2021-03-13 19:04   ` Sergey Ostanevich via Tarantool-patches
  2021-03-22 18:52   ` Igor Munkin via Tarantool-patches
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 3/3] test: adapt Lua 5.1 test suite for Tarantool Sergey Kaplun via Tarantool-patches
  2 siblings, 2 replies; 13+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-12  5:36 UTC (permalink / raw)
  To: Igor Munkin, Sergey Ostanevich; +Cc: tarantool-patches

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 22160 bytes --]

In some insignificant details LuaJIT's behaviour is not the same
as the behaviour of Lua 5.1.

Tests in the following files are disabled with corresponding comments:
* closure.lua
* constructs.lua
* db.lua
* errors.lua
* literals.lua
* main.lua
* math.lua
* nextvar.lua
* pm.lua
* strings.lua
* vararg.lua

See full list of disabled tests to adapt in
https://github.com/tarantool/tarantool/issues/5870.

jit.off() as prologue and jit.on() as epilogue is added to one test
chunk in gc.lua for stable (JIT unrelated) GC test results.

Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
 test/PUC-Lua-5.1-tests/closure.lua    | 12 ++++-
 test/PUC-Lua-5.1-tests/constructs.lua |  7 +++
 test/PUC-Lua-5.1-tests/db.lua         | 75 ++++++++++++++++++++-------
 test/PUC-Lua-5.1-tests/errors.lua     | 28 +++++++---
 test/PUC-Lua-5.1-tests/gc.lua         |  5 ++
 test/PUC-Lua-5.1-tests/literals.lua   |  5 ++
 test/PUC-Lua-5.1-tests/main.lua       | 56 ++++++++++++++------
 test/PUC-Lua-5.1-tests/math.lua       |  7 ++-
 test/PUC-Lua-5.1-tests/nextvar.lua    |  7 +++
 test/PUC-Lua-5.1-tests/pm.lua         |  6 ++-
 test/PUC-Lua-5.1-tests/strings.lua    | 17 +++++-
 test/PUC-Lua-5.1-tests/vararg.lua     | 20 ++++---
 12 files changed, 195 insertions(+), 50 deletions(-)

diff --git a/test/PUC-Lua-5.1-tests/closure.lua b/test/PUC-Lua-5.1-tests/closure.lua
index 27ca0ad..e9bd564 100644
--- a/test/PUC-Lua-5.1-tests/closure.lua
+++ b/test/PUC-Lua-5.1-tests/closure.lua
@@ -174,7 +174,10 @@ f = coroutine.wrap(foo)
 local a = {}
 assert(f(a) == _G)
 local a,b = pcall(f)
-assert(a and b == _G)
+-- LuaJIT getfenv() behaviour is different in tail calls.
+-- 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
@@ -261,6 +264,12 @@ end
 
 local x = gen(100)
 local a = {}
+-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
+-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
+-- LuaJIT also has math.fmod() instead math.mod() builtin.
+-- See also https://github.com/tarantool/tarantool/issues/5711.
+-- Test is disabled.
+--[=[
 while 1 do
   local n = x()
   if n == nil then break end
@@ -269,6 +278,7 @@ while 1 do
 end
 
 assert(table.getn(a) == 25 and a[table.getn(a)] == 97)
+--]=]
 
 
 -- errors in coroutines
diff --git a/test/PUC-Lua-5.1-tests/constructs.lua b/test/PUC-Lua-5.1-tests/constructs.lua
index 5fb3798..6776ee6 100644
--- a/test/PUC-Lua-5.1-tests/constructs.lua
+++ b/test/PUC-Lua-5.1-tests/constructs.lua
@@ -200,6 +200,12 @@ a,b = F(nil)==nil; assert(a == true and b == nil)
 
 function ID(x) return x end
 
+-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
+-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
+-- LuaJIT also has math.fmod() instead math.mod() builtin.
+-- See also https://github.com/tarantool/tarantool/issues/5711.
+-- Test is disabled.
+--[=[
 function f(t, i)
   local b = t.n
   local res = math.mod(math.floor(i/c), b)+1
@@ -236,5 +242,6 @@ repeat
   if math.mod(i,4000) == 0 then print('+') end
   i = i+1
 until i==c
+--]=]
 
 print'OK'
diff --git a/test/PUC-Lua-5.1-tests/db.lua b/test/PUC-Lua-5.1-tests/db.lua
index 9d2c86f..591a006 100644
--- a/test/PUC-Lua-5.1-tests/db.lua
+++ b/test/PUC-Lua-5.1-tests/db.lua
@@ -95,6 +95,10 @@ repeat
   assert(g(f) == 'a')
 until 1
 
+-- LuaJIT interprets a return from calling result of loadstring()
+-- with a new line number unlike Lua does.
+-- See also https://github.com/tarantool/tarantool/issues/5693.
+--[=[
 test([[if
 math.sin(1)
 then
@@ -149,7 +153,7 @@ end
 ]], {1,2,1,2,1,3})
 
 test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
-
+--]=]
 
 
 print'+'
@@ -178,8 +182,13 @@ function f(a,b)
   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")
+  -- f() function is called only from g(...) vararg function.
+  -- Lua 5.1 interprets ... in the vararg functions like additional
+  -- first argument unlike LuaJIT does.
+  -- This extension is from Lua 5.2.
+  -- See also https://github.com/tarantool/tarantool/issues/5694.
+  -- 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"))
@@ -208,11 +217,13 @@ function g(...)
   local feijao
   local AAAA,B = "xuxu", "mamão"
   f(AAAA,B)
-  assert(AAAA == "pera" and B == "maçã")
+  -- Test is disabled for LuaJIT for now. See comment in f().
+  -- assert(AAAA == "pera" and B == "maçã")
   do
      local B = 13
      local x,y = debug.getlocal(1,5)
-     assert(x == 'B' and y == 13)
+     -- Test is disabled for LuaJIT for now. See comment in f().
+     -- assert(x == 'B' and y == 13)
   end
 end
 
@@ -276,7 +287,8 @@ 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)
+-- Test is disabled for LuaJIT for now. See comment in f().
+-- 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)
 
@@ -314,12 +326,20 @@ assert(debug.setupvalue(io.read, 1, 10) == nil)
 
 -- testing count hooks
 local a=0
+-- 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.
+--[[
 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
@@ -352,18 +372,24 @@ function g1(x) g(x) end
 
 local function h (x) local f=g1; return f(x) end
 
-h(true)
+-- LuaJIT does not provide information about tail calls,
+-- unlike Lua does. getfenv() behaviour is also different here.
+-- Test is disabled for LuaJIT for now.
+-- 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()
+-- Behavior is different for LuaJIT. See the comment above.
+-- 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
+-- Behavior is different for LuaJIT. See the comment above.
+-- for _, k in ipairs(res) do assert(k == table.remove(b, 1)) end
 
 
 lim = 30000
@@ -375,7 +401,8 @@ local function foo (x)
   end
 end
 
-foo(lim)
+-- Behavior is different for LuaJIT. See the comment above.
+-- foo(lim)
 
 
 print"+"
@@ -411,7 +438,11 @@ end
 
 local co = coroutine.create(f)
 coroutine.resume(co, 3)
-checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
+-- LuaJIT does not provide information about tail calls,
+-- unlike Lua does.
+-- See also https://github.com/tarantool/tarantool/issues/5703.
+-- Test is disabled for LuaJIT for now.
+-- checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
 
 
 co = coroutine.create(function (x)
@@ -429,8 +460,12 @@ 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")
+-- LuaJIT does not report line with single "end" statement as
+-- an active line in debug.getinfo(), unlike Lua does.
+-- See also https://github.com/tarantool/tarantool/issues/5708.
+-- Test is disabled for LuaJIT for now.
 for i=x.linedefined + 1, x.lastlinedefined do
-  assert(x.activelines[i])
+  -- assert(x.activelines[i])
   x.activelines[i] = nil
 end
 assert(next(x.activelines) == nil)   -- no 'extra' elements
@@ -441,8 +476,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)
+-- LuaJIT does not support per-coroutine hooks.
+-- 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)
@@ -450,9 +487,11 @@ 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)
+-- Behavior is different for LuaJIT. See the comment above.
+-- assert(table.getn(tr) == 4 and tr[4] == l.currentline+2)
 assert(debug.gethook(co) == foo)
-assert(debug.gethook() == nil)
+-- Behavior is different for LuaJIT. See the comment above.
+-- assert(debug.gethook() == nil)
 checktraceback(co, {})
 
 
diff --git a/test/PUC-Lua-5.1-tests/errors.lua b/test/PUC-Lua-5.1-tests/errors.lua
index e881211..3270033 100644
--- a/test/PUC-Lua-5.1-tests/errors.lua
+++ b/test/PUC-Lua-5.1-tests/errors.lua
@@ -72,8 +72,12 @@ 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 reports the error as the following here:
+-- "attempt to perform arithmetic on global 'aaa' (a table value)"
+-- Lua 5.1 doesn't report variable name here.
+-- Test is 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
@@ -100,9 +104,12 @@ while 1 do
   insert(prefix, a)
 end]], "global 'insert'")
 
-checkmessage([[  -- tail call
-  return math.sin("a")
-]], "'sin'")
+-- Implementation of fast functions in LuaJIT does not provide
+-- enough info on failure.
+-- Test is disabled for LuaJIT.
+-- checkmessage([[  -- tail call
+--   return math.sin("a")
+-- ]], "'sin'")
 
 checkmessage([[collectgarbage("nooption")]], "invalid option")
 
@@ -193,7 +200,11 @@ checksyntax("[[a]]", "", "[[a]]", 1)
 checksyntax("'aa'", "", "'aa'", 1)
 
 -- test 255 as first char in a chunk
-checksyntax("\255a = 1", "", "\255", 1)
+-- LuaJIT does not avoid to use non-alphabetic 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)
@@ -215,7 +226,10 @@ local function testrep (init, rep)
 end
 testrep("a=", "{")
 testrep("a=", "(")
-testrep("", "a(")
+-- When compiled with LUAJIT_ENABLE_GC64 LJ_MAX_SLOTS limit
+-- is reached and error is LJ_ERR_XSLOTS ("function or expression too
+-- complex"). Test is disabled for LuaJIT.
+-- testrep("", "a(")
 testrep("", "do ")
 testrep("", "while a do ")
 testrep("", "if a then else ")
diff --git a/test/PUC-Lua-5.1-tests/gc.lua b/test/PUC-Lua-5.1-tests/gc.lua
index 86a9f75..b767104 100644
--- a/test/PUC-Lua-5.1-tests/gc.lua
+++ b/test/PUC-Lua-5.1-tests/gc.lua
@@ -108,11 +108,16 @@ local function dosteps (siz)
   return i
 end
 
+-- JIT compilation can unpredictable allocate or reference objects
+-- (or traces itself). Disable it for this chunk for stable
+-- GC results.
+jit.off()
 assert(dosteps(0) > 10)
 assert(dosteps(6) < dosteps(2))
 assert(dosteps(10000) == 1)
 assert(collectgarbage("step", 1000000) == true)
 assert(collectgarbage("step", 1000000))
+jit.on()
 
 
 do
diff --git a/test/PUC-Lua-5.1-tests/literals.lua b/test/PUC-Lua-5.1-tests/literals.lua
index 01d84d5..ee16a3e 100644
--- a/test/PUC-Lua-5.1-tests/literals.lua
+++ b/test/PUC-Lua-5.1-tests/literals.lua
@@ -158,6 +158,10 @@ end
 
 
 -- testing decimal point locale
+-- LuaJIT doesn't use `strtod()` depended 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-Lua-5.1-tests/main.lua b/test/PUC-Lua-5.1-tests/main.lua
index f520896..12f3981 100644
--- a/test/PUC-Lua-5.1-tests/main.lua
+++ b/test/PUC-Lua-5.1-tests/main.lua
@@ -65,9 +65,16 @@ 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)
+-- test 'arg' availability in libraries
+-- 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.
+-- prepfile"assert(arg==nil)"
+-- prepfile("assert(arg)", otherprog)
+-- RUN("lua -l%s - < %s", prog, otherprog)
 
 prepfile""
 RUN("lua - < %s > %s", prog, out)
@@ -89,26 +96,35 @@ prepfile[[
 RUN("lua - < %s > %s", prog, out)
 checkout("1\tnil\n")
 
+-- Version and status are printed in stdout instead 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.
+-- 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")
+-- 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")
+-- 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")
+-- 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 )
@@ -126,19 +142,29 @@ 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")
+-- 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)
 
+-- test loading and running bytecode files.
+-- 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.
 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")
+-- Behavior is different for LuaJIT. See the comment above.
+-- 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))
diff --git a/test/PUC-Lua-5.1-tests/math.lua b/test/PUC-Lua-5.1-tests/math.lua
index 5076f38..b46a3f5 100644
--- a/test/PUC-Lua-5.1-tests/math.lua
+++ b/test/PUC-Lua-5.1-tests/math.lua
@@ -100,7 +100,12 @@ 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)
+-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
+-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
+-- LuaJIT also has math.fmod() instead math.mod() builtin.
+-- See also https://github.com/tarantool/tarantool/issues/5711.
+-- Test is disabled.
+-- 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))
diff --git a/test/PUC-Lua-5.1-tests/nextvar.lua b/test/PUC-Lua-5.1-tests/nextvar.lua
index 7ceaa75..a63f97e 100644
--- a/test/PUC-Lua-5.1-tests/nextvar.lua
+++ b/test/PUC-Lua-5.1-tests/nextvar.lua
@@ -199,6 +199,12 @@ _G["xxx"] = 1
 assert(xxx==find("xxx"))
 print('+')
 
+-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
+-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
+-- LuaJIT also has math.fmod() instead math.mod() builtin.
+-- See also https://github.com/tarantool/tarantool/issues/5711.
+-- Test is disabled.
+--[=[
 a = {}
 for i=0,10000 do
   if math.mod(i,10) ~= 0 then
@@ -213,6 +219,7 @@ for i,v in pairs(a) do
 end
 assert(n.n == 9000)
 a = nil
+--]=]
 
 -- remove those 10000 new global variables
 for i=1,10000 do _G[i] = nil end
diff --git a/test/PUC-Lua-5.1-tests/pm.lua b/test/PUC-Lua-5.1-tests/pm.lua
index fa125dc..366a31c 100644
--- a/test/PUC-Lua-5.1-tests/pm.lua
+++ b/test/PUC-Lua-5.1-tests/pm.lua
@@ -223,7 +223,11 @@ assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI")
 
 
 -- tests for gmatch
-assert(string.gfind == string.gmatch)
+-- 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 builtin is removed from LuaJIT. Test is disabled.
+-- 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)
diff --git a/test/PUC-Lua-5.1-tests/strings.lua b/test/PUC-Lua-5.1-tests/strings.lua
index 237dbad..a97c888 100644
--- a/test/PUC-Lua-5.1-tests/strings.lua
+++ b/test/PUC-Lua-5.1-tests/strings.lua
@@ -102,7 +102,18 @@ print('+')
 
 x = '"ílo"\n\\'
 assert(string.format('%q%s', x, x) == '"\\"ílo\\"\\\n\\\\""ílo"\n\\')
-assert(string.format('%q', "\0") == [["\000"]])
+-- LuaJIT since v2.0.0-beta6 has extension from Lua 5.2:
+-- string.format(): %q reversible.
+-- In Lua 5.1 string.format() does not accept string values
+-- containing embedded zeros, except as arguments to the q option.
+-- In Lua 5.2 '\0' is not handled differently from other
+-- control chars in string.format('%q', ...).
+-- See commit 7cc981c14067d4b0e774a6bfb0acfc2f5c911f0d
+-- (string.format("%q", str) is now fully reversible
+-- (from Lua 5.2).).
+-- See also https://github.com/tarantool/tarantool/issues/5710.
+-- Test is disabled for LuaJIT for now.
+-- 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('') == "")
@@ -152,6 +163,9 @@ local function trylocale (w)
   return false
 end
 
+-- 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
@@ -166,6 +180,7 @@ else
   assert(string.gsub("áÁéÉ", "%u", "x") == "áxéx")
   assert(string.upper"áÁé{xuxu}ção" == "ÁÁÉ{XUXU}ÇÃO")
 end
+--]]
 
 os.setlocale("C")
 assert(os.setlocale() == 'C')
diff --git a/test/PUC-Lua-5.1-tests/vararg.lua b/test/PUC-Lua-5.1-tests/vararg.lua
index ae068fa..e2de1ad 100644
--- a/test/PUC-Lua-5.1-tests/vararg.lua
+++ b/test/PUC-Lua-5.1-tests/vararg.lua
@@ -21,9 +21,14 @@ 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)
+-- Lua 5.1 interprets ... in the vararg functions like additional
+-- first argument unlike LuaJIT does. All extra arguments is set
+-- into `arg` variable. This extension is from Lua 5.2.
+-- See also https://github.com/tarantool/tarantool/issues/5712.
+-- Test is disabled for LuaJIT.
+-- 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}))
@@ -35,15 +40,18 @@ 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)
+-- Test is disabled for LuaJIT for now. See the comment above.
+-- 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)
+-- Test is disabled for LuaJIT for now. See the comment above.
+-- 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)
+-- Test is disabled for LuaJIT for now. See the comment above.
+-- assert(t:f(1,4) == 3 and t:f(2) == 11)
 print('+')
 
 lim = 20
-- 
2.28.0


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Tarantool-patches] [PATCH luajit 3/3] test: adapt Lua 5.1 test suite for Tarantool
  2021-03-12  5:36 [Tarantool-patches] [PATCH luajit 0/3] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 1/3] test: add " Sergey Kaplun via Tarantool-patches
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 2/3] test: adapt PUC-Rio Lua 5.1 test suite for LuaJIT Sergey Kaplun via Tarantool-patches
@ 2021-03-12  5:36 ` Sergey Kaplun via Tarantool-patches
  2021-03-13 19:07   ` Sergey Ostanevich via Tarantool-patches
  2 siblings, 1 reply; 13+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-12  5:36 UTC (permalink / raw)
  To: Igor Munkin, Sergey Ostanevich; +Cc: tarantool-patches

In some insignificant details Tarantool's behaviour is not the same
as the behaviour of Lua 5.1.

`progname` is not edged by '"' to be able run other test suites.

Tests in the following files are disabled with corresponding comments:
* gc.lua
* main.lua
* pm.lua

See full list of disabled tests to adapt in
https://github.com/tarantool/tarantool/issues/5870.

Tests in the following files are adapted for testing with Tarantool's
out-of-source build:
* all.lua
* verybig.lua

Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
 test/PUC-Lua-5.1-tests/CMakeLists.txt |  3 +++
 test/PUC-Lua-5.1-tests/all.lua        | 16 ++++++++++++----
 test/PUC-Lua-5.1-tests/gc.lua         |  9 ++++++---
 test/PUC-Lua-5.1-tests/main.lua       | 24 +++++++++++++++++-------
 test/PUC-Lua-5.1-tests/pm.lua         |  6 +++++-
 test/PUC-Lua-5.1-tests/verybig.lua    |  4 +++-
 6 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/test/PUC-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Lua-5.1-tests/CMakeLists.txt
index 08bee36..1249cab 100644
--- a/test/PUC-Lua-5.1-tests/CMakeLists.txt
+++ b/test/PUC-Lua-5.1-tests/CMakeLists.txt
@@ -82,6 +82,9 @@ add_custom_command(TARGET PUC-Lua-5.1-tests
     # LUA_INIT="package.path='?\;'..package.path"
     # So use less preferable way for tests.
     LUA_PATH="${LUA_PATH}\;\;"
+    # XXX: Adapt to run test on readonly file systems
+    # with loadfile(CUR_SOURCE_DIR..filename).
+    CUR_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
     ${LUAJIT_TEST_COMMAND} ${TEST_RUNNER}
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
 )
diff --git a/test/PUC-Lua-5.1-tests/all.lua b/test/PUC-Lua-5.1-tests/all.lua
index 8c4afac..52a6235 100755
--- a/test/PUC-Lua-5.1-tests/all.lua
+++ b/test/PUC-Lua-5.1-tests/all.lua
@@ -58,9 +58,13 @@ end
 --
 -- redefine dofile to run files through dump/undump
 --
-dofile = function (n)
+-- Adapt test for testing with Tarantool's out-of-source build
+-- on read only file system. CUR_SOURCE_DIR is set via CMake.
+local path_to_sources = os.getenv('CUR_SOURCE_DIR')..'/'
+dofile = function (n, prefix)
+  local pr = prefix or path_to_sources
   showmem()
-  local f = assert(loadfile(n))
+  local f = assert(loadfile(pr..n))
   local b = string.dump(f)
   f = assert(loadstring(b))
   return f()
@@ -77,7 +81,9 @@ do
   end
 end
 
-local f = assert(loadfile('gc.lua'))
+-- Adapt test for testing with Tarantool's out-of-source build
+-- on read only file system.
+local f = assert(loadfile(path_to_sources..'gc.lua'))
 f()
 dofile('db.lua')
 assert(dofile('calls.lua') == deep and deep)
@@ -88,7 +94,9 @@ assert(dofile('locals.lua') == 5)
 dofile('constructs.lua')
 dofile('code.lua')
 do
-  local f = coroutine.wrap(assert(loadfile('big.lua')))
+  -- Adapt test for testing with Tarantool's out-of-source build
+  -- on read only file system.
+  local f = coroutine.wrap(assert(loadfile(path_to_sources..'big.lua')))
   assert(f() == 'b')
   assert(f() == 'a')
 end
diff --git a/test/PUC-Lua-5.1-tests/gc.lua b/test/PUC-Lua-5.1-tests/gc.lua
index b767104..6c4097a 100644
--- a/test/PUC-Lua-5.1-tests/gc.lua
+++ b/test/PUC-Lua-5.1-tests/gc.lua
@@ -128,9 +128,12 @@ do
     local a = {}
   until gcinfo() > 1000
   collectgarbage"restart"
-  repeat
-    local a = {}
-  until gcinfo() < 1000
+  -- Tarantool has too much objects at start.
+  -- gcinfo() is always greater than 1000.
+  -- Test is disabled for Tarantool binary.
+  -- repeat
+  --   local a = {}
+  -- until gcinfo() < 1000
 end
 
 lim = 15
diff --git a/test/PUC-Lua-5.1-tests/main.lua b/test/PUC-Lua-5.1-tests/main.lua
index 12f3981..69eb5db 100644
--- a/test/PUC-Lua-5.1-tests/main.lua
+++ b/test/PUC-Lua-5.1-tests/main.lua
@@ -11,7 +11,7 @@ out = os.tmpname()
 do
   local i = 0
   while arg[i] do i=i-1 end
-  progname = '"'..arg[i+1]..'"'
+  progname = arg[i+1]
 end
 print(progname)
 
@@ -50,8 +50,10 @@ 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")
+-- Test is disabled for 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")
 
 local a = [[
   assert(table.getn(arg) == 3 and arg[1] == 'a' and
@@ -63,7 +65,10 @@ local a = [[
 ]]
 a = string.format(a, progname)
 prepfile(a)
-RUN('lua "-e " -- %s a b c', prog)
+-- Tarantool has different command line argument parsing.
+-- For example it always set itself as arg[-1].
+-- Test is disabled for Tarantool binary.
+-- RUN('lua "-e " -- %s a b c', prog)
 
 -- test 'arg' availability in libraries
 -- LuaJIT v2.1.0-beta3 has extension from Lua 5.3:
@@ -85,8 +90,10 @@ 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")
+-- Test is disabled for 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(
@@ -177,7 +184,10 @@ assert(not os.remove(out))
 
 RUN("lua -v")
 
-NoRun("lua -h")
+-- Tarantool returns zero status at exit with -h option, unlike
+-- Lua does.
+-- Test is disabled for Tarantool binary.
+-- NoRun("lua -h")
 NoRun("lua -e")
 NoRun("lua -e a")
 NoRun("lua -f")
diff --git a/test/PUC-Lua-5.1-tests/pm.lua b/test/PUC-Lua-5.1-tests/pm.lua
index 366a31c..6e1b403 100644
--- a/test/PUC-Lua-5.1-tests/pm.lua
+++ b/test/PUC-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)
+-- 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.
+-- Test is disabled for Tarantool binary.
+-- assert(rev(rev(x)) == x)
 
 
 -- gsub with tables
diff --git a/test/PUC-Lua-5.1-tests/verybig.lua b/test/PUC-Lua-5.1-tests/verybig.lua
index 59e0142..bfb95df 100644
--- a/test/PUC-Lua-5.1-tests/verybig.lua
+++ b/test/PUC-Lua-5.1-tests/verybig.lua
@@ -93,7 +93,9 @@ for s in string.gmatch(prog, "$([^$]+)") do
   if not n then io.write(s) else F[n]() end
 end
 io.close()
-result = dofile(file)
+-- Adapt test for testing with Tarantool's out-of-source build
+-- on read only file system.
+result = dofile(file, "")
 assert(os.remove(file))
 print'OK'
 return result
-- 
2.28.0


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit 2/3] test: adapt PUC-Rio Lua 5.1 test suite for LuaJIT
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 2/3] test: adapt PUC-Rio Lua 5.1 test suite for LuaJIT Sergey Kaplun via Tarantool-patches
@ 2021-03-13 19:04   ` Sergey Ostanevich via Tarantool-patches
  2021-03-22 18:52   ` Igor Munkin via Tarantool-patches
  1 sibling, 0 replies; 13+ messages in thread
From: Sergey Ostanevich via Tarantool-patches @ 2021-03-13 19:04 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Hi!

Thanks for the patch!

LGTM.

Sergos.

> On 12 Mar 2021, at 08:36, Sergey Kaplun <skaplun@tarantool.org> wrote:
> 
> In some insignificant details LuaJIT's behaviour is not the same
> as the behaviour of Lua 5.1.
> 
> Tests in the following files are disabled with corresponding comments:
> * closure.lua
> * constructs.lua
> * db.lua
> * errors.lua
> * literals.lua
> * main.lua
> * math.lua
> * nextvar.lua
> * pm.lua
> * strings.lua
> * vararg.lua
> 
> See full list of disabled tests to adapt in
> https://github.com/tarantool/tarantool/issues/5870.
> 
> jit.off() as prologue and jit.on() as epilogue is added to one test
> chunk in gc.lua for stable (JIT unrelated) GC test results.
> 
> Part of tarantool/tarantool#5845
> Part of tarantool/tarantool#4473
> ---
> test/PUC-Lua-5.1-tests/closure.lua    | 12 ++++-
> test/PUC-Lua-5.1-tests/constructs.lua |  7 +++
> test/PUC-Lua-5.1-tests/db.lua         | 75 ++++++++++++++++++++-------
> test/PUC-Lua-5.1-tests/errors.lua     | 28 +++++++---
> test/PUC-Lua-5.1-tests/gc.lua         |  5 ++
> test/PUC-Lua-5.1-tests/literals.lua   |  5 ++
> test/PUC-Lua-5.1-tests/main.lua       | 56 ++++++++++++++------
> test/PUC-Lua-5.1-tests/math.lua       |  7 ++-
> test/PUC-Lua-5.1-tests/nextvar.lua    |  7 +++
> test/PUC-Lua-5.1-tests/pm.lua         |  6 ++-
> test/PUC-Lua-5.1-tests/strings.lua    | 17 +++++-
> test/PUC-Lua-5.1-tests/vararg.lua     | 20 ++++---
> 12 files changed, 195 insertions(+), 50 deletions(-)
> 
> diff --git a/test/PUC-Lua-5.1-tests/closure.lua b/test/PUC-Lua-5.1-tests/closure.lua
> index 27ca0ad..e9bd564 100644
> --- a/test/PUC-Lua-5.1-tests/closure.lua
> +++ b/test/PUC-Lua-5.1-tests/closure.lua
> @@ -174,7 +174,10 @@ f = coroutine.wrap(foo)
> local a = {}
> assert(f(a) == _G)
> local a,b = pcall(f)
> -assert(a and b == _G)
> +-- LuaJIT getfenv() behaviour is different in tail calls.
> +-- 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
> @@ -261,6 +264,12 @@ end
> 
> local x = gen(100)
> local a = {}
> +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> +-- See also https://github.com/tarantool/tarantool/issues/5711.
> +-- Test is disabled.
> +--[=[
> while 1 do
>   local n = x()
>   if n == nil then break end
> @@ -269,6 +278,7 @@ while 1 do
> end
> 
> assert(table.getn(a) == 25 and a[table.getn(a)] == 97)
> +--]=]
> 
> 
> -- errors in coroutines
> diff --git a/test/PUC-Lua-5.1-tests/constructs.lua b/test/PUC-Lua-5.1-tests/constructs.lua
> index 5fb3798..6776ee6 100644
> --- a/test/PUC-Lua-5.1-tests/constructs.lua
> +++ b/test/PUC-Lua-5.1-tests/constructs.lua
> @@ -200,6 +200,12 @@ a,b = F(nil)==nil; assert(a == true and b == nil)
> 
> function ID(x) return x end
> 
> +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> +-- See also https://github.com/tarantool/tarantool/issues/5711.
> +-- Test is disabled.
> +--[=[
> function f(t, i)
>   local b = t.n
>   local res = math.mod(math.floor(i/c), b)+1
> @@ -236,5 +242,6 @@ repeat
>   if math.mod(i,4000) == 0 then print('+') end
>   i = i+1
> until i==c
> +--]=]
> 
> print'OK'
> diff --git a/test/PUC-Lua-5.1-tests/db.lua b/test/PUC-Lua-5.1-tests/db.lua
> index 9d2c86f..591a006 100644
> --- a/test/PUC-Lua-5.1-tests/db.lua
> +++ b/test/PUC-Lua-5.1-tests/db.lua
> @@ -95,6 +95,10 @@ repeat
>   assert(g(f) == 'a')
> until 1
> 
> +-- LuaJIT interprets a return from calling result of loadstring()
> +-- with a new line number unlike Lua does.
> +-- See also https://github.com/tarantool/tarantool/issues/5693.
> +--[=[
> test([[if
> math.sin(1)
> then
> @@ -149,7 +153,7 @@ end
> ]], {1,2,1,2,1,3})
> 
> test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
> -
> +--]=]
> 
> 
> print'+'
> @@ -178,8 +182,13 @@ function f(a,b)
>   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")
> +  -- f() function is called only from g(...) vararg function.
> +  -- Lua 5.1 interprets ... in the vararg functions like additional
> +  -- first argument unlike LuaJIT does.
> +  -- This extension is from Lua 5.2.
> +  -- See also https://github.com/tarantool/tarantool/issues/5694.
> +  -- 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"))
> @@ -208,11 +217,13 @@ function g(...)
>   local feijao
>   local AAAA,B = "xuxu", "mam�o"
>   f(AAAA,B)
> -  assert(AAAA == "pera" and B == "ma��")
> +  -- Test is disabled for LuaJIT for now. See comment in f().
> +  -- assert(AAAA == "pera" and B == "ma��")
>   do
>      local B = 13
>      local x,y = debug.getlocal(1,5)
> -     assert(x == 'B' and y == 13)
> +     -- Test is disabled for LuaJIT for now. See comment in f().
> +     -- assert(x == 'B' and y == 13)
>   end
> end
> 
> @@ -276,7 +287,8 @@ 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)
> +-- Test is disabled for LuaJIT for now. See comment in f().
> +-- 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)
> 
> @@ -314,12 +326,20 @@ assert(debug.setupvalue(io.read, 1, 10) == nil)
> 
> -- testing count hooks
> local a=0
> +-- 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.
> +--[[
> 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
> @@ -352,18 +372,24 @@ function g1(x) g(x) end
> 
> local function h (x) local f=g1; return f(x) end
> 
> -h(true)
> +-- LuaJIT does not provide information about tail calls,
> +-- unlike Lua does. getfenv() behaviour is also different here.
> +-- Test is disabled for LuaJIT for now.
> +-- 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()
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- 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
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- for _, k in ipairs(res) do assert(k == table.remove(b, 1)) end
> 
> 
> lim = 30000
> @@ -375,7 +401,8 @@ local function foo (x)
>   end
> end
> 
> -foo(lim)
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- foo(lim)
> 
> 
> print"+"
> @@ -411,7 +438,11 @@ end
> 
> local co = coroutine.create(f)
> coroutine.resume(co, 3)
> -checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
> +-- LuaJIT does not provide information about tail calls,
> +-- unlike Lua does.
> +-- See also https://github.com/tarantool/tarantool/issues/5703.
> +-- Test is disabled for LuaJIT for now.
> +-- checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
> 
> 
> co = coroutine.create(function (x)
> @@ -429,8 +460,12 @@ 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")
> +-- LuaJIT does not report line with single "end" statement as
> +-- an active line in debug.getinfo(), unlike Lua does.
> +-- See also https://github.com/tarantool/tarantool/issues/5708.
> +-- Test is disabled for LuaJIT for now.
> for i=x.linedefined + 1, x.lastlinedefined do
> -  assert(x.activelines[i])
> +  -- assert(x.activelines[i])
>   x.activelines[i] = nil
> end
> assert(next(x.activelines) == nil)   -- no 'extra' elements
> @@ -441,8 +476,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)
> +-- LuaJIT does not support per-coroutine hooks.
> +-- 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)
> @@ -450,9 +487,11 @@ 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)
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- assert(table.getn(tr) == 4 and tr[4] == l.currentline+2)
> assert(debug.gethook(co) == foo)
> -assert(debug.gethook() == nil)
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- assert(debug.gethook() == nil)
> checktraceback(co, {})
> 
> 
> diff --git a/test/PUC-Lua-5.1-tests/errors.lua b/test/PUC-Lua-5.1-tests/errors.lua
> index e881211..3270033 100644
> --- a/test/PUC-Lua-5.1-tests/errors.lua
> +++ b/test/PUC-Lua-5.1-tests/errors.lua
> @@ -72,8 +72,12 @@ 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 reports the error as the following here:
> +-- "attempt to perform arithmetic on global 'aaa' (a table value)"
> +-- Lua 5.1 doesn't report variable name here.
> +-- Test is 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
> @@ -100,9 +104,12 @@ while 1 do
>   insert(prefix, a)
> end]], "global 'insert'")
> 
> -checkmessage([[  -- tail call
> -  return math.sin("a")
> -]], "'sin'")
> +-- Implementation of fast functions in LuaJIT does not provide
> +-- enough info on failure.
> +-- Test is disabled for LuaJIT.
> +-- checkmessage([[  -- tail call
> +--   return math.sin("a")
> +-- ]], "'sin'")
> 
> checkmessage([[collectgarbage("nooption")]], "invalid option")
> 
> @@ -193,7 +200,11 @@ checksyntax("[[a]]", "", "[[a]]", 1)
> checksyntax("'aa'", "", "'aa'", 1)
> 
> -- test 255 as first char in a chunk
> -checksyntax("\255a = 1", "", "\255", 1)
> +-- LuaJIT does not avoid to use non-alphabetic 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)
> @@ -215,7 +226,10 @@ local function testrep (init, rep)
> end
> testrep("a=", "{")
> testrep("a=", "(")
> -testrep("", "a(")
> +-- When compiled with LUAJIT_ENABLE_GC64 LJ_MAX_SLOTS limit
> +-- is reached and error is LJ_ERR_XSLOTS ("function or expression too
> +-- complex"). Test is disabled for LuaJIT.
> +-- testrep("", "a(")
> testrep("", "do ")
> testrep("", "while a do ")
> testrep("", "if a then else ")
> diff --git a/test/PUC-Lua-5.1-tests/gc.lua b/test/PUC-Lua-5.1-tests/gc.lua
> index 86a9f75..b767104 100644
> --- a/test/PUC-Lua-5.1-tests/gc.lua
> +++ b/test/PUC-Lua-5.1-tests/gc.lua
> @@ -108,11 +108,16 @@ local function dosteps (siz)
>   return i
> end
> 
> +-- JIT compilation can unpredictable allocate or reference objects
> +-- (or traces itself). Disable it for this chunk for stable
> +-- GC results.
> +jit.off()
> assert(dosteps(0) > 10)
> assert(dosteps(6) < dosteps(2))
> assert(dosteps(10000) == 1)
> assert(collectgarbage("step", 1000000) == true)
> assert(collectgarbage("step", 1000000))
> +jit.on()
> 
> 
> do
> diff --git a/test/PUC-Lua-5.1-tests/literals.lua b/test/PUC-Lua-5.1-tests/literals.lua
> index 01d84d5..ee16a3e 100644
> --- a/test/PUC-Lua-5.1-tests/literals.lua
> +++ b/test/PUC-Lua-5.1-tests/literals.lua
> @@ -158,6 +158,10 @@ end
> 
> 
> -- testing decimal point locale
> +-- LuaJIT doesn't use `strtod()` depended 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-Lua-5.1-tests/main.lua b/test/PUC-Lua-5.1-tests/main.lua
> index f520896..12f3981 100644
> --- a/test/PUC-Lua-5.1-tests/main.lua
> +++ b/test/PUC-Lua-5.1-tests/main.lua
> @@ -65,9 +65,16 @@ 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)
> +-- test 'arg' availability in libraries
> +-- 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.
> +-- prepfile"assert(arg==nil)"
> +-- prepfile("assert(arg)", otherprog)
> +-- RUN("lua -l%s - < %s", prog, otherprog)
> 
> prepfile""
> RUN("lua - < %s > %s", prog, out)
> @@ -89,26 +96,35 @@ prepfile[[
> RUN("lua - < %s > %s", prog, out)
> checkout("1\tnil\n")
> 
> +-- Version and status are printed in stdout instead 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.
> +-- 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")
> +-- 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")
> +-- 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")
> +-- 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 )
> @@ -126,19 +142,29 @@ 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")
> +-- 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)
> 
> +-- test loading and running bytecode files.
> +-- 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.
> 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")
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- 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))
> diff --git a/test/PUC-Lua-5.1-tests/math.lua b/test/PUC-Lua-5.1-tests/math.lua
> index 5076f38..b46a3f5 100644
> --- a/test/PUC-Lua-5.1-tests/math.lua
> +++ b/test/PUC-Lua-5.1-tests/math.lua
> @@ -100,7 +100,12 @@ 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)
> +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> +-- See also https://github.com/tarantool/tarantool/issues/5711.
> +-- Test is disabled.
> +-- 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))
> diff --git a/test/PUC-Lua-5.1-tests/nextvar.lua b/test/PUC-Lua-5.1-tests/nextvar.lua
> index 7ceaa75..a63f97e 100644
> --- a/test/PUC-Lua-5.1-tests/nextvar.lua
> +++ b/test/PUC-Lua-5.1-tests/nextvar.lua
> @@ -199,6 +199,12 @@ _G["xxx"] = 1
> assert(xxx==find("xxx"))
> print('+')
> 
> +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> +-- See also https://github.com/tarantool/tarantool/issues/5711.
> +-- Test is disabled.
> +--[=[
> a = {}
> for i=0,10000 do
>   if math.mod(i,10) ~= 0 then
> @@ -213,6 +219,7 @@ for i,v in pairs(a) do
> end
> assert(n.n == 9000)
> a = nil
> +--]=]
> 
> -- remove those 10000 new global variables
> for i=1,10000 do _G[i] = nil end
> diff --git a/test/PUC-Lua-5.1-tests/pm.lua b/test/PUC-Lua-5.1-tests/pm.lua
> index fa125dc..366a31c 100644
> --- a/test/PUC-Lua-5.1-tests/pm.lua
> +++ b/test/PUC-Lua-5.1-tests/pm.lua
> @@ -223,7 +223,11 @@ assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI")
> 
> 
> -- tests for gmatch
> -assert(string.gfind == string.gmatch)
> +-- 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 builtin is removed from LuaJIT. Test is disabled.
> +-- 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)
> diff --git a/test/PUC-Lua-5.1-tests/strings.lua b/test/PUC-Lua-5.1-tests/strings.lua
> index 237dbad..a97c888 100644
> --- a/test/PUC-Lua-5.1-tests/strings.lua
> +++ b/test/PUC-Lua-5.1-tests/strings.lua
> @@ -102,7 +102,18 @@ print('+')
> 
> x = '"�lo"\n\\'
> assert(string.format('%q%s', x, x) == '"\\"�lo\\"\\\n\\\\""�lo"\n\\')
> -assert(string.format('%q', "\0") == [["\000"]])
> +-- LuaJIT since v2.0.0-beta6 has extension from Lua 5.2:
> +-- string.format(): %q reversible.
> +-- In Lua 5.1 string.format() does not accept string values
> +-- containing embedded zeros, except as arguments to the q option.
> +-- In Lua 5.2 '\0' is not handled differently from other
> +-- control chars in string.format('%q', ...).
> +-- See commit 7cc981c14067d4b0e774a6bfb0acfc2f5c911f0d
> +-- (string.format("%q", str) is now fully reversible
> +-- (from Lua 5.2).).
> +-- See also https://github.com/tarantool/tarantool/issues/5710.
> +-- Test is disabled for LuaJIT for now.
> +-- 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('') == "")
> @@ -152,6 +163,9 @@ local function trylocale (w)
>   return false
> end
> 
> +-- 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
> @@ -166,6 +180,7 @@ else
>   assert(string.gsub("����", "%u", "x") == "�x�x")
>   assert(string.upper"���{xuxu}��o" == "���{XUXU}��O")
> end
> +--]]
> 
> os.setlocale("C")
> assert(os.setlocale() == 'C')
> diff --git a/test/PUC-Lua-5.1-tests/vararg.lua b/test/PUC-Lua-5.1-tests/vararg.lua
> index ae068fa..e2de1ad 100644
> --- a/test/PUC-Lua-5.1-tests/vararg.lua
> +++ b/test/PUC-Lua-5.1-tests/vararg.lua
> @@ -21,9 +21,14 @@ 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)
> +-- Lua 5.1 interprets ... in the vararg functions like additional
> +-- first argument unlike LuaJIT does. All extra arguments is set
> +-- into `arg` variable. This extension is from Lua 5.2.
> +-- See also https://github.com/tarantool/tarantool/issues/5712.
> +-- Test is disabled for LuaJIT.
> +-- 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}))
> @@ -35,15 +40,18 @@ 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)
> +-- Test is disabled for LuaJIT for now. See the comment above.
> +-- 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)
> +-- Test is disabled for LuaJIT for now. See the comment above.
> +-- 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)
> +-- Test is disabled for LuaJIT for now. See the comment above.
> +-- assert(t:f(1,4) == 3 and t:f(2) == 11)
> print('+')
> 
> lim = 20
> -- 
> 2.28.0
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit 3/3] test: adapt Lua 5.1 test suite for Tarantool
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 3/3] test: adapt Lua 5.1 test suite for Tarantool Sergey Kaplun via Tarantool-patches
@ 2021-03-13 19:07   ` Sergey Ostanevich via Tarantool-patches
  0 siblings, 0 replies; 13+ messages in thread
From: Sergey Ostanevich via Tarantool-patches @ 2021-03-13 19:07 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Hi!

Thanks for the patch!

LGTM.

Sergos.

> On 12 Mar 2021, at 08:36, Sergey Kaplun <skaplun@tarantool.org> wrote:
> 
> In some insignificant details Tarantool's behaviour is not the same
> as the behaviour of Lua 5.1.
> 
> `progname` is not edged by '"' to be able run other test suites.
> 
> Tests in the following files are disabled with corresponding comments:
> * gc.lua
> * main.lua
> * pm.lua
> 
> See full list of disabled tests to adapt in
> https://github.com/tarantool/tarantool/issues/5870.
> 
> Tests in the following files are adapted for testing with Tarantool's
> out-of-source build:
> * all.lua
> * verybig.lua
> 
> Part of tarantool/tarantool#5845
> Part of tarantool/tarantool#4473
> ---
> test/PUC-Lua-5.1-tests/CMakeLists.txt |  3 +++
> test/PUC-Lua-5.1-tests/all.lua        | 16 ++++++++++++----
> test/PUC-Lua-5.1-tests/gc.lua         |  9 ++++++---
> test/PUC-Lua-5.1-tests/main.lua       | 24 +++++++++++++++++-------
> test/PUC-Lua-5.1-tests/pm.lua         |  6 +++++-
> test/PUC-Lua-5.1-tests/verybig.lua    |  4 +++-
> 6 files changed, 46 insertions(+), 16 deletions(-)
> 
> diff --git a/test/PUC-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Lua-5.1-tests/CMakeLists.txt
> index 08bee36..1249cab 100644
> --- a/test/PUC-Lua-5.1-tests/CMakeLists.txt
> +++ b/test/PUC-Lua-5.1-tests/CMakeLists.txt
> @@ -82,6 +82,9 @@ add_custom_command(TARGET PUC-Lua-5.1-tests
>     # LUA_INIT="package.path='?\;'..package.path"
>     # So use less preferable way for tests.
>     LUA_PATH="${LUA_PATH}\;\;"
> +    # XXX: Adapt to run test on readonly file systems
> +    # with loadfile(CUR_SOURCE_DIR..filename).
> +    CUR_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
>     ${LUAJIT_TEST_COMMAND} ${TEST_RUNNER}
>   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> )
> diff --git a/test/PUC-Lua-5.1-tests/all.lua b/test/PUC-Lua-5.1-tests/all.lua
> index 8c4afac..52a6235 100755
> --- a/test/PUC-Lua-5.1-tests/all.lua
> +++ b/test/PUC-Lua-5.1-tests/all.lua
> @@ -58,9 +58,13 @@ end
> --
> -- redefine dofile to run files through dump/undump
> --
> -dofile = function (n)
> +-- Adapt test for testing with Tarantool's out-of-source build
> +-- on read only file system. CUR_SOURCE_DIR is set via CMake.
> +local path_to_sources = os.getenv('CUR_SOURCE_DIR')..'/'
> +dofile = function (n, prefix)
> +  local pr = prefix or path_to_sources
>   showmem()
> -  local f = assert(loadfile(n))
> +  local f = assert(loadfile(pr..n))
>   local b = string.dump(f)
>   f = assert(loadstring(b))
>   return f()
> @@ -77,7 +81,9 @@ do
>   end
> end
> 
> -local f = assert(loadfile('gc.lua'))
> +-- Adapt test for testing with Tarantool's out-of-source build
> +-- on read only file system.
> +local f = assert(loadfile(path_to_sources..'gc.lua'))
> f()
> dofile('db.lua')
> assert(dofile('calls.lua') == deep and deep)
> @@ -88,7 +94,9 @@ assert(dofile('locals.lua') == 5)
> dofile('constructs.lua')
> dofile('code.lua')
> do
> -  local f = coroutine.wrap(assert(loadfile('big.lua')))
> +  -- Adapt test for testing with Tarantool's out-of-source build
> +  -- on read only file system.
> +  local f = coroutine.wrap(assert(loadfile(path_to_sources..'big.lua')))
>   assert(f() == 'b')
>   assert(f() == 'a')
> end
> diff --git a/test/PUC-Lua-5.1-tests/gc.lua b/test/PUC-Lua-5.1-tests/gc.lua
> index b767104..6c4097a 100644
> --- a/test/PUC-Lua-5.1-tests/gc.lua
> +++ b/test/PUC-Lua-5.1-tests/gc.lua
> @@ -128,9 +128,12 @@ do
>     local a = {}
>   until gcinfo() > 1000
>   collectgarbage"restart"
> -  repeat
> -    local a = {}
> -  until gcinfo() < 1000
> +  -- Tarantool has too much objects at start.
> +  -- gcinfo() is always greater than 1000.
> +  -- Test is disabled for Tarantool binary.
> +  -- repeat
> +  --   local a = {}
> +  -- until gcinfo() < 1000
> end
> 
> lim = 15
> diff --git a/test/PUC-Lua-5.1-tests/main.lua b/test/PUC-Lua-5.1-tests/main.lua
> index 12f3981..69eb5db 100644
> --- a/test/PUC-Lua-5.1-tests/main.lua
> +++ b/test/PUC-Lua-5.1-tests/main.lua
> @@ -11,7 +11,7 @@ out = os.tmpname()
> do
>   local i = 0
>   while arg[i] do i=i-1 end
> -  progname = '"'..arg[i+1]..'"'
> +  progname = arg[i+1]
> end
> print(progname)
> 
> @@ -50,8 +50,10 @@ 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")
> +-- Test is disabled for 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")
> 
> local a = [[
>   assert(table.getn(arg) == 3 and arg[1] == 'a' and
> @@ -63,7 +65,10 @@ local a = [[
> ]]
> a = string.format(a, progname)
> prepfile(a)
> -RUN('lua "-e " -- %s a b c', prog)
> +-- Tarantool has different command line argument parsing.
> +-- For example it always set itself as arg[-1].
> +-- Test is disabled for Tarantool binary.
> +-- RUN('lua "-e " -- %s a b c', prog)
> 
> -- test 'arg' availability in libraries
> -- LuaJIT v2.1.0-beta3 has extension from Lua 5.3:
> @@ -85,8 +90,10 @@ 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")
> +-- Test is disabled for 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(
> @@ -177,7 +184,10 @@ assert(not os.remove(out))
> 
> RUN("lua -v")
> 
> -NoRun("lua -h")
> +-- Tarantool returns zero status at exit with -h option, unlike
> +-- Lua does.
> +-- Test is disabled for Tarantool binary.
> +-- NoRun("lua -h")
> NoRun("lua -e")
> NoRun("lua -e a")
> NoRun("lua -f")
> diff --git a/test/PUC-Lua-5.1-tests/pm.lua b/test/PUC-Lua-5.1-tests/pm.lua
> index 366a31c..6e1b403 100644
> --- a/test/PUC-Lua-5.1-tests/pm.lua
> +++ b/test/PUC-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)
> +-- 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.
> +-- Test is disabled for Tarantool binary.
> +-- assert(rev(rev(x)) == x)
> 
> 
> -- gsub with tables
> diff --git a/test/PUC-Lua-5.1-tests/verybig.lua b/test/PUC-Lua-5.1-tests/verybig.lua
> index 59e0142..bfb95df 100644
> --- a/test/PUC-Lua-5.1-tests/verybig.lua
> +++ b/test/PUC-Lua-5.1-tests/verybig.lua
> @@ -93,7 +93,9 @@ for s in string.gmatch(prog, "$([^$]+)") do
>   if not n then io.write(s) else F[n]() end
> end
> io.close()
> -result = dofile(file)
> +-- Adapt test for testing with Tarantool's out-of-source build
> +-- on read only file system.
> +result = dofile(file, "")
> assert(os.remove(file))
> print'OK'
> return result
> -- 
> 2.28.0
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit 1/3] test: add PUC-Rio Lua 5.1 test suite
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 1/3] test: add " Sergey Kaplun via Tarantool-patches
@ 2021-03-16 13:35   ` Sergey Ostanevich via Tarantool-patches
  2021-03-17 15:17     ` Igor Munkin via Tarantool-patches
  2021-03-17 14:55   ` Igor Munkin via Tarantool-patches
  1 sibling, 1 reply; 13+ messages in thread
From: Sergey Ostanevich via Tarantool-patches @ 2021-03-16 13:35 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Hi!

Thanks for the patch!



> On 12 Mar 2021, at 08:36, Sergey Kaplun <skaplun@tarantool.org> wrote:
> 
> This patch adds PUC-Rio Lua 5.1 test suite as a part of the LuaJIT
> test suite. Source code taken verbatim from
> https://www.lua.org/tests/lua5.1-tests.tar.gz.
> 
> <lib1.c> and <lib2.c> is slightly modified to be consistent with the
> current LuaJIT's LuaC API.
> 

This should be a different commit, isn’t it?

> Some tests may fail after this commit. They will be disabled
> or adapted in the next patches.

The fact patch causes - even temporarily - some fails is no good. The
only exception is initial commit, that brings original test suite.
Can you please make a consistent change that will left the tests disabled
until they adapted and enabled back?

regards,
Sergos

> 
> Part of tarantool/tarantool#5845
> Part of tarantool/tarantool#4473
> ---
> .luacheckrc                           |    5 +-
> test/CMakeLists.txt                   |    4 +-
> test/PUC-Lua-5.1-tests/CMakeLists.txt |   89 ++
> test/PUC-Lua-5.1-tests/README         |   41 +
> test/PUC-Lua-5.1-tests/all.lua        |  137 +++
> test/PUC-Lua-5.1-tests/api.lua        |  711 +++++++++++++++
> test/PUC-Lua-5.1-tests/attrib.lua     |  339 ++++++++
> test/PUC-Lua-5.1-tests/big.lua        |  381 ++++++++
> test/PUC-Lua-5.1-tests/calls.lua      |  294 +++++++
> test/PUC-Lua-5.1-tests/checktable.lua |   77 ++
> test/PUC-Lua-5.1-tests/closure.lua    |  422 +++++++++
> test/PUC-Lua-5.1-tests/code.lua       |  143 +++
> test/PUC-Lua-5.1-tests/constructs.lua |  240 ++++++
> test/PUC-Lua-5.1-tests/db.lua         |  499 +++++++++++
> test/PUC-Lua-5.1-tests/errors.lua     |  250 ++++++
> test/PUC-Lua-5.1-tests/etc/ltests.c   | 1147 +++++++++++++++++++++++++
> test/PUC-Lua-5.1-tests/etc/ltests.h   |   92 ++
> test/PUC-Lua-5.1-tests/events.lua     |  360 ++++++++
> test/PUC-Lua-5.1-tests/files.lua      |  324 +++++++
> test/PUC-Lua-5.1-tests/gc.lua         |  312 +++++++
> test/PUC-Lua-5.1-tests/libs/lib1.c    |   40 +
> test/PUC-Lua-5.1-tests/libs/lib11.c   |   18 +
> test/PUC-Lua-5.1-tests/libs/lib2.c    |   28 +
> test/PUC-Lua-5.1-tests/libs/lib21.c   |   18 +
> test/PUC-Lua-5.1-tests/literals.lua   |  176 ++++
> test/PUC-Lua-5.1-tests/locals.lua     |  127 +++
> test/PUC-Lua-5.1-tests/main.lua       |  159 ++++
> test/PUC-Lua-5.1-tests/math.lua       |  208 +++++
> test/PUC-Lua-5.1-tests/nextvar.lua    |  396 +++++++++
> test/PUC-Lua-5.1-tests/pm.lua         |  273 ++++++
> test/PUC-Lua-5.1-tests/sort.lua       |   74 ++
> test/PUC-Lua-5.1-tests/strings.lua    |  176 ++++
> test/PUC-Lua-5.1-tests/vararg.lua     |  126 +++
> test/PUC-Lua-5.1-tests/verybig.lua    |  100 +++
> 34 files changed, 7783 insertions(+), 3 deletions(-)
> create mode 100644 test/PUC-Lua-5.1-tests/CMakeLists.txt
> create mode 100644 test/PUC-Lua-5.1-tests/README
> create mode 100755 test/PUC-Lua-5.1-tests/all.lua
> create mode 100644 test/PUC-Lua-5.1-tests/api.lua
> create mode 100644 test/PUC-Lua-5.1-tests/attrib.lua
> create mode 100644 test/PUC-Lua-5.1-tests/big.lua
> create mode 100644 test/PUC-Lua-5.1-tests/calls.lua
> create mode 100644 test/PUC-Lua-5.1-tests/checktable.lua
> create mode 100644 test/PUC-Lua-5.1-tests/closure.lua
> create mode 100644 test/PUC-Lua-5.1-tests/code.lua
> create mode 100644 test/PUC-Lua-5.1-tests/constructs.lua
> create mode 100644 test/PUC-Lua-5.1-tests/db.lua
> create mode 100644 test/PUC-Lua-5.1-tests/errors.lua
> create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.c
> create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.h
> create mode 100644 test/PUC-Lua-5.1-tests/events.lua
> create mode 100644 test/PUC-Lua-5.1-tests/files.lua
> create mode 100644 test/PUC-Lua-5.1-tests/gc.lua
> create mode 100644 test/PUC-Lua-5.1-tests/libs/lib1.c
> create mode 100644 test/PUC-Lua-5.1-tests/libs/lib11.c
> create mode 100644 test/PUC-Lua-5.1-tests/libs/lib2.c
> create mode 100644 test/PUC-Lua-5.1-tests/libs/lib21.c
> create mode 100644 test/PUC-Lua-5.1-tests/literals.lua
> create mode 100644 test/PUC-Lua-5.1-tests/locals.lua
> create mode 100644 test/PUC-Lua-5.1-tests/main.lua
> create mode 100644 test/PUC-Lua-5.1-tests/math.lua
> create mode 100644 test/PUC-Lua-5.1-tests/nextvar.lua
> create mode 100644 test/PUC-Lua-5.1-tests/pm.lua
> create mode 100644 test/PUC-Lua-5.1-tests/sort.lua
> create mode 100644 test/PUC-Lua-5.1-tests/strings.lua
> create mode 100644 test/PUC-Lua-5.1-tests/vararg.lua
> create mode 100644 test/PUC-Lua-5.1-tests/verybig.lua
> 
> diff --git a/.luacheckrc b/.luacheckrc
> index 1a76108..cbd2912 100644
> --- a/.luacheckrc
> +++ b/.luacheckrc
> @@ -3,10 +3,11 @@ 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-Lua-5.1-tests/',
> }
> diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
> index 99471db..93c43ea 100644
> --- a/test/CMakeLists.txt
> +++ b/test/CMakeLists.txt
> @@ -43,11 +43,13 @@ endif()
> set(LUAJIT_TEST_COMMAND "${LUAJIT_TEST_BINARY} -e dofile[[${LUAJIT_TEST_INIT}]]")
> separate_arguments(LUAJIT_TEST_COMMAND)
> 
> -add_subdirectory(tarantool-tests)
> add_subdirectory(LuaJIT-tests)
> +add_subdirectory(PUC-Lua-5.1-tests)
> +add_subdirectory(tarantool-tests)
> 
> add_custom_target(${PROJECT_NAME}-test DEPENDS
>   LuaJIT-tests
> +  PUC-Lua-5.1-tests
>   tarantool-tests
> )
> 
> diff --git a/test/PUC-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Lua-5.1-tests/CMakeLists.txt
> new file mode 100644
> index 0000000..08bee36
> --- /dev/null
> +++ b/test/PUC-Lua-5.1-tests/CMakeLists.txt
> @@ -0,0 +1,89 @@
> +# Test suite that has been added from PUC-Rio Lua 5.1 test archive
> +# in scope of https://github.com/tarantool/tarantool/issues/4473.
> +
> +# See the rationale in the root CMakeLists.txt.
> +cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
> +
> +set(TEST_RUNNER  ${CMAKE_CURRENT_SOURCE_DIR}/all.lua)
> +set(LIB_SOURCES  ${CMAKE_CURRENT_SOURCE_DIR}/libs)
> +set(TESTLIB_PATH ${CMAKE_CURRENT_BINARY_DIR}/libs)
> +
> +# XXX: -fPIC is required to linking with static library.
> +if(NOT BUILDMODE STREQUAL "static")
> +  # Build additional C libraries for tests.
> +  macro(build_lib 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 "${TESTLIB_PATH}"
> +      PREFIX ""
> +    )
> +    if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
> +      set_target_properties(${lib} PROPERTIES
> +        LINK_FLAGS "-undefined dynamic_lookup"
> +      )
> +    endif()
> +    target_link_libraries(${lib} PRIVATE libluajit_shared)
> +    list(APPEND TESTLIBS ${lib})
> +  endmacro()
> +
> +  build_lib(lib1  ${LIB_SOURCES}/lib1.c)
> +  build_lib(lib11 ${LIB_SOURCES}/lib1.c ${LIB_SOURCES}/lib11.c)
> +  build_lib(lib2  ${LIB_SOURCES}/lib2.c)
> +  build_lib(lib21 ${LIB_SOURCES}/lib2.c ${LIB_SOURCES}/lib21.c)
> +
> +  set(LIB2COPY "${TESTLIB_PATH}/lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
> +  set(LIB_COPY "${TESTLIB_PATH}/-lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
> +
> +  add_custom_command(
> +    COMMENT "Copping lib2 to -lib2 for PUC-Rio Lua 5.1 tests"
> +    OUTPUT  ${LIB_COPY}
> +    DEPENDS ${TESTLIBS}
> +    COMMAND ${CMAKE_COMMAND} -E copy ${LIB2COPY} ${LIB_COPY}
> +    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> +  )
> +  list(APPEND TESTLIBS ${LIB_COPY})
> +endif()
> +
> +set(CUSTOM_TEST_DIR ${TESTLIB_PATH}/P1)
> +add_custom_command(
> +  COMMENT "Create directory for PUC-Rio Lua 5.1 tests"
> +  OUTPUT  ${CUSTOM_TEST_DIR}
> +  COMMAND ${CMAKE_COMMAND} -E make_directory ${CUSTOM_TEST_DIR}
> +  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> +)
> +
> +set(LUA_PATH "?\;${CMAKE_CURRENT_SOURCE_DIR}/?.lua")
> +
> +# 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 adopted for LuaJIT.
> +
> +add_custom_target(PUC-Lua-5.1-tests
> +  DEPENDS ${LUAJIT_TEST_BINARY} ${TESTLIBS} ${CUSTOM_TEST_DIR}
> +)
> +
> +add_custom_command(TARGET PUC-Lua-5.1-tests
> +  COMMENT "Running PUC-Rio Lua 5.1 tests"
> +  COMMAND
> +  env
> +    # Tarantool doesn't support LUA_INIT and most likely it
> +    # never will.
> +    # See https://github.com/tarantool/tarantool/issues/5744
> +    # for more info.
> +    # LUA_PATH="${CMAKE_CURRENT_BINARY_DIR}/?.lua\;\;"
> +    # LUA_INIT="package.path='?\;'..package.path"
> +    # So use less preferable way for tests.
> +    LUA_PATH="${LUA_PATH}\;\;"
> +    ${LUAJIT_TEST_COMMAND} ${TEST_RUNNER}
> +  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> +)
> +
> +# vim: expandtab tabstop=2 shiftwidth=2
> diff --git a/test/PUC-Lua-5.1-tests/README b/test/PUC-Lua-5.1-tests/README
> new file mode 100644
> index 0000000..e2d4b28
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/all.lua b/test/PUC-Lua-5.1-tests/all.lua
> new file mode 100755
> index 0000000..8c4afac
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/api.lua b/test/PUC-Lua-5.1-tests/api.lua
> new file mode 100644
> index 0000000..c955ebf
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/attrib.lua b/test/PUC-Lua-5.1-tests/attrib.lua
> new file mode 100644
> index 0000000..655669b
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/big.lua b/test/PUC-Lua-5.1-tests/big.lua
> new file mode 100644
> index 0000000..9261288
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/calls.lua b/test/PUC-Lua-5.1-tests/calls.lua
> new file mode 100644
> index 0000000..788f9a1
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/checktable.lua b/test/PUC-Lua-5.1-tests/checktable.lua
> new file mode 100644
> index 0000000..f0938be
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/closure.lua b/test/PUC-Lua-5.1-tests/closure.lua
> new file mode 100644
> index 0000000..27ca0ad
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/code.lua b/test/PUC-Lua-5.1-tests/code.lua
> new file mode 100644
> index 0000000..875d488
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/constructs.lua b/test/PUC-Lua-5.1-tests/constructs.lua
> new file mode 100644
> index 0000000..5fb3798
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/db.lua b/test/PUC-Lua-5.1-tests/db.lua
> new file mode 100644
> index 0000000..9d2c86f
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/errors.lua b/test/PUC-Lua-5.1-tests/errors.lua
> new file mode 100644
> index 0000000..e881211
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/etc/ltests.c b/test/PUC-Lua-5.1-tests/etc/ltests.c
> new file mode 100644
> index 0000000..be949e5
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/etc/ltests.h b/test/PUC-Lua-5.1-tests/etc/ltests.h
> new file mode 100644
> index 0000000..e570212
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/events.lua b/test/PUC-Lua-5.1-tests/events.lua
> new file mode 100644
> index 0000000..5234b00
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/files.lua b/test/PUC-Lua-5.1-tests/files.lua
> new file mode 100644
> index 0000000..903488c
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/gc.lua b/test/PUC-Lua-5.1-tests/gc.lua
> new file mode 100644
> index 0000000..86a9f75
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/libs/lib1.c b/test/PUC-Lua-5.1-tests/libs/lib1.c
> new file mode 100644
> index 0000000..22fe6de
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/libs/lib11.c b/test/PUC-Lua-5.1-tests/libs/lib11.c
> new file mode 100644
> index 0000000..3efa3d3
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/libs/lib2.c b/test/PUC-Lua-5.1-tests/libs/lib2.c
> new file mode 100644
> index 0000000..876a212
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/libs/lib21.c b/test/PUC-Lua-5.1-tests/libs/lib21.c
> new file mode 100644
> index 0000000..167507f
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/literals.lua b/test/PUC-Lua-5.1-tests/literals.lua
> new file mode 100644
> index 0000000..01d84d5
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/locals.lua b/test/PUC-Lua-5.1-tests/locals.lua
> new file mode 100644
> index 0000000..011645a
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/main.lua b/test/PUC-Lua-5.1-tests/main.lua
> new file mode 100644
> index 0000000..f520896
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/math.lua b/test/PUC-Lua-5.1-tests/math.lua
> new file mode 100644
> index 0000000..5076f38
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/nextvar.lua b/test/PUC-Lua-5.1-tests/nextvar.lua
> new file mode 100644
> index 0000000..7ceaa75
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/pm.lua b/test/PUC-Lua-5.1-tests/pm.lua
> new file mode 100644
> index 0000000..fa125dc
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/sort.lua b/test/PUC-Lua-5.1-tests/sort.lua
> new file mode 100644
> index 0000000..6fccd49
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/strings.lua b/test/PUC-Lua-5.1-tests/strings.lua
> new file mode 100644
> index 0000000..237dbad
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/vararg.lua b/test/PUC-Lua-5.1-tests/vararg.lua
> new file mode 100644
> index 0000000..ae068fa
> --- /dev/null
> +++ b/test/PUC-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-Lua-5.1-tests/verybig.lua b/test/PUC-Lua-5.1-tests/verybig.lua
> new file mode 100644
> index 0000000..59e0142
> --- /dev/null
> +++ b/test/PUC-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.28.0
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit 1/3] test: add PUC-Rio Lua 5.1 test suite
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 1/3] test: add " Sergey Kaplun via Tarantool-patches
  2021-03-16 13:35   ` Sergey Ostanevich via Tarantool-patches
@ 2021-03-17 14:55   ` Igor Munkin via Tarantool-patches
  2021-03-19 11:26     ` Sergey Kaplun via Tarantool-patches
  1 sibling, 1 reply; 13+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-03-17 14:55 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Sergey,

Thanks for the patch!

On 12.03.21, Sergey Kaplun wrote:
> This patch adds PUC-Rio Lua 5.1 test suite as a part of the LuaJIT
> test suite. Source code taken verbatim from

Unfortunately, this is not true. Consider the following:
| $ md5sum lua5.1-tests.tar.gz
| b376d315ada7bd9d379ec820d6cc27ed  lua5.1-tests.tar.gz
| <...>
| $ pwd
| /lua5.1-tests
| $ find . -type f | sort | xargs md5sum > ~/vanilla
| <...>
| $ pwd
| /tarantool-luajit/test/PUC-Lua-5.1-tests
| $ git remote -v
| origin  git@github.com:tarantool/luajit (fetch)
| origin  git@github.com:tarantool/luajit (push)
| $ git lo -1
| 19e526e (HEAD) test: add PUC-Rio Lua 5.1 test suite
| $ find . -type f | sort | xargs md5sum > ~/tarantool
| $ diff ~/vanilla ~/tarantool
| 2,3c2,3
| < 70085c31a4cd70096dea1636e8fb3d9d  ./api.lua
| < b863b536cfb6114ec70d846c2f2c1a5f  ./attrib.lua
| ---
| > 9e9888c13bce8de45b470370cb6f5d11  ./api.lua
| > f2e3148cbdacf6bd8a06c1744dea3a16  ./attrib.lua
| 7,12c7,13
| < 428b214012380dbb8922b70f8e3a174f  ./closure.lua
| < 580aeb1bf3efd526c8b62efcbb7b7ff2  ./code.lua
| < f11d5bc5a7809d5d34a4fe0b0a86905b  ./constructs.lua
| < 29c56553a51f06ec14ebd45ea2789eaa  ./db.lua
| < 62ef206224896aac4e5998f78305083a  ./errors.lua
| < 2b2a4688858d7b01ead2d94217705c4f  ./etc/ltests.c
| ---
| > 2fe3dc8ae11397c08c8343cad6f251ab  ./closure.lua
| > cbeb7f7013161dd2d558a7b1adc77327  ./CMakeLists.txt
| > d72539840341a07aae459cac9991e41f  ./code.lua
| > 0f0bdf9e2e0cf758e0e76600f7afc700  ./constructs.lua
| > 596f4340c66fd9f0ff6ecacef955ade0  ./db.lua
| > a2b968868f2d4b7165f561076639c98b  ./errors.lua
| > 2b901df9ba9024f0279a7bbfeaf47f1f  ./etc/ltests.c
| 15c16
| < fae357bb29cc0ea5ec380a2678674330  ./files.lua
| ---
| > 77d39dbfac5abc7a9dcd8e9595ccf517  ./files.lua
| 18c19
| < b0536a009fd46b3c54759ce447883cd8  ./libs/lib1.c
| ---
| > 1efd07d7bd4efe1b334cc3e11ce83115  ./libs/lib1.c
| 20,21c21
| < e27b1cfafb3a4f60cee764beaa761059  ./libs/lib2.c
| < aa964093a6483e66e434a5ae22816a24  ./libs/makefile
| ---
| > b2ac9185c54826707cce0ab1bbfb1289  ./libs/lib2.c
| 23,24c23,24
| < e3c8a3668564606e8387ce695229c24f  ./locals.lua
| < a83fe79ec8c8c21dac7ee4f882344178  ./main.lua
| ---
| > e3fdc6da784973cf96d19861f79908b3  ./locals.lua
| > f99dc272fedc3e9bf21344f06e6fa6b7  ./main.lua
| 26c26
| < 41119d8062a9f66b89c30b4ff87a7a1f  ./nextvar.lua
| ---
| > 52e9e6bbac229d72a46672aff5e84874  ./nextvar.lua

Well, as you mentioned in the cover letter, you removed the trailing
whitespace. Just for the history, I collected everything to the list:
* api.lua: 1 occurrence
* attrib.lua: 1 occurrence
* closure.lua: 1 occurrence
* code.lua: 1 occurrence
* constructs.lua: 2 occurrences
* db.lua: 4 occurrences
* errors.lua: 2 occurrences
* etc/ltests.c: 3 occurrences
* files.lua: 3 occurrences
* lib/lib1.c: 2 occurrences + luaL_reg fix
* lib/lib2.c: luaL_reg fix
* locals.lua: 2 occurrences
* main.lua: 5 occurrences
* nextvar.lua: 2 occurrences

IMHO, this is so neglible, that we can move suite intact, but if it
makes you happier, I believe we can relax the adopting rule for the case
with such tiny whitespace changes. At the same time there are also a
couple of *functional* changes: you adjusted auxiliary C sources
regarding LuaJIT specifics. This violates the rule we discussed so much.

As you mentioned below, tests still fail after this commit, so please
move all functional changes to a separate patch.

> https://www.lua.org/tests/lua5.1-tests.tar.gz.
> 
> <lib1.c> and <lib2.c> is slightly modified to be consistent with the
> current LuaJIT's LuaC API.
> 
> 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                   |    4 +-
>  test/PUC-Lua-5.1-tests/CMakeLists.txt |   89 ++
>  test/PUC-Lua-5.1-tests/README         |   41 +
>  test/PUC-Lua-5.1-tests/all.lua        |  137 +++
>  test/PUC-Lua-5.1-tests/api.lua        |  711 +++++++++++++++
>  test/PUC-Lua-5.1-tests/attrib.lua     |  339 ++++++++
>  test/PUC-Lua-5.1-tests/big.lua        |  381 ++++++++
>  test/PUC-Lua-5.1-tests/calls.lua      |  294 +++++++
>  test/PUC-Lua-5.1-tests/checktable.lua |   77 ++
>  test/PUC-Lua-5.1-tests/closure.lua    |  422 +++++++++
>  test/PUC-Lua-5.1-tests/code.lua       |  143 +++
>  test/PUC-Lua-5.1-tests/constructs.lua |  240 ++++++
>  test/PUC-Lua-5.1-tests/db.lua         |  499 +++++++++++
>  test/PUC-Lua-5.1-tests/errors.lua     |  250 ++++++
>  test/PUC-Lua-5.1-tests/etc/ltests.c   | 1147 +++++++++++++++++++++++++
>  test/PUC-Lua-5.1-tests/etc/ltests.h   |   92 ++
>  test/PUC-Lua-5.1-tests/events.lua     |  360 ++++++++
>  test/PUC-Lua-5.1-tests/files.lua      |  324 +++++++
>  test/PUC-Lua-5.1-tests/gc.lua         |  312 +++++++
>  test/PUC-Lua-5.1-tests/libs/lib1.c    |   40 +
>  test/PUC-Lua-5.1-tests/libs/lib11.c   |   18 +
>  test/PUC-Lua-5.1-tests/libs/lib2.c    |   28 +
>  test/PUC-Lua-5.1-tests/libs/lib21.c   |   18 +
>  test/PUC-Lua-5.1-tests/literals.lua   |  176 ++++
>  test/PUC-Lua-5.1-tests/locals.lua     |  127 +++
>  test/PUC-Lua-5.1-tests/main.lua       |  159 ++++
>  test/PUC-Lua-5.1-tests/math.lua       |  208 +++++
>  test/PUC-Lua-5.1-tests/nextvar.lua    |  396 +++++++++
>  test/PUC-Lua-5.1-tests/pm.lua         |  273 ++++++
>  test/PUC-Lua-5.1-tests/sort.lua       |   74 ++
>  test/PUC-Lua-5.1-tests/strings.lua    |  176 ++++
>  test/PUC-Lua-5.1-tests/vararg.lua     |  126 +++
>  test/PUC-Lua-5.1-tests/verybig.lua    |  100 +++
>  34 files changed, 7783 insertions(+), 3 deletions(-)
>  create mode 100644 test/PUC-Lua-5.1-tests/CMakeLists.txt
>  create mode 100644 test/PUC-Lua-5.1-tests/README
>  create mode 100755 test/PUC-Lua-5.1-tests/all.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/api.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/attrib.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/big.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/calls.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/checktable.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/closure.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/code.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/constructs.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/db.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/errors.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.c
>  create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.h
>  create mode 100644 test/PUC-Lua-5.1-tests/events.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/files.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/gc.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/libs/lib1.c
>  create mode 100644 test/PUC-Lua-5.1-tests/libs/lib11.c
>  create mode 100644 test/PUC-Lua-5.1-tests/libs/lib2.c
>  create mode 100644 test/PUC-Lua-5.1-tests/libs/lib21.c
>  create mode 100644 test/PUC-Lua-5.1-tests/literals.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/locals.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/main.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/math.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/nextvar.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/pm.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/sort.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/strings.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/vararg.lua
>  create mode 100644 test/PUC-Lua-5.1-tests/verybig.lua
> 

<snipped>

> diff --git a/test/PUC-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Lua-5.1-tests/CMakeLists.txt
> new file mode 100644
> index 0000000..08bee36
> --- /dev/null
> +++ b/test/PUC-Lua-5.1-tests/CMakeLists.txt
> @@ -0,0 +1,89 @@
> +# Test suite that has been added from PUC-Rio Lua 5.1 test archive
> +# in scope of https://github.com/tarantool/tarantool/issues/4473.
> +
> +# See the rationale in the root CMakeLists.txt.
> +cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
> +
> +set(TEST_RUNNER  ${CMAKE_CURRENT_SOURCE_DIR}/all.lua)

I guess this variable is excess: there is no special variable for runner
in LuaJIT-tests/CMakeLists.txt, so let's also follow this practice here.

Moreover, the following part (from here to the line of dashes) should be
moved to a new CMakeLists.txt in libs subdirectory.

> +set(LIB_SOURCES  ${CMAKE_CURRENT_SOURCE_DIR}/libs)
> +set(TESTLIB_PATH ${CMAKE_CURRENT_BINARY_DIR}/libs)

After moving this part into a separate CMakeLists.txt this variables
become excess.

> +
> +# XXX: -fPIC is required to linking with static library.
> +if(NOT BUILDMODE STREQUAL "static")

What does block you from building the libs against the static build? I
don't get the reason and it looks like everything works fine (at least
on my working station).

> +  # Build additional C libraries for tests.
> +  macro(build_lib lib sources)

Consider CMake macro naming convention in LuaJIT.

> +    add_library(${lib} SHARED EXCLUDE_FROM_ALL ${sources})
> +    target_include_directories(${lib} PRIVATE
> +      ${LUAJIT_SOURCE_DIR}
> +    )
> +    set_target_properties(${lib} PROPERTIES
> +      LIBRARY_OUTPUT_DIRECTORY "${TESTLIB_PATH}"
> +      PREFIX ""
> +    )
> +    if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
> +      set_target_properties(${lib} PROPERTIES
> +        LINK_FLAGS "-undefined dynamic_lookup"
> +      )
> +    endif()
> +    target_link_libraries(${lib} PRIVATE libluajit_shared)

This looks to be excess, doesn't it?

> +    list(APPEND TESTLIBS ${lib})
> +  endmacro()
> +
> +  build_lib(lib1  ${LIB_SOURCES}/lib1.c)
> +  build_lib(lib11 ${LIB_SOURCES}/lib1.c ${LIB_SOURCES}/lib11.c)
> +  build_lib(lib2  ${LIB_SOURCES}/lib2.c)
> +  build_lib(lib21 ${LIB_SOURCES}/lib2.c ${LIB_SOURCES}/lib21.c)
> +
> +  set(LIB2COPY "${TESTLIB_PATH}/lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
> +  set(LIB_COPY "${TESTLIB_PATH}/-lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
> +
> +  add_custom_command(
> +    COMMENT "Copping lib2 to -lib2 for PUC-Rio Lua 5.1 tests"
> +    OUTPUT  ${LIB_COPY}
> +    DEPENDS ${TESTLIBS}
> +    COMMAND ${CMAKE_COMMAND} -E copy ${LIB2COPY} ${LIB_COPY}
> +    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> +  )
> +  list(APPEND TESTLIBS ${LIB_COPY})
> +endif()
> +
> +set(CUSTOM_TEST_DIR ${TESTLIB_PATH}/P1)
> +add_custom_command(
> +  COMMENT "Create directory for PUC-Rio Lua 5.1 tests"
> +  OUTPUT  ${CUSTOM_TEST_DIR}
> +  COMMAND ${CMAKE_COMMAND} -E make_directory ${CUSTOM_TEST_DIR}
> +  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> +)

--------------------------------------------------------------------------------

> +
> +set(LUA_PATH "?\;${CMAKE_CURRENT_SOURCE_DIR}/?.lua")

It's worth to mention right here, why did you choose this way instead of
the "better yet" (and the LUA_INIT problem). I see you referred to the
well-known issue below, but IMHO it's better to group the rationale
right here.

> +
> +# 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 adopted for LuaJIT.

Typo: s/adopted/adapted/ or simply use "adjusted" here.

> +
> +add_custom_target(PUC-Lua-5.1-tests
> +  DEPENDS ${LUAJIT_TEST_BINARY} ${TESTLIBS} ${CUSTOM_TEST_DIR}
> +)
> +
> +add_custom_command(TARGET PUC-Lua-5.1-tests
> +  COMMENT "Running PUC-Rio Lua 5.1 tests"
> +  COMMAND
> +  env
> +    # Tarantool doesn't support LUA_INIT and most likely it
> +    # never will.
> +    # See https://github.com/tarantool/tarantool/issues/5744
> +    # for more info.
> +    # LUA_PATH="${CMAKE_CURRENT_BINARY_DIR}/?.lua\;\;"
> +    # LUA_INIT="package.path='?\;'..package.path"
> +    # So use less preferable way for tests.
> +    LUA_PATH="${LUA_PATH}\;\;"
> +    ${LUAJIT_TEST_COMMAND} ${TEST_RUNNER}
> +  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> +)
> +

Consider the fixup patch on my branch[1] and below. I don't run CI for
this revision, since the queue is overloaded. I'll push the bump in
Tarantool repo a bit later.

================================================================================

commit c0c53e890252dd60dbad7d98a47e9e3c3ee55cff
Author: Igor Munkin <imun@tarantool.org>
Date:   Wed Mar 17 17:15:02 2021 +0300

    fixup-1

diff --git a/test/PUC-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Lua-5.1-tests/CMakeLists.txt
index 08bee36e..da066eb8 100644
--- a/test/PUC-Lua-5.1-tests/CMakeLists.txt
+++ b/test/PUC-Lua-5.1-tests/CMakeLists.txt
@@ -1,61 +1,26 @@
 # Test suite that has been added from PUC-Rio Lua 5.1 test archive
-# in scope of https://github.com/tarantool/tarantool/issues/4473.
+# 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)
 
-set(TEST_RUNNER  ${CMAKE_CURRENT_SOURCE_DIR}/all.lua)
-set(LIB_SOURCES  ${CMAKE_CURRENT_SOURCE_DIR}/libs)
-set(TESTLIB_PATH ${CMAKE_CURRENT_BINARY_DIR}/libs)
-
-# XXX: -fPIC is required to linking with static library.
-if(NOT BUILDMODE STREQUAL "static")
-  # Build additional C libraries for tests.
-  macro(build_lib 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 "${TESTLIB_PATH}"
-      PREFIX ""
-    )
-    if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
-      set_target_properties(${lib} PROPERTIES
-        LINK_FLAGS "-undefined dynamic_lookup"
-      )
-    endif()
-    target_link_libraries(${lib} PRIVATE libluajit_shared)
-    list(APPEND TESTLIBS ${lib})
-  endmacro()
-
-  build_lib(lib1  ${LIB_SOURCES}/lib1.c)
-  build_lib(lib11 ${LIB_SOURCES}/lib1.c ${LIB_SOURCES}/lib11.c)
-  build_lib(lib2  ${LIB_SOURCES}/lib2.c)
-  build_lib(lib21 ${LIB_SOURCES}/lib2.c ${LIB_SOURCES}/lib21.c)
-
-  set(LIB2COPY "${TESTLIB_PATH}/lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
-  set(LIB_COPY "${TESTLIB_PATH}/-lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
-
-  add_custom_command(
-    COMMENT "Copping lib2 to -lib2 for PUC-Rio Lua 5.1 tests"
-    OUTPUT  ${LIB_COPY}
-    DEPENDS ${TESTLIBS}
-    COMMAND ${CMAKE_COMMAND} -E copy ${LIB2COPY} ${LIB_COPY}
-    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-  )
-  list(APPEND TESTLIBS ${LIB_COPY})
-endif()
-
-set(CUSTOM_TEST_DIR ${TESTLIB_PATH}/P1)
-add_custom_command(
-  COMMENT "Create directory for PUC-Rio Lua 5.1 tests"
-  OUTPUT  ${CUSTOM_TEST_DIR}
-  COMMAND ${CMAKE_COMMAND} -E make_directory ${CUSTOM_TEST_DIR}
-  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-)
-
+add_subdirectory(libs)
+
+# XXX: There are two ways to set up the proper environment in
+# the suite 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")
+# XXX: All libraries required for the tests are built in libs
+# directory. To use them in the suite being run in the current
+# working directory, LUA_CPATH has to be adjusted.
+set(LUA_CPATH "${CMAKE_CURRENT_BINARY_DIR}/libs/?${CMAKE_SHARED_LIBRARY_SUFFIX}")
 
 # TODO: PUC-Rio Lua 5.1 test suite also has special header
 # <ltests.h> and <ltests.c> translation unit to check some
@@ -64,25 +29,17 @@ set(LUA_PATH "?\;${CMAKE_CURRENT_SOURCE_DIR}/?.lua")
 # 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 adopted for LuaJIT.
-
-add_custom_target(PUC-Lua-5.1-tests
-  DEPENDS ${LUAJIT_TEST_BINARY} ${TESTLIBS} ${CUSTOM_TEST_DIR}
-)
+# internal headers and should be adapted for LuaJIT.
 
+add_custom_target(PUC-Lua-5.1-tests DEPENDS ${LUAJIT_TEST_BINARY}
+  PUC-Lua-5.1-tests-prepare)
 add_custom_command(TARGET PUC-Lua-5.1-tests
   COMMENT "Running PUC-Rio Lua 5.1 tests"
   COMMAND
   env
-    # Tarantool doesn't support LUA_INIT and most likely it
-    # never will.
-    # See https://github.com/tarantool/tarantool/issues/5744
-    # for more info.
-    # LUA_PATH="${CMAKE_CURRENT_BINARY_DIR}/?.lua\;\;"
-    # LUA_INIT="package.path='?\;'..package.path"
-    # So use less preferable way for tests.
     LUA_PATH="${LUA_PATH}\;\;"
-    ${LUAJIT_TEST_COMMAND} ${TEST_RUNNER}
+    LUA_CPATH="${LUA_CPATH}\;\;"
+    ${LUAJIT_TEST_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR}/all.lua
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
 )
 
diff --git a/test/PUC-Lua-5.1-tests/libs/CMakeLists.txt b/test/PUC-Lua-5.1-tests/libs/CMakeLists.txt
new file mode 100644
index 00000000..b7765a25
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/libs/CMakeLists.txt
@@ -0,0 +1,51 @@
+# 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)
+
+# 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 ""
+  )
+  if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+    set_target_properties(${lib} PROPERTIES
+      LINK_FLAGS "-undefined dynamic_lookup"
+    )
+  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)
+
+# TODO: Add the rationale for this (mention the test case it is
+# needed for).
+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})
+
+# TODO: Add the comment pointing to README.
+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
+  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+# vim: expandtab tabstop=2 shiftwidth=2

================================================================================

> +# vim: expandtab tabstop=2 shiftwidth=2

<snipped>

> -- 
> 2.28.0
> 

[1]: https://github.com/tarantool/luajit/commit/c0c53e8

-- 
Best regards,
IM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit 1/3] test: add PUC-Rio Lua 5.1 test suite
  2021-03-16 13:35   ` Sergey Ostanevich via Tarantool-patches
@ 2021-03-17 15:17     ` Igor Munkin via Tarantool-patches
  2021-03-19 11:30       ` Sergey Kaplun via Tarantool-patches
  0 siblings, 1 reply; 13+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-03-17 15:17 UTC (permalink / raw)
  To: Sergey Ostanevich; +Cc: tarantool-patches

Sergos,

Thanks for you review!

On 16.03.21, Sergey Ostanevich wrote:
> Hi!
> 
> Thanks for the patch!
> 
> 
> 
> > On 12 Mar 2021, at 08:36, Sergey Kaplun <skaplun@tarantool.org> wrote:
> > 
> > This patch adds PUC-Rio Lua 5.1 test suite as a part of the LuaJIT
> > test suite. Source code taken verbatim from
> > https://www.lua.org/tests/lua5.1-tests.tar.gz.
> > 
> > <lib1.c> and <lib2.c> is slightly modified to be consistent with the
> > current LuaJIT's LuaC API.
> > 
> 
> This should be a different commit, isn’t it?

Yes, it does.

> 
> > Some tests may fail after this commit. They will be disabled
> > or adapted in the next patches.
> 
> The fact patch causes - even temporarily - some fails is no good. The
> only exception is initial commit, that brings original test suite.
> Can you please make a consistent change that will left the tests disabled
> until they adapted and enabled back?

I believe such juggling with enabling/disabling is quite unprofitable.
We iteratively fix broken tests within the series making CI green as a
result. Even if lib[12].c fails to compile -- it is not a problem, since
these libraries are test dependencies, not build ones. Sergey can simply
mention the fact the build of suite-related tests is broken, so one can
find the comment in commit message while e.g. bisecting the bug.
Otherwise, the patches are spoiled with unnecessary changes.

> 
> regards,
> Sergos
> 
> > 

<snipped>

> > -- 
> > 2.28.0
> > 
> 

-- 
Best regards,
IM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit 1/3] test: add PUC-Rio Lua 5.1 test suite
  2021-03-17 14:55   ` Igor Munkin via Tarantool-patches
@ 2021-03-19 11:26     ` Sergey Kaplun via Tarantool-patches
  0 siblings, 0 replies; 13+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-19 11:26 UTC (permalink / raw)
  To: Igor Munkin; +Cc: tarantool-patches

Igor,

Thanks for the review!

On 17.03.21, Igor Munkin wrote:
> Sergey,
> 
> Thanks for the patch!
> 
> On 12.03.21, Sergey Kaplun wrote:
> > This patch adds PUC-Rio Lua 5.1 test suite as a part of the LuaJIT
> > test suite. Source code taken verbatim from
> 
> Unfortunately, this is not true. Consider the following:
> | $ md5sum lua5.1-tests.tar.gz
> | b376d315ada7bd9d379ec820d6cc27ed  lua5.1-tests.tar.gz
> | <...>
> | $ pwd
> | /lua5.1-tests
> | $ find . -type f | sort | xargs md5sum > ~/vanilla
> | <...>
> | $ pwd
> | /tarantool-luajit/test/PUC-Lua-5.1-tests
> | $ git remote -v
> | origin  git@github.com:tarantool/luajit (fetch)
> | origin  git@github.com:tarantool/luajit (push)
> | $ git lo -1
> | 19e526e (HEAD) test: add PUC-Rio Lua 5.1 test suite
> | $ find . -type f | sort | xargs md5sum > ~/tarantool
> | $ diff ~/vanilla ~/tarantool
> | 2,3c2,3
> | < 70085c31a4cd70096dea1636e8fb3d9d  ./api.lua
> | < b863b536cfb6114ec70d846c2f2c1a5f  ./attrib.lua
> | ---
> | > 9e9888c13bce8de45b470370cb6f5d11  ./api.lua
> | > f2e3148cbdacf6bd8a06c1744dea3a16  ./attrib.lua
> | 7,12c7,13
> | < 428b214012380dbb8922b70f8e3a174f  ./closure.lua
> | < 580aeb1bf3efd526c8b62efcbb7b7ff2  ./code.lua
> | < f11d5bc5a7809d5d34a4fe0b0a86905b  ./constructs.lua
> | < 29c56553a51f06ec14ebd45ea2789eaa  ./db.lua
> | < 62ef206224896aac4e5998f78305083a  ./errors.lua
> | < 2b2a4688858d7b01ead2d94217705c4f  ./etc/ltests.c
> | ---
> | > 2fe3dc8ae11397c08c8343cad6f251ab  ./closure.lua
> | > cbeb7f7013161dd2d558a7b1adc77327  ./CMakeLists.txt
> | > d72539840341a07aae459cac9991e41f  ./code.lua
> | > 0f0bdf9e2e0cf758e0e76600f7afc700  ./constructs.lua
> | > 596f4340c66fd9f0ff6ecacef955ade0  ./db.lua
> | > a2b968868f2d4b7165f561076639c98b  ./errors.lua
> | > 2b901df9ba9024f0279a7bbfeaf47f1f  ./etc/ltests.c
> | 15c16
> | < fae357bb29cc0ea5ec380a2678674330  ./files.lua
> | ---
> | > 77d39dbfac5abc7a9dcd8e9595ccf517  ./files.lua
> | 18c19
> | < b0536a009fd46b3c54759ce447883cd8  ./libs/lib1.c
> | ---
> | > 1efd07d7bd4efe1b334cc3e11ce83115  ./libs/lib1.c
> | 20,21c21
> | < e27b1cfafb3a4f60cee764beaa761059  ./libs/lib2.c
> | < aa964093a6483e66e434a5ae22816a24  ./libs/makefile
> | ---
> | > b2ac9185c54826707cce0ab1bbfb1289  ./libs/lib2.c
> | 23,24c23,24
> | < e3c8a3668564606e8387ce695229c24f  ./locals.lua
> | < a83fe79ec8c8c21dac7ee4f882344178  ./main.lua
> | ---
> | > e3fdc6da784973cf96d19861f79908b3  ./locals.lua
> | > f99dc272fedc3e9bf21344f06e6fa6b7  ./main.lua
> | 26c26
> | < 41119d8062a9f66b89c30b4ff87a7a1f  ./nextvar.lua
> | ---
> | > 52e9e6bbac229d72a46672aff5e84874  ./nextvar.lua
> 
> Well, as you mentioned in the cover letter, you removed the trailing
> whitespace. Just for the history, I collected everything to the list:
> * api.lua: 1 occurrence
> * attrib.lua: 1 occurrence
> * closure.lua: 1 occurrence
> * code.lua: 1 occurrence
> * constructs.lua: 2 occurrences
> * db.lua: 4 occurrences
> * errors.lua: 2 occurrences
> * etc/ltests.c: 3 occurrences
> * files.lua: 3 occurrences
> * lib/lib1.c: 2 occurrences + luaL_reg fix
> * lib/lib2.c: luaL_reg fix
> * locals.lua: 2 occurrences
> * main.lua: 5 occurrences
> * nextvar.lua: 2 occurrences
> 
> IMHO, this is so neglible, that we can move suite intact, but if it
> makes you happier, I believe we can relax the adopting rule for the case
> with such tiny whitespace changes. At the same time there are also a
> couple of *functional* changes: you adjusted auxiliary C sources
> regarding LuaJIT specifics. This violates the rule we discussed so much.
> 
> As you mentioned below, tests still fail after this commit, so please
> move all functional changes to a separate patch.

Yep, moved to the separate patch.

> 
> > https://www.lua.org/tests/lua5.1-tests.tar.gz.
> > 
> > <lib1.c> and <lib2.c> is slightly modified to be consistent with the
> > current LuaJIT's LuaC API.
> > 
> > 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                   |    4 +-
> >  test/PUC-Lua-5.1-tests/CMakeLists.txt |   89 ++
> >  test/PUC-Lua-5.1-tests/README         |   41 +
> >  test/PUC-Lua-5.1-tests/all.lua        |  137 +++
> >  test/PUC-Lua-5.1-tests/api.lua        |  711 +++++++++++++++
> >  test/PUC-Lua-5.1-tests/attrib.lua     |  339 ++++++++
> >  test/PUC-Lua-5.1-tests/big.lua        |  381 ++++++++
> >  test/PUC-Lua-5.1-tests/calls.lua      |  294 +++++++
> >  test/PUC-Lua-5.1-tests/checktable.lua |   77 ++
> >  test/PUC-Lua-5.1-tests/closure.lua    |  422 +++++++++
> >  test/PUC-Lua-5.1-tests/code.lua       |  143 +++
> >  test/PUC-Lua-5.1-tests/constructs.lua |  240 ++++++
> >  test/PUC-Lua-5.1-tests/db.lua         |  499 +++++++++++
> >  test/PUC-Lua-5.1-tests/errors.lua     |  250 ++++++
> >  test/PUC-Lua-5.1-tests/etc/ltests.c   | 1147 +++++++++++++++++++++++++
> >  test/PUC-Lua-5.1-tests/etc/ltests.h   |   92 ++
> >  test/PUC-Lua-5.1-tests/events.lua     |  360 ++++++++
> >  test/PUC-Lua-5.1-tests/files.lua      |  324 +++++++
> >  test/PUC-Lua-5.1-tests/gc.lua         |  312 +++++++
> >  test/PUC-Lua-5.1-tests/libs/lib1.c    |   40 +
> >  test/PUC-Lua-5.1-tests/libs/lib11.c   |   18 +
> >  test/PUC-Lua-5.1-tests/libs/lib2.c    |   28 +
> >  test/PUC-Lua-5.1-tests/libs/lib21.c   |   18 +
> >  test/PUC-Lua-5.1-tests/literals.lua   |  176 ++++
> >  test/PUC-Lua-5.1-tests/locals.lua     |  127 +++
> >  test/PUC-Lua-5.1-tests/main.lua       |  159 ++++
> >  test/PUC-Lua-5.1-tests/math.lua       |  208 +++++
> >  test/PUC-Lua-5.1-tests/nextvar.lua    |  396 +++++++++
> >  test/PUC-Lua-5.1-tests/pm.lua         |  273 ++++++
> >  test/PUC-Lua-5.1-tests/sort.lua       |   74 ++
> >  test/PUC-Lua-5.1-tests/strings.lua    |  176 ++++
> >  test/PUC-Lua-5.1-tests/vararg.lua     |  126 +++
> >  test/PUC-Lua-5.1-tests/verybig.lua    |  100 +++
> >  34 files changed, 7783 insertions(+), 3 deletions(-)
> >  create mode 100644 test/PUC-Lua-5.1-tests/CMakeLists.txt
> >  create mode 100644 test/PUC-Lua-5.1-tests/README
> >  create mode 100755 test/PUC-Lua-5.1-tests/all.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/api.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/attrib.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/big.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/calls.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/checktable.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/closure.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/code.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/constructs.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/db.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/errors.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.c
> >  create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.h
> >  create mode 100644 test/PUC-Lua-5.1-tests/events.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/files.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/gc.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/libs/lib1.c
> >  create mode 100644 test/PUC-Lua-5.1-tests/libs/lib11.c
> >  create mode 100644 test/PUC-Lua-5.1-tests/libs/lib2.c
> >  create mode 100644 test/PUC-Lua-5.1-tests/libs/lib21.c
> >  create mode 100644 test/PUC-Lua-5.1-tests/literals.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/locals.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/main.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/math.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/nextvar.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/pm.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/sort.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/strings.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/vararg.lua
> >  create mode 100644 test/PUC-Lua-5.1-tests/verybig.lua
> > 
> 
> <snipped>
> 
> > diff --git a/test/PUC-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Lua-5.1-tests/CMakeLists.txt
> > new file mode 100644
> > index 0000000..08bee36
> > --- /dev/null
> > +++ b/test/PUC-Lua-5.1-tests/CMakeLists.txt
> > @@ -0,0 +1,89 @@
> > +# Test suite that has been added from PUC-Rio Lua 5.1 test archive
> > +# in scope of https://github.com/tarantool/tarantool/issues/4473.
> > +
> > +# See the rationale in the root CMakeLists.txt.
> > +cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
> > +
> > +set(TEST_RUNNER  ${CMAKE_CURRENT_SOURCE_DIR}/all.lua)
> 
> I guess this variable is excess: there is no special variable for runner
> in LuaJIT-tests/CMakeLists.txt, so let's also follow this practice here.
> 
> Moreover, the following part (from here to the line of dashes) should be
> moved to a new CMakeLists.txt in libs subdirectory.

Fixed, thanks.

> 
> > +set(LIB_SOURCES  ${CMAKE_CURRENT_SOURCE_DIR}/libs)
> > +set(TESTLIB_PATH ${CMAKE_CURRENT_BINARY_DIR}/libs)
> 
> After moving this part into a separate CMakeLists.txt this variables
> become excess.

Yep, done.

> 
> > +
> > +# XXX: -fPIC is required to linking with static library.
> > +if(NOT BUILDMODE STREQUAL "static")
> 
> What does block you from building the libs against the static build? I
> don't get the reason and it looks like everything works fine (at least
> on my working station).

Yes, if we don't need linking with library instead dynamic lookup.
Fixed.

> 
> > +  # Build additional C libraries for tests.
> > +  macro(build_lib lib sources)
> 
> Consider CMake macro naming convention in LuaJIT.

Yep, done.

> 
> > +    add_library(${lib} SHARED EXCLUDE_FROM_ALL ${sources})
> > +    target_include_directories(${lib} PRIVATE
> > +      ${LUAJIT_SOURCE_DIR}
> > +    )
> > +    set_target_properties(${lib} PROPERTIES
> > +      LIBRARY_OUTPUT_DIRECTORY "${TESTLIB_PATH}"
> > +      PREFIX ""
> > +    )
> > +    if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
> > +      set_target_properties(${lib} PROPERTIES
> > +        LINK_FLAGS "-undefined dynamic_lookup"
> > +      )
> > +    endif()
> > +    target_link_libraries(${lib} PRIVATE libluajit_shared)
> 
> This looks to be excess, doesn't it?

Yes, static check gone too.

> 
> > +    list(APPEND TESTLIBS ${lib})
> > +  endmacro()
> > +
> > +  build_lib(lib1  ${LIB_SOURCES}/lib1.c)
> > +  build_lib(lib11 ${LIB_SOURCES}/lib1.c ${LIB_SOURCES}/lib11.c)
> > +  build_lib(lib2  ${LIB_SOURCES}/lib2.c)
> > +  build_lib(lib21 ${LIB_SOURCES}/lib2.c ${LIB_SOURCES}/lib21.c)
> > +
> > +  set(LIB2COPY "${TESTLIB_PATH}/lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
> > +  set(LIB_COPY "${TESTLIB_PATH}/-lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
> > +
> > +  add_custom_command(
> > +    COMMENT "Copping lib2 to -lib2 for PUC-Rio Lua 5.1 tests"
> > +    OUTPUT  ${LIB_COPY}
> > +    DEPENDS ${TESTLIBS}
> > +    COMMAND ${CMAKE_COMMAND} -E copy ${LIB2COPY} ${LIB_COPY}
> > +    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> > +  )
> > +  list(APPEND TESTLIBS ${LIB_COPY})
> > +endif()
> > +
> > +set(CUSTOM_TEST_DIR ${TESTLIB_PATH}/P1)
> > +add_custom_command(
> > +  COMMENT "Create directory for PUC-Rio Lua 5.1 tests"
> > +  OUTPUT  ${CUSTOM_TEST_DIR}
> > +  COMMAND ${CMAKE_COMMAND} -E make_directory ${CUSTOM_TEST_DIR}
> > +  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> > +)
> 
> --------------------------------------------------------------------------------
> 
> > +
> > +set(LUA_PATH "?\;${CMAKE_CURRENT_SOURCE_DIR}/?.lua")
> 
> It's worth to mention right here, why did you choose this way instead of
> the "better yet" (and the LUA_INIT problem). I see you referred to the
> well-known issue below, but IMHO it's better to group the rationale
> right here.

OK, fixed.

> 
> > +
> > +# 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 adopted for LuaJIT.
> 
> Typo: s/adopted/adapted/ or simply use "adjusted" here.

Fixed.

> 
> > +
> > +add_custom_target(PUC-Lua-5.1-tests
> > +  DEPENDS ${LUAJIT_TEST_BINARY} ${TESTLIBS} ${CUSTOM_TEST_DIR}
> > +)
> > +
> > +add_custom_command(TARGET PUC-Lua-5.1-tests
> > +  COMMENT "Running PUC-Rio Lua 5.1 tests"
> > +  COMMAND
> > +  env
> > +    # Tarantool doesn't support LUA_INIT and most likely it
> > +    # never will.
> > +    # See https://github.com/tarantool/tarantool/issues/5744
> > +    # for more info.
> > +    # LUA_PATH="${CMAKE_CURRENT_BINARY_DIR}/?.lua\;\;"
> > +    # LUA_INIT="package.path='?\;'..package.path"
> > +    # So use less preferable way for tests.
> > +    LUA_PATH="${LUA_PATH}\;\;"
> > +    ${LUAJIT_TEST_COMMAND} ${TEST_RUNNER}
> > +  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> > +)
> > +
> 
> Consider the fixup patch on my branch[1] and below. I don't run CI for
> this revision, since the queue is overloaded. I'll push the bump in
> Tarantool repo a bit later.

Thanks for the fixup-patch. I've applied it with some modifications:
* drop LUA_CPATH variable as far as it is redundant
* split changes into two separate patches
* add stripping of "-Wl,--no-undefined" linker option (see rationale
  below in the patch
* add comments

Side note: I've fixed missed dot at the end of sentence in a comment, so
the gihtub-ci checked a little bit different commits hashes :).

There is the iterative patch for the first commit:

===================================================================
diff --git a/test/PUC-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Lua-5.1-tests/CMakeLists.txt
index 08bee36..066f668 100644
--- a/test/PUC-Lua-5.1-tests/CMakeLists.txt
+++ b/test/PUC-Lua-5.1-tests/CMakeLists.txt
@@ -1,88 +1,44 @@
 # Test suite that has been added from PUC-Rio Lua 5.1 test archive
-# in scope of https://github.com/tarantool/tarantool/issues/4473.
+# 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)
 
-set(TEST_RUNNER  ${CMAKE_CURRENT_SOURCE_DIR}/all.lua)
-set(LIB_SOURCES  ${CMAKE_CURRENT_SOURCE_DIR}/libs)
-set(TESTLIB_PATH ${CMAKE_CURRENT_BINARY_DIR}/libs)
-
-# XXX: -fPIC is required to linking with static library.
-if(NOT BUILDMODE STREQUAL "static")
-  # Build additional C libraries for tests.
-  macro(build_lib 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 "${TESTLIB_PATH}"
-      PREFIX ""
-    )
-    if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
-      set_target_properties(${lib} PROPERTIES
-        LINK_FLAGS "-undefined dynamic_lookup"
-      )
-    endif()
-    target_link_libraries(${lib} PRIVATE libluajit_shared)
-    list(APPEND TESTLIBS ${lib})
-  endmacro()
-
-  build_lib(lib1  ${LIB_SOURCES}/lib1.c)
-  build_lib(lib11 ${LIB_SOURCES}/lib1.c ${LIB_SOURCES}/lib11.c)
-  build_lib(lib2  ${LIB_SOURCES}/lib2.c)
-  build_lib(lib21 ${LIB_SOURCES}/lib2.c ${LIB_SOURCES}/lib21.c)
-
-  set(LIB2COPY "${TESTLIB_PATH}/lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
-  set(LIB_COPY "${TESTLIB_PATH}/-lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
-
-  add_custom_command(
-    COMMENT "Copping lib2 to -lib2 for PUC-Rio Lua 5.1 tests"
-    OUTPUT  ${LIB_COPY}
-    DEPENDS ${TESTLIBS}
-    COMMAND ${CMAKE_COMMAND} -E copy ${LIB2COPY} ${LIB_COPY}
-    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-  )
-  list(APPEND TESTLIBS ${LIB_COPY})
-endif()
-
-set(CUSTOM_TEST_DIR ${TESTLIB_PATH}/P1)
-add_custom_command(
-  COMMENT "Create directory for PUC-Rio Lua 5.1 tests"
-  OUTPUT  ${CUSTOM_TEST_DIR}
-  COMMAND ${CMAKE_COMMAND} -E make_directory ${CUSTOM_TEST_DIR}
-  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-)
-
+# 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")
 
+# Set 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 adopted for LuaJIT.
+# But, unfortunately, <ltests.c> depends on specific PUC-Rio
+# Lua 5.1 internal headers and should be adapted for LuaJIT.
 
 add_custom_target(PUC-Lua-5.1-tests
-  DEPENDS ${LUAJIT_TEST_BINARY} ${TESTLIBS} ${CUSTOM_TEST_DIR}
+  DEPENDS ${LUAJIT_TEST_BINARY} PUC-Lua-5.1-tests-prepare
 )
 
 add_custom_command(TARGET PUC-Lua-5.1-tests
   COMMENT "Running PUC-Rio Lua 5.1 tests"
   COMMAND
   env
-    # Tarantool doesn't support LUA_INIT and most likely it
-    # never will.
-    # See https://github.com/tarantool/tarantool/issues/5744
-    # for more info.
-    # LUA_PATH="${CMAKE_CURRENT_BINARY_DIR}/?.lua\;\;"
-    # LUA_INIT="package.path='?\;'..package.path"
-    # So use less preferable way for tests.
     LUA_PATH="${LUA_PATH}\;\;"
-    ${LUAJIT_TEST_COMMAND} ${TEST_RUNNER}
+    ${LUAJIT_TEST_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR}/all.lua
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
 )
 
diff --git a/test/PUC-Lua-5.1-tests/libs/CMakeLists.txt b/test/PUC-Lua-5.1-tests/libs/CMakeLists.txt
new file mode 100644
index 0000000..f24e7f3
--- /dev/null
+++ b/test/PUC-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-Lua-5.1-tests/libs/lib1.c b/test/PUC-Lua-5.1-tests/libs/lib1.c
index 22fe6de..812bb9a 100644
--- a/test/PUC-Lua-5.1-tests/libs/lib1.c
+++ b/test/PUC-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-Lua-5.1-tests/libs/lib2.c b/test/PUC-Lua-5.1-tests/libs/lib2.c
index 876a212..9972cbe 100644
--- a/test/PUC-Lua-5.1-tests/libs/lib2.c
+++ b/test/PUC-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}
 };
===================================================================

And here is the second patch to add lib\d+ compilation and tests.

===================================================================
commit 54f575819a7790abc932b992e2ff13c3e6177d81
Author: Sergey Kaplun <skaplun@tarantool.org>
Date:   Wed Mar 17 19:28:47 2021 +0300

    test: add compiling for C libs from PUC-Rio-Lua5.1

    This patch adds commands 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

diff --git a/test/PUC-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Lua-5.1-tests/CMakeLists.txt
index 066f668..2015936 100644
--- a/test/PUC-Lua-5.1-tests/CMakeLists.txt
+++ b/test/PUC-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")
 
-# Set PUC-Lua-5.1-tests-prepare target that creates <libs/P1>
+# Set 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-Lua-5.1-tests/libs/CMakeLists.txt b/test/PUC-Lua-5.1-tests/libs/CMakeLists.txt
index f24e7f3..aa64a44 100644
--- a/test/PUC-Lua-5.1-tests/libs/CMakeLists.txt
+++ b/test/PUC-Lua-5.1-tests/libs/CMakeLists.txt
@@ -4,11 +4,57 @@
 # 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 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-Lua-5.1-tests/libs/lib1.c b/test/PUC-Lua-5.1-tests/libs/lib1.c
index 812bb9a..22fe6de 100644
--- a/test/PUC-Lua-5.1-tests/libs/lib1.c
+++ b/test/PUC-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-Lua-5.1-tests/libs/lib2.c b/test/PUC-Lua-5.1-tests/libs/lib2.c
index 9972cbe..876a212 100644
--- a/test/PUC-Lua-5.1-tests/libs/lib2.c
+++ b/test/PUC-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}
 };
===================================================================

> 
> ================================================================================

<snipped>

> ================================================================================
> 
> > +# vim: expandtab tabstop=2 shiftwidth=2
> 
> <snipped>
> 
> > -- 
> > 2.28.0
> > 
> 
> [1]: https://github.com/tarantool/luajit/commit/c0c53e8
> 
> -- 
> Best regards,
> IM

-- 
Best regards,
Sergey Kaplun

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit 1/3] test: add PUC-Rio Lua 5.1 test suite
  2021-03-17 15:17     ` Igor Munkin via Tarantool-patches
@ 2021-03-19 11:30       ` Sergey Kaplun via Tarantool-patches
  0 siblings, 0 replies; 13+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-19 11:30 UTC (permalink / raw)
  To: Igor Munkin; +Cc: tarantool-patches

Sergos, Igor,

Thanks for the review!

On 17.03.21, Igor Munkin wrote:
> Sergos,
> 
> Thanks for you review!
> 
> On 16.03.21, Sergey Ostanevich wrote:
> > Hi!
> > 
> > Thanks for the patch!
> > 
> > 
> > 
> > > On 12 Mar 2021, at 08:36, Sergey Kaplun <skaplun@tarantool.org> wrote:
> > > 
> > > This patch adds PUC-Rio Lua 5.1 test suite as a part of the LuaJIT
> > > test suite. Source code taken verbatim from
> > > https://www.lua.org/tests/lua5.1-tests.tar.gz.
> > > 
> > > <lib1.c> and <lib2.c> is slightly modified to be consistent with the
> > > current LuaJIT's LuaC API.
> > > 
> > 
> > This should be a different commit, isn’t it?
> 
> Yes, it does.

Moved into sparate commit, see here [1].

> 
> > 
> > > Some tests may fail after this commit. They will be disabled
> > > or adapted in the next patches.
> > 
> > The fact patch causes - even temporarily - some fails is no good. The
> > only exception is initial commit, that brings original test suite.
> > Can you please make a consistent change that will left the tests disabled
> > until they adapted and enabled back?
> 
> I believe such juggling with enabling/disabling is quite unprofitable.
> We iteratively fix broken tests within the series making CI green as a
> result. Even if lib[12].c fails to compile -- it is not a problem, since

I've moved compilation rules for this libraries in the separate commit.
See patch here [1].

> these libraries are test dependencies, not build ones. Sergey can simply
> mention the fact the build of suite-related tests is broken, so one can
> find the comment in commit message while e.g. bisecting the bug.
> Otherwise, the patches are spoiled with unnecessary changes.
> 
> > 
> > regards,
> > Sergos
> > 
> > > 
> 
> <snipped>
> 
> > > -- 
> > > 2.28.0
> > > 
> > 
> 
> -- 
> Best regards,
> IM

[1]: https://lists.tarantool.org/pipermail/tarantool-patches/2021-March/022788.html

-- 
Best regards,
Sergey Kaplun

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit 2/3] test: adapt PUC-Rio Lua 5.1 test suite for LuaJIT
  2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 2/3] test: adapt PUC-Rio Lua 5.1 test suite for LuaJIT Sergey Kaplun via Tarantool-patches
  2021-03-13 19:04   ` Sergey Ostanevich via Tarantool-patches
@ 2021-03-22 18:52   ` Igor Munkin via Tarantool-patches
  2021-03-26  8:26     ` Sergey Kaplun via Tarantool-patches
  1 sibling, 1 reply; 13+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-03-22 18:52 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Sergey,

Thanks for the patch! It's so sad that you ignored the path and approach
for adopting test suites we have discussed so much. You've squashed all
changes into one. For what? To save SHA1 hashes? To write less commit
messages? But it simply makes my job harder. I haven't checked the
changes below (yet), since I need to revert them manually one by one.
The wording is not clear in some places. This is simply a mess. Please
split the changes, otherwise it's too hard to review them now and
maintain them later.

As a result, I only glanced the changes: there are some unnecessary,
since you can simply fix the issue in a standalone commit, there are
several with unclear reasoning (so nobody except you can fix it for a
couple of hours). There is even not a keyword to find the tests you
commented (but I remember we agreed to use one, e.g. FIXME).

See other comments inline.

On 12.03.21, Sergey Kaplun wrote:
> In some insignificant details LuaJIT's behaviour is not the same
> as the behaviour of Lua 5.1.
> 
> Tests in the following files are disabled with corresponding comments:
> * closure.lua
> * constructs.lua
> * db.lua
> * errors.lua
> * literals.lua
> * main.lua
> * math.lua
> * nextvar.lua
> * pm.lua
> * strings.lua
> * vararg.lua
> 
> See full list of disabled tests to adapt in
> https://github.com/tarantool/tarantool/issues/5870.
> 
> jit.off() as prologue and jit.on() as epilogue is added to one test
> chunk in gc.lua for stable (JIT unrelated) GC test results.
> 
> Part of tarantool/tarantool#5845
> Part of tarantool/tarantool#4473
> ---
>  test/PUC-Lua-5.1-tests/closure.lua    | 12 ++++-
>  test/PUC-Lua-5.1-tests/constructs.lua |  7 +++
>  test/PUC-Lua-5.1-tests/db.lua         | 75 ++++++++++++++++++++-------
>  test/PUC-Lua-5.1-tests/errors.lua     | 28 +++++++---
>  test/PUC-Lua-5.1-tests/gc.lua         |  5 ++
>  test/PUC-Lua-5.1-tests/literals.lua   |  5 ++
>  test/PUC-Lua-5.1-tests/main.lua       | 56 ++++++++++++++------
>  test/PUC-Lua-5.1-tests/math.lua       |  7 ++-
>  test/PUC-Lua-5.1-tests/nextvar.lua    |  7 +++
>  test/PUC-Lua-5.1-tests/pm.lua         |  6 ++-
>  test/PUC-Lua-5.1-tests/strings.lua    | 17 +++++-
>  test/PUC-Lua-5.1-tests/vararg.lua     | 20 ++++---
>  12 files changed, 195 insertions(+), 50 deletions(-)
> 
> diff --git a/test/PUC-Lua-5.1-tests/closure.lua b/test/PUC-Lua-5.1-tests/closure.lua
> index 27ca0ad..e9bd564 100644
> --- a/test/PUC-Lua-5.1-tests/closure.lua
> +++ b/test/PUC-Lua-5.1-tests/closure.lua
> @@ -174,7 +174,10 @@ f = coroutine.wrap(foo)
>  local a = {}
>  assert(f(a) == _G)
>  local a,b = pcall(f)
> -assert(a and b == _G)
> +-- LuaJIT getfenv() behaviour is different in tail calls.
> +-- See also https://github.com/tarantool/tarantool/issues/5713.

OK, the behaviour is different... So what? To understand what is
different, one need to uncomment the line below and make another
investigation for the issue. But you've already done one... There is not
a word regarding what is broken and what is the difference between Lua
and LuaJIT. Only the recipe, you need to implement for 2.10.1.

Please, clarify the root problem you faced, considering anyone except
you can take this issue and fix it.

> +-- Test is disabled for LuaJIT for now.
> +-- assert(a and b == _G)
>  
>  
>  -- tests for multiple yield/resume arguments
> @@ -261,6 +264,12 @@ end
>  
>  local x = gen(100)
>  local a = {}
> +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> +-- See also https://github.com/tarantool/tarantool/issues/5711.

I believe, you can s/math.mod/math.fmod/ within this series and resolve
the mentioned issue. The problem is trivial and the fix is quite simple.

> +-- Test is disabled.
> +--[=[
>  while 1 do
>    local n = x()
>    if n == nil then break end
> @@ -269,6 +278,7 @@ while 1 do
>  end
>  
>  assert(table.getn(a) == 25 and a[table.getn(a)] == 97)
> +--]=]
>  
>  
>  -- errors in coroutines
> diff --git a/test/PUC-Lua-5.1-tests/constructs.lua b/test/PUC-Lua-5.1-tests/constructs.lua
> index 5fb3798..6776ee6 100644
> --- a/test/PUC-Lua-5.1-tests/constructs.lua
> +++ b/test/PUC-Lua-5.1-tests/constructs.lua
> @@ -200,6 +200,12 @@ a,b = F(nil)==nil; assert(a == true and b == nil)
>  
>  function ID(x) return x end
>  
> +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> +-- See also https://github.com/tarantool/tarantool/issues/5711.

Ditto.

> +-- Test is disabled.
> +--[=[
>  function f(t, i)
>    local b = t.n
>    local res = math.mod(math.floor(i/c), b)+1
> @@ -236,5 +242,6 @@ repeat
>    if math.mod(i,4000) == 0 then print('+') end
>    i = i+1
>  until i==c
> +--]=]
>  
>  print'OK'
> diff --git a/test/PUC-Lua-5.1-tests/db.lua b/test/PUC-Lua-5.1-tests/db.lua
> index 9d2c86f..591a006 100644
> --- a/test/PUC-Lua-5.1-tests/db.lua
> +++ b/test/PUC-Lua-5.1-tests/db.lua
> @@ -95,6 +95,10 @@ repeat
>    assert(g(f) == 'a')
>  until 1
>  
> +-- LuaJIT interprets a return from calling result of loadstring()
> +-- with a new line number unlike Lua does.

I don't get the problem neither from comment nor from the issue. Could
you clarify what is the problem with a line number?

> +-- See also https://github.com/tarantool/tarantool/issues/5693.
> +--[=[
>  test([[if
>  math.sin(1)
>  then
> @@ -149,7 +153,7 @@ end
>  ]], {1,2,1,2,1,3})
>  
>  test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
> -
> +--]=]
>  
>  
>  print'+'
> @@ -178,8 +182,13 @@ function f(a,b)
>    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")
> +  -- f() function is called only from g(...) vararg function.
> +  -- Lua 5.1 interprets ... in the vararg functions like additional
> +  -- first argument unlike LuaJIT does.
> +  -- This extension is from Lua 5.2.
> +  -- See also https://github.com/tarantool/tarantool/issues/5694.
> +  -- 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"))
> @@ -208,11 +217,13 @@ function g(...)
>    local feijao
>    local AAAA,B = "xuxu", "mam?o"
>    f(AAAA,B)
> -  assert(AAAA == "pera" and B == "ma??")
> +  -- Test is disabled for LuaJIT for now. See comment in f().
> +  -- assert(AAAA == "pera" and B == "ma??")
>    do
>       local B = 13
>       local x,y = debug.getlocal(1,5)
> -     assert(x == 'B' and y == 13)
> +     -- Test is disabled for LuaJIT for now. See comment in f().
> +     -- assert(x == 'B' and y == 13)
>    end
>  end
>  
> @@ -276,7 +287,8 @@ 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)
> +-- Test is disabled for LuaJIT for now. See comment in f().

Which one "f()" contains the necessary comment? <a:f> used here has no
words regarding the problem.

> +-- 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)
>  
> @@ -314,12 +326,20 @@ assert(debug.setupvalue(io.read, 1, 10) == nil)
>  
>  -- testing count hooks
>  local a=0
> +-- 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.

I guess you can use the first recipe you provided in the issue:
| local js = jit.status()
| js and jit.off()
| <...>
| js and jit.on()

You can omit the check if it is guaranteed JIT status doesn't change
from run to run, and leave the corresponding comment.

> +--[[
>  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
> @@ -352,18 +372,24 @@ function g1(x) g(x) end
>  
>  local function h (x) local f=g1; return f(x) end
>  
> -h(true)
> +-- LuaJIT does not provide information about tail calls,
> +-- unlike Lua does. getfenv() behaviour is also different here.
> +-- Test is disabled for LuaJIT for now.

This looks like an unresolvable issue, doesn't it? So why it is disabled
*for now*? Furthermore, the ticket lacks the precise description
regarding the differences, you're talking about.

Minor: BTW, why didn't you comment the whole block? The declarations are
necessary only for the assertions. Feel free to ignore.

> +-- 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()
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- 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
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- for _, k in ipairs(res) do assert(k == table.remove(b, 1)) end
>  
>  
>  lim = 30000
> @@ -375,7 +401,8 @@ local function foo (x)
>    end
>  end
>  
> -foo(lim)
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- foo(lim)
>  
>  
>  print"+"
> @@ -411,7 +438,11 @@ end
>  
>  local co = coroutine.create(f)
>  coroutine.resume(co, 3)
> -checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
> +-- LuaJIT does not provide information about tail calls,
> +-- unlike Lua does.
> +-- See also https://github.com/tarantool/tarantool/issues/5703.

Ditto. Besides, what is the difference from #5702?

> +-- Test is disabled for LuaJIT for now.
> +-- checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
>  
>  
>  co = coroutine.create(function (x)
> @@ -429,8 +460,12 @@ 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")
> +-- LuaJIT does not report line with single "end" statement as
> +-- an active line in debug.getinfo(), unlike Lua does.

Too hard to understand... It's worth to reword the comment considering
the issue name and make it more verbose.

> +-- See also https://github.com/tarantool/tarantool/issues/5708.
> +-- Test is disabled for LuaJIT for now.
>  for i=x.linedefined + 1, x.lastlinedefined do
> -  assert(x.activelines[i])
> +  -- assert(x.activelines[i])
>    x.activelines[i] = nil
>  end
>  assert(next(x.activelines) == nil)   -- no 'extra' elements
> @@ -441,8 +476,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)
> +-- LuaJIT does not support per-coroutine hooks.

Please, mention the issue/doc page with the behaviour description.

> +-- 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)
> @@ -450,9 +487,11 @@ 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)
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- assert(table.getn(tr) == 4 and tr[4] == l.currentline+2)
>  assert(debug.gethook(co) == foo)
> -assert(debug.gethook() == nil)
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- assert(debug.gethook() == nil)
>  checktraceback(co, {})
>  
>  
> diff --git a/test/PUC-Lua-5.1-tests/errors.lua b/test/PUC-Lua-5.1-tests/errors.lua
> index e881211..3270033 100644
> --- a/test/PUC-Lua-5.1-tests/errors.lua
> +++ b/test/PUC-Lua-5.1-tests/errors.lua
> @@ -72,8 +72,12 @@ 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 reports the error as the following here:
> +-- "attempt to perform arithmetic on global 'aaa' (a table value)"
> +-- Lua 5.1 doesn't report variable name here.

So the issue is only in different error message? It's unclear from you
message (I've got this only at the third attempt).

> +-- Test is 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
> @@ -100,9 +104,12 @@ while 1 do
>    insert(prefix, a)
>  end]], "global 'insert'")
>  
> -checkmessage([[  -- tail call
> -  return math.sin("a")
> -]], "'sin'")
> +-- Implementation of fast functions in LuaJIT does not provide
> +-- enough info on failure.

What info do fast functions lack? Not an issue. Not a word. The comment
just to comment...

> +-- Test is disabled for LuaJIT.
> +-- checkmessage([[  -- tail call
> +--   return math.sin("a")
> +-- ]], "'sin'")
>  
>  checkmessage([[collectgarbage("nooption")]], "invalid option")
>  
> @@ -193,7 +200,11 @@ checksyntax("[[a]]", "", "[[a]]", 1)
>  checksyntax("'aa'", "", "'aa'", 1)
>  
>  -- test 255 as first char in a chunk
> -checksyntax("\255a = 1", "", "\255", 1)
> +-- LuaJIT does not avoid to use non-alphabetic symbols

Minor: I guess you mean alphanumeric, not alphabetic.

> +-- 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)
> @@ -215,7 +226,10 @@ local function testrep (init, rep)
>  end
>  testrep("a=", "{")
>  testrep("a=", "(")
> -testrep("", "a(")
> +-- When compiled with LUAJIT_ENABLE_GC64 LJ_MAX_SLOTS limit
> +-- is reached and error is LJ_ERR_XSLOTS ("function or expression too
> +-- complex"). Test is disabled for LuaJIT.

And what is the expected behaviour?

> +-- testrep("", "a(")
>  testrep("", "do ")
>  testrep("", "while a do ")
>  testrep("", "if a then else ")
> diff --git a/test/PUC-Lua-5.1-tests/gc.lua b/test/PUC-Lua-5.1-tests/gc.lua
> index 86a9f75..b767104 100644
> --- a/test/PUC-Lua-5.1-tests/gc.lua
> +++ b/test/PUC-Lua-5.1-tests/gc.lua
> @@ -108,11 +108,16 @@ local function dosteps (siz)
>    return i
>  end
>  
> +-- JIT compilation can unpredictable allocate or reference objects
> +-- (or traces itself). Disable it for this chunk for stable
> +-- GC results.

Is JIT unconditionally enabled? If it's not, it is unconditionally
enabled "back" below... If it is, please mention this in the comment.

Side note: amazingly, you didn't comment these assertions but adjust the
block... It's better, but inconsistent with the other changes.

> +jit.off()
>  assert(dosteps(0) > 10)
>  assert(dosteps(6) < dosteps(2))
>  assert(dosteps(10000) == 1)
>  assert(collectgarbage("step", 1000000) == true)
>  assert(collectgarbage("step", 1000000))
> +jit.on()
>  
>  
>  do
> diff --git a/test/PUC-Lua-5.1-tests/literals.lua b/test/PUC-Lua-5.1-tests/literals.lua
> index 01d84d5..ee16a3e 100644
> --- a/test/PUC-Lua-5.1-tests/literals.lua
> +++ b/test/PUC-Lua-5.1-tests/literals.lua
> @@ -158,6 +158,10 @@ end
>  
>  
>  -- testing decimal point locale
> +-- LuaJIT doesn't use `strtod()` depended on the locale, unlike
> +-- Lua does. See <src/lj_strscan.c> for more info.

I see the related issue in LuaJIT queue[1] (looks like <os.setlocale>
does nothing for many case). Please mention it here.

> +-- 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-Lua-5.1-tests/main.lua b/test/PUC-Lua-5.1-tests/main.lua
> index f520896..12f3981 100644
> --- a/test/PUC-Lua-5.1-tests/main.lua
> +++ b/test/PUC-Lua-5.1-tests/main.lua
> @@ -65,9 +65,16 @@ 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)
> +-- test 'arg' availability in libraries
> +-- 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.
> +-- prepfile"assert(arg==nil)"
> +-- prepfile("assert(arg)", otherprog)
> +-- RUN("lua -l%s - < %s", prog, otherprog)
>  
>  prepfile""
>  RUN("lua - < %s > %s", prog, out)
> @@ -89,26 +96,35 @@ prepfile[[
>  RUN("lua - < %s > %s", prog, out)
>  checkout("1\tnil\n")
>  
> +-- Version and status are printed in stdout instead 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.
> +-- 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")
> +-- 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")
> +-- 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")
> +-- 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 )
> @@ -126,19 +142,29 @@ 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")
> +-- 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)
>  
> +-- test loading and running bytecode files.
> +-- 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.
>  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")
> +-- Behavior is different for LuaJIT. See the comment above.
> +-- 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))
> diff --git a/test/PUC-Lua-5.1-tests/math.lua b/test/PUC-Lua-5.1-tests/math.lua
> index 5076f38..b46a3f5 100644
> --- a/test/PUC-Lua-5.1-tests/math.lua
> +++ b/test/PUC-Lua-5.1-tests/math.lua
> @@ -100,7 +100,12 @@ 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)
> +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> +-- See also https://github.com/tarantool/tarantool/issues/5711.

The same as for math.mod occurrence above.

> +-- Test is disabled.
> +-- 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))
> diff --git a/test/PUC-Lua-5.1-tests/nextvar.lua b/test/PUC-Lua-5.1-tests/nextvar.lua
> index 7ceaa75..a63f97e 100644
> --- a/test/PUC-Lua-5.1-tests/nextvar.lua
> +++ b/test/PUC-Lua-5.1-tests/nextvar.lua
> @@ -199,6 +199,12 @@ _G["xxx"] = 1
>  assert(xxx==find("xxx"))
>  print('+')
>  
> +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> +-- See also https://github.com/tarantool/tarantool/issues/5711.

The same as for math.mod occurrence above.

> +-- Test is disabled.
> +--[=[
>  a = {}
>  for i=0,10000 do
>    if math.mod(i,10) ~= 0 then
> @@ -213,6 +219,7 @@ for i,v in pairs(a) do
>  end
>  assert(n.n == 9000)
>  a = nil
> +--]=]
>  
>  -- remove those 10000 new global variables
>  for i=1,10000 do _G[i] = nil end
> diff --git a/test/PUC-Lua-5.1-tests/pm.lua b/test/PUC-Lua-5.1-tests/pm.lua
> index fa125dc..366a31c 100644
> --- a/test/PUC-Lua-5.1-tests/pm.lua
> +++ b/test/PUC-Lua-5.1-tests/pm.lua
> @@ -223,7 +223,11 @@ assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI")
>  
>  
>  -- tests for gmatch
> -assert(string.gfind == string.gmatch)
> +-- 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 builtin is removed from LuaJIT. Test is disabled.

Just remove the test in a separate commit and mention the patch that
removes the builtin. I see no reason for disabling this test.

> +-- 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)
> diff --git a/test/PUC-Lua-5.1-tests/strings.lua b/test/PUC-Lua-5.1-tests/strings.lua
> index 237dbad..a97c888 100644
> --- a/test/PUC-Lua-5.1-tests/strings.lua
> +++ b/test/PUC-Lua-5.1-tests/strings.lua
> @@ -102,7 +102,18 @@ print('+')
>  
>  x = '"?lo"\n\\'
>  assert(string.format('%q%s', x, x) == '"\\"?lo\\"\\\n\\\\""?lo"\n\\')
> -assert(string.format('%q', "\0") == [["\000"]])
> +-- LuaJIT since v2.0.0-beta6 has extension from Lua 5.2:
> +-- string.format(): %q reversible.
> +-- In Lua 5.1 string.format() does not accept string values
> +-- containing embedded zeros, except as arguments to the q option.
> +-- In Lua 5.2 '\0' is not handled differently from other
> +-- control chars in string.format('%q', ...).
> +-- See commit 7cc981c14067d4b0e774a6bfb0acfc2f5c911f0d
> +-- (string.format("%q", str) is now fully reversible
> +-- (from Lua 5.2).).
> +-- See also https://github.com/tarantool/tarantool/issues/5710.
> +-- Test is disabled for LuaJIT for now.
> +-- 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('') == "")
> @@ -152,6 +163,9 @@ local function trylocale (w)
>    return false
>  end
>  
> +-- 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
> @@ -166,6 +180,7 @@ else
>    assert(string.gsub("????", "%u", "x") == "?x?x")
>    assert(string.upper"???{xuxu}??o" == "???{XUXU}??O")
>  end
> +--]]
>  
>  os.setlocale("C")
>  assert(os.setlocale() == 'C')
> diff --git a/test/PUC-Lua-5.1-tests/vararg.lua b/test/PUC-Lua-5.1-tests/vararg.lua
> index ae068fa..e2de1ad 100644
> --- a/test/PUC-Lua-5.1-tests/vararg.lua
> +++ b/test/PUC-Lua-5.1-tests/vararg.lua
> @@ -21,9 +21,14 @@ 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)
> +-- Lua 5.1 interprets ... in the vararg functions like additional
> +-- first argument unlike LuaJIT does. All extra arguments is set
> +-- into `arg` variable. This extension is from Lua 5.2.
> +-- See also https://github.com/tarantool/tarantool/issues/5712.
> +-- Test is disabled for LuaJIT.
> +-- 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}))
> @@ -35,15 +40,18 @@ 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)
> +-- Test is disabled for LuaJIT for now. See the comment above.
> +-- 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)
> +-- Test is disabled for LuaJIT for now. See the comment above.
> +-- 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)
> +-- Test is disabled for LuaJIT for now. See the comment above.
> +-- assert(t:f(1,4) == 3 and t:f(2) == 11)
>  print('+')
>  
>  lim = 20
> -- 
> 2.28.0
> 

[1]: https://github.com/LuaJIT/LuaJIT/issues/673

-- 
Best regards,
IM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit 2/3] test: adapt PUC-Rio Lua 5.1 test suite for LuaJIT
  2021-03-22 18:52   ` Igor Munkin via Tarantool-patches
@ 2021-03-26  8:26     ` Sergey Kaplun via Tarantool-patches
  0 siblings, 0 replies; 13+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-26  8:26 UTC (permalink / raw)
  To: Igor Munkin; +Cc: tarantool-patches

Igor,

Thanks for the review!

On 22.03.21, Igor Munkin wrote:
> Sergey,
> 
> Thanks for the patch! It's so sad that you ignored the path and approach
> for adopting test suites we have discussed so much. You've squashed all
> changes into one. For what? To save SHA1 hashes? To write less commit
> messages? But it simply makes my job harder. I haven't checked the
> changes below (yet), since I need to revert them manually one by one.
> The wording is not clear in some places. This is simply a mess. Please
> split the changes, otherwise it's too hard to review them now and
> maintain them later.

This was discussed with you offline and you asked about it personally.
I don't understand why do you blame me in this situation -- you've taken
a part in this decision too. I don't try to make your job harder, just
follow our previous agreements.
OK, I've resent the series [1] with separated commits as you want it now.

> 
> As a result, I only glanced the changes: there are some unnecessary,
> since you can simply fix the issue in a standalone commit, there are

I didn't done it before only because you asked me not to do that, but
only commented these tests (even obvious cases) and create corresponding
issue if we want to fix them. I'll uncomment and fix obvious tests.

> several with unclear reasoning (so nobody except you can fix it for a
> couple of hours). There is even not a keyword to find the tests you
> commented (but I remember we agreed to use one, e.g. FIXME).

Yes, we came to agreement discuss that on review. Let's use FIXME for
test to adjust and LuaJIT for fixed tests.

> 
> See other comments inline.

> 
> On 12.03.21, Sergey Kaplun wrote:
> > In some insignificant details LuaJIT's behaviour is not the same
> > as the behaviour of Lua 5.1.
> > 
> > Tests in the following files are disabled with corresponding comments:
> > * closure.lua
> > * constructs.lua
> > * db.lua
> > * errors.lua
> > * literals.lua
> > * main.lua
> > * math.lua
> > * nextvar.lua
> > * pm.lua
> > * strings.lua
> > * vararg.lua
> > 
> > See full list of disabled tests to adapt in
> > https://github.com/tarantool/tarantool/issues/5870.
> > 
> > jit.off() as prologue and jit.on() as epilogue is added to one test
> > chunk in gc.lua for stable (JIT unrelated) GC test results.
> > 
> > Part of tarantool/tarantool#5845
> > Part of tarantool/tarantool#4473
> > ---
> >  test/PUC-Lua-5.1-tests/closure.lua    | 12 ++++-
> >  test/PUC-Lua-5.1-tests/constructs.lua |  7 +++
> >  test/PUC-Lua-5.1-tests/db.lua         | 75 ++++++++++++++++++++-------
> >  test/PUC-Lua-5.1-tests/errors.lua     | 28 +++++++---
> >  test/PUC-Lua-5.1-tests/gc.lua         |  5 ++
> >  test/PUC-Lua-5.1-tests/literals.lua   |  5 ++
> >  test/PUC-Lua-5.1-tests/main.lua       | 56 ++++++++++++++------
> >  test/PUC-Lua-5.1-tests/math.lua       |  7 ++-
> >  test/PUC-Lua-5.1-tests/nextvar.lua    |  7 +++
> >  test/PUC-Lua-5.1-tests/pm.lua         |  6 ++-
> >  test/PUC-Lua-5.1-tests/strings.lua    | 17 +++++-
> >  test/PUC-Lua-5.1-tests/vararg.lua     | 20 ++++---
> >  12 files changed, 195 insertions(+), 50 deletions(-)
> > 
> > diff --git a/test/PUC-Lua-5.1-tests/closure.lua b/test/PUC-Lua-5.1-tests/closure.lua
> > index 27ca0ad..e9bd564 100644
> > --- a/test/PUC-Lua-5.1-tests/closure.lua
> > +++ b/test/PUC-Lua-5.1-tests/closure.lua
> > @@ -174,7 +174,10 @@ f = coroutine.wrap(foo)
> >  local a = {}
> >  assert(f(a) == _G)
> >  local a,b = pcall(f)
> > -assert(a and b == _G)
> > +-- LuaJIT getfenv() behaviour is different in tail calls.
> > +-- See also https://github.com/tarantool/tarantool/issues/5713.
> 
> OK, the behaviour is different... So what? To understand what is
> different, one need to uncomment the line below and make another
> investigation for the issue. But you've already done one... There is not
> a word regarding what is broken and what is the difference between Lua
> and LuaJIT. Only the recipe, you need to implement for 2.10.1.
> 
> Please, clarify the root problem you faced, considering anyone except
> you can take this issue and fix it.

Reworded in the new version.

> 
> > +-- Test is disabled for LuaJIT for now.
> > +-- assert(a and b == _G)
> >  
> >  
> >  -- tests for multiple yield/resume arguments
> > @@ -261,6 +264,12 @@ end
> >  
> >  local x = gen(100)
> >  local a = {}
> > +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> > +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> > +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> > +-- See also https://github.com/tarantool/tarantool/issues/5711.
> 
> I believe, you can s/math.mod/math.fmod/ within this series and resolve
> the mentioned issue. The problem is trivial and the fix is quite simple.

Done in the new version.

> 
> > +-- Test is disabled.
> > +--[=[
> >  while 1 do
> >    local n = x()
> >    if n == nil then break end
> > @@ -269,6 +278,7 @@ while 1 do
> >  end
> >  
> >  assert(table.getn(a) == 25 and a[table.getn(a)] == 97)
> > +--]=]
> >  
> >  
> >  -- errors in coroutines
> > diff --git a/test/PUC-Lua-5.1-tests/constructs.lua b/test/PUC-Lua-5.1-tests/constructs.lua
> > index 5fb3798..6776ee6 100644
> > --- a/test/PUC-Lua-5.1-tests/constructs.lua
> > +++ b/test/PUC-Lua-5.1-tests/constructs.lua
> > @@ -200,6 +200,12 @@ a,b = F(nil)==nil; assert(a == true and b == nil)
> >  
> >  function ID(x) return x end
> >  
> > +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> > +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> > +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> > +-- See also https://github.com/tarantool/tarantool/issues/5711.
> 
> Ditto.

Ditto.

> 
> > +-- Test is disabled.
> > +--[=[
> >  function f(t, i)
> >    local b = t.n
> >    local res = math.mod(math.floor(i/c), b)+1
> > @@ -236,5 +242,6 @@ repeat
> >    if math.mod(i,4000) == 0 then print('+') end
> >    i = i+1
> >  until i==c
> > +--]=]
> >  
> >  print'OK'
> > diff --git a/test/PUC-Lua-5.1-tests/db.lua b/test/PUC-Lua-5.1-tests/db.lua
> > index 9d2c86f..591a006 100644
> > --- a/test/PUC-Lua-5.1-tests/db.lua
> > +++ b/test/PUC-Lua-5.1-tests/db.lua
> > @@ -95,6 +95,10 @@ repeat
> >    assert(g(f) == 'a')
> >  until 1
> >  
> > +-- LuaJIT interprets a return from calling result of loadstring()
> > +-- with a new line number unlike Lua does.
> 
> I don't get the problem neither from comment nor from the issue. Could
> you clarify what is the problem with a line number?

Reworded in the new version.

> 
> > +-- See also https://github.com/tarantool/tarantool/issues/5693.
> > +--[=[
> >  test([[if
> >  math.sin(1)
> >  then
> > @@ -149,7 +153,7 @@ end
> >  ]], {1,2,1,2,1,3})
> >  
> >  test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
> > -
> > +--]=]
> >  
> >  
> >  print'+'
> > @@ -178,8 +182,13 @@ function f(a,b)
> >    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")
> > +  -- f() function is called only from g(...) vararg function.
> > +  -- Lua 5.1 interprets ... in the vararg functions like additional
> > +  -- first argument unlike LuaJIT does.
> > +  -- This extension is from Lua 5.2.
> > +  -- See also https://github.com/tarantool/tarantool/issues/5694.
> > +  -- 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"))
> > @@ -208,11 +217,13 @@ function g(...)
> >    local feijao
> >    local AAAA,B = "xuxu", "mam?o"
> >    f(AAAA,B)
> > -  assert(AAAA == "pera" and B == "ma??")
> > +  -- Test is disabled for LuaJIT for now. See comment in f().
> > +  -- assert(AAAA == "pera" and B == "ma??")
> >    do
> >       local B = 13
> >       local x,y = debug.getlocal(1,5)
> > -     assert(x == 'B' and y == 13)
> > +     -- Test is disabled for LuaJIT for now. See comment in f().
> > +     -- assert(x == 'B' and y == 13)
> >    end
> >  end
> >  
> > @@ -276,7 +287,8 @@ 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)
> > +-- Test is disabled for LuaJIT for now. See comment in f().
> 
> Which one "f()" contains the necessary comment? <a:f> used here has no
> words regarding the problem.

Reimplemented in the new version.

> 
> > +-- 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)
> >  
> > @@ -314,12 +326,20 @@ assert(debug.setupvalue(io.read, 1, 10) == nil)
> >  
> >  -- testing count hooks
> >  local a=0
> > +-- 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.
> 
> I guess you can use the first recipe you provided in the issue:
> | local js = jit.status()
> | js and jit.off()
> | <...>
> | js and jit.on()
> 
> You can omit the check if it is guaranteed JIT status doesn't change
> from run to run, and leave the corresponding comment.

Done.

> 
> > +--[[
> >  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
> > @@ -352,18 +372,24 @@ function g1(x) g(x) end
> >  
> >  local function h (x) local f=g1; return f(x) end
> >  
> > -h(true)
> > +-- LuaJIT does not provide information about tail calls,
> > +-- unlike Lua does. getfenv() behaviour is also different here.
> > +-- Test is disabled for LuaJIT for now.
> 
> This looks like an unresolvable issue, doesn't it? So why it is disabled
> *for now*? Furthermore, the ticket lacks the precise description
> regarding the differences, you're talking about.

Test may be adapted for LuaJIT's behaviour.

> 
> Minor: BTW, why didn't you comment the whole block? The declarations are
> necessary only for the assertions. Feel free to ignore.

We came to agreement offline not to change unnecessary blocks
to coverage more branches.

> 
> > +-- 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()
> > +-- Behavior is different for LuaJIT. See the comment above.
> > +-- 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
> > +-- Behavior is different for LuaJIT. See the comment above.
> > +-- for _, k in ipairs(res) do assert(k == table.remove(b, 1)) end
> >  
> >  
> >  lim = 30000
> > @@ -375,7 +401,8 @@ local function foo (x)
> >    end
> >  end
> >  
> > -foo(lim)
> > +-- Behavior is different for LuaJIT. See the comment above.
> > +-- foo(lim)
> >  
> >  
> >  print"+"
> > @@ -411,7 +438,11 @@ end
> >  
> >  local co = coroutine.create(f)
> >  coroutine.resume(co, 3)
> > -checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
> > +-- LuaJIT does not provide information about tail calls,
> > +-- unlike Lua does.
> > +-- See also https://github.com/tarantool/tarantool/issues/5703.
> 
> Ditto. Besides, what is the difference from #5702?

Answered above. The test can be adjusted independently from previous,
so there is separate issue.

> 
> > +-- Test is disabled for LuaJIT for now.
> > +-- checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
> >  
> >  
> >  co = coroutine.create(function (x)
> > @@ -429,8 +460,12 @@ 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")
> > +-- LuaJIT does not report line with single "end" statement as
> > +-- an active line in debug.getinfo(), unlike Lua does.
> 
> Too hard to understand... It's worth to reword the comment considering
> the issue name and make it more verbose.

Reformulated in the new version.

> 
> > +-- See also https://github.com/tarantool/tarantool/issues/5708.
> > +-- Test is disabled for LuaJIT for now.
> >  for i=x.linedefined + 1, x.lastlinedefined do
> > -  assert(x.activelines[i])
> > +  -- assert(x.activelines[i])
> >    x.activelines[i] = nil
> >  end
> >  assert(next(x.activelines) == nil)   -- no 'extra' elements
> > @@ -441,8 +476,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)
> > +-- LuaJIT does not support per-coroutine hooks.
> 
> Please, mention the issue/doc page with the behaviour description.

Done.

> 
> > +-- 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)
> > @@ -450,9 +487,11 @@ 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)
> > +-- Behavior is different for LuaJIT. See the comment above.
> > +-- assert(table.getn(tr) == 4 and tr[4] == l.currentline+2)
> >  assert(debug.gethook(co) == foo)
> > -assert(debug.gethook() == nil)
> > +-- Behavior is different for LuaJIT. See the comment above.
> > +-- assert(debug.gethook() == nil)
> >  checktraceback(co, {})
> >  
> >  
> > diff --git a/test/PUC-Lua-5.1-tests/errors.lua b/test/PUC-Lua-5.1-tests/errors.lua
> > index e881211..3270033 100644
> > --- a/test/PUC-Lua-5.1-tests/errors.lua
> > +++ b/test/PUC-Lua-5.1-tests/errors.lua
> > @@ -72,8 +72,12 @@ 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 reports the error as the following here:
> > +-- "attempt to perform arithmetic on global 'aaa' (a table value)"
> > +-- Lua 5.1 doesn't report variable name here.
> 
> So the issue is only in different error message? It's unclear from you
> message (I've got this only at the third attempt).

It tests only error messages, described it more verbosly in the new
version.

> 
> > +-- Test is 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
> > @@ -100,9 +104,12 @@ while 1 do
> >    insert(prefix, a)
> >  end]], "global 'insert'")
> >  
> > -checkmessage([[  -- tail call
> > -  return math.sin("a")
> > -]], "'sin'")
> > +-- Implementation of fast functions in LuaJIT does not provide
> > +-- enough info on failure.
> 
> What info do fast functions lack? Not an issue. Not a word. The comment
> just to comment...

Reworded in the new version.

> 
> > +-- Test is disabled for LuaJIT.
> > +-- checkmessage([[  -- tail call
> > +--   return math.sin("a")
> > +-- ]], "'sin'")
> >  
> >  checkmessage([[collectgarbage("nooption")]], "invalid option")
> >  
> > @@ -193,7 +200,11 @@ checksyntax("[[a]]", "", "[[a]]", 1)
> >  checksyntax("'aa'", "", "'aa'", 1)
> >  
> >  -- test 255 as first char in a chunk
> > -checksyntax("\255a = 1", "", "\255", 1)
> > +-- LuaJIT does not avoid to use non-alphabetic symbols
> 
> Minor: I guess you mean alphanumeric, not alphabetic.

Fixed.

> 
> > +-- 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)
> > @@ -215,7 +226,10 @@ local function testrep (init, rep)
> >  end
> >  testrep("a=", "{")
> >  testrep("a=", "(")
> > -testrep("", "a(")
> > +-- When compiled with LUAJIT_ENABLE_GC64 LJ_MAX_SLOTS limit
> > +-- is reached and error is LJ_ERR_XSLOTS ("function or expression too
> > +-- complex"). Test is disabled for LuaJIT.
> 
> And what is the expected behaviour?

See the test above. Answered in the new version.

> 
> > +-- testrep("", "a(")
> >  testrep("", "do ")
> >  testrep("", "while a do ")
> >  testrep("", "if a then else ")
> > diff --git a/test/PUC-Lua-5.1-tests/gc.lua b/test/PUC-Lua-5.1-tests/gc.lua
> > index 86a9f75..b767104 100644
> > --- a/test/PUC-Lua-5.1-tests/gc.lua
> > +++ b/test/PUC-Lua-5.1-tests/gc.lua
> > @@ -108,11 +108,16 @@ local function dosteps (siz)
> >    return i
> >  end
> >  
> > +-- JIT compilation can unpredictable allocate or reference objects
> > +-- (or traces itself). Disable it for this chunk for stable
> > +-- GC results.
> 
> Is JIT unconditionally enabled? If it's not, it is unconditionally
> enabled "back" below... If it is, please mention this in the comment.

Applied.

> 
> Side note: amazingly, you didn't comment these assertions but adjust the
> block... It's better, but inconsistent with the other changes.
> 
> > +jit.off()
> >  assert(dosteps(0) > 10)
> >  assert(dosteps(6) < dosteps(2))
> >  assert(dosteps(10000) == 1)
> >  assert(collectgarbage("step", 1000000) == true)
> >  assert(collectgarbage("step", 1000000))
> > +jit.on()
> >  
> >  
> >  do
> > diff --git a/test/PUC-Lua-5.1-tests/literals.lua b/test/PUC-Lua-5.1-tests/literals.lua
> > index 01d84d5..ee16a3e 100644
> > --- a/test/PUC-Lua-5.1-tests/literals.lua
> > +++ b/test/PUC-Lua-5.1-tests/literals.lua
> > @@ -158,6 +158,10 @@ end
> >  
> >  
> >  -- testing decimal point locale
> > +-- LuaJIT doesn't use `strtod()` depended on the locale, unlike
> > +-- Lua does. See <src/lj_strscan.c> for more info.
> 
> I see the related issue in LuaJIT queue[1] (looks like <os.setlocale>
> does nothing for many case). Please mention it here.

It just mentioned documentation, see no reason to reference this issue
here.

> 
> > +-- 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-Lua-5.1-tests/main.lua b/test/PUC-Lua-5.1-tests/main.lua
> > index f520896..12f3981 100644
> > --- a/test/PUC-Lua-5.1-tests/main.lua
> > +++ b/test/PUC-Lua-5.1-tests/main.lua
> > @@ -65,9 +65,16 @@ 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)
> > +-- test 'arg' availability in libraries
> > +-- 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.
> > +-- prepfile"assert(arg==nil)"
> > +-- prepfile("assert(arg)", otherprog)
> > +-- RUN("lua -l%s - < %s", prog, otherprog)
> >  
> >  prepfile""
> >  RUN("lua - < %s > %s", prog, out)
> > @@ -89,26 +96,35 @@ prepfile[[
> >  RUN("lua - < %s > %s", prog, out)
> >  checkout("1\tnil\n")
> >  
> > +-- Version and status are printed in stdout instead 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.
> > +-- 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")
> > +-- 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")
> > +-- 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")
> > +-- 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 )
> > @@ -126,19 +142,29 @@ 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")
> > +-- 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)
> >  
> > +-- test loading and running bytecode files.
> > +-- 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.
> >  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")
> > +-- Behavior is different for LuaJIT. See the comment above.
> > +-- 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))
> > diff --git a/test/PUC-Lua-5.1-tests/math.lua b/test/PUC-Lua-5.1-tests/math.lua
> > index 5076f38..b46a3f5 100644
> > --- a/test/PUC-Lua-5.1-tests/math.lua
> > +++ b/test/PUC-Lua-5.1-tests/math.lua
> > @@ -100,7 +100,12 @@ 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)
> > +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> > +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> > +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> > +-- See also https://github.com/tarantool/tarantool/issues/5711.
> 
> The same as for math.mod occurrence above.

Answered above.

> 
> > +-- Test is disabled.
> > +-- 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))
> > diff --git a/test/PUC-Lua-5.1-tests/nextvar.lua b/test/PUC-Lua-5.1-tests/nextvar.lua
> > index 7ceaa75..a63f97e 100644
> > --- a/test/PUC-Lua-5.1-tests/nextvar.lua
> > +++ b/test/PUC-Lua-5.1-tests/nextvar.lua
> > @@ -199,6 +199,12 @@ _G["xxx"] = 1
> >  assert(xxx==find("xxx"))
> >  print('+')
> >  
> > +-- In Lua 5.1 math.mod() is renamed to math.fmod() if build
> > +-- Lua 5.1 without flag `-DLUA_COMPAT_MOD`.
> > +-- LuaJIT also has math.fmod() instead math.mod() builtin.
> > +-- See also https://github.com/tarantool/tarantool/issues/5711.
> 
> The same as for math.mod occurrence above.

Answered above.

> 
> > +-- Test is disabled.
> > +--[=[
> >  a = {}
> >  for i=0,10000 do
> >    if math.mod(i,10) ~= 0 then
> > @@ -213,6 +219,7 @@ for i,v in pairs(a) do
> >  end
> >  assert(n.n == 9000)
> >  a = nil
> > +--]=]
> >  
> >  -- remove those 10000 new global variables
> >  for i=1,10000 do _G[i] = nil end
> > diff --git a/test/PUC-Lua-5.1-tests/pm.lua b/test/PUC-Lua-5.1-tests/pm.lua
> > index fa125dc..366a31c 100644
> > --- a/test/PUC-Lua-5.1-tests/pm.lua
> > +++ b/test/PUC-Lua-5.1-tests/pm.lua
> > @@ -223,7 +223,11 @@ assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI")
> >  
> >  
> >  -- tests for gmatch
> > -assert(string.gfind == string.gmatch)
> > +-- 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 builtin is removed from LuaJIT. Test is disabled.
> 
> Just remove the test in a separate commit and mention the patch that
> removes the builtin. I see no reason for disabling this test.

Done. I've failed to find this patch grepped by 'gfind', can you provide
reference to it please? I supposed it has be done before v2.0 is
released.

> 
> > +-- 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)
> > diff --git a/test/PUC-Lua-5.1-tests/strings.lua b/test/PUC-Lua-5.1-tests/strings.lua
> > index 237dbad..a97c888 100644
> > --- a/test/PUC-Lua-5.1-tests/strings.lua
> > +++ b/test/PUC-Lua-5.1-tests/strings.lua
> > @@ -102,7 +102,18 @@ print('+')
> >  
> >  x = '"?lo"\n\\'
> >  assert(string.format('%q%s', x, x) == '"\\"?lo\\"\\\n\\\\""?lo"\n\\')
> > -assert(string.format('%q', "\0") == [["\000"]])
> > +-- LuaJIT since v2.0.0-beta6 has extension from Lua 5.2:
> > +-- string.format(): %q reversible.
> > +-- In Lua 5.1 string.format() does not accept string values
> > +-- containing embedded zeros, except as arguments to the q option.
> > +-- In Lua 5.2 '\0' is not handled differently from other
> > +-- control chars in string.format('%q', ...).
> > +-- See commit 7cc981c14067d4b0e774a6bfb0acfc2f5c911f0d
> > +-- (string.format("%q", str) is now fully reversible
> > +-- (from Lua 5.2).).
> > +-- See also https://github.com/tarantool/tarantool/issues/5710.
> > +-- Test is disabled for LuaJIT for now.
> > +-- 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('') == "")
> > @@ -152,6 +163,9 @@ local function trylocale (w)
> >    return false
> >  end
> >  
> > +-- 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
> > @@ -166,6 +180,7 @@ else
> >    assert(string.gsub("????", "%u", "x") == "?x?x")
> >    assert(string.upper"???{xuxu}??o" == "???{XUXU}??O")
> >  end
> > +--]]
> >  
> >  os.setlocale("C")
> >  assert(os.setlocale() == 'C')
> > diff --git a/test/PUC-Lua-5.1-tests/vararg.lua b/test/PUC-Lua-5.1-tests/vararg.lua
> > index ae068fa..e2de1ad 100644
> > --- a/test/PUC-Lua-5.1-tests/vararg.lua
> > +++ b/test/PUC-Lua-5.1-tests/vararg.lua
> > @@ -21,9 +21,14 @@ 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)
> > +-- Lua 5.1 interprets ... in the vararg functions like additional
> > +-- first argument unlike LuaJIT does. All extra arguments is set
> > +-- into `arg` variable. This extension is from Lua 5.2.
> > +-- See also https://github.com/tarantool/tarantool/issues/5712.
> > +-- Test is disabled for LuaJIT.
> > +-- 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}))
> > @@ -35,15 +40,18 @@ 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)
> > +-- Test is disabled for LuaJIT for now. See the comment above.
> > +-- 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)
> > +-- Test is disabled for LuaJIT for now. See the comment above.
> > +-- 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)
> > +-- Test is disabled for LuaJIT for now. See the comment above.
> > +-- assert(t:f(1,4) == 3 and t:f(2) == 11)
> >  print('+')
> >  
> >  lim = 20
> > -- 
> > 2.28.0
> > 
> 
> [1]: https://github.com/LuaJIT/LuaJIT/issues/673
> 
> -- 
> Best regards,
> IM

[1]: https://lists.tarantool.org/pipermail/tarantool-patches/2021-March/022979.html

-- 
Best regards,
Sergey Kaplun

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2021-03-26  8:27 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-12  5:36 [Tarantool-patches] [PATCH luajit 0/3] Adapt PUC-Rio Lua 5.1 test suite Sergey Kaplun via Tarantool-patches
2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 1/3] test: add " Sergey Kaplun via Tarantool-patches
2021-03-16 13:35   ` Sergey Ostanevich via Tarantool-patches
2021-03-17 15:17     ` Igor Munkin via Tarantool-patches
2021-03-19 11:30       ` Sergey Kaplun via Tarantool-patches
2021-03-17 14:55   ` Igor Munkin via Tarantool-patches
2021-03-19 11:26     ` Sergey Kaplun via Tarantool-patches
2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 2/3] test: adapt PUC-Rio Lua 5.1 test suite for LuaJIT Sergey Kaplun via Tarantool-patches
2021-03-13 19:04   ` Sergey Ostanevich via Tarantool-patches
2021-03-22 18:52   ` Igor Munkin via Tarantool-patches
2021-03-26  8:26     ` Sergey Kaplun via Tarantool-patches
2021-03-12  5:36 ` [Tarantool-patches] [PATCH luajit 3/3] test: adapt Lua 5.1 test suite for Tarantool Sergey Kaplun via Tarantool-patches
2021-03-13 19:07   ` Sergey Ostanevich 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