Tarantool development patches archive
 help / color / mirror / Atom feed
* [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite
@ 2021-03-12  5:27 Sergey Kaplun via Tarantool-patches
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 1/6] test: add " Sergey Kaplun via Tarantool-patches
                   ` (6 more replies)
  0 siblings, 7 replies; 19+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-12  5:27 UTC (permalink / raw)
  To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches

In this patchset lua-Harness test suite is adapted for the LuaJIT fork
and Tarantool.

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

You can check the accuracy of the first patch with the following commands:
| $ cd ~/tmp/lua-Harness && git remote -v && echo $(git log -n1) && cd -
| origin  https://framagit.org/fperrad/lua-Harness.git (fetch)
| origin  https://framagit.org/fperrad/lua-Harness.git (push)
| commit a74be274d299dc299228dc7a09052759da9ceac4 Author: Francois Perrad <francois.perrad@gadz.org> Date: Wed Mar 3 15:15:59 2021 +0100 Makefile for lua-5.4.3-rc1
|
| $ diff --color -ur ~/tmp/lua-Harness/test_lua/ test/lua-Harness-tests/

Mergen Imeev (2):
  test: add lua-Harness test suite
  test: adjust lua-Harness test suite for Tarantool

Sergey Kaplun (4):
  test: disable 305-utf8 of lua-Harness suite
  test: disable 241-standalone of lua-Harness suite
  test: disable 411-luajit of lua-Harness suite
  test: skip test for getenv in 309-os.t

 .gitignore                                    |   1 +
 .luacheckrc                                   |   1 +
 test/CMakeLists.txt                           |   4 +-
 test/lua-Harness-tests/000-sanity.t           |  54 ++
 test/lua-Harness-tests/001-if.t               |  88 ++
 test/lua-Harness-tests/002-table.t            |  67 ++
 test/lua-Harness-tests/011-while.t            |  89 ++
 test/lua-Harness-tests/012-repeat.t           |  85 ++
 test/lua-Harness-tests/014-fornum.t           | 151 +++
 test/lua-Harness-tests/015-forlist.t          | 111 +++
 test/lua-Harness-tests/090-tap.t              |  37 +
 test/lua-Harness-tests/091-profile.t          |  45 +
 test/lua-Harness-tests/101-boolean.t          | 127 +++
 test/lua-Harness-tests/102-function.t         | 206 +++++
 test/lua-Harness-tests/103-nil.t              | 127 +++
 test/lua-Harness-tests/104-number.t           | 246 +++++
 test/lua-Harness-tests/105-string.t           | 277 ++++++
 test/lua-Harness-tests/106-table.t            | 135 +++
 test/lua-Harness-tests/107-thread.t           | 135 +++
 test/lua-Harness-tests/108-userdata.t         | 132 +++
 test/lua-Harness-tests/200-examples.t         | 104 +++
 test/lua-Harness-tests/201-assign.t           | 150 +++
 test/lua-Harness-tests/202-expr.t             | 157 ++++
 test/lua-Harness-tests/203-lexico.t           | 147 +++
 test/lua-Harness-tests/204-grammar.t          | 233 +++++
 test/lua-Harness-tests/211-scope.t            |  86 ++
 test/lua-Harness-tests/212-function.t         | 288 ++++++
 test/lua-Harness-tests/213-closure.t          |  98 ++
 test/lua-Harness-tests/214-coroutine.t        | 244 +++++
 test/lua-Harness-tests/221-table.t            | 120 +++
 test/lua-Harness-tests/222-constructor.t      | 119 +++
 test/lua-Harness-tests/223-iterator.t         | 203 +++++
 test/lua-Harness-tests/231-metatable.t        | 602 ++++++++++++
 test/lua-Harness-tests/232-object.t           | 314 +++++++
 .../241-standalone.t.disabled                 | 269 ++++++
 test/lua-Harness-tests/242-luac.t             | 341 +++++++
 test/lua-Harness-tests/301-basic.t            | 859 ++++++++++++++++++
 test/lua-Harness-tests/303-package.t          | 290 ++++++
 test/lua-Harness-tests/304-string.t           | 633 +++++++++++++
 test/lua-Harness-tests/305-utf8.t.disabled    |  55 ++
 test/lua-Harness-tests/306-table.t            | 372 ++++++++
 test/lua-Harness-tests/307-math.t             | 375 ++++++++
 test/lua-Harness-tests/308-io.t               | 397 ++++++++
 test/lua-Harness-tests/309-os.t               | 275 ++++++
 test/lua-Harness-tests/310-debug.t            | 322 +++++++
 test/lua-Harness-tests/311-bit32.t            | 127 +++
 test/lua-Harness-tests/314-regex.t            | 222 +++++
 test/lua-Harness-tests/320-stdin.t            | 133 +++
 test/lua-Harness-tests/401-bitop.t            | 106 +++
 test/lua-Harness-tests/402-ffi.t              | 142 +++
 test/lua-Harness-tests/403-jit.t              | 163 ++++
 test/lua-Harness-tests/404-ext.t              | 171 ++++
 test/lua-Harness-tests/411-luajit.t.disabled  | 211 +++++
 test/lua-Harness-tests/CMakeLists.txt         |  62 ++
 test/lua-Harness-tests/lexico52/lexico.t      |  45 +
 test/lua-Harness-tests/lexico53/boolean.t     |  43 +
 test/lua-Harness-tests/lexico53/function.t    |  66 ++
 test/lua-Harness-tests/lexico53/lexico.t      |  30 +
 test/lua-Harness-tests/lexico53/nil.t         |  43 +
 test/lua-Harness-tests/lexico53/number.t      | 181 ++++
 test/lua-Harness-tests/lexico53/string.t      | 169 ++++
 test/lua-Harness-tests/lexico53/table.t       |  43 +
 test/lua-Harness-tests/lexico53/thread.t      |  45 +
 test/lua-Harness-tests/lexico53/userdata.t    |  45 +
 test/lua-Harness-tests/lexico53/utf8.t        | 179 ++++
 test/lua-Harness-tests/lexico54/lexico.t      |  19 +
 test/lua-Harness-tests/lexico54/metatable.t   |  38 +
 test/lua-Harness-tests/lexico54/utf8.t        |  54 ++
 test/lua-Harness-tests/lexicojit/basic.t      |  27 +
 test/lua-Harness-tests/lexicojit/ext.t        |  52 ++
 test/lua-Harness-tests/lexicojit/lexico.t     |  32 +
 test/lua-Harness-tests/profile.lua            |  53 ++
 test/lua-Harness-tests/profile_lua51.lua      |  46 +
 .../profile_lua51_strict.lua                  |  46 +
 test/lua-Harness-tests/profile_lua52.lua      |  46 +
 .../profile_lua52_strict.lua                  |  46 +
 test/lua-Harness-tests/profile_lua53.lua      |  52 ++
 .../profile_lua53_noconv.lua                  |  55 ++
 .../profile_lua53_strict.lua                  |  52 ++
 test/lua-Harness-tests/profile_lua54.lua      |  52 ++
 .../profile_lua54_noconv.lua                  |  55 ++
 .../profile_lua54_strict.lua                  |  53 ++
 test/lua-Harness-tests/profile_luajit20.lua   |  53 ++
 .../profile_luajit20_compat52.lua             |  53 ++
 test/lua-Harness-tests/profile_luajit21.lua   |  53 ++
 .../profile_luajit21_compat52.lua             |  53 ++
 test/lua-Harness-tests/profile_openresty.lua  |  53 ++
 test/lua-Harness-tests/profile_ravi.lua       |  58 ++
 test/lua-Harness-tests/profile_tiny_fork.lua  |  60 ++
 test/lua-Harness-tests/rx_captures            |  13 +
 test/lua-Harness-tests/rx_charclass           |  38 +
 test/lua-Harness-tests/rx_metachars           | 117 +++
 test/lua-Harness-tests/tap_harness.lua        | 212 +++++
 93 files changed, 12937 insertions(+), 1 deletion(-)
 create mode 100755 test/lua-Harness-tests/000-sanity.t
 create mode 100755 test/lua-Harness-tests/001-if.t
 create mode 100755 test/lua-Harness-tests/002-table.t
 create mode 100755 test/lua-Harness-tests/011-while.t
 create mode 100755 test/lua-Harness-tests/012-repeat.t
 create mode 100755 test/lua-Harness-tests/014-fornum.t
 create mode 100755 test/lua-Harness-tests/015-forlist.t
 create mode 100755 test/lua-Harness-tests/090-tap.t
 create mode 100755 test/lua-Harness-tests/091-profile.t
 create mode 100755 test/lua-Harness-tests/101-boolean.t
 create mode 100755 test/lua-Harness-tests/102-function.t
 create mode 100755 test/lua-Harness-tests/103-nil.t
 create mode 100755 test/lua-Harness-tests/104-number.t
 create mode 100755 test/lua-Harness-tests/105-string.t
 create mode 100755 test/lua-Harness-tests/106-table.t
 create mode 100755 test/lua-Harness-tests/107-thread.t
 create mode 100755 test/lua-Harness-tests/108-userdata.t
 create mode 100755 test/lua-Harness-tests/200-examples.t
 create mode 100755 test/lua-Harness-tests/201-assign.t
 create mode 100755 test/lua-Harness-tests/202-expr.t
 create mode 100755 test/lua-Harness-tests/203-lexico.t
 create mode 100755 test/lua-Harness-tests/204-grammar.t
 create mode 100755 test/lua-Harness-tests/211-scope.t
 create mode 100755 test/lua-Harness-tests/212-function.t
 create mode 100755 test/lua-Harness-tests/213-closure.t
 create mode 100755 test/lua-Harness-tests/214-coroutine.t
 create mode 100755 test/lua-Harness-tests/221-table.t
 create mode 100755 test/lua-Harness-tests/222-constructor.t
 create mode 100755 test/lua-Harness-tests/223-iterator.t
 create mode 100755 test/lua-Harness-tests/231-metatable.t
 create mode 100755 test/lua-Harness-tests/232-object.t
 create mode 100755 test/lua-Harness-tests/241-standalone.t.disabled
 create mode 100755 test/lua-Harness-tests/242-luac.t
 create mode 100755 test/lua-Harness-tests/301-basic.t
 create mode 100755 test/lua-Harness-tests/303-package.t
 create mode 100755 test/lua-Harness-tests/304-string.t
 create mode 100755 test/lua-Harness-tests/305-utf8.t.disabled
 create mode 100755 test/lua-Harness-tests/306-table.t
 create mode 100755 test/lua-Harness-tests/307-math.t
 create mode 100755 test/lua-Harness-tests/308-io.t
 create mode 100755 test/lua-Harness-tests/309-os.t
 create mode 100755 test/lua-Harness-tests/310-debug.t
 create mode 100755 test/lua-Harness-tests/311-bit32.t
 create mode 100755 test/lua-Harness-tests/314-regex.t
 create mode 100755 test/lua-Harness-tests/320-stdin.t
 create mode 100755 test/lua-Harness-tests/401-bitop.t
 create mode 100755 test/lua-Harness-tests/402-ffi.t
 create mode 100755 test/lua-Harness-tests/403-jit.t
 create mode 100755 test/lua-Harness-tests/404-ext.t
 create mode 100755 test/lua-Harness-tests/411-luajit.t.disabled
 create mode 100644 test/lua-Harness-tests/CMakeLists.txt
 create mode 100644 test/lua-Harness-tests/lexico52/lexico.t
 create mode 100644 test/lua-Harness-tests/lexico53/boolean.t
 create mode 100644 test/lua-Harness-tests/lexico53/function.t
 create mode 100644 test/lua-Harness-tests/lexico53/lexico.t
 create mode 100644 test/lua-Harness-tests/lexico53/nil.t
 create mode 100644 test/lua-Harness-tests/lexico53/number.t
 create mode 100644 test/lua-Harness-tests/lexico53/string.t
 create mode 100644 test/lua-Harness-tests/lexico53/table.t
 create mode 100644 test/lua-Harness-tests/lexico53/thread.t
 create mode 100644 test/lua-Harness-tests/lexico53/userdata.t
 create mode 100644 test/lua-Harness-tests/lexico53/utf8.t
 create mode 100644 test/lua-Harness-tests/lexico54/lexico.t
 create mode 100644 test/lua-Harness-tests/lexico54/metatable.t
 create mode 100644 test/lua-Harness-tests/lexico54/utf8.t
 create mode 100644 test/lua-Harness-tests/lexicojit/basic.t
 create mode 100644 test/lua-Harness-tests/lexicojit/ext.t
 create mode 100644 test/lua-Harness-tests/lexicojit/lexico.t
 create mode 100644 test/lua-Harness-tests/profile.lua
 create mode 100644 test/lua-Harness-tests/profile_lua51.lua
 create mode 100644 test/lua-Harness-tests/profile_lua51_strict.lua
 create mode 100644 test/lua-Harness-tests/profile_lua52.lua
 create mode 100644 test/lua-Harness-tests/profile_lua52_strict.lua
 create mode 100644 test/lua-Harness-tests/profile_lua53.lua
 create mode 100644 test/lua-Harness-tests/profile_lua53_noconv.lua
 create mode 100644 test/lua-Harness-tests/profile_lua53_strict.lua
 create mode 100644 test/lua-Harness-tests/profile_lua54.lua
 create mode 100644 test/lua-Harness-tests/profile_lua54_noconv.lua
 create mode 100644 test/lua-Harness-tests/profile_lua54_strict.lua
 create mode 100644 test/lua-Harness-tests/profile_luajit20.lua
 create mode 100644 test/lua-Harness-tests/profile_luajit20_compat52.lua
 create mode 100644 test/lua-Harness-tests/profile_luajit21.lua
 create mode 100644 test/lua-Harness-tests/profile_luajit21_compat52.lua
 create mode 100644 test/lua-Harness-tests/profile_openresty.lua
 create mode 100644 test/lua-Harness-tests/profile_ravi.lua
 create mode 100644 test/lua-Harness-tests/profile_tiny_fork.lua
 create mode 100644 test/lua-Harness-tests/rx_captures
 create mode 100644 test/lua-Harness-tests/rx_charclass
 create mode 100644 test/lua-Harness-tests/rx_metachars
 create mode 100644 test/lua-Harness-tests/tap_harness.lua

-- 
2.28.0


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

* [Tarantool-patches] [PATCH luajit 1/6] test: add lua-Harness test suite
  2021-03-12  5:27 [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite Sergey Kaplun via Tarantool-patches
@ 2021-03-12  5:27 ` Sergey Kaplun via Tarantool-patches
  2021-03-15 13:05   ` Igor Munkin via Tarantool-patches
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 2/6] test: adjust lua-Harness test suite for Tarantool Sergey Kaplun via Tarantool-patches
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-12  5:27 UTC (permalink / raw)
  To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches

This patch adds lua-Harness test suite:
https://fperrad.frama.io/lua-Harness/

For lua binary name detection the new function `get_lua_binary_name()`
is introduced. It is necessary because LUAJIT_TEST_COMMAND
always extends an amount of line argument by two and a new universal
way to detect program name is required.

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

Part of tarantool/tarantool#5844
Part of tarantool/tarantool#4473
---
Author: Mergen Imeev <imeevma@gmail.com>

 .luacheckrc                                   |   1 +
 test/CMakeLists.txt                           |   4 +-
 test/lua-Harness-tests/000-sanity.t           |  54 ++
 test/lua-Harness-tests/001-if.t               |  88 ++
 test/lua-Harness-tests/002-table.t            |  67 ++
 test/lua-Harness-tests/011-while.t            |  89 ++
 test/lua-Harness-tests/012-repeat.t           |  85 ++
 test/lua-Harness-tests/014-fornum.t           | 151 +++
 test/lua-Harness-tests/015-forlist.t          | 111 +++
 test/lua-Harness-tests/090-tap.t              |  37 +
 test/lua-Harness-tests/091-profile.t          |  45 +
 test/lua-Harness-tests/101-boolean.t          | 127 +++
 test/lua-Harness-tests/102-function.t         | 206 +++++
 test/lua-Harness-tests/103-nil.t              | 127 +++
 test/lua-Harness-tests/104-number.t           | 246 +++++
 test/lua-Harness-tests/105-string.t           | 277 ++++++
 test/lua-Harness-tests/106-table.t            | 135 +++
 test/lua-Harness-tests/107-thread.t           | 135 +++
 test/lua-Harness-tests/108-userdata.t         | 132 +++
 test/lua-Harness-tests/200-examples.t         | 104 +++
 test/lua-Harness-tests/201-assign.t           | 150 +++
 test/lua-Harness-tests/202-expr.t             | 157 ++++
 test/lua-Harness-tests/203-lexico.t           | 143 +++
 test/lua-Harness-tests/204-grammar.t          | 233 +++++
 test/lua-Harness-tests/211-scope.t            |  86 ++
 test/lua-Harness-tests/212-function.t         | 288 ++++++
 test/lua-Harness-tests/213-closure.t          |  98 ++
 test/lua-Harness-tests/214-coroutine.t        | 244 +++++
 test/lua-Harness-tests/221-table.t            | 120 +++
 test/lua-Harness-tests/222-constructor.t      | 119 +++
 test/lua-Harness-tests/223-iterator.t         | 203 +++++
 test/lua-Harness-tests/231-metatable.t        | 602 ++++++++++++
 test/lua-Harness-tests/232-object.t           | 314 +++++++
 test/lua-Harness-tests/241-standalone.t       | 269 ++++++
 test/lua-Harness-tests/242-luac.t             | 341 +++++++
 test/lua-Harness-tests/301-basic.t            | 856 ++++++++++++++++++
 test/lua-Harness-tests/303-package.t          | 290 ++++++
 test/lua-Harness-tests/304-string.t           | 633 +++++++++++++
 test/lua-Harness-tests/305-utf8.t             |  55 ++
 test/lua-Harness-tests/306-table.t            | 372 ++++++++
 test/lua-Harness-tests/307-math.t             | 375 ++++++++
 test/lua-Harness-tests/308-io.t               | 397 ++++++++
 test/lua-Harness-tests/309-os.t               | 271 ++++++
 test/lua-Harness-tests/310-debug.t            | 322 +++++++
 test/lua-Harness-tests/311-bit32.t            | 127 +++
 test/lua-Harness-tests/314-regex.t            | 222 +++++
 test/lua-Harness-tests/320-stdin.t            | 133 +++
 test/lua-Harness-tests/401-bitop.t            | 106 +++
 test/lua-Harness-tests/402-ffi.t              | 142 +++
 test/lua-Harness-tests/403-jit.t              | 163 ++++
 test/lua-Harness-tests/404-ext.t              | 171 ++++
 test/lua-Harness-tests/411-luajit.t           | 211 +++++
 test/lua-Harness-tests/CMakeLists.txt         |  49 +
 test/lua-Harness-tests/lexico52/lexico.t      |  45 +
 test/lua-Harness-tests/lexico53/boolean.t     |  43 +
 test/lua-Harness-tests/lexico53/function.t    |  66 ++
 test/lua-Harness-tests/lexico53/lexico.t      |  30 +
 test/lua-Harness-tests/lexico53/nil.t         |  43 +
 test/lua-Harness-tests/lexico53/number.t      | 181 ++++
 test/lua-Harness-tests/lexico53/string.t      | 169 ++++
 test/lua-Harness-tests/lexico53/table.t       |  43 +
 test/lua-Harness-tests/lexico53/thread.t      |  45 +
 test/lua-Harness-tests/lexico53/userdata.t    |  45 +
 test/lua-Harness-tests/lexico53/utf8.t        | 179 ++++
 test/lua-Harness-tests/lexico54/lexico.t      |  19 +
 test/lua-Harness-tests/lexico54/metatable.t   |  38 +
 test/lua-Harness-tests/lexico54/utf8.t        |  54 ++
 test/lua-Harness-tests/lexicojit/basic.t      |  27 +
 test/lua-Harness-tests/lexicojit/ext.t        |  52 ++
 test/lua-Harness-tests/lexicojit/lexico.t     |  32 +
 test/lua-Harness-tests/profile.lua            |  53 ++
 test/lua-Harness-tests/profile_lua51.lua      |  46 +
 .../profile_lua51_strict.lua                  |  46 +
 test/lua-Harness-tests/profile_lua52.lua      |  46 +
 .../profile_lua52_strict.lua                  |  46 +
 test/lua-Harness-tests/profile_lua53.lua      |  52 ++
 .../profile_lua53_noconv.lua                  |  55 ++
 .../profile_lua53_strict.lua                  |  52 ++
 test/lua-Harness-tests/profile_lua54.lua      |  52 ++
 .../profile_lua54_noconv.lua                  |  55 ++
 .../profile_lua54_strict.lua                  |  53 ++
 test/lua-Harness-tests/profile_luajit20.lua   |  53 ++
 .../profile_luajit20_compat52.lua             |  53 ++
 test/lua-Harness-tests/profile_luajit21.lua   |  53 ++
 .../profile_luajit21_compat52.lua             |  53 ++
 test/lua-Harness-tests/profile_openresty.lua  |  53 ++
 test/lua-Harness-tests/profile_ravi.lua       |  58 ++
 test/lua-Harness-tests/profile_tiny_fork.lua  |  60 ++
 test/lua-Harness-tests/rx_captures            |  13 +
 test/lua-Harness-tests/rx_charclass           |  38 +
 test/lua-Harness-tests/rx_metachars           | 117 +++
 test/lua-Harness-tests/tap.lua                | 212 +++++
 92 files changed, 12912 insertions(+), 1 deletion(-)
 create mode 100755 test/lua-Harness-tests/000-sanity.t
 create mode 100755 test/lua-Harness-tests/001-if.t
 create mode 100755 test/lua-Harness-tests/002-table.t
 create mode 100755 test/lua-Harness-tests/011-while.t
 create mode 100755 test/lua-Harness-tests/012-repeat.t
 create mode 100755 test/lua-Harness-tests/014-fornum.t
 create mode 100755 test/lua-Harness-tests/015-forlist.t
 create mode 100755 test/lua-Harness-tests/090-tap.t
 create mode 100755 test/lua-Harness-tests/091-profile.t
 create mode 100755 test/lua-Harness-tests/101-boolean.t
 create mode 100755 test/lua-Harness-tests/102-function.t
 create mode 100755 test/lua-Harness-tests/103-nil.t
 create mode 100755 test/lua-Harness-tests/104-number.t
 create mode 100755 test/lua-Harness-tests/105-string.t
 create mode 100755 test/lua-Harness-tests/106-table.t
 create mode 100755 test/lua-Harness-tests/107-thread.t
 create mode 100755 test/lua-Harness-tests/108-userdata.t
 create mode 100755 test/lua-Harness-tests/200-examples.t
 create mode 100755 test/lua-Harness-tests/201-assign.t
 create mode 100755 test/lua-Harness-tests/202-expr.t
 create mode 100755 test/lua-Harness-tests/203-lexico.t
 create mode 100755 test/lua-Harness-tests/204-grammar.t
 create mode 100755 test/lua-Harness-tests/211-scope.t
 create mode 100755 test/lua-Harness-tests/212-function.t
 create mode 100755 test/lua-Harness-tests/213-closure.t
 create mode 100755 test/lua-Harness-tests/214-coroutine.t
 create mode 100755 test/lua-Harness-tests/221-table.t
 create mode 100755 test/lua-Harness-tests/222-constructor.t
 create mode 100755 test/lua-Harness-tests/223-iterator.t
 create mode 100755 test/lua-Harness-tests/231-metatable.t
 create mode 100755 test/lua-Harness-tests/232-object.t
 create mode 100755 test/lua-Harness-tests/241-standalone.t
 create mode 100755 test/lua-Harness-tests/242-luac.t
 create mode 100755 test/lua-Harness-tests/301-basic.t
 create mode 100755 test/lua-Harness-tests/303-package.t
 create mode 100755 test/lua-Harness-tests/304-string.t
 create mode 100755 test/lua-Harness-tests/305-utf8.t
 create mode 100755 test/lua-Harness-tests/306-table.t
 create mode 100755 test/lua-Harness-tests/307-math.t
 create mode 100755 test/lua-Harness-tests/308-io.t
 create mode 100755 test/lua-Harness-tests/309-os.t
 create mode 100755 test/lua-Harness-tests/310-debug.t
 create mode 100755 test/lua-Harness-tests/311-bit32.t
 create mode 100755 test/lua-Harness-tests/314-regex.t
 create mode 100755 test/lua-Harness-tests/320-stdin.t
 create mode 100755 test/lua-Harness-tests/401-bitop.t
 create mode 100755 test/lua-Harness-tests/402-ffi.t
 create mode 100755 test/lua-Harness-tests/403-jit.t
 create mode 100755 test/lua-Harness-tests/404-ext.t
 create mode 100755 test/lua-Harness-tests/411-luajit.t
 create mode 100644 test/lua-Harness-tests/CMakeLists.txt
 create mode 100644 test/lua-Harness-tests/lexico52/lexico.t
 create mode 100644 test/lua-Harness-tests/lexico53/boolean.t
 create mode 100644 test/lua-Harness-tests/lexico53/function.t
 create mode 100644 test/lua-Harness-tests/lexico53/lexico.t
 create mode 100644 test/lua-Harness-tests/lexico53/nil.t
 create mode 100644 test/lua-Harness-tests/lexico53/number.t
 create mode 100644 test/lua-Harness-tests/lexico53/string.t
 create mode 100644 test/lua-Harness-tests/lexico53/table.t
 create mode 100644 test/lua-Harness-tests/lexico53/thread.t
 create mode 100644 test/lua-Harness-tests/lexico53/userdata.t
 create mode 100644 test/lua-Harness-tests/lexico53/utf8.t
 create mode 100644 test/lua-Harness-tests/lexico54/lexico.t
 create mode 100644 test/lua-Harness-tests/lexico54/metatable.t
 create mode 100644 test/lua-Harness-tests/lexico54/utf8.t
 create mode 100644 test/lua-Harness-tests/lexicojit/basic.t
 create mode 100644 test/lua-Harness-tests/lexicojit/ext.t
 create mode 100644 test/lua-Harness-tests/lexicojit/lexico.t
 create mode 100644 test/lua-Harness-tests/profile.lua
 create mode 100644 test/lua-Harness-tests/profile_lua51.lua
 create mode 100644 test/lua-Harness-tests/profile_lua51_strict.lua
 create mode 100644 test/lua-Harness-tests/profile_lua52.lua
 create mode 100644 test/lua-Harness-tests/profile_lua52_strict.lua
 create mode 100644 test/lua-Harness-tests/profile_lua53.lua
 create mode 100644 test/lua-Harness-tests/profile_lua53_noconv.lua
 create mode 100644 test/lua-Harness-tests/profile_lua53_strict.lua
 create mode 100644 test/lua-Harness-tests/profile_lua54.lua
 create mode 100644 test/lua-Harness-tests/profile_lua54_noconv.lua
 create mode 100644 test/lua-Harness-tests/profile_lua54_strict.lua
 create mode 100644 test/lua-Harness-tests/profile_luajit20.lua
 create mode 100644 test/lua-Harness-tests/profile_luajit20_compat52.lua
 create mode 100644 test/lua-Harness-tests/profile_luajit21.lua
 create mode 100644 test/lua-Harness-tests/profile_luajit21_compat52.lua
 create mode 100644 test/lua-Harness-tests/profile_openresty.lua
 create mode 100644 test/lua-Harness-tests/profile_ravi.lua
 create mode 100644 test/lua-Harness-tests/profile_tiny_fork.lua
 create mode 100644 test/lua-Harness-tests/rx_captures
 create mode 100644 test/lua-Harness-tests/rx_charclass
 create mode 100644 test/lua-Harness-tests/rx_metachars
 create mode 100644 test/lua-Harness-tests/tap.lua

diff --git a/.luacheckrc b/.luacheckrc
index 1a76108..a5f90b9 100644
--- a/.luacheckrc
+++ b/.luacheckrc
@@ -8,5 +8,6 @@ read_globals = { 'misc' }
 exclude_files = {
   'dynasm/',
   'src/',
+  'test/lua-Harness-tests/',
   'test/LuaJIT-tests/',
 }
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 99471db..3a42f41 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -43,10 +43,12 @@ endif()
 set(LUAJIT_TEST_COMMAND "${LUAJIT_TEST_BINARY} -e dofile[[${LUAJIT_TEST_INIT}]]")
 separate_arguments(LUAJIT_TEST_COMMAND)
 
-add_subdirectory(tarantool-tests)
+add_subdirectory(lua-Harness-tests)
 add_subdirectory(LuaJIT-tests)
+add_subdirectory(tarantool-tests)
 
 add_custom_target(${PROJECT_NAME}-test DEPENDS
+  lua-Harness-tests
   LuaJIT-tests
   tarantool-tests
 )
diff --git a/test/lua-Harness-tests/000-sanity.t b/test/lua-Harness-tests/000-sanity.t
new file mode 100755
index 0000000..e039153
--- /dev/null
+++ b/test/lua-Harness-tests/000-sanity.t
@@ -0,0 +1,54 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua test suite
+
+=head2 Synopsis
+
+    % prove 000-sanity.t
+
+=head2 Description
+
+=cut
+
+]]
+
+function f (n)
+    return n + 1
+end
+
+function g (m, p)
+    return m + p
+end
+
+print('1..9')
+print("ok 1 -")
+print('ok', 2, "- list")
+print("ok " .. tostring(3) .. " - concatenation")
+i = 4
+print("ok " .. tostring(i) .. " - var")
+i = i + 1
+print("ok " .. tostring(i) .. " - var incr")
+print("ok " .. tostring(i+1) .. " - expr")
+j = f(i + 1)
+print("ok " .. tostring(j) .. " - call f")
+k = g(i, 3)
+print("ok " .. tostring(k) .. " - call g")
+local print = print
+print("ok 9 - local")
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/001-if.t b/test/lua-Harness-tests/001-if.t
new file mode 100755
index 0000000..b84e331
--- /dev/null
+++ b/test/lua-Harness-tests/001-if.t
@@ -0,0 +1,88 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua if statement
+
+=head2 Synopsis
+
+    % prove 001-if.t
+
+=head2 Description
+
+See section "Control Structures" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.4.4>,
+L<https://www.lua.org/manual/5.2/manual.html#3.3.4>,
+L<https://www.lua.org/manual/5.3/manual.html#3.3.4>,
+L<https://www.lua.org/manual/5.4/manual.html#3.3.4>
+
+=cut
+
+]]
+
+print("1..6")
+
+if true then
+    print("ok 1")
+else
+    print("not ok 1")
+end
+
+if not true then
+    print("not ok 2")
+else
+    print("ok 2")
+end
+
+a = 12
+b = 34
+if a < b then
+    print("ok 3")
+else
+    print("not ok 3")
+end
+
+a = 0
+b = 4
+if a < b then
+    print("ok 4")
+elseif a == b then
+    print("not ok 4")
+else
+    print("not ok 4")
+end
+
+a = 5
+b = 5
+if a < b then
+    print("not ok 5")
+elseif a == b then
+    print("ok 5")
+else
+    print("not ok 5")
+end
+
+a = 10
+b = 6
+if a < b then
+    print("not ok 6")
+elseif a == b then
+    print("not ok 6")
+else
+    print("ok 6")
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/002-table.t b/test/lua-Harness-tests/002-table.t
new file mode 100755
index 0000000..b84afd6
--- /dev/null
+++ b/test/lua-Harness-tests/002-table.t
@@ -0,0 +1,67 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua table
+
+=head2 Synopsis
+
+    % prove 002-table.t
+
+=head2 Description
+
+See section "Tables" in "Programming in Lua".
+
+=cut
+
+]]
+
+print("1..8")
+
+a = {"ok 1", "ok 2", "ok 3"}
+print(a[1])
+i = 2
+print(a[i])
+print(a[i+1])
+if #a == 3 then
+    print("ok 4 - len")
+else
+    print("not ok 4")
+end
+if a[7] == nil then
+    print("ok 5")
+else
+    print("not ok 5")
+end
+
+t = {a=10, b=100}
+if t['a'] == 10 then
+    print("ok 6")
+else
+    print("not ok 6")
+end
+if t.b == 100 then
+    print("ok 7")
+else
+    print("not ok 7")
+end
+if t.z == nil then
+    print("ok 8")
+else
+    print("not ok 8")
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/011-while.t b/test/lua-Harness-tests/011-while.t
new file mode 100755
index 0000000..8ba4c6b
--- /dev/null
+++ b/test/lua-Harness-tests/011-while.t
@@ -0,0 +1,89 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua while statement
+
+=head2 Synopsis
+
+    % prove 011-while.t
+
+=head2 Description
+
+See section "Control Structures" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.4.4>,
+L<https://www.lua.org/manual/5.2/manual.html#3.3.4>,
+L<https://www.lua.org/manual/5.3/manual.html#3.3.4>,
+L<https://www.lua.org/manual/5.4/manual.html#3.3.4>
+
+=cut
+
+]]
+
+print("1..11")
+
+do
+    local a = {}
+    local i = 1
+    while a[i] do
+        i = i + 1
+    end
+    if i == 1 then
+        print("ok 1 - while empty")
+    else
+        print("not ok 1 - " .. i)
+    end
+end
+
+do
+    local a = {"ok 2 - while ", "ok 3", "ok 4"}
+    local i = 1
+    while a[i] do
+        print(a[i])
+        i = i + 1
+    end
+end
+
+do
+    local a = {"ok 5 - with break", "ok 6", "stop", "more"}
+    local i = 1
+    while a[i] do
+        if a[i] == 'stop' then break end
+        print(a[i])
+        i = i + 1
+    end
+    if i == 3 then
+        print("ok 7 - break")
+    else
+        print("not ok 7 - " .. i)
+    end
+end
+
+do
+    local x = 3
+    local i = 1
+    while i<=x do
+        print("ok " .. tostring(7+i))
+        i = i + 1
+    end
+    if i == 4 then
+        print("ok 11")
+    else
+        print("not ok 11 - " .. tostring(i))
+    end
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/012-repeat.t b/test/lua-Harness-tests/012-repeat.t
new file mode 100755
index 0000000..527db63
--- /dev/null
+++ b/test/lua-Harness-tests/012-repeat.t
@@ -0,0 +1,85 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua repeat statement
+
+=head2 Synopsis
+
+    % prove 012-repeat.t
+
+=head2 Description
+
+See section "Control Structures" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.4.4>,
+L<https://www.lua.org/manual/5.2/manual.html#3.3.4>,
+L<https://www.lua.org/manual/5.3/manual.html#3.3.4>,
+L<https://www.lua.org/manual/5.4/manual.html#3.3.4>
+
+=cut
+
+]]
+
+print("1..8")
+
+do
+    local a = {"ok 1 - repeat", "ok 2", "ok 3"}
+    local i = 0
+    repeat
+        i = i + 1
+        if a[i] then
+            print(a[i])
+        end
+    until not a[i]
+    if i == 4 then
+        print("ok 4")
+    else
+        print("not ok 4 - " .. i)
+    end
+end
+
+do
+    local a = {"ok 5 - with break", "ok 6", 'stop', 'more'}
+    local i = 0
+    repeat
+        i = i + 1
+        if a[i] == 'stop' then break end
+        print(a[i])
+    until not a[i]
+    if a[i] == 'stop' then
+        print("ok 7 - break")
+    else
+        print("not ok 7 - " .. a[i])
+    end
+end
+
+do
+    local function f () return true end
+
+    local i = 1
+    repeat
+        local v = f()
+        if i == 1 then
+            print("ok 8 - scope")
+        else
+            print("not ok")
+            break
+        end
+        i = i + 1
+    until v
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/014-fornum.t b/test/lua-Harness-tests/014-fornum.t
new file mode 100755
index 0000000..3f6d1b1
--- /dev/null
+++ b/test/lua-Harness-tests/014-fornum.t
@@ -0,0 +1,151 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua for statement
+
+=head2 Synopsis
+
+    % prove 014-fornum.t
+
+=head2 Description
+
+See section "For Statement" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.4.5>,
+L<https://www.lua.org/manual/5.2/manual.html#3.3.5>,
+L<https://www.lua.org/manual/5.3/manual.html#3.3.5>,
+L<https://www.lua.org/manual/5.4/manual.html#3.3.5>
+
+=cut
+
+--]]
+
+print("1..36")
+
+for i = 1.0, 3.0, 0.5 do
+    print("ok " .. tostring(2*i-1) .. " - for 1.0, 3.0, 0.5")
+end
+
+for i = 1.0, 3.0, 0.5 do
+    local function f ()
+        print("ok " .. tostring(2*i+4) .. " - for 1.0, 3.0, 0.5 lex")
+    end
+    f()
+end
+
+local function f (i)
+    print("ok " .. tostring(2*i+9) .. " - for 1.0, 3.0, 0.5 !lex")
+end
+for i = 1.0, 3.0, 0.5 do
+    f(i)
+end
+
+for i = 3, 5 do
+    print("ok " .. tostring(13+i) .. " - for 3, 5")
+    i = i + 1
+end
+
+for i = 5, 1, -1 do
+    print("ok " .. tostring(24-i) .. " - for 5, 1, -1")
+end
+
+for i = 5, 5 do
+    print("ok " .. tostring(19+i) .. " - for 5, 5")
+end
+
+for i = 5, 5, -1 do
+    print("ok " .. tostring(20+i) .. " - for 5, 5, -1")
+end
+
+do
+    local v = false
+    for i = 5, 3 do
+        v = true
+    end
+    if v then
+        print("not ok 26 - for 5, 3")
+    else
+        print("ok 26 - for 5, 3")
+    end
+end
+
+do
+    local v = false
+    for i = 5, 7, -1 do
+        v = true
+    end
+    if v then
+        print("not ok 27 - for 5, 7, -1")
+    else
+        print("ok 27 - for 5, 7, -1")
+    end
+end
+
+do
+    local v = false
+    if _VERSION <= 'Lua 5.3' then
+        for i = 5, 7, 0 do
+            v = true
+            break -- avoid infinite loop with LuaJIT
+        end
+    end
+    if jit then
+        print("not ok 28 - for 5, 7, 0 # TODO # LuaJIT intentional.")
+    elseif v then
+        print("not ok 28 - for 5, 7, 0")
+    else
+        print("ok 28 - for 5, 7, 0")
+    end
+end
+
+do
+    local v = nil
+    for i = 1, 10, 2 do
+        if i > 4 then break end
+        print("ok " .. tostring((i+57)/2) .. " - for break")
+        v = i
+    end
+    if v == 3 then
+        print("ok 31 - break")
+    else
+        print("not ok 31 - " .. v)
+    end
+end
+
+do
+    local function first() return 1 end
+    local function limit() return 8 end
+    local function step()  return 2 end
+    for i = first(), limit(), step() do
+        print("ok " .. tostring((i+63)/2) .. " - with functions")
+    end
+end
+
+do
+    local a = {}
+    for i = 1, 10 do
+        a[i] = function () return i end
+    end
+    local v = a[5]()
+    if v == 5 then
+        print("ok 36 - for & upval")
+    else
+        print("not ok 36 - for & upval")
+        print("#", v)
+    end
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/015-forlist.t b/test/lua-Harness-tests/015-forlist.t
new file mode 100755
index 0000000..cd9db61
--- /dev/null
+++ b/test/lua-Harness-tests/015-forlist.t
@@ -0,0 +1,111 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua for statement
+
+=head2 Synopsis
+
+    % prove 015-forlist.t
+
+=head2 Description
+
+See section "For Statement" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.4.5>,
+L<https://www.lua.org/manual/5.2/manual.html#3.3.5>,
+L<https://www.lua.org/manual/5.3/manual.html#3.3.5>,
+L<https://www.lua.org/manual/5.4/manual.html#3.3.5>
+
+=cut
+
+--]]
+
+print("1..18")
+
+do
+    local a = {"ok 1 - for ipairs", "ok 2 - for ipairs", "ok 3 - for ipairs"}
+
+    for _, v in ipairs(a) do
+        print(v)
+    end
+
+    for i, v in ipairs(a) do
+        print("ok " .. tostring(3+i) .. " - for ipairs")
+    end
+
+    for k in pairs(a) do
+        print("ok " .. tostring(6+k) .. " - for pairs")
+    end
+end
+
+do
+    local r = false
+    local t = {a=10, b=100}
+
+    for i, v in ipairs(t) do
+        print(i, v)
+        r = true
+    end
+    if r then
+        print("not ok 10 - for ipairs (hash)")
+    else
+        print("ok 10 - for ipairs (hash)")
+    end
+
+    local i = 1
+    for k in pairs(t) do
+        if k == 'a' or k == 'b' then
+            print("ok " .. tostring(10+i) .. " - for pairs (hash)")
+        else
+            print("not ok " .. tostring(10+i) .. " - " .. k)
+        end
+        i = i + 1
+    end
+end
+
+do
+    local a = {"ok 13 - for break", "ok 14 - for break", "stop", "more"}
+    local i
+    for _, v in ipairs(a) do
+        if v == "stop" then break end
+        print(v)
+        i = _
+    end
+    if i == 2 then
+        print("ok 15 - break")
+    else
+        print("not ok 15 - " .. i)
+    end
+end
+
+do
+    local a = {"ok 16 - for & upval", "ok 17 - for & upval", "ok 18 - for & upval"}
+    local b = {}
+    for i, v in ipairs(a) do
+        b[i] = function () return v end
+    end
+    for i, v in ipairs(a) do
+        local r = b[i]()
+        if r == a[i] then
+            print(r)
+        else
+            print("not " .. a[i])
+            print("#", r)
+        end
+    end
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/090-tap.t b/test/lua-Harness-tests/090-tap.t
new file mode 100755
index 0000000..92f04d8
--- /dev/null
+++ b/test/lua-Harness-tests/090-tap.t
@@ -0,0 +1,37 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua test suite
+
+=head2 Synopsis
+
+    % prove 090-tap.t
+
+=head2 Description
+
+=cut
+
+]]
+
+require'tap'
+
+plan(3)
+ok( true, 'ok' )
+is( 42, 42, '42 == 42' )
+pass( 'pass' )
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/091-profile.t b/test/lua-Harness-tests/091-profile.t
new file mode 100755
index 0000000..db47438
--- /dev/null
+++ b/test/lua-Harness-tests/091-profile.t
@@ -0,0 +1,45 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua test suite
+
+=head2 Synopsis
+
+    % prove 091-profile.t
+
+=head2 Description
+
+=cut
+
+]]
+
+require'tap'
+
+plan'no_plan'
+
+type_ok(_VERSION, 'string', "variable _VERSION")
+like(_VERSION, '^Lua 5%.%d$')
+
+if jit then
+    type_ok(jit.version_num, 'number', "variable jit.version_num")
+end
+
+local profile = require_ok'profile'
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/101-boolean.t b/test/lua-Harness-tests/101-boolean.t
new file mode 100755
index 0000000..0033eff
--- /dev/null
+++ b/test/lua-Harness-tests/101-boolean.t
@@ -0,0 +1,127 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1  Lua boolean & coercion
+
+=head2 Synopsis
+
+    % prove 101-boolean.t
+
+=head2 Description
+
+=cut
+
+]]
+
+require'tap'
+local has_op53 = _VERSION >= 'Lua 5.3'
+
+plan'no_plan'
+
+error_like(function () return -true end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a %w+ value",
+           "-true")
+
+error_like(function () return #true end,
+           "^[^:]+:%d+: attempt to get length of a boolean value",
+           "#true")
+
+is(not false, true, "not false")
+
+error_like(function () return true + 10 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a boolean value",
+           "true + 10")
+
+error_like(function () return true - 2 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a boolean value",
+           "true - 2")
+
+error_like(function () return true * 3.14 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a boolean value",
+           "true * 3.14")
+
+error_like(function () return true / -7 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a boolean value",
+           "true / -7")
+
+error_like(function () return true % 4 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a boolean value",
+           "true % 4")
+
+error_like(function () return true ^ 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a boolean value",
+           "true ^ 3")
+
+error_like(function () return true .. 'end' end,
+           "^[^:]+:%d+: attempt to concatenate a boolean value",
+           "true .. 'end'")
+
+is(true == true, true, "true == true")
+
+is(true ~= false, true, "true ~= false")
+
+is(true == 1, false, "true == 1")
+
+is(true ~= 1, true, "true ~= 1")
+
+error_like(function () return true < false end,
+           "^[^:]+:%d+: attempt to compare two boolean values",
+           "true < false")
+
+error_like(function () return true <= false end,
+           "^[^:]+:%d+: attempt to compare two boolean values",
+           "true <= false")
+
+error_like(function () return true > false end,
+           "^[^:]+:%d+: attempt to compare two boolean values",
+           "true > false")
+
+error_like(function () return true >= false end,
+           "^[^:]+:%d+: attempt to compare two boolean values",
+           "true >= false")
+
+error_like(function () return true < 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "true < 0")
+
+error_like(function () return true <= 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "true <= 0")
+
+error_like(function () return true > 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "true > 0")
+
+error_like(function () return true >= 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "true >= 0")
+
+error_like(function () local a = true; local b = a[1]; end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+error_like(function () local a = true; a[1] = 1; end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+if has_op53 then
+    dofile'lexico53/boolean.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/102-function.t b/test/lua-Harness-tests/102-function.t
new file mode 100755
index 0000000..48ed814
--- /dev/null
+++ b/test/lua-Harness-tests/102-function.t
@@ -0,0 +1,206 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua function & coercion
+
+=head2 Synopsis
+
+    % prove 102-function.t
+
+=head2 Description
+
+=cut
+
+--]]
+
+require'tap'
+local has_op53 = _VERSION >= 'Lua 5.3'
+
+plan'no_plan'
+
+local f = function () return 1 end
+
+error_like(function () return -f end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "-f")
+
+error_like(function () f = print; return -f end,
+           "^[^:]+:%d+: attempt to perform arithmetic on")
+
+error_like(function () return #f end,
+           "^[^:]+:%d+: attempt to get length of",
+           "#f")
+
+error_like(function () f = print; return #f end,
+           "^[^:]+:%d+: attempt to get length of")
+
+is(not f, false, "not f")
+
+is(not print, false)
+
+error_like(function () return f + 10 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "f + 10")
+
+error_like(function () f = print; return f + 10 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on")
+
+error_like(function () return f - 2 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "f - 2")
+
+error_like(function () f = print; return f - 2 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on")
+
+error_like(function () return f * 3.14 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "f * 3.14")
+
+error_like(function () f = print; return f * 3.14 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on")
+
+error_like(function () return f / -7 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "f / -7")
+
+error_like(function () f = print; return f / -7 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on")
+
+error_like(function () return f % 4 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "f % 4")
+
+error_like(function () f = print; return f % 4 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on")
+
+error_like(function () return f ^ 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "f ^ 3")
+
+error_like(function () f = print; return f ^ 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on")
+
+error_like(function () return f .. 'end' end,
+           "^[^:]+:%d+: attempt to concatenate",
+           "f .. 'end'")
+
+error_like(function () f = print; return f .. 'end' end,
+           "^[^:]+:%d+: attempt to concatenate")
+
+local g = f
+is(f == g, true, "f == f")
+
+g = print
+is(g == print, true)
+
+g = function () return 2 end
+is(f ~= g, true, "f ~= g")
+local h = type
+is(f ~= h, true)
+
+is(print ~= g, true)
+is(print ~= h, true)
+
+is(f == 1, false, "f == 1")
+
+is(print == 1, false)
+
+is(f ~= 1, true, "f ~= 1")
+
+is(print ~= 1, true)
+
+error_like(function () return f < g end,
+           "^[^:]+:%d+: attempt to compare two function values",
+           "f < g")
+
+error_like(function () f = print; g = type; return f < g end,
+           "^[^:]+:%d+: attempt to compare two function values")
+
+error_like(function () return f <= g end,
+           "^[^:]+:%d+: attempt to compare two function values",
+           "f <= g")
+
+error_like(function () f = print; g = type; return f <= g end,
+           "^[^:]+:%d+: attempt to compare two function values")
+
+error_like(function () return f > g end,
+           "^[^:]+:%d+: attempt to compare two function values",
+           "f > g")
+
+error_like(function () f = print; g = type; return f > g end,
+           "^[^:]+:%d+: attempt to compare two function values")
+
+error_like(function () return f >= g end,
+           "^[^:]+:%d+: attempt to compare two function values",
+           "f >= g")
+
+error_like(function () f = print; g = type; return f >= g end,
+           "^[^:]+:%d+: attempt to compare two function values")
+
+error_like(function () return f < 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "f < 0")
+
+error_like(function () f = print; return f < 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+")
+
+error_like(function () return f <= 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "f <= 0")
+
+error_like(function () f = print; return f <= 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+")
+
+error_like(function () return f > 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "f > 0")
+
+error_like(function () f = print; return f > 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+")
+
+error_like(function () return f > 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "f >= 0")
+
+error_like(function () f = print; return f >= 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+")
+
+error_like(function () local a = f; local b = a[1]; end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+error_like(function () local a = print; local b = a[1]; end,
+           "^[^:]+:%d+: attempt to index")
+
+error_like(function () local a = f; a[1] = 1; end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+error_like(function () local a = print; a[1] = 1; end,
+           "^[^:]+:%d+: attempt to index")
+
+local t = {}
+t[print] = true
+ok(t[print])
+
+if has_op53 then
+    dofile'lexico53/function.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/103-nil.t b/test/lua-Harness-tests/103-nil.t
new file mode 100755
index 0000000..561b101
--- /dev/null
+++ b/test/lua-Harness-tests/103-nil.t
@@ -0,0 +1,127 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua nil & coercion
+
+=head2 Synopsis
+
+    % prove 103-nil.t
+
+=head2 Description
+
+=cut
+
+--]]
+
+require'tap'
+local has_op53 = _VERSION >= 'Lua 5.3'
+
+plan'no_plan'
+
+error_like(function () return -nil end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a nil value",
+           "-nil")
+
+error_like(function () return #nil end,
+           "^[^:]+:%d+: attempt to get length of a nil value",
+           "#nil")
+
+is(not nil, true, "not nil")
+
+error_like(function () return nil + 10 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a nil value",
+           "nil + 10")
+
+error_like(function () return nil - 2 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a nil value",
+           "nil - 2")
+
+error_like(function () return nil * 3.14 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a nil value",
+           "nil * 3.14")
+
+error_like(function () return nil / -7 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a nil value",
+           "nil / -7")
+
+error_like(function () return nil % 4 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a nil value",
+           "nil % 4")
+
+error_like(function () return nil ^ 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a nil value",
+           "nil ^ 3")
+
+error_like(function () return nil .. 'end' end,
+           "^[^:]+:%d+: attempt to concatenate a nil value",
+           "nil .. 'end'")
+
+is(nil == nil, true, "nil == nil")
+
+is(nil ~= nil, false, "nil ~= nil")
+
+is(nil == 1, false, "nil == 1")
+
+is(nil ~= 1, true, "nil ~= 1")
+
+error_like(function () return nil < nil end,
+           "^[^:]+:%d+: attempt to compare two nil values",
+           "nil < nil")
+
+error_like(function () return nil <= nil end,
+           "^[^:]+:%d+: attempt to compare two nil values",
+           "nil <= nil")
+
+error_like(function () return nil > nil end,
+           "^[^:]+:%d+: attempt to compare two nil values",
+           "nil > nil")
+
+error_like(function () return nil > nil end,
+           "^[^:]+:%d+: attempt to compare two nil values",
+           "nil >= nil")
+
+error_like(function () return nil < 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "nil < 0")
+
+error_like(function () return nil <= 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "nil <= 0")
+
+error_like(function () return nil > 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "nil > 0")
+
+error_like(function () return nil >= 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "nil >= 0")
+
+error_like(function () local a = nil; local b = a[1]; end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+error_like(function () local a = nil; a[1] = 1; end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+if has_op53 then
+    dofile'lexico53/nil.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/104-number.t b/test/lua-Harness-tests/104-number.t
new file mode 100755
index 0000000..0d4d3fd
--- /dev/null
+++ b/test/lua-Harness-tests/104-number.t
@@ -0,0 +1,246 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2019, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua number & coercion
+
+=head2 Synopsis
+
+    % prove 104-number.t
+
+=head2 Description
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local has_op53 = _VERSION >= 'Lua 5.3'
+
+plan'no_plan'
+
+is(-1, -(1), "-1")
+
+is(not 1, false, "not 1")
+
+is(10 + 2, 12, "10 + 2")
+
+is(2 - 10.5, -8.5, "2 - 10.5")
+
+is(2 * 3, 6, "2 * 3")
+
+is(3.14 * 1, 3.14, "3.14 * 1")
+
+is(-7 / 0.5, -14, "-7 / 0.5")
+
+type_ok(1.0 / 0.0, 'number', "1.0 / 0.0")
+
+is(-25 % 3, 2, "-25 % 3")
+
+if _VERSION >= 'Lua 5.3' then
+    error_like(function () return 1 % 0 end,
+               "^[^:]+:%d+: attempt to perform 'n%%0'",
+               "1 % 0")
+else
+    type_ok(1 % 0, 'number', "1 % 0")
+end
+
+error_like(function () return 10 + true end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a boolean value",
+           "10 + true")
+
+error_like(function () return 2 - nil end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a nil value",
+           "2 - nil")
+
+error_like(function () return 2 * {} end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a table value",
+           "2 * {}")
+
+error_like(function () return 3.14 * false end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a boolean value",
+           "3.14 * false")
+
+error_like(function () return -7 / {} end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a table value",
+           "-7 / {}")
+
+error_like(function () return 3 ^ true end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a boolean value",
+           "3 ^ true")
+
+error_like(function () return -25 % false end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a boolean value",
+           "-25 % false")
+
+error_like(function () return 10 + 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "10 + 'text'")
+
+error_like(function () return 2 - 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "2 - 'text'")
+
+error_like(function () return 2 * 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "2 * 'text'")
+
+error_like(function () return 3.14 * 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "3.14 * 'text'")
+
+error_like(function () return -7 / 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "-7 / 'text'")
+
+error_like(function () return 25 % 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "25 % 'text'")
+
+error_like(function () return 3 ^ 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "3 ^ 'text'")
+
+if profile.nocvts2n then
+    error_like(function () return 10 + '2' end,
+               "^[^:]+:%d+: attempt to",
+               "10 + '2'")
+
+    error_like(function () return 2 - '10.5' end,
+               "^[^:]+:%d+: attempt to",
+               "2 - '10.5'")
+
+    error_like(function () return 2 * '3' end,
+               "^[^:]+:%d+: attempt to",
+               "2 * '3'")
+
+    error_like(function () return 3.14 * '1' end,
+               "^[^:]+:%d+: attempt to",
+               "3.14 * '1'")
+
+    error_like(function () return -7 / '0.5' end,
+               "^[^:]+:%d+: attempt to",
+               "-7 / '0.5'")
+
+    error_like(function () return -25 % '3' end,
+               "^[^:]+:%d+: attempt to",
+               "-25 % '3'")
+
+    error_like(function () return 3 ^ '3' end,
+               "^[^:]+:%d+: attempt to",
+               "3 ^ '3'")
+else
+    is(10 + '2', 12, "10 + '2'")
+
+    is(2 - '10.5', -8.5, "2 - '10.5'")
+
+    is(2 * '3', 6, "2 * '3'")
+
+    is(3.14 * '1', 3.14, "3.14 * '1'")
+
+    is(-7 / '0.5', -14, "-7 / '0.5'")
+
+    is(-25 % '3', 2, "-25 % '3'")
+
+    is(3 ^ '3', 27, "3 ^ '3'")
+end
+
+if profile.nocvtn2s then
+    error_like(function () return 1 .. 'end' end,
+               "^[^:]+:%d+: attempt to concatenate a number value",
+               "1 .. 'end'")
+
+    error_like(function () return 1 .. 2 end,
+               "^[^:]+:%d+: attempt to concatenate a number value",
+               "1 .. 2")
+else
+    is(1 .. 'end', '1end', "1 .. 'end'")
+
+    is(1 .. 2, '12', "1 .. 2")
+end
+
+error_like(function () return 1 .. true end,
+           "^[^:]+:%d+: attempt to concatenate a %w+ value",
+           "1 .. true")
+
+is(1.0 == 1, true, "1.0 == 1")
+
+is(1 ~= 2, true, "1 ~= 2")
+
+is(1 == true, false, "1 == true")
+
+is(1 ~= nil, true, "1 ~= nil")
+
+is(1 == '1', false, "1 == '1'")
+
+is(1 ~= '1', true, "1 ~= '1'")
+
+is(1 < 0, false, "1 < 0")
+
+is(1 <= 0, false, "1 <= 0")
+
+is(1 > 0, true, "1 > 0")
+
+is(1 >= 0, true, "1 >= 0")
+
+error_like(function () return 1 < false end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "1 < false")
+
+error_like(function () return 1 <= nil end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "1 <= nil")
+
+error_like(function () return 1 > true end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "1 > true")
+
+error_like(function () return 1 >= {} end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "1 >= {}")
+
+error_like(function () return 1 < '0' end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "1 < '0'")
+
+error_like(function () return 1 <= '0' end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "1 <= '0'")
+
+error_like(function () return 1 > '0' end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "1 > '0'")
+
+error_like(function () return 1 >= '0' end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "1 >= '0'")
+
+error_like(function () local a= 3.14; local b = a[1]; end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+error_like(function () local a = 3.14; a[1] = 1; end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+if has_op53 then
+    dofile'lexico53/number.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/105-string.t b/test/lua-Harness-tests/105-string.t
new file mode 100755
index 0000000..cd8c88b
--- /dev/null
+++ b/test/lua-Harness-tests/105-string.t
@@ -0,0 +1,277 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2019, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua string & coercion
+
+=head2 Synopsis
+
+    % prove 105-string.t
+
+=head2 Description
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local has_op53 = _VERSION >= 'Lua 5.3'
+
+plan'no_plan'
+
+if profile.nocvts2n then
+    error_like(function () return - '1' end,
+               "^[^:]+:%d+: attempt to",
+               "-'1'")
+else
+    is(- '1', -1, "-'1'")
+end
+
+error_like(function () return - 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "-'text'")
+
+is(# 'text', 4, "#'text'")
+
+is(not 'text', false, "not 'text'")
+
+if profile.nocvts2n then
+    error_like(function () return '10' + 2 end,
+               "^[^:]+:%d+: attempt to",
+               "'10' + 2")
+
+    error_like(function () return '2' - 10.5 end,
+               "^[^:]+:%d+: attempt to",
+               "'2' - 10.5")
+
+    error_like(function () return '2' * 3 end,
+               "^[^:]+:%d+: attempt to",
+               "'2' * 3")
+
+    error_like(function () return '3.14' * 1 end,
+               "^[^:]+:%d+: attempt to",
+               "'3.14' * 1")
+
+    error_like(function () return '-7' / 0.5 end,
+               "^[^:]+:%d+: attempt to",
+               "'-7' / 0.5")
+
+    error_like(function () return '-25' % 3 end,
+               "^[^:]+:%d+: attempt to",
+               "'-25' % 3")
+
+    error_like(function () return '3' ^ 3 end,
+               "^[^:]+:%d+: attempt to",
+               "'3' ^ 3")
+else
+    is('10' + 2, 12, "'10' + 2")
+
+    is('2' - 10.5, -8.5, "'2' - 10.5")
+
+    is('2' * 3, 6, "'2' * 3")
+
+    is('3.14' * 1, 3.14, "'3.14' * 1")
+
+    is('-7' / 0.5, -14, "'-7' / 0.5")
+
+    is('-25' % 3, 2, "'-25' % 3")
+
+    is('3' ^ 3, 27, "'3' ^ 3")
+end
+
+error_like(function () return '10' + true end,
+           "^[^:]+:%d+: attempt to",
+           "'10' + true")
+
+error_like(function () return '2' - nil end,
+           "^[^:]+:%d+: attempt to",
+           "'2' - nil")
+
+error_like(function () return '2' * {} end,
+           "^[^:]+:%d+: attempt to",
+           "'2' * {}")
+
+error_like(function () return '3.14' * false end,
+           "^[^:]+:%d+: attempt to",
+           "'3.14' * false")
+
+error_like(function () return '-7' / {} end,
+           "^[^:]+:%d+: attempt to",
+           "'-7' / {}")
+
+error_like(function () return '-25' % false end,
+           "^[^:]+:%d+: attempt to",
+           "'-25' % false")
+
+error_like(function () return '3' ^ true end,
+           "^[^:]+:%d+: attempt to",
+           "'3' ^ true")
+
+error_like(function () return '10' + 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'10' + 'text'")
+
+error_like(function () return '2' - 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'2' - 'text'")
+
+error_like(function () return '3.14' * 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'3.14' * 'text'")
+
+error_like(function () return '-7' / 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'-7' / 'text'")
+
+error_like(function () return '-25' % 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'-25' % 'text'")
+
+error_like(function () return '3' ^ 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'3' ^ 'text'")
+
+if profile.nocvts2n then
+    error_like(function () return '10' + '2' end,
+               "^[^:]+:%d+: attempt to",
+               "'10' + '2'")
+
+    error_like(function () return '2' - '10.5' end,
+               "^[^:]+:%d+: attempt to",
+               "'2' - '10.5'")
+
+    error_like(function () return '2' * '3' end,
+               "^[^:]+:%d+: attempt to",
+               "'2' * '3'")
+
+    error_like(function () return '3.14' * '1' end,
+               "^[^:]+:%d+: attempt to",
+               "'3.14' * '1'")
+
+    error_like(function () return '-7' / '0.5' end,
+               "^[^:]+:%d+: attempt to",
+               "'-7' / '0.5'")
+
+    error_like(function () return '-25' % '3' end,
+               "^[^:]+:%d+: attempt to",
+               "'-25' % '3'")
+
+    error_like(function () return '3' ^ '3' end,
+               "^[^:]+:%d+: attempt to",
+               "'3' ^ '3'")
+else
+    is('10' + '2', 12, "'10' + '2'")
+
+    is('2' - '10.5', -8.5, "'2' - '10.5'")
+
+    is('2' * '3', 6, "'2' * '3'")
+
+    is('3.14' * '1', 3.14, "'3.14' * '1'")
+
+    is('-7' / '0.5', -14, "'-7' / '0.5'")
+
+    is('-25' % '3', 2, "'-25' % '3'")
+
+    is('3' ^ '3', 27, "'3' ^ '3'")
+end
+
+is('1' .. 'end', '1end', "'1' .. 'end'")
+
+if profile.nocvtn2s then
+    error_like(function () return '1' .. 2 end,
+               "^[^:]+:%d+: attempt to concatenate a number value",
+               "'1' .. 2")
+else
+    is('1' .. 2, '12', "'1' .. 2")
+end
+
+error_like(function () return '1' .. true end,
+           "^[^:]+:%d+: attempt to concatenate a boolean value",
+           "'1' .. true")
+
+is('foo\0bar' <= 'foo\0baz', true, "'foo\\0bar' <= 'foo\\0baz'")
+
+is('foo\0bar' ~= 'foo', true, "'foo\\0bar' ~= 'foo'")
+
+is('foo\0bar' >= 'foo', true, "'foo\\0bar' >= 'foo'")
+
+is('1.0' == '1', false, "'1.0' == '1'")
+
+is('1' ~= '2', true, "'1' ~= '2'")
+
+is('1' == true, false, "'1' == true")
+
+is('1' ~= nil, true, "'1' ~= nil")
+
+is('1' == 1, false, "'1' == 1")
+
+is('1' ~= 1, true, "'1' ~= 1")
+
+is('1' < '0', false, "'1' < '0'")
+
+is('1' <= '0', false, "'1' <= '0'")
+
+is('1' > '0', true, "'1' > '0'")
+
+is('1' >= '0', true, "'1' >= '0'")
+
+error_like(function () return '1' < false end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "'1' < false")
+
+error_like(function () return '1' <= nil end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "'1' <= nil")
+
+error_like(function () return '1' > true end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "'1' > true")
+
+error_like(function () return '1' >= {} end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "'1' >= {}")
+
+error_like(function () return '1' < 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "'1' < 0")
+
+error_like(function () return '1' <= 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "'1' <= 0")
+
+error_like(function () return '1' > 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "'1' > 0")
+
+error_like(function () return '1' > 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "'1' >== 0")
+
+local a = 'text'
+is(a[1], nil, "index")
+
+error_like(function () a = 'text'; a[1] = 1; end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+if has_op53 then
+    dofile'lexico53/string.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/106-table.t b/test/lua-Harness-tests/106-table.t
new file mode 100755
index 0000000..0c0ba49
--- /dev/null
+++ b/test/lua-Harness-tests/106-table.t
@@ -0,0 +1,135 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua table & coercion
+
+=head2 Synopsis
+
+    % prove 106-table.t
+
+=head2 Description
+
+=cut
+
+--]]
+
+require'tap'
+local has_op53 = _VERSION >= 'Lua 5.3'
+
+plan'no_plan'
+
+error_like(function () return -{} end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "-{}")
+
+is(# {}, 0, "#{}")
+is(# {4,5,6}, 3)
+
+is(not {}, false, "not {}")
+
+error_like(function () return {} + 10 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "{} + 10")
+
+error_like(function () return {} - 2 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "{} - 2")
+
+error_like(function () return {} * 3.14 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "{} * 3.14")
+
+error_like(function () return {} / 7 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "{} / 7")
+
+error_like(function () return {} % 4 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "{} % 4")
+
+error_like(function () return {} ^ 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "{} ^ 3")
+
+error_like(function () return {} .. 'end' end,
+           "^[^:]+:%d+: attempt to concatenate",
+           "{} .. 'end'")
+
+is({} == {}, false, "{} == {}")
+
+local t1 = {}
+local t2 = {}
+is(t1 == t1, true, "t1 == t1")
+is(t1 == t2, false, "t1 == t2")
+is(t1 ~= t2, true, "t1 ~= t2")
+
+is({} == 1, false, "{} == 1")
+
+is({} ~= 1, true, "{} ~= 1")
+
+error_like(function () return t1 < t2 end,
+           "^[^:]+:%d+: attempt to compare two table values",
+           "t1 < t2")
+
+error_like(function () return t1 <= t2 end,
+           "^[^:]+:%d+: attempt to compare two table values",
+           "t1 <= t2")
+
+error_like(function () return t1 > t2 end,
+           "^[^:]+:%d+: attempt to compare two table values",
+           "t1 > t2")
+
+error_like(function () return t1 >= t2 end,
+           "^[^:]+:%d+: attempt to compare two table values",
+           "t1 >= t2")
+
+error_like(function () return {} < 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "{} < 0")
+
+error_like(function () return {} <= 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "{} <= 0")
+
+error_like(function () return {} > 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "{} > 0")
+
+error_like(function () return {} >= 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "{} >= 0")
+
+local t = {}
+is( t[1], nil, "index" )
+t[1] = 42
+is( t[1], 42, "index" )
+
+error_like(function () t = {}; t[nil] = 42 end,
+           "^[^:]+:%d+: table index is nil",
+           "table index is nil")
+
+error_like(function () t = {}; t[0/0] = 42 end,
+           "^[^:]+:%d+: table index is NaN",
+           "table index is NaN")
+
+if has_op53 then
+    dofile'lexico53/table.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/107-thread.t b/test/lua-Harness-tests/107-thread.t
new file mode 100755
index 0000000..3d4af18
--- /dev/null
+++ b/test/lua-Harness-tests/107-thread.t
@@ -0,0 +1,135 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua thread & coercion
+
+=head2 Synopsis
+
+    % prove 107-thread.t
+
+=head2 Description
+
+=cut
+
+--]]
+
+require'tap'
+local has_op53 = _VERSION >= 'Lua 5.3'
+
+plan'no_plan'
+
+local co = coroutine.create(function () return 1 end)
+
+error_like(function () return -co end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "-co")
+
+error_like(function () return #co end,
+           "^[^:]+:%d+: attempt to get length of",
+           "#co")
+
+is(not co, false, "not co")
+
+error_like(function () return co + 10 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "co + 10")
+
+error_like(function () return co - 2 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "co - 2")
+
+error_like(function () return co * 3.14 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "co * 3.14")
+
+error_like(function () return co / 7 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "co / 7")
+
+error_like(function () return co % 4 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "co % 4")
+
+error_like(function () return co ^ 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "co ^ 3")
+
+error_like(function () return co .. 'end' end,
+           "^[^:]+:%d+: attempt to concatenate",
+           "co .. 'end'")
+
+is(co == co, true, "co == co")
+
+local co1 = coroutine.create(function () return 1 end)
+local co2 = coroutine.create(function () return 2 end)
+is(co1 ~= co2, true, "co1 ~= co2")
+
+is(co == 1, false, "co == 1")
+
+is(co ~= 1, true, "co ~= 1")
+
+error_like(function () return co1 < co2 end,
+           "^[^:]+:%d+: attempt to compare two thread values",
+           "co1 < co2")
+
+error_like(function () return co1 <= co2 end,
+           "^[^:]+:%d+: attempt to compare two thread values",
+           "co1 <= co2")
+
+error_like(function () return co1 > co2 end,
+           "^[^:]+:%d+: attempt to compare two thread values",
+           "co1 > co2")
+
+error_like(function () return co1 >= co2 end,
+           "^[^:]+:%d+: attempt to compare two thread values",
+           "co1 >= co2")
+
+error_like(function () return co < 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "co < 0")
+
+error_like(function () return co <= 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "co <= 0")
+
+error_like(function () return co > 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "co > 0")
+
+error_like(function () return co > 0 end,
+           "^[^:]+:%d+: attempt to compare %w+ with %w+",
+           "co >= 0")
+
+error_like(function () local a = co[1] end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+error_like(function () co[1] = 1 end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+local t = {}
+t[co] = true
+ok(t[co])
+
+if has_op53 then
+    dofile'lexico53/thread.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/108-userdata.t b/test/lua-Harness-tests/108-userdata.t
new file mode 100755
index 0000000..b1e3641
--- /dev/null
+++ b/test/lua-Harness-tests/108-userdata.t
@@ -0,0 +1,132 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua userdata & coercion
+
+=head2 Synopsis
+
+    % prove 108-userdata.t
+
+=head2 Description
+
+=cut
+
+--]]
+
+require'tap'
+local has_op53 = _VERSION >= 'Lua 5.3'
+
+plan'no_plan'
+
+local u = io.stdin
+
+error_like(function () return -u end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "-u")
+
+error_like(function () return #u end,
+           "^[^:]+:%d+: attempt to get length of",
+           "#u")
+
+is(not u, false, "not u")
+
+error_like(function () return u + 10 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "u + 10")
+
+error_like(function () return u - 2 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "u - 2")
+
+error_like(function () return u * 3.14 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "u * 3.14")
+
+error_like(function () return u / 7 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "u / 7")
+
+error_like(function () return u % 4 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "u % 4")
+
+error_like(function () return u ^ 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "u ^ 3")
+
+error_like(function () return u .. 'end' end,
+           "^[^:]+:%d+: attempt to concatenate",
+           "u .. 'end'")
+
+is(u == u, true, "u == u")
+
+local v = io.stdout
+is(u ~= v, true, "u ~= v")
+
+is(u == 1, false, "u == 1")
+
+is(u ~= 1, true, "u ~= 1")
+
+error_like(function () return u < v end,
+           "^[^:]+:%d+: attempt to compare two",
+           "u < v")
+
+error_like(function () return u <= v end,
+           "^[^:]+:%d+: attempt to compare two",
+           "u <= v")
+
+error_like(function () return u > v end,
+           "^[^:]+:%d+: attempt to compare two",
+           "u > v")
+
+error_like(function () return u >= v end,
+           "^[^:]+:%d+: attempt to compare two",
+           "u >= v")
+
+error_like(function () return u < 0 end,
+           "^[^:]+:%d+: attempt to compare",
+           "u < 0")
+
+error_like(function () return u <= 0 end,
+           "^[^:]+:%d+: attempt to compare",
+           "u <= 0")
+
+error_like(function () return u > 0 end,
+           "^[^:]+:%d+: attempt to compare",
+           "u > 0")
+
+error_like(function () return u > 0 end,
+           "^[^:]+:%d+: attempt to compare",
+           "u >= 0")
+
+is(u[1], nil, "index")
+
+error_like(function () u[1] = 1 end,
+           "^[^:]+:%d+: attempt to index",
+           "index")
+
+local t = {}
+t[u] = true
+ok(t[u])
+
+if has_op53 then
+    dofile'lexico53/userdata.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/200-examples.t b/test/lua-Harness-tests/200-examples.t
new file mode 100755
index 0000000..362aae3
--- /dev/null
+++ b/test/lua-Harness-tests/200-examples.t
@@ -0,0 +1,104 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 some Lua code examples
+
+=head2 Synopsis
+
+    % prove 200-examples.t
+
+=head2 Description
+
+First tests in order to check infrastructure.
+
+=cut
+
+--]]
+
+require'tap'
+
+plan(5)
+
+function factorial (n)
+    if n == 0 then
+        return 1
+    else
+        return n * factorial(n-1)
+    end
+end
+is(factorial(7), 5040, "factorial (recursive)")
+
+local function local_factorial (n)
+    if n == 0 then
+        return 1
+    else
+        return n * local_factorial(n-1)
+    end
+end
+is(local_factorial(7), 5040, "factorial (recursive)")
+
+local function loop_factorial (n)
+    local a = 1
+    for i = 1, n, 1 do
+        a = a*i
+    end
+    return a
+end
+is(loop_factorial(7), 5040, "factorial (loop)")
+
+local function iter_factorial (n)
+    local function iter (product, counter)
+        if counter > n then
+            return product
+        else
+            return iter(counter*product, counter+1)
+        end
+    end
+    return iter(1, 1)
+end
+is(iter_factorial(7), 5040, "factorial (iter)")
+
+--[[
+
+  Knuth's "man or boy" test.
+  See http://en.wikipedia.org/wiki/Man_or_boy_test
+
+]]
+
+local function A (k, x1, x2, x3, x4, x5)
+    local function B ()
+        k = k - 1
+        return A(k, B, x1, x2, x3, x4)
+    end
+    if k <= 0 then
+        return x4() + x5()
+    else
+        return B()
+    end
+end
+
+is(A(10,
+        function () return 1 end,
+        function () return -1 end,
+        function () return -1 end,
+        function () return 1 end,
+        function () return 0 end),
+   -67,
+   "man or boy"
+)
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/201-assign.t b/test/lua-Harness-tests/201-assign.t
new file mode 100755
index 0000000..7d023d8
--- /dev/null
+++ b/test/lua-Harness-tests/201-assign.t
@@ -0,0 +1,150 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua assignment
+
+=head2 Synopsis
+
+    % prove 201-assign.t
+
+=head2 Description
+
+See section "Assignment" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.4.3>,
+L<https://www.lua.org/manual/5.2/manual.html#3.3.3>,
+L<https://www.lua.org/manual/5.3/manual.html#3.3.3>,
+L<https://www.lua.org/manual/5.4/manual.html#3.3.3>
+
+=cut
+
+--]]
+
+require'tap'
+local has_env = _VERSION >= 'Lua 5.2'
+
+plan'no_plan'
+
+do
+    is(b, nil, "global variable")
+    b = 10
+    is(b, 10)
+    if has_env then
+        is(_ENV.b, 10, "_ENV")
+        is(_G, _ENV, "_G")
+        error_like([[ _ENV = nil; b = 20 ]],
+                   "attempt to ")
+    else
+        is(_ENV, nil, "no _ENV");
+    end
+    b = nil
+    is(b, nil)
+end
+
+do
+    local a = {}
+    local i = 3
+    i, a[i] = i+1, 20
+    -- this behavior is undefined
+    -- see http://lua-users.org/lists/lua-l/2006-06/msg00378.html
+    is(i, 4, "check eval")
+    is(a[3], 20)
+end
+
+do
+    local x = 1.
+    local y = 2.
+    x, y = y, x -- swap
+    is(x, 2, "check swap")
+    is(y, 1)
+end
+
+do
+    local a, b, c = 0, 1
+    is(a, 0, "check padding")
+    is(b, 1)
+    is(c, nil)
+    a, b = a+1, b+1, a+b
+    is(a, 1)
+    is(b, 2)
+    a, b, c = 0
+    is(a, 0)
+    is(b, nil)
+    is(c, nil)
+end
+
+do
+    local function f() return 1, 2 end
+    local a, b, c, d = f()
+    is(a, 1, "adjust with function")
+    is(b, 2)
+    is(c, nil)
+    is(d, nil)
+end
+
+do
+    local function f() print('# f') end
+    local a = 2
+    local b, c
+    a, b, c = f(), 3
+    is(a, nil, "padding with function")
+    is(b, 3)
+    is(c, nil)
+end
+
+do
+    local my_i = 1
+    is(my_i, 1, "local variable")
+    local my_i = 2
+    is(my_i, 2)
+end
+
+do
+    local i = 1
+    local j = i
+    is(i, 1, "local variable")
+    is(j, 1)
+    j = 2
+    is(i, 1)
+    is(j, 2)
+end
+
+do
+    local function f(x) return 2*x end
+    is(f(2), 4, "param & result of function")
+    local a = 2
+    a = f(a)
+    is(a, 4)
+    local b = 2
+    b = f(b)
+    is(b, 4)
+end
+
+do
+    local n1 = 1
+    local n2 = 2
+    local n3 = 3
+    local n4 = 4
+    n1,n2,n3,n4 = n4,n3,n2,n1
+    is(n1, 4, "assignment list swap values")
+    is(n2, 3)
+    is(n3, 2)
+    is(n4, 1)
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/202-expr.t b/test/lua-Harness-tests/202-expr.t
new file mode 100755
index 0000000..2576750
--- /dev/null
+++ b/test/lua-Harness-tests/202-expr.t
@@ -0,0 +1,157 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua expression
+
+=head2 Synopsis
+
+    % prove 202-expr.t
+
+=head2 Description
+
+See section "Expressions" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.5>,
+L<https://www.lua.org/manual/5.2/manual.html#3.4>,
+L<https://www.lua.org/manual/5.3/manual.html#3.4>,
+L<https://www.lua.org/manual/5.4/manual.html#3.4>
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local nocvtn2s = profile.nocvtn2s
+local nocvts2n = profile.nocvts2n
+
+plan'no_plan'
+
+local x = math.pi
+is(tostring(x - x%0.0001), tostring(3.1415), "modulo")
+
+local a = {}; a.x = 1; a.y = 0;
+local b = {}; b.x = 1; b.y = 0;
+local c = a
+is(a == c, true, "relational op (by reference)")
+is(a ~= b, true)
+
+is('0' == 0, false, "relational op")
+is(2 < 15, true)
+is('2' < '15', false)
+
+error_like(function () return 2 < '15' end,
+           "compare",
+           "relational op")
+
+error_like(function () return '2' < 15 end,
+           "compare",
+           "relational op")
+
+is(4 and 5, 5, "logical op")
+is(nil and 13, nil)
+is(false and 13, false)
+is(4 or 5, 4)
+is(false or 5, 5)
+is(false or 'text', 'text')
+
+is(10 or 20, 10, "logical op")
+is(10 or error(), 10)
+is(nil or 'a', 'a')
+is(nil and 10, nil)
+is(false and error(), false)
+is(false and nil, false)
+is(false or nil, nil)
+is(10 and 20, 20)
+
+is(not nil, true, "logical not")
+is(not false, true)
+is(not 0, false)
+is(not not nil, false)
+is(not 'text', false)
+a = {}
+is(not a, false)
+is(not (a == a), false)
+is(not (a ~= a), true)
+
+is("Hello " .. "World", "Hello World", "concatenation")
+if not nocvtn2s then
+    is(0 .. 1, '01')
+end
+a = "Hello"
+is(a .. " World", "Hello World")
+is(a, "Hello")
+
+if not nocvts2n then
+    is('10' + 1, 11, "coercion")
+    is('-5.3' * '2', -10.6)
+end
+is(tostring(10), '10')
+if not nocvtn2s then
+    is(10 .. 20, '1020')
+    is(10 .. '', '10')
+end
+
+error_like(function () return 'hello' + 1 end,
+           ((not nocvts2n and _VERSION >= 'Lua 5.4') or ravi) and "attempt to add" or "perform arithmetic",
+           "no coercion")
+
+error_like(function ()
+                local function first() return end
+                local function limit() return 2 end
+                local function step()  return 1 end
+                for i = first(), limit(), step() do
+                    print(i)
+                end
+           end,
+           "^[^:]+:%d+:.- 'for' initial value",
+           "for tonumber")
+
+error_like(function ()
+                local function first() return 1 end
+                local function limit() return end
+                local function step()  return 2 end
+                for i = first(), limit(), step() do
+                    print(i)
+                end
+           end,
+           "^[^:]+:%d+:.- 'for' limit",
+           "for tonumber")
+
+error_like(function ()
+                local function first() return 1 end
+                local function limit() return 2 end
+                local function step()  return end
+                for i = first(), limit(), step() do
+                    print(i)
+                end
+           end,
+           "^[^:]+:%d+:.- 'for' step",
+           "for tonumber")
+
+if _VERSION >= 'Lua 5.4' then
+    error_like(function ()
+                    for i = 1, 10, 0 do
+                        print(i)
+                    end
+               end,
+               "^[^:]+:%d+: 'for' step is zero",
+               "for step zero")
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/203-lexico.t b/test/lua-Harness-tests/203-lexico.t
new file mode 100755
index 0000000..c1abebf
--- /dev/null
+++ b/test/lua-Harness-tests/203-lexico.t
@@ -0,0 +1,143 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2010-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Lexicography
+
+=head2 Synopsis
+
+    % prove 203-lexico.t
+
+=head2 Description
+
+See "Lua 5.3 Reference Manual", section 3.1 "Lexical Conventions",
+L<http://www.lua.org/manual/5.3/manual.html#3.1>.
+
+See section "Lexical Conventions"
+L<https://www.lua.org/manual/5.1/manual.html#2.1>,
+L<https://www.lua.org/manual/5.2/manual.html#3.1>,
+L<https://www.lua.org/manual/5.3/manual.html#3.1>,
+L<https://www.lua.org/manual/5.4/manual.html#3.1>
+
+=cut
+
+--]]
+
+require'tap'
+local loadstring = loadstring or load
+local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
+
+plan'no_plan'
+
+is("\65", "A")
+is("\065", "A")
+
+is(string.byte("\a"), 7)
+is(string.byte("\b"), 8)
+is(string.byte("\f"), 12)
+is(string.byte("\n"), 10)
+is(string.byte("\r"), 13)
+is(string.byte("\t"), 9)
+is(string.byte("\v"), 11)
+is(string.byte("\\"), 92)
+
+is(string.len("A\0B"), 3)
+
+do
+    local f, msg = loadstring [[a = "A\300"]]
+    if _VERSION == 'Lua 5.1' then
+        like(msg, "^[^:]+:%d+: .- near")
+    else
+        like(msg, "^[^:]+:%d+: .- escape .- near")
+    end
+
+    f, msg = loadstring [[a = " unfinished string ]]
+    like(msg, "^[^:]+:%d+: unfinished string near")
+
+    f, msg = loadstring [[a = " unfinished string
+]]
+    like(msg, "^[^:]+:%d+: unfinished string near")
+
+    f, msg = loadstring [[a = " unfinished string \
+]]
+    like(msg, "^[^:]+:%d+: unfinished string near")
+
+    f, msg = loadstring [[a = " unfinished string \]]
+    like(msg, "^[^:]+:%d+: unfinished string near")
+
+    f, msg = loadstring "a = [[ unfinished long string "
+    like(msg, "^[^:]+:%d+: unfinished long string .-near")
+
+    f, msg = loadstring "a = [== invalid long string delimiter "
+    like(msg, "^[^:]+:%d+: invalid long string delimiter near")
+end
+
+do
+    local a = 'alo\n123"'
+    is('alo\n123"', a)
+    is("alo\n123\"", a)
+    is('\97lo\10\04923"', a)
+    is([[alo
+123"]], a)
+    is([==[
+alo
+123"]==], a)
+end
+
+is(3.0, 3)
+is(314.16e-2, 3.1416)
+is(0.31416E1, 3.1416)
+is(.3, 0.3)
+is(0xff, 255)
+is(0x56, 86)
+
+do
+    local f, msg = loadstring [[a = 12e34e56]]
+    like(msg, "^[^:]+:%d+: malformed number near")
+end
+
+--[===[
+--[[
+--[=[
+    nested long comments
+--]=]
+--]]
+--]===]
+
+do
+    local f, msg = loadstring "  --[[ unfinished long comment "
+    like(msg, "^[^:]+:%d+: unfinished long comment .-near")
+end
+
+if _VERSION >= 'Lua 5.2' or jit then
+    dofile'lexico52/lexico.t'
+end
+
+if _VERSION >= 'Lua 5.3' or luajit21 then
+    dofile'lexico53/lexico.t'
+end
+
+if _VERSION >= 'Lua 5.4' then
+    dofile'lexico54/lexico.t'
+end
+
+if jit and pcall(require, 'ffi') then
+    dofile'lexicojit/lexico.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/204-grammar.t b/test/lua-Harness-tests/204-grammar.t
new file mode 100755
index 0000000..d9ae3a6
--- /dev/null
+++ b/test/lua-Harness-tests/204-grammar.t
@@ -0,0 +1,233 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2010-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Grammar
+
+=head2 Synopsis
+
+    % prove 204-grammar.t
+
+=head2 Description
+
+See section "The Complete Syntax of Lua" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#8>,
+L<https://www.lua.org/manual/5.2/manual.html#9>,
+L<https://www.lua.org/manual/5.3/manual.html#9>,
+L<https://www.lua.org/manual/5.4/manual.html#9>
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local has_goto = _VERSION >= 'Lua 5.2' or jit
+local has_attr = _VERSION >= 'Lua 5.4'
+local loadstring = loadstring or load
+
+plan'no_plan'
+
+do --[[ empty statement ]]
+    local f, msg = loadstring [[; a = 1]]
+    if _VERSION == 'Lua 5.1' and not profile.luajit_compat52 then
+        like(msg, "^[^:]+:%d+: unexpected symbol near ';'", "empty statement")
+    else
+        type_ok(f, 'function', "empty statement")
+    end
+
+    f = loadstring [[a = 1; a = 2]]
+    type_ok(f, 'function')
+
+    f, msg = loadstring [[a = 1;;; a = 2]]
+    if _VERSION == 'Lua 5.1' and not profile.luajit_compat52 then
+        like(msg, "^[^:]+:%d+: unexpected symbol near ';'")
+    else
+        type_ok(f, 'function')
+    end
+end
+
+do --[[ orphan break ]]
+    local f, msg = loadstring [[
+function f()
+    print "before"
+    do
+        print "inner"
+        break
+    end
+    print "after"
+end
+]]
+    if _VERSION == 'Lua 5.1' then
+        like(msg, "^[^:]+:%d+: no loop to break", "orphan break")
+    elseif _VERSION <= 'Lua 5.3' then
+        like(msg, "^[^:]+:%d+: <break> at line 5 not inside a loop", "orphan break")
+    else
+        like(msg, "^[^:]+:%d+: break outside loop at line 5", "orphan break")
+    end
+end
+
+do --[[ break anywhere ]]
+    local f, msg = loadstring [[
+function f()
+    print "before"
+    while true do
+        print "inner"
+        break
+        print "break"
+    end
+    print "after"
+end
+]]
+    if _VERSION == 'Lua 5.1' and not profile.luajit_compat52 then
+        like(msg, "^[^:]+:%d+: 'end' expected %(to close 'while' at line 3%) near 'print'", "break anywhere")
+    else
+        type_ok(f, 'function', "break anywhere")
+    end
+
+    f, msg = loadstring [[
+function f()
+    print "before"
+    while true do
+        print "inner"
+        if cond then
+            break
+            print "break"
+        end
+    end
+    print "after"
+end
+]]
+    if _VERSION == 'Lua 5.1' and not profile.luajit_compat52 then
+        like(msg, "^[^:]+:%d+: 'end' expected %(to close 'if' at line 5%) near 'print'", "break anywhere")
+    else
+        type_ok(f, 'function', "break anywhere")
+    end
+end
+
+--[[ goto ]]
+if has_goto then
+    local f, msg = loadstring [[
+::label::
+    goto unknown
+]]
+    if jit then
+        like(msg, ":%d+: undefined label 'unknown'", "unknown goto")
+    else
+        like(msg, ":%d+: no visible label 'unknown' for <goto> at line %d+", "unknown goto")
+    end
+
+    f, msg = loadstring [[
+::label::
+    goto label
+::label::
+]]
+    if jit then
+        like(msg, ":%d+: duplicate label 'label'", "duplicate label")
+    else
+        like(msg, ":%d+: label 'label' already defined on line %d+", "duplicate label")
+    end
+
+    f, msg = loadstring [[
+::e::
+    goto f
+    local x
+::f::
+    goto e
+]]
+    if jit then
+        like(msg, ":%d+: <goto f> jumps into the scope of local 'x'", "bad goto")
+    else
+        like(msg, ":%d+: <goto f> at line %d+ jumps into the scope of local 'x'", "bad goto")
+    end
+
+    f= loadstring [[
+do
+::s1:: ;
+    goto s2
+
+::s2::
+    goto s3
+
+::s3::
+end
+]]
+    type_ok(f, 'function', "goto")
+else
+    diag("no goto")
+end
+
+do --[[ syntax error ]]
+    local f, msg = loadstring [[a = { 1, 2, 3)]]
+    like(msg, ":%d+: '}' expected near '%)'", "constructor { }")
+
+    f, msg = loadstring [[a = (1 + 2}]]
+    like(msg, ":%d+: '%)' expected near '}'", "expr ( )")
+
+    f, msg = loadstring [[a = f(1, 2}]]
+    like(msg, ":%d+: '%)' expected near '}'", "expr ( )")
+
+    f, msg = loadstring [[function f () return 1]]
+    like(msg, ":%d+: 'end' expected near '?<eof>'?", "function end")
+
+    f, msg = loadstring [[do local a = f()]]
+    like(msg, ":%d+: 'end' expected near '?<eof>'?", "do end")
+
+    f, msg = loadstring [[for i = 1, 2 do print(i)]]
+    like(msg, ":%d+: 'end' expected near '?<eof>'?", "for end")
+
+    f, msg = loadstring [[if true then f()]]
+    like(msg, ":%d+: 'end' expected near '?<eof>'?", "if end")
+
+    f, msg = loadstring [[while true do f()]]
+    like(msg, ":%d+: 'end' expected near '?<eof>'?", "while end")
+
+    f, msg = loadstring [[repeat f()]]
+    like(msg, ":%d+: 'until' expected near '?<eof>'?", "repeat until")
+
+    f, msg = loadstring [[function f (a, 2) return a * 2 end]]
+    like(msg, ":%d+: <name> or '...' expected near '2'", "function parameter list")
+
+    f, msg = loadstring [[a = o:m[1, 2)]]
+    like(msg, ":%d+: function arguments expected near '%['", "function argument list")
+
+    f, msg = loadstring [[for i do print(i) end]]
+    like(msg, ":%d+: '=' or 'in' expected near 'do'", "for init")
+
+    f, msg = loadstring [[for i = 1, 2 print(i) end]]
+    like(msg, ":%d+: 'do' expected near 'print'", "for do")
+
+    f, msg = loadstring [[if true f() end]]
+    like(msg, ":%d+: 'then' expected near 'f'", "if then")
+
+    f, msg = loadstring [[while true f() end]]
+    like(msg, ":%d+: 'do' expected near 'f", "while do")
+end
+
+if has_attr then
+    local f, msg = load [[local foo < bar > = 'bar']]
+    like(msg, "^[^:]+:%d+: unknown attribute 'bar'")
+
+    f, msg = load [[local foo <const> = 'bar'; foo = 'baz']]
+    like(msg, "^[^:]+:%d+: attempt to assign to const variable 'foo'")
+
+    f, msg = load [[local foo <close> = 'bar'; foo = 'baz']]
+    like(msg, "^[^:]+:%d+: attempt to assign to const variable 'foo'")
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/211-scope.t b/test/lua-Harness-tests/211-scope.t
new file mode 100755
index 0000000..64eed52
--- /dev/null
+++ b/test/lua-Harness-tests/211-scope.t
@@ -0,0 +1,86 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua scope
+
+=head2 Synopsis
+
+    % prove 211-scope.t
+
+=head2 Description
+
+See section "Visibility Rules" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.6>,
+L<https://www.lua.org/manual/5.2/manual.html#3.5>,
+L<https://www.lua.org/manual/5.3/manual.html#3.5>,
+L<https://www.lua.org/manual/5.4/manual.html#3.5>
+
+See section "Local Variables and Blocks" in "Programming in Lua".
+
+=cut
+
+--]]
+
+require'tap'
+
+plan(10)
+
+--[[ scope ]]
+x = 10
+do
+    local x = x
+    is(x, 10, "scope")
+    x = x + 1
+    do
+        local x = x + 1
+        is(x, 12)
+    end
+    is(x, 11)
+end
+is(x, 10)
+
+--[[ scope ]]
+x = 10
+local i = 1
+
+while i<=x do
+    local x = i*2
+--    print(x)
+    i = i + 1
+end
+
+if i > 20 then
+    local x
+    x = 20
+    nok("scope")
+else
+    is(x, 10, "scope")
+end
+
+is(x, 10)
+
+--[[ scope ]]
+local a, b = 1, 10
+if a < b then
+    is(a, 1, "scope")
+    local a
+    is(a, nil)
+end
+is(a, 1)
+is(b, 10)
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/212-function.t b/test/lua-Harness-tests/212-function.t
new file mode 100755
index 0000000..2851053
--- /dev/null
+++ b/test/lua-Harness-tests/212-function.t
@@ -0,0 +1,288 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua functions
+
+=head2 Synopsis
+
+    % prove 212-function.t
+
+=head2 Description
+
+See section "Function Definitions" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.5.9>,
+L<https://www.lua.org/manual/5.2/manual.html#3.4.10>,
+L<https://www.lua.org/manual/5.3/manual.html#3.4.11>,
+L<https://www.lua.org/manual/5.4/manual.html#3.4.11>
+
+See section "Functions" in "Programming in Lua".
+
+=cut
+
+--]]
+
+require'tap'
+local loadstring = loadstring or load
+
+plan(68)
+
+do --[[ add ]]
+    local function add (a)
+        local sum = 0
+        for i,v in ipairs(a) do
+            sum = sum + v
+        end
+        return sum
+    end
+
+    local t = { 10, 20, 30, 40 }
+    is(add(t), 100, "add")
+end
+
+do --[[ f ]]
+    local function f(a, b) return a or b end
+
+    is(f(3), 3, "f")
+    is(f(3, 4), 3)
+    is(f(3, 4, 5), 3)
+end
+
+do --[[ incCount ]]
+    local count = 0
+
+    local function incCount (n)
+        n = n or 1
+        count = count + n
+    end
+
+    is(count, 0, "inCount")
+    incCount()
+    is(count, 1)
+    incCount(2)
+    is(count, 3)
+    incCount(1)
+    is(count, 4)
+end
+
+do --[[ maximum ]]
+    local function maximum (a)
+        local mi = 1                -- maximum index
+        local m = a[mi]             -- maximum value
+        for i,val in ipairs(a) do
+            if val > m then
+                mi = i
+                m = val
+            end
+        end
+        return m, mi
+    end
+
+    local m, mi = maximum({8,10,23,12,5})
+    is(m, 23, "maximum")
+    is(mi, 3)
+end
+
+do --[[ call by value ]]
+    local function f (n)
+        n = n - 1
+        return n
+    end
+
+    local a = 12
+    is(a, 12, "call by value")
+    local b = f(a)
+    is(b, 11)
+    is(a, 12)
+    local c = f(12)
+    is(c, 11)
+    is(a, 12)
+end
+
+do --[[ call by ref ]]
+    local function f (t)
+        t[#t+1] = 'end'
+        return t
+    end
+
+    local a = { 'a', 'b', 'c' }
+    is(table.concat(a, ','), 'a,b,c', "call by ref")
+    local b = f(a)
+    is(table.concat(b, ','), 'a,b,c,end')
+    is(table.concat(a, ','), 'a,b,c,end')
+end
+
+do --[[ var args ]]
+    local function g1(a, b, ...)
+        local arg = {...}
+        is(a, 3, "vararg")
+        is(b, nil)
+        is(#arg, 0)
+        is(arg[1], nil)
+    end
+    g1(3)
+
+    local function g2(a, b, ...)
+        local arg = {...}
+        is(a, 3)
+        is(b, 4)
+        is(#arg, 0)
+        is(arg[1], nil)
+    end
+    g2(3, 4)
+
+    local function g3(a, b, ...)
+        local arg = {...}
+        is(a, 3)
+        is(b, 4)
+        is(#arg, 2)
+        is(arg[1], 5)
+        is(arg[2], 8)
+    end
+    g3(3, 4, 5, 8)
+end
+
+do --[[ var args ]]
+    local function g1(a, b, ...)
+        local c, d, e = ...
+        is(a, 3, "var args")
+        is(b, nil)
+        is(c, nil)
+        is(d, nil)
+        is(e, nil)
+    end
+    g1(3)
+
+    local function g2(a, b, ...)
+        local c, d, e = ...
+        is(a, 3)
+        is(b, 4)
+        is(c, nil)
+        is(d, nil)
+        is(e, nil)
+    end
+    g2(3, 4)
+
+    local function g3(a, b, ...)
+        local c, d, e = ...
+        is(a, 3)
+        is(b, 4)
+        is(c, 5)
+        is(d, 8)
+        is(e, nil)
+    end
+    g3(3, 4, 5, 8)
+end
+
+do --[[ var args ]]
+    local function g1(a, b, ...)
+        is(#{a, b, ...}, 1, "varargs")
+    end
+    g1(3)
+
+    local function g2(a, b, ...)
+        is(#{a, b, ...}, 2)
+    end
+    g2(3, 4)
+
+    local function g3(a, b, ...)
+        is(#{a, b, ...}, 4)
+    end
+    g3(3, 4, 5, 8)
+end
+
+do --[[ var args ]]
+    local function f() return 1, 2 end
+    local function g() return 'a', f() end
+    local function h() return f(), 'b' end
+    local function k() return 'c', (f()) end
+
+    local x, y = f()
+    is(x, 1, "var args")
+    is(y, 2)
+    local z
+    x, y, z = g()
+    is(x, 'a')
+    is(y, 1)
+    is(z, 2)
+    x, y = h()
+    is(x, 1)
+    is(y, 'b')
+    x, y, z = k()
+    is(x, 'c')
+    is(y, 1)
+    is(z, nil)
+end
+
+do --[[ invalid var args ]]
+    local f, msg = loadstring [[
+function f ()
+    print(...)
+end
+]]
+    like(msg, "^[^:]+:%d+: cannot use '...' outside a vararg function", "invalid var args")
+end
+
+do --[[ tail call ]]
+    local output = {}
+    local function foo (n)
+        output[#output+1] = n
+        if n > 0 then
+            return foo(n -1)
+        end
+        return 'end', 0
+    end
+
+    eq_array({foo(3)}, {'end', 0}, "tail call")
+    eq_array(output, {3, 2, 1, 0})
+end
+
+do --[[ no tail call ]]
+    local output = {}
+    local function foo (n)
+        output[#output+1] = n
+        if n > 0 then
+            return (foo(n -1))
+        end
+        return 'end', 0
+    end
+
+    is(foo(3), 'end', "no tail call")
+    eq_array(output, {3, 2, 1, 0})
+end
+
+do --[[ no tail call ]]
+    local output = {}
+    local function foo (n)
+        output[#output+1] = n
+        if n > 0 then
+            foo(n -1)
+        end
+    end
+
+    is(foo(3), nil, "no tail call")
+    eq_array(output, {3, 2, 1, 0})
+end
+
+do --[[ sub name ]]
+    local function f () return 1 end
+    is(f(), 1, "sub name")
+
+    function f () return 2 end
+    is(f(), 2)
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/213-closure.t b/test/lua-Harness-tests/213-closure.t
new file mode 100755
index 0000000..fc3bd29
--- /dev/null
+++ b/test/lua-Harness-tests/213-closure.t
@@ -0,0 +1,98 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua closures
+
+=head2 Synopsis
+
+    % prove 213-closure.t
+
+=head2 Description
+
+See section "Closures" in "Programming in Lua".
+
+=cut
+
+--]]
+
+require'tap'
+
+plan(15)
+
+do --[[ inc ]]
+    local counter = 0
+
+    local function inc (x)
+        counter = counter + x
+        return counter
+    end
+
+    is(inc(1), 1, "inc")
+    is(inc(2), 3)
+end
+
+do --[[ newCounter ]]
+    local function newCounter ()
+        local i = 0
+        return function ()  -- anonymous function
+                   i = i + 1
+                   return i
+               end
+    end
+
+    local c1 = newCounter()
+    is(c1(), 1, "newCounter")
+    is(c1(), 2)
+
+    local c2 = newCounter()
+    is(c2(), 1)
+    is(c1(), 3)
+    is(c2(), 2)
+end
+
+do --[[
+The loop creates ten closures (that is, ten instances of the anonymous
+function). Each of these closures uses a different y variable, while all
+of them share the same x.
+]]
+    local a = {}
+    local x = 20
+    for i=1,10 do
+        local y = 0
+        a[i] = function () y=y+1; return x+y end
+    end
+
+    is(a[1](), 21, "ten closures")
+    is(a[1](), 22)
+    is(a[2](), 21)
+end
+
+do --[[ add ]]
+    local function add(x)
+        return function (y) return (x + y) end
+    end
+
+    local f = add(2)
+    type_ok(f, 'function', "add")
+    is(f(10), 12)
+    local g = add(5)
+    is(g(1), 6)
+    is(g(10), 15)
+    is(f(1), 3)
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/214-coroutine.t b/test/lua-Harness-tests/214-coroutine.t
new file mode 100755
index 0000000..92929e1
--- /dev/null
+++ b/test/lua-Harness-tests/214-coroutine.t
@@ -0,0 +1,244 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua coroutines
+
+=head2 Synopsis
+
+    % prove 214-coroutine.t
+
+=head2 Description
+
+See section "Coroutines" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.11>,
+L<https://www.lua.org/manual/5.2/manual.html#2.6>,
+L<https://www.lua.org/manual/5.3/manual.html#2.6>,
+L<https://www.lua.org/manual/5.4/manual.html#2.6>
+
+See section "Coroutines" in "Programming in Lua".
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
+local has_coroutine52 = _VERSION >= 'Lua 5.2' or jit
+local has_running52 = _VERSION >= 'Lua 5.2' or (profile.luajit_compat52 and not ujit)
+local has_isyieldable = _VERSION >= 'Lua 5.3' or luajit21
+local has_close = _VERSION >= 'Lua 5.4'
+
+plan'no_plan'
+
+do
+    local output = {}
+
+    local function foo1 (a)
+        output[#output+1] = "foo " .. tostring(a)
+        return coroutine.yield(2*a)
+    end
+
+    local co = coroutine.create(function (a,b)
+        local r, s
+        output[#output+1] = "co-body " .. tostring(a) .." " .. tostring(b)
+        r = foo1(a+1)
+        output[#output+1] = "co-body " .. r
+        r, s = coroutine.yield(a+b, a-b)
+        output[#output+1] = "co-body " .. r .. " " .. s
+        return b, 'end'
+    end)
+
+    eq_array({coroutine.resume(co, 1, 10)}, {true, 4}, "foo1")
+    eq_array({coroutine.resume(co, 'r')}, {true, 11, -9})
+    eq_array({coroutine.resume(co, "x", "y")}, {true, 10, 'end'})
+    eq_array({coroutine.resume(co, "x", "y")}, {false, "cannot resume dead coroutine"})
+    eq_array(output, {
+        'co-body 1 10',
+        'foo 2',
+        'co-body r',
+        'co-body x y',
+    })
+end
+
+do
+    local output = ''
+    local co = coroutine.create(function ()
+        output = 'hi'
+    end)
+    like(co, '^thread: 0?[Xx]?%x+$', "basics")
+
+    is(coroutine.status(co), 'suspended')
+    coroutine.resume(co)
+    is(output, 'hi')
+    is(coroutine.status(co), 'dead')
+
+    error_like(function () coroutine.create(true) end,
+               "^[^:]+:%d+: bad argument #1 to 'create' %(.- expected")
+
+    error_like(function () coroutine.resume(true) end,
+               "^[^:]+:%d+: bad argument #1 to 'resume' %(.- expected")
+
+    error_like(function () coroutine.status(true) end,
+               "^[^:]+:%d+: bad argument #1 to 'status' %(.- expected")
+end
+
+do
+    local output = {}
+    local co = coroutine.create(function ()
+        for i=1,10 do
+            output[#output+1] = i
+            coroutine.yield()
+        end
+    end)
+
+    coroutine.resume(co)
+    if has_running52 then
+        local thr, ismain = coroutine.running()
+        type_ok(thr, 'thread', "running")
+        is(ismain, true, "running")
+    else
+        local thr = coroutine.running()
+        is(thr, nil, "main thread")
+    end
+    is(coroutine.status(co), 'suspended', "basics")
+    coroutine.resume(co)
+    coroutine.resume(co)
+    coroutine.resume(co)
+    coroutine.resume(co)
+    coroutine.resume(co)
+    coroutine.resume(co)
+    coroutine.resume(co)
+    coroutine.resume(co)
+    coroutine.resume(co)
+    coroutine.resume(co)
+    eq_array({coroutine.resume(co)}, {false, 'cannot resume dead coroutine'})
+    eq_array(output, {1,2,3,4,5,6,7,8,9,10})
+end
+
+do
+    local co = coroutine.create(function (a,b)
+        coroutine.yield(a + b, a - b)
+    end)
+
+    eq_array({coroutine.resume(co, 20, 10)}, {true, 30, 10}, "basics")
+end
+
+do
+    local co = coroutine.create(function ()
+        return 6, 7
+    end)
+
+    eq_array({coroutine.resume(co)}, {true, 6, 7}, "basics")
+end
+
+if has_coroutine52 then
+    local co = coroutine.wrap(function(...)
+        return pcall(function(...)
+            return coroutine.yield(...)
+        end, ...)
+    end)
+    eq_array({co("Hello")}, {"Hello"})
+    eq_array({co("World")}, {true, "World"})
+end
+
+if has_coroutine52 then
+    local co = coroutine.wrap(function(...)
+        local function backtrace ()
+            return 'not a back trace'
+        end
+        return xpcall(function(...)
+            return coroutine.yield(...)
+        end, backtrace, ...)
+    end)
+    eq_array({co("Hello")}, {"Hello"})
+    eq_array({co("World")}, {true, "World"})
+end
+
+if has_coroutine52 then
+    local output = {}
+    local co = coroutine.wrap(function()
+        while true do
+            local t = setmetatable({}, {
+                __eq = function(...)
+                    return coroutine.yield(...)
+                end}
+            )
+            local t2 = setmetatable({}, getmetatable(t))
+            output[#output+1] = t == t2
+        end
+    end)
+    co()
+    co(true)
+    co(false)
+    eq_array(output, {true, false})
+end
+
+if has_coroutine52 then
+    local co = coroutine.wrap(print)
+    type_ok(co, 'function')
+
+    error_like(function () coroutine.wrap(true) end,
+               "^[^:]+:%d+: bad argument #1 to 'wrap' %(function expected, got boolean%)")
+
+    co = coroutine.wrap(function () error"in coro" end)
+    error_like(function () co() end,
+               "^[^:]+:%d+: [^:]+:%d+: in coro$")
+end
+
+do
+    local co = coroutine.create(function ()
+        error "in coro"
+    end)
+    local r, msg = coroutine.resume(co)
+    is(r, false)
+    like(msg, "^[^:]+:%d+: in coro$")
+end
+
+do
+    error_like(function () coroutine.yield() end,
+               "attempt to yield")
+
+    if has_isyieldable then
+        is(coroutine.isyieldable(), false, "isyieldable")
+    else
+        is(coroutine.isyieldable, nil, "no coroutine.isyieldable")
+    end
+end
+
+-- close
+if has_close then
+    local output = ''
+    local co = coroutine.create(function ()
+        output = 'hi'
+    end)
+    is(coroutine.close(co), true, "close")
+    is(coroutine.status(co), 'dead')
+    is(coroutine.close(co), true, "close again")
+
+    error_like(function () coroutine.close(coroutine.running()) end,
+               "^[^:]+:%d+: cannot close a running coroutine")
+
+    error_like(function () coroutine.close(42) end,
+               "^[^:]+:%d+: bad argument #1 to 'close' %(thread expected, got number%)")
+else
+    is(coroutine.close, nil, "no coroutine.close")
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/221-table.t b/test/lua-Harness-tests/221-table.t
new file mode 100755
index 0000000..c064a33
--- /dev/null
+++ b/test/lua-Harness-tests/221-table.t
@@ -0,0 +1,120 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua tables
+
+=head2 Synopsis
+
+    % prove 221-table.t
+
+=head2 Description
+
+See section "Tables" in "Programming in Lua".
+
+=cut
+
+--]]
+
+require'tap'
+
+plan(25)
+
+do
+    local a = {}
+    local k = 'x'
+    a[k] = 10
+    a[20] = 'great'
+    is(a['x'], 10)
+    k = 20
+    is(a[k], 'great')
+    a['x'] = a ['x'] + 1
+    is(a['x'], 11)
+end
+
+do
+    local a = {}
+    a['x'] = 10
+    local b = a
+    is(b['x'], 10)
+    b['x'] = 20
+    is(a['x'], 20)
+    a = nil
+    b = nil
+end
+
+do
+    local a = {}
+    for i=1,1000 do a[i] = i*2 end
+    is(a[9], 18)
+    a['x'] = 10
+    is(a['x'], 10)
+    is(a['y'], nil)
+end
+
+do
+    local a = {}
+    local x = 'y'
+    a[x] = 10
+    is(a[x], 10)
+    is(a.x, nil)
+    is(a.y, 10)
+end
+
+do
+    local i = 10; local j = '10'; local k = '+10'
+    local a = {}
+    a[i] = "one value"
+    a[j] = "another value"
+    a[k] = "yet another value"
+    is(a[j], "another value")
+    is(a[k], "yet another value")
+    is(a[tonumber(j)], "one value")
+    is(a[tonumber(k)], "one value")
+end
+
+do
+    local t = { {'a','b','c'}, 10 }
+    is(t[2], 10)
+    is(t[1][3], 'c')
+    t[1][1] = 'A'
+    is(table.concat(t[1],','), 'A,b,c')
+end
+
+do
+    local tt = { {'a','b','c'}, 10 }
+    is(tt[2], 10)
+    is(tt[1][3], 'c')
+    tt[1][1] = 'A'
+    is(table.concat(tt[1],','), 'A,b,c')
+end
+
+do
+    local a = {}
+    error_like(function () a() end,
+               "^[^:]+:%d+: .- call")
+end
+
+do
+    local tt = { {'a','b','c'}, 10 }
+    is((tt)[2], 10)
+    is((tt[1])[3], 'c');
+    (tt)[1][2] = 'B'
+    (tt[1])[3] = 'C'
+    is(table.concat(tt[1],','), 'a,B,C')
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/222-constructor.t b/test/lua-Harness-tests/222-constructor.t
new file mode 100755
index 0000000..a01be2e
--- /dev/null
+++ b/test/lua-Harness-tests/222-constructor.t
@@ -0,0 +1,119 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Table Constructors
+
+=head2 Synopsis
+
+    % prove 222-constructor.t
+
+=head2 Description
+
+See section "Table Constructors" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.5.7>,
+L<https://www.lua.org/manual/5.2/manual.html#3.4.8>,
+L<https://www.lua.org/manual/5.3/manual.html#3.4.9>,
+L<https://www.lua.org/manual/5.4/manual.html#3.4.9>
+
+See section "Table Constructors" in "Programming in Lua".
+
+=cut
+
+--]]
+
+require'tap'
+
+plan(16)
+
+do --[[ list-style init ]]
+    local days = {'Sunday', 'Monday', 'Tuesday', 'Wednesday',
+                  'Thursday', 'Friday', 'Saturday'}
+    is(days[4], 'Wednesday', "list-style init")
+    is(#days, 7)
+end
+
+do
+    local large = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+                    1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+                    1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+                    1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+                    1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+                    1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+                    1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+                    1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+                    1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+                    1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }
+    is(#large, 100)
+    large = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+              1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+              1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+              1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+              1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+              1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+              1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+              1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+              1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+              1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }
+    is(#large, 200)
+end
+
+do --[[ record-style init ]]
+    local a = {x=0, y=0}
+    is(a.x, 0, "record-style init")
+    is(a.y, 0)
+end
+
+do
+    local w = {x=0, y=0, label='console'}
+    local x = {0, 1, 2}
+    w[1] = "another field"
+    x.f = w
+    is(w['x'], 0, "ctor")
+    is(w[1], "another field")
+    is(x.f[1], "another field")
+    w.x = nil
+end
+
+do --[[ mix record-style and list-style init ]]
+    local polyline = {color='blue', thickness=2, npoints=4,
+                       {x=0,   y=0},
+                       {x=-10, y=0},
+                       {x=-10, y=1},
+                       {x=0,   y=1}
+                     }
+    is(polyline[2].x, -10, "mix record-style and list-style init")
+end
+
+do
+    local opnames = {['+'] = 'add', ['-'] = 'sub',
+                     ['*'] = 'mul', ['/'] = 'div'}
+    local i = 20; local s = '-'
+    local a = {[i+0] = s, [i+1] = s..s, [i+2] = s..s..s}
+    is(opnames[s], 'sub', "ctor")
+    is(a[22], '---')
+end
+
+do
+    local function f() return 10, 20 end
+
+    eq_array({f()}, {10, 20}, "ctor")
+    eq_array({'a', f()}, {'a', 10, 20})
+    eq_array({f(), 'b'}, {10, 'b'})
+    eq_array({'c', (f())}, {'c', 10})
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/223-iterator.t b/test/lua-Harness-tests/223-iterator.t
new file mode 100755
index 0000000..777ad73
--- /dev/null
+++ b/test/lua-Harness-tests/223-iterator.t
@@ -0,0 +1,203 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua iterators
+
+=head2 Synopsis
+
+    % prove 223-iterator.t
+
+=head2 Description
+
+See section "Iterators and the Generic for" and
+section "Coroutines as Iterators" in "Programming in Lua".
+
+=cut
+
+--]]
+
+require'tap'
+
+plan(8)
+
+do --[[ list_iter ]]
+    local function list_iter (t)
+        local i = 0
+        local n = #t
+        return function ()
+                   i = i + 1
+                   if i <= n then
+                       return t[i]
+                   else
+                       return nil
+                   end
+               end
+    end
+
+    local t = {10, 20, 30}
+    local output = {}
+    for element in list_iter(t) do
+        output[#output+1] = element
+    end
+    eq_array(output, t, "list_iter")
+end
+
+do --[[ values ]]
+    local function values (t)
+        local i = 0
+        return function ()
+                   i = i + 1
+                   return t[i]
+               end
+    end
+
+    local t = {10, 20, 30}
+    local output = {}
+    for element in values(t) do
+        output[#output+1] = element
+    end
+    eq_array(output, t, "values")
+end
+
+do --[[ emul ipairs ]]
+    local function iter (a, i)
+        i = i + 1
+        local v = a[i]
+        if v then
+            return i, v
+        end
+    end
+
+    local function my_ipairs (a)
+        return iter, a, 0
+    end
+
+    local a = {'one', 'two', 'three'}
+    local output = {}
+    for i, v in my_ipairs(a) do
+        output[#output+1] = i
+        output[#output+1] = v
+    end
+    eq_array(output, {1, 'one', 2, 'two', 3, 'three'}, "emul ipairs")
+end
+
+do --[[ emul pairs ]]
+    local function my_pairs (t)
+        return next, t, nil
+    end
+
+    local a = {'one', 'two', 'three'}
+    local output = {}
+    for k, v in my_pairs(a) do
+        output[#output+1] = k
+        output[#output+1] = v
+    end
+    eq_array(output, {1, 'one', 2, 'two', 3, 'three'}, "emul ipairs")
+end
+
+do --[[ with next ]]
+    local t = {'one', 'two', 'three'}
+    local output = {}
+    for k, v in next, t do
+        output[#output+1] = k
+        output[#output+1] = v
+    end
+    eq_array(output, {1, 'one', 2, 'two', 3, 'three'}, "with next")
+end
+
+do --[[ permutations ]]
+    local function permgen (a, n)
+        n = n or #a         -- default for 'n' is size of 'a'
+        if n <= 1 then      -- nothing to change?
+            coroutine.yield(a)
+        else
+            for i=1,n do
+                -- put i-th element as the last one
+                a[n], a[i] = a[i], a[n]
+                -- generate all permutations of the other elements
+                permgen(a, n - 1)
+                -- restore i-th element
+                a[n], a[i] = a[i], a[n]
+            end
+        end
+    end
+
+    local function permutations (a)
+        local co = coroutine.create(function () permgen(a) end)
+        return function ()  -- iterator
+                   local code, res = coroutine.resume(co)
+                   return res
+               end
+    end
+
+    local output = {}
+    for p in permutations{'a', 'b', 'c'} do
+        output[#output+1] = table.concat(p, ' ')
+    end
+    eq_array(output, {'b c a','c b a','c a b','a c b','b a c','a b c'}, "permutations")
+end
+
+do --[[ permutations with wrap ]]
+    local function permgen (a, n)
+        n = n or #a         -- default for 'n' is size of 'a'
+        if n <= 1 then      -- nothing to change?
+            coroutine.yield(a)
+        else
+            for i=1,n do
+                -- put i-th element as the last one
+                a[n], a[i] = a[i], a[n]
+                -- generate all permutations of the other elements
+                permgen(a, n - 1)
+                -- restore i-th element
+                a[n], a[i] = a[i], a[n]
+            end
+        end
+    end
+
+    local function permutations (a)
+        return coroutine.wrap(function () permgen(a) end)
+    end
+
+    local output = {}
+    for p in permutations{'a', 'b', 'c'} do
+        output[#output+1] = table.concat(p, ' ')
+    end
+    eq_array(output, {'b c a','c b a','c a b','a c b','b a c','a b c'}, "permutations with wrap")
+end
+
+do --[[ fibo ]]
+    local function fibogen ()
+        local x, y = 0, 1
+        while true do
+            coroutine.yield(x)
+            x, y = y, x + y
+        end
+    end
+
+    local function fibo ()
+        return coroutine.wrap(function () fibogen() end)
+    end
+
+    local output = {}
+    for n in fibo() do
+        output[#output+1] = n
+        if n > 30 then break end
+    end
+    eq_array(output, {0, 1, 1, 2, 3, 5, 8, 13, 21, 34}, "fibo")
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/231-metatable.t b/test/lua-Harness-tests/231-metatable.t
new file mode 100755
index 0000000..a2c6499
--- /dev/null
+++ b/test/lua-Harness-tests/231-metatable.t
@@ -0,0 +1,602 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua metatables
+
+=head2 Synopsis
+
+    % prove 231-metatable.t
+
+=head2 Description
+
+See section "Metatables and Metamethods" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#2.8>,
+L<https://www.lua.org/manual/5.2/manual.html#2.4>,
+L<https://www.lua.org/manual/5.3/manual.html#2.4>,
+L<https://www.lua.org/manual/5.4/manual.html#2.4>
+
+See section "Metatables and Metamethods" in "Programming in Lua".
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local has_metamethod52 = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local has_metamethod_ipairs = _VERSION == 'Lua 5.2' or profile.compat52 or profile.luajit_compat52
+local has_metamethod_le_emulated = _VERSION <= 'Lua 5.3' or profile.compat53
+local has_metamethod_pairs = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local has_metamethod_tostring53 = _VERSION >= 'Lua 5.3'
+local has_metamethod_tostring54 = _VERSION >= 'Lua 5.4'
+local has_anno_toclose = _VERSION >= 'Lua 5.4'
+
+plan'no_plan'
+
+do
+    local t = {}
+    is(getmetatable(t), nil, "metatable")
+    local t1 = {}
+    is(setmetatable(t, t1), t)
+    is(getmetatable(t), t1)
+    is(setmetatable(t, nil), t)
+    error_like(function () setmetatable(t, true) end,
+               "^[^:]+:%d+: bad argument #2 to 'setmetatable' %(nil or table expected")
+
+    local mt = {}
+    mt.__metatable = "not your business"
+    setmetatable(t, mt)
+    is(getmetatable(t), "not your business", "protected metatable")
+    error_like(function () setmetatable(t, {}) end,
+               "^[^:]+:%d+: cannot change a protected metatable")
+
+    is(getmetatable('').__index, string, "metatable for string")
+
+    is(getmetatable(nil), nil, "metatable for nil")
+    is(getmetatable(false), nil, "metatable for boolean")
+    is(getmetatable(2), nil, "metatable for number")
+    is(getmetatable(print), nil, "metatable for function")
+end
+
+do
+    local t = {}
+    local mt = { __tostring=function () return '__TABLE__' end }
+    setmetatable(t, mt)
+    is(tostring(t), '__TABLE__', "__tostring")
+end
+
+do
+    local t = {}
+    local mt = {}
+    local a = nil
+    function mt.__tostring () a = "return nothing" end
+    setmetatable(t, mt)
+    if has_metamethod_tostring53 then
+        error_like(function () tostring(t) end,
+                   "^[^:]+:%d+: '__tostring' must return a string")
+        is(a, "return nothing")
+        if has_metamethod_tostring54 then
+            error_like(function () print(t) end,
+                       "^[^:]+:%d+: '__tostring' must return a string")
+        else
+            error_is(function () print(t) end,
+                     "'__tostring' must return a string")
+        end
+    else
+        is(tostring(t), nil, "__tostring no-output")
+        is(a, "return nothing")
+        error_like(function () print(t) end,
+                   "^[^:]+:%d+: 'tostring' must return a string to 'print'")
+    end
+
+    mt.__tostring = function () return '__FIRST__', 2 end
+    setmetatable(t, mt)
+    is(tostring(t), '__FIRST__', "__tostring too-many-output")
+end
+
+do
+    local t = {}
+    t.mt = {}
+    setmetatable(t, t.mt)
+    t.mt.__tostring = "not a function"
+    error_like(function () tostring(t) end,
+               "attempt to call",
+               "__tostring invalid")
+end
+
+do
+    local t = {}
+    local mt = { __len=function () return 42 end }
+    setmetatable(t, mt)
+    if has_metamethod52 then
+        is(#t, 42, "__len")
+    else
+        is(#t, 0, "__len 5.1")
+    end
+end
+
+if has_metamethod52 then
+    local t = {}
+    local mt = { __len=function () return nil end }
+    setmetatable(t, mt)
+    if jit then
+        todo("not with LuaJIT")
+    end
+    error_like(function () print(table.concat(t)) end,
+               "object length is not a.-er",
+               "__len invalid")
+end
+
+do
+    local t = {}
+    local mt = {
+        __tostring=function () return 't' end,
+        __concat=function (op1, op2)
+            return tostring(op1) .. '|' .. tostring(op2)
+        end,
+    }
+    setmetatable(t, mt)
+    is(t .. t .. t ..'end' .. '.', "t|t|t|end.", "__concat")
+end
+
+do --[[ Cplx ]]
+    local Cplx = {}
+    Cplx.mt = {}
+    local tointeger = math.tointeger or math.floor
+
+    function Cplx.new (re, im)
+        local c = {}
+        setmetatable(c, Cplx.mt)
+        c.re = tonumber(re)
+        if im == nil then
+            c.im = 0.0
+        else
+            c.im = tonumber(im)
+        end
+        return c
+    end
+
+    function Cplx.mt.__tostring (c)
+        return '(' .. tostring(tointeger(c.re)) .. ',' .. tostring(tointeger(c.im)) .. ')'
+    end
+
+    function Cplx.mt.__add (a, b)
+        if type(a) ~= 'table' then
+            a = Cplx.new(a, 0)
+        end
+        if type(b) ~= 'table' then
+            b = Cplx.new(b, 0)
+        end
+        local r = Cplx.new(a.re + b.re, a.im + b.im)
+        return r
+    end
+
+    local c1 = Cplx.new(1, 3)
+    local c2 = Cplx.new(2, -1)
+
+    is(tostring(c1 + c2), '(3,2)', "cplx __add")
+    is(tostring(c1 + 3), '(4,3)')
+    is(tostring(-2 + c1), '(-1,3)')
+    is(tostring(c1 + '3'), '(4,3)')
+    is(tostring('-2' + c1), '(-1,3)')
+
+    function Cplx.mt.__sub (a, b)
+        if type(a) ~= 'table' then
+            a = Cplx.new(a, 0)
+        end
+        if type(b) ~= 'table' then
+            b = Cplx.new(b, 0)
+        end
+        local r = Cplx.new(a.re - b.re, a.im - b.im)
+        return r
+    end
+
+    is(tostring(c1 - c2), '(-1,4)', "cplx __sub")
+    is(tostring(c1 - 3), '(-2,3)')
+    is(tostring(-2 - c1), '(-3,-3)')
+    is(tostring(c1 - '3'), '(-2,3)')
+    is(tostring('-2' - c1), '(-3,-3)')
+
+    function Cplx.mt.__mul (a, b)
+        if type(a) ~= 'table' then
+            a = Cplx.new(a, 0)
+        end
+        if type(b) ~= 'table' then
+            b = Cplx.new(b, 0)
+        end
+        local r = Cplx.new(a.re*b.re - a.im*b.im,
+            a.re*b.im + a.im*b.re)
+        return r
+    end
+
+    is(tostring(c1 * c2), '(5,5)', "cplx __mul")
+    is(tostring(c1 * 3), '(3,9)')
+    is(tostring(-2 * c1), '(-2,-6)')
+    is(tostring(c1 * '3'), '(3,9)')
+    is(tostring('-2' * c1), '(-2,-6)')
+
+    function Cplx.mt.__div (a, b)
+        if type(a) ~= 'table' then
+            a = Cplx.new(a, 0)
+        end
+        if type(b) ~= 'table' then
+            b = Cplx.new(b, 0)
+        end
+        local n = b.re*b.re + b.im*b.im
+        local inv = Cplx.new(b.re/n, b.im/n)
+        local r = Cplx.new(a.re*inv.re - a.im*inv.im,
+                           a.re*inv.im + a.im*inv.re)
+        return r
+    end
+
+    c1 = Cplx.new(2, 6)
+    c2 = Cplx.new(2, 0)
+
+    is(tostring(c1 / c2), '(1,3)', "cplx __div")
+    is(tostring(c1 / 2), '(1,3)')
+    is(tostring(-4 / c2), '(-2,0)')
+    is(tostring(c1 / '2'), '(1,3)')
+    is(tostring('-4' / c2), '(-2,0)')
+
+    function Cplx.mt.__unm (a)
+        if type(a) ~= 'table' then
+            a = Cplx.new(a, 0)
+        end
+        local r = Cplx.new(-a.re, -a.im)
+        return r
+    end
+
+    c1 = Cplx.new(1, 3)
+    is(tostring(- c1), '(-1,-3)', "cplx __unm")
+
+    function Cplx.mt.__len (a)
+        return math.sqrt(a.re*a.re + a.im*a.im)
+    end
+
+    c1 = Cplx.new(3, 4)
+    if has_metamethod52 then
+        is( #c1, 5, "cplx __len")
+    else
+        is( #c1, 0, "__len 5.1")
+    end
+
+    function Cplx.mt.__eq (a, b)
+        if type(a) ~= 'table' then
+            a = Cplx.new(a, 0)
+        end
+        if type(b) ~= 'table' then
+            b = Cplx.new(b, 0)
+        end
+        return (a.re == b.re) and (b.im == b.im)
+    end
+
+    c1 = Cplx.new(2, 0)
+    c2 = Cplx.new(1, 3)
+    local c3 = Cplx.new(2, 0)
+
+    is(c1 ~= c2, true, "cplx __eq")
+    is(c1 == c3, true)
+    is(c1 == 2, false)
+    is(Cplx.mt.__eq(c1, 2), true)
+
+    function Cplx.mt.__lt (a, b)
+        if type(a) ~= 'table' then
+            a = Cplx.new(a, 0)
+        end
+        if type(b) ~= 'table' then
+            b = Cplx.new(b, 0)
+        end
+        local ra = a.re*a.re + a.im*a.im
+        local rb = b.re*b.re + b.im*b.im
+        return ra < rb
+    end
+
+    is(c1 < c2, true, "cplx __lt")
+    is(c1 < c3, false)
+    if has_metamethod_le_emulated then
+        is(c1 <= c3, true)
+    end
+    if has_metamethod52 then
+        is(c1 < 1, false)
+        is(c1 < 4, true)
+    end
+
+    function Cplx.mt.__le (a, b)
+        if type(a) ~= 'table' then
+            a = Cplx.new(a, 0)
+        end
+        if type(b) ~= 'table' then
+            b = Cplx.new(b, 0)
+        end
+        local ra = a.re*a.re + a.im*a.im
+        local rb = b.re*b.re + b.im*b.im
+        return ra <= rb
+    end
+
+    is(c1 < c2, true, "cplx __lt __le")
+    is(c1 < c3, false)
+    is(c1 <= c3, true)
+
+    local a = nil
+    function Cplx.mt.__call (obj)
+        a = "Cplx.__call " .. tostring(obj)
+        return true
+    end
+
+    c1 = Cplx.new(2, 0)
+    local r = c1()
+    is(r, true, "cplx __call (without args)")
+    is(a, "Cplx.__call (2,0)")
+
+    function Cplx.mt.__call (obj, ...)
+        a = "Cplx.__call " .. tostring(obj) .. ", " .. table.concat({...}, ", ")
+        return true
+    end
+
+    is(c1(), true, "cplx __call (with args)")
+    is(a, "Cplx.__call (2,0), ")
+    is(c1('a'), true)
+    is(a, "Cplx.__call (2,0), a")
+    is(c1('a', 'b', 'c'), true)
+    is(a, "Cplx.__call (2,0), a, b, c")
+end
+
+--[[ delegate ]]
+if has_metamethod_pairs then
+    local t = {
+        _VALUES = {
+            a = 1,
+            b = 'text',
+            c = true,
+        }
+    }
+    local mt = {
+        __pairs = function (op)
+            return next, op._VALUES
+        end
+    }
+    setmetatable(t, mt)
+
+    local r = {}
+    for k in pairs(t) do
+        r[#r+1] = k
+    end
+    table.sort(r)
+    is( table.concat(r, ','), 'a,b,c', "__pairs" )
+end
+if has_metamethod_ipairs then
+    local t = {
+        _VALUES = { 'a', 'b', 'c' }
+    }
+    local mt = {
+        __ipairs = function (op)
+            return ipairs(op._VALUES)
+        end
+    }
+    setmetatable(t, mt)
+
+    local r = ''
+    for i, v in ipairs(t) do
+        r = r .. v
+    end
+    is( r, 'abc', "__ipairs" )
+end
+
+do --[[ Window ]]
+    -- create a namespace
+    local Window = {}
+    -- create a prototype with default values
+    Window.prototype = {x=0, y=0, width=100, heigth=100, }
+    -- create a metatable
+    Window.mt = {}
+    -- declare the constructor function
+    function Window.new (o)
+        setmetatable(o, Window.mt)
+        return o
+    end
+
+    Window.mt.__index = function (table, key)
+        return Window.prototype[key]
+    end
+
+    local w = Window.new{x=10, y=20}
+    is(w.x, 10, "table-access")
+    is(w.width, 100)
+    is(rawget(w, 'x'), 10)
+    is(rawget(w, 'width'), nil)
+
+    Window.mt.__index = Window.prototype  -- just a table
+    w = Window.new{x=10, y=20}
+    is(w.x, 10, "table-access")
+    is(w.width, 100)
+    is(rawget(w, 'x'), 10)
+    is(rawget(w, 'width'), nil)
+end
+
+do --[[ tables with default values ]]
+    local function setDefault_1 (t, d)
+        local mt = {__index = function () return d end}
+        setmetatable (t, mt)
+    end
+
+    local tab = {x=10, y=20}
+    is(tab.x, 10, "tables with default values")
+    is(tab.z, nil)
+    setDefault_1(tab, 0)
+    is(tab.x, 10)
+    is(tab.z, 0)
+end
+
+do --[[ tables with default values ]]
+    local mt = {__index = function (t) return t.___ end}
+    local function setDefault_2 (t, d)
+        t.___ = d
+        setmetatable (t, mt)
+    end
+
+    local tab = {x=10, y=20}
+    is(tab.x, 10, "tables with default values")
+    is(tab.z, nil)
+    setDefault_2(tab, 0)
+    is(tab.x, 10)
+    is(tab.z, 0)
+end
+
+do --[[ tables with default values ]]
+    local key = {}
+    local mt = {__index = function (t) return t[key] end}
+    local function setDefault_3 (t, d)
+        t[key] = d
+        setmetatable (t, mt)
+    end
+
+    local tab = {x=10, y=20}
+    is(tab.x, 10, "tables with default values")
+    is(tab.z, nil)
+    setDefault_3(tab, 0)
+    is(tab.x, 10)
+    is(tab.z, 0)
+end
+
+do --[[ private access ]]
+    local t = {}  -- original table
+    -- keep a private access to original table
+    local _t = t
+    -- create proxy
+    t = {}
+
+    local w = nil
+    local r = nil
+    -- create metatable
+    local mt = {
+        __index = function (t,k)
+            r = "*access to element " .. tostring(k)
+            return _t[k]  -- access the original table
+        end,
+
+        __newindex = function (t,k,v)
+             w = "*update of element " .. tostring(k) ..
+                                " to " .. tostring(v)
+            _t[k] = v  -- update original table
+        end
+    }
+    setmetatable(t, mt)
+
+    t[2] = 'hello'
+    is(t[2], 'hello', "tracking table accesses")
+    is(w, "*update of element 2 to hello")
+    is(r, "*access to element 2")
+end
+
+do --[[ private access ]]
+    -- create private index
+    local index = {}
+
+    local w = nil
+    local r = nil
+    -- create metatable
+    local mt = {
+        __index = function (t,k)
+            r = "*access to element " .. tostring(k)
+            return t[index][k]  -- access the original table
+        end,
+
+        __newindex = function (t,k,v)
+            w = "*update of element " .. tostring(k) ..
+                               " to " .. tostring(v)
+            t[index][k] = v  -- update original table
+        end
+    }
+    local function track (t)
+        local proxy = {}
+        proxy[index] = t
+        setmetatable(proxy, mt)
+        return proxy
+    end
+
+    local t = {}
+    t = track(t)
+
+    t[2] = 'hello'
+    is(t[2], 'hello', "tracking table accesses")
+    is(w, "*update of element 2 to hello")
+    is(r, "*access to element 2")
+end
+
+do --[[ read-only table ]]
+    local function readOnly (t)
+        local proxy = {}
+        local mt = {
+            __index = t,
+            __newindex = function (_t,k,v)
+                error("attempt to update a read-only table", 2)
+            end
+        }
+        setmetatable(proxy, mt)
+        return proxy
+    end
+
+    local days = readOnly{'Sunday', 'Monday', 'Tuesday', 'Wednesday',
+                         'Thurday', 'Friday', 'Saturday'}
+
+    is(days[1], 'Sunday', "read-only tables")
+
+    error_like(function () days[2] = 'Noday' end,
+               "^[^:]+:%d+: attempt to update a read%-only table")
+end
+
+do --[[ declare global ]]
+    local function declare (name, initval)
+        rawset(_G, name, initval or false)
+    end
+
+    setmetatable(_G, {
+        __newindex = function (_, n)
+            error("attempt to write to undeclared variable " .. n, 2)
+        end,
+        __index = function (_, n)
+            error("attempt to read undeclared variable" .. n, 2)
+        end,
+    })
+
+    error_like(function () new_a = 1 end,
+               "^[^:]+:%d+: attempt to write to undeclared variable new_a",
+               "declaring global variables")
+
+    declare 'new_a'
+    new_a = 1
+    is(new_a, 1)
+end
+
+do
+    local newindex = {}
+    -- create metatable
+    local mt = {
+        __newindex = newindex
+    }
+    local t = setmetatable({}, mt)
+    t[1] = 42
+    is(newindex[1], 42, "__newindex")
+end
+
+if has_anno_toclose then
+    dofile'lexico54/metatable.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/232-object.t b/test/lua-Harness-tests/232-object.t
new file mode 100755
index 0000000..0d87572
--- /dev/null
+++ b/test/lua-Harness-tests/232-object.t
@@ -0,0 +1,314 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua object
+
+=head2 Synopsis
+
+    % prove 232-object.t
+
+=head2 Description
+
+See section "Object-Oriented Programming" in "Programming in Lua".
+
+=cut
+
+--]]
+
+require'tap'
+
+plan(18)
+
+do --[[ object ]]
+    local Account = {balance = 0}
+
+    function Account.withdraw (self, v)
+        self.balance = self.balance - v
+    end
+
+    local a1 = Account; Account = nil
+    a1.withdraw(a1, 100.00)
+    is(a1.balance, -100, "object")
+
+    local a2 = {balance = 0, withdraw = a1.withdraw}
+    a2.withdraw(a2, 260.00)
+    is(a2.balance, -260)
+end
+
+do --[[ object ]]
+    local Account = {balance = 0}
+
+    function Account:withdraw (v)
+        self.balance = self.balance - v
+    end
+
+    local a = Account
+    a:withdraw(100.00)
+    is(a.balance, -100, "object")
+
+    Account = { balance = 0,
+                withdraw = function (self, v)
+                               self.balance = self.balance -v
+                           end
+              }
+    function Account:deposit (v)
+        self.balance = self.balance + v
+    end
+
+    Account.deposit(Account, 200.00)
+    is(Account.balance, 200, "object")
+    Account:withdraw(100.00)
+    is(Account.balance, 100)
+end
+
+do --[[ class ]]
+    local Account = {balance = 0}
+
+    function Account:new (o)
+        o = o or {}
+        setmetatable(o, self)
+        self.__index = self
+        return o
+    end
+
+    function Account:deposit (v)
+        self.balance = self.balance + v
+    end
+
+    function Account:withdraw (v)
+        self.balance = self.balance - v
+    end
+
+    local a = Account:new{balance = 0}
+    a:deposit(100.00)
+    is(a.balance, 100, "classe")
+
+    local b = Account:new()
+    is(b.balance, 0)
+    b:deposit(200.00)
+    is(b.balance, 200)
+end
+
+do --[[ inheritance ]]
+    local Account = {balance = 0}
+
+    function Account:new (o)
+    --    print "Account:new"
+        o = o or {}
+        setmetatable(o, self)
+        self.__index = self
+        return o
+    end
+
+    function Account:deposit (v)
+    --    print "Account:deposit"
+        self.balance = self.balance + v
+    end
+
+    function Account:withdraw (v)
+    --    print "Account:withdraw"
+        if v > self.balance then error"insuficient funds" end
+        self.balance = self.balance - v
+    end
+
+    local a = Account:new()
+    is(a.balance, 0, "inheritance")
+    -- r, msg = pcall(Account.withdraw, a, 100)
+    -- print(msg)
+
+    local SpecialAccount = Account:new()
+
+    function SpecialAccount:withdraw (v)
+    --    print "SpecialAccount:withdraw"
+        if self.balance - v <= -self:getLimit() then
+            error"insuficient funds"
+        end
+        self.balance = self.balance - v
+    end
+
+    function SpecialAccount:getLimit ()
+    --    print "SpecialAccount:getLimit"
+        return self.limit or 0
+    end
+
+    local s = SpecialAccount:new{limit=1000.00}
+
+    s:deposit(100.00)
+    is(s.balance, 100)
+
+    s:withdraw(200.00)
+    is(s.balance, -100)
+end
+
+do --[[ multiple inheritance ]]
+    -- look up for 'k' in list of tables 'plist'
+    local function search (k, plist)
+        for i=1, #plist do
+            local v = plist[i][k]  -- try 'i'-th superclass
+            if v then return v end
+        end
+    end
+
+    local function createClass (...)
+        local c = {}  -- new class
+        local arg = {...}
+
+        -- class will search for each method in the list of its
+        -- parents ('arg' is the list of parents)
+        setmetatable(c, {__index = function (t, k)
+            return search(k, arg)
+        end})
+
+        -- prepare 'c' to be the metatable of its instance
+        c.__index = c
+
+        -- define a new constructor for this new class
+        function c:new (o)
+            o = o or {}
+            setmetatable(o, c)
+            return o
+        end
+
+        -- return new class
+        return c
+    end
+
+    local Account = {balance = 0}
+    function Account:deposit (v)
+        self.balance = self.balance + v
+    end
+    function Account:withdraw (v)
+        self.balance = self.balance - v
+    end
+
+    local Named = {}
+    function Named:getname ()
+        return self.name
+    end
+    function Named:setname (n)
+        self.name = n
+    end
+
+    local NamedAccount = createClass(Account, Named)
+
+    local account = NamedAccount:new{name = "Paul"}
+    is(account:getname(), 'Paul', "multiple inheritance")
+    account:deposit(100.00)
+    is(account.balance, 100)
+end
+
+do --[[ multiple inheritance (patched) ]]
+    -- look up for 'k' in list of tables 'plist'
+    local function search (k, plist)
+        for i=1, #plist do
+            local v = plist[i][k]  -- try 'i'-th superclass
+            if v then return v end
+        end
+    end
+
+    local function createClass (...)
+        local c = {}  -- new class
+        local arg = {...}
+
+        -- class will search for each method in the list of its
+        -- parents ('arg' is the list of parents)
+        setmetatable(c, {__index = function (t, k)
+            -- return search(k, arg)
+            return (search(k, arg))
+        end})
+
+        -- prepare 'c' to be the metatable of its instance
+        c.__index = c
+
+        -- define a new constructor for this new class
+        function c:new (o)
+            o = o or {}
+            setmetatable(o, c)
+            return o
+        end
+
+        -- return new class
+        return c
+    end
+
+    local Account = {balance = 0}
+    function Account:deposit (v)
+        self.balance = self.balance + v
+    end
+    function Account:withdraw (v)
+        self.balance = self.balance - v
+    end
+
+    local Named = {}
+    function Named:getname ()
+        return self.name
+    end
+    function Named:setname (n)
+        self.name = n
+    end
+
+    local NamedAccount = createClass(Account, Named)
+
+    local account = NamedAccount:new{name = "Paul"}
+    is(account:getname(), 'Paul', "multiple inheritance (patched)")
+    account:deposit(100.00)
+    is(account.balance, 100)
+end
+
+do --[[ privacy ]]
+    local function newAccount (initialBalance)
+        local self = {balance = initialBalance}
+
+        local withdraw = function (v)
+                             self.balance = self.balance - v
+                         end
+
+        local deposit = function (v)
+                            self.balance = self.balance + v
+                        end
+
+        local getBalance = function () return self.balance end
+
+        return {
+            withdraw = withdraw,
+            deposit = deposit,
+            getBalance = getBalance
+        }
+    end
+
+    local acc1 = newAccount(100.00)
+    acc1.withdraw(40.00)
+    is(acc1.getBalance(), 60, "privacy")
+end
+
+do --[[ single-method approach ]]
+    local function newObject (value)
+        return function (action, v)
+            if action == 'get' then return value
+            elseif action == 'set' then value = v
+            else error("invalid action")
+            end
+        end
+    end
+
+    local d = newObject(0)
+    is(d('get'), 0, "single-method approach")
+    d('set', 10)
+    is(d('get'), 10)
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/241-standalone.t b/test/lua-Harness-tests/241-standalone.t
new file mode 100755
index 0000000..c5237ee
--- /dev/null
+++ b/test/lua-Harness-tests/241-standalone.t
@@ -0,0 +1,269 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Stand-alone
+
+=head2 Synopsis
+
+    % prove 241-standalone.t
+
+=head2 Description
+
+See section "Lua Stand-alone" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#6>,
+L<https://www.lua.org/manual/5.2/manual.html#7>,
+L<https://www.lua.org/manual/5.3/manual.html#7>,
+L<https://www.lua.org/manual/5.4/manual.html#7>
+
+=cut
+
+--]]
+
+require'tap'
+local has_bytecode = not ujit and not ravi
+local has_error52 = _VERSION >= 'Lua 5.2'
+local has_error53 = _VERSION >= 'Lua 5.3'
+local has_opt_E = _VERSION >= 'Lua 5.2' or jit
+local has_opt_W = _VERSION >= 'Lua 5.4'
+local banner = '^[%w%s%-%.]-Copyright %(C%) %d%d%d%d'
+if jit and jit.version:match'^RaptorJIT' then
+    banner = '^[%w%s%.]- %-%- '
+elseif ravi then
+    banner = '^Ravi %d%.%d%.%d'
+end
+
+local lua = get_lua_binary_name()
+local luac = jit and lua or (lua .. 'c')
+
+if not pcall(io.popen, lua .. [[ -e "a=1"]]) then
+    skip_all "io.popen not supported"
+end
+
+plan'no_plan'
+diag(lua)
+
+local f = io.open('hello-241.lua', 'w')
+f:write([[
+print 'Hello World'
+]])
+f:close()
+
+local cmd = lua .. " hello-241.lua"
+f = io.popen(cmd)
+is(f:read'*l', 'Hello World', "file")
+f:close()
+
+cmd = lua .. " -- hello-241.lua"
+f = io.popen(cmd)
+is(f:read'*l', 'Hello World', "-- file")
+f:close()
+
+cmd = lua .. " no_file-241.lua 2>&1"
+f = io.popen(cmd)
+like(f:read'*l', "^[^:]+: cannot open no_file%-241%.lua", "no file")
+f:close()
+
+if has_bytecode then
+    if jit then
+        os.execute(lua .. " -b hello-241.lua hello-241.luac")
+    else
+        os.execute(luac .. " -s -o hello-241.luac hello-241.lua")
+    end
+    cmd = lua .. " hello-241.luac"
+    f = io.popen(cmd)
+    is(f:read'*l', 'Hello World', "bytecode")
+    f:close()
+    os.remove('hello-241.luac') -- clean up
+
+    if not jit then
+        os.execute(luac .. " -s -o hello-hello-241.luac hello-241.lua hello-241.lua")
+        cmd = lua .. " hello-hello-241.luac"
+        f = io.popen(cmd)
+        is(f:read'*l', 'Hello World', "combine 1")
+        is(f:read'*l', 'Hello World', "combine 2")
+        f:close()
+        os.remove('hello-hello-241.luac') -- clean up
+    end
+end
+
+cmd = lua .. " < hello-241.lua"
+f = io.popen(cmd)
+is(f:read'*l', 'Hello World', "redirect")
+f:close()
+
+cmd = lua .. " - < hello-241.lua"
+f = io.popen(cmd)
+is(f:read'*l', 'Hello World', "redirect")
+f:close()
+
+cmd = lua .. " -i hello-241.lua < hello-241.lua 2>&1"
+f = io.popen(cmd)
+like(f:read'*l', banner, "-i")
+if ujit then
+    like(f:read'*l', '^JIT:')
+end
+if ravi then
+    like(f:read'*l', '^Copyright %(C%)')
+    like(f:read'*l', '^Portions Copyright %(C%)')
+    like(f:read'*l', '^Options')
+end
+is(f:read'*l', 'Hello World')
+f:close()
+
+cmd = lua .. [[ -e"a=1" -e "print(a)"]]
+f = io.popen(cmd)
+is(f:read'*l', '1', "-e")
+f:close()
+
+cmd = lua .. [[ -e "error('msg')"  2>&1]]
+f = io.popen(cmd)
+is(f:read'*l', lua .. [[: (command line):1: msg]], "error")
+is(f:read'*l', "stack traceback:", "backtrace")
+f:close()
+
+cmd = lua .. [[ -e "error(setmetatable({}, {__tostring=function() return 'MSG' end}))"  2>&1]]
+f = io.popen(cmd)
+if has_error52 or jit then
+    is(f:read'*l', lua .. [[: MSG]], "error with object")
+else
+    is(f:read'*l', lua .. [[: (error object is not a string)]], "error with object")
+end
+if jit then
+    is(f:read'*l', "stack traceback:", "backtrace")
+else
+    is(f:read'*l', nil, "not backtrace")
+end
+f:close()
+
+cmd = lua .. [[ -e "error{}"  2>&1]]
+f = io.popen(cmd)
+if has_error53 then
+    is(f:read'l', lua .. [[: (error object is a table value)]], "error")
+    is(f:read'l', "stack traceback:", "backtrace")
+elseif has_error52 then
+    is(f:read'*l', lua .. [[: (no error message)]], "error")
+    is(f:read'*l', nil, "not backtrace")
+else
+    is(f:read'*l', lua .. [[: (error object is not a string)]], "error")
+    is(f:read'*l', nil, "not backtrace")
+end
+f:close()
+
+cmd = lua .. [[ -e"a=1" -e "print(a)" hello-241.lua]]
+f = io.popen(cmd)
+is(f:read'*l', '1', "-e & script")
+is(f:read'*l', 'Hello World')
+f:close()
+
+cmd = lua .. [[ -e"a=1" -i < hello-241.lua 2>&1]]
+f = io.popen(cmd)
+like(f:read'*l', banner, "-e & -i")
+f:close()
+
+cmd = lua .. [[ -e "?syntax error?" 2>&1]]
+f = io.popen(cmd)
+like(f:read'*l', "^.-%d: unexpected symbol near '%?'", "-e bad")
+f:close()
+
+cmd = lua .. [[ -e 2>&1]]
+f = io.popen(cmd)
+if _VERSION ~= 'Lua 5.1' then
+    like(f:read'*l', "^[^:]+: '%-e' needs argument", "no file")
+end
+like(f:read'*l', "^usage: ", "no file")
+f:close()
+
+cmd = lua .. [[ -v 2>&1]]
+f = io.popen(cmd)
+like(f:read'*l', banner, "-v")
+f:close()
+
+cmd = lua .. [[ -v hello-241.lua 2>&1]]
+f = io.popen(cmd)
+like(f:read'*l', banner, "-v & script")
+if ravi then
+    like(f:read'*l', '^Copyright %(C%)')
+    like(f:read'*l', '^Portions Copyright %(C%)')
+    like(f:read'*l', '^Options')
+end
+is(f:read'*l', 'Hello World')
+f:close()
+
+cmd = lua .. [[ -v -- 2>&1]]
+f = io.popen(cmd)
+like(f:read'*l', banner, "-v --")
+f:close()
+
+if has_opt_E then
+    cmd = lua .. [[ -E hello-241.lua 2>&1]]
+    f = io.popen(cmd)
+    is(f:read'*l', 'Hello World', "-E")
+    f:close()
+else
+    diag("no -E")
+end
+
+cmd = lua .. [[ -u 2>&1]]
+f = io.popen(cmd)
+if _VERSION ~= 'Lua 5.1' then
+    like(f:read'*l', "^[^:]+: unrecognized option '%-u'", "unknown option")
+end
+like(f:read'*l', "^usage: ", "no file")
+f:close()
+
+cmd = lua .. [[ --u 2>&1]]
+f = io.popen(cmd)
+if _VERSION ~= 'Lua 5.1' then
+    like(f:read'*l', "^[^:]+: unrecognized option '%-%-u'", "unknown option")
+end
+like(f:read'*l', "^usage: ", "no file")
+f:close()
+
+cmd = lua .. [[ -ltap -e "print(type(ok))"]]
+f = io.popen(cmd)
+is(f:read'*l', 'function', "-ltap")
+f:close()
+
+cmd = lua .. [[ -l tap -e "print(type(ok))"]]
+f = io.popen(cmd)
+is(f:read'*l', 'function', "-l tap")
+f:close()
+
+cmd = lua .. [[ -l lpeg -e "print(1)" 2>&1]]
+f = io.popen(cmd)
+isnt(f:read'*l', nil, "-l lpeg")
+f:close()
+
+cmd = lua .. [[ -l no_lib hello-241.lua 2>&1]]
+f = io.popen(cmd)
+like(f:read'*l', "^[^:]+: module 'no_lib' not found:", "-l no lib")
+f:close()
+
+if has_opt_W then
+    cmd = lua .. [[ -W -e "warn'foo'" 2>&1]]
+    f = io.popen(cmd)
+    is(f:read'*l', 'Lua warning: foo', "-W")
+    is(f:read'*l', nil)
+    f:close()
+else
+    diag("no -W")
+end
+
+os.remove('hello-241.lua') -- clean up
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/242-luac.t b/test/lua-Harness-tests/242-luac.t
new file mode 100755
index 0000000..a95a334
--- /dev/null
+++ b/test/lua-Harness-tests/242-luac.t
@@ -0,0 +1,341 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2010-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Stand-alone
+
+=head2 Synopsis
+
+    % prove t/242-luac.t
+
+=head2 Description
+
+See section "Lua Stand-alone" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#6>,
+L<https://www.lua.org/manual/5.2/manual.html#7>,
+L<https://www.lua.org/manual/5.3/manual.html#7>,
+L<https://www.lua.org/manual/5.4/manual.html#7>
+
+=cut
+
+--]]
+
+require'tap'
+
+if jit then
+    skip_all("LuaJIT")
+end
+
+if ravi then
+    skip_all("ravi")
+end
+
+local lua = get_lua_binary_name()
+local luac = lua .. 'c'
+
+if not pcall(io.popen, lua .. [[ -e "a=1"]]) then
+    skip_all "io.popen not supported"
+end
+
+plan'no_plan'
+diag(luac)
+
+local signature = "\x1bLua"
+local bin_version
+if     _VERSION == 'Lua 5.1' then
+    bin_version = "\x51"
+elseif _VERSION == 'Lua 5.2' then
+    bin_version = "\x52"
+elseif _VERSION == 'Lua 5.3' then
+    bin_version = "\x53"
+elseif _VERSION == 'Lua 5.4' then
+    bin_version = "\x54"
+end
+local format = "\x00"
+local data = "\x19\x93\r\n\x1a\n"
+local size_i = string.char(string.packsize and string.packsize'i' or 0) -- int
+local size_T = string.char(string.packsize and string.packsize'T' or 0) -- size_t
+local size_I = string.char(string.packsize and string.packsize'I' or 0) -- Instruction
+local size_j = string.char(string.packsize and string.packsize'j' or 0) -- lua_Integer
+local size_n = string.char(string.packsize and string.packsize'n' or 0) -- lua_Number
+local sizes = size_i .. size_T .. size_I .. size_j .. size_n
+
+do -- hello.lua
+    local f = io.open('hello-242.lua', 'w')
+    f:write([[
+print 'Hello World'
+]])
+    f:close()
+end
+
+do -- luac -v
+    local cmd = luac .. [[ -v 2>&1]]
+    local f = io.popen(cmd)
+    like(f:read'*l', '^Lua', "-v")
+    f:close()
+end
+
+do -- luac -v --
+    local cmd = luac .. [[ -v -- 2>&1]]
+    local f = io.popen(cmd)
+    like(f:read'*l', '^Lua', "-v --")
+    f:close()
+end
+
+do -- luac -u
+    local cmd = luac .. [[ -u 2>&1]]
+    local f = io.popen(cmd)
+    like(f:read'*l', "^[^:]+: unrecognized option '%-u'", "unknown option")
+    like(f:read'*l', "^usage:")
+    f:close()
+end
+
+do -- luac --u
+    local cmd = luac .. [[ --u 2>&1]]
+    local f = io.popen(cmd)
+    like(f:read'*l', "^[^:]+: unrecognized option '%-%-u'", "unknown option")
+    like(f:read'*l', "^usage:")
+    f:close()
+end
+
+do -- luac -p hello-242.lua
+    local cmd = luac .. [[ -p hello-242.lua 2>&1]]
+    local f = io.popen(cmd)
+    is(f:read'*l', nil)
+    f:close()
+end
+
+do -- luac -p - < hello-242.lua
+    local cmd = luac .. [[ -p - < hello-242.lua 2>&1]]
+    local f = io.popen(cmd)
+    is(f:read'*l', nil)
+    f:close()
+end
+
+do -- luac -p no_file-242.lua
+    local cmd = luac .. [[ -p no_file-242.lua 2>&1]]
+    local f = io.popen(cmd)
+    like(f:read'*l', "^[^:]+: cannot open no_file%-242%.lua", "no file")
+    f:close()
+end
+
+do -- luac -o
+    local cmd = luac .. [[ -o 2>&1]]
+    local f = io.popen(cmd)
+    like(f:read'*l', "^[^:]+: '%-o' needs argument", "-o needs argument")
+    f:close()
+end
+
+do -- luac -v -l -l hello-242.lua
+    local cmd = luac .. [[ -v -l -l hello-242.lua]]
+    local f = io.popen(cmd)
+    like(f:read'*l', '^Lua', "-v -l -l")
+    is(f:read'*l', '')
+    like(f:read'*l', "^main")
+    f:close()
+end
+
+os.remove('hello-242.lua') -- clean up
+
+do -- luac -l luac.out
+    local cmd = luac .. [[ -l luac.out]]
+    local f = io.popen(cmd)
+    is(f:read'*l', '', "-l luac.out")
+    like(f:read'*l', "^main")
+    f:close()
+end
+
+do -- luac -l
+    local cmd = luac .. [[ -l]]
+    local f = io.popen(cmd)
+    is(f:read'*l', '', "-l")
+    like(f:read'*l', "^main")
+    f:close()
+end
+
+do -- luac -l - < luac.out
+    local cmd = luac .. [[ -l - < luac.out]]
+    local f = io.popen(cmd)
+    is(f:read'*l', '', "-l -")
+    like(f:read'*l', "^main")
+    f:close()
+end
+
+if _VERSION ~= 'Lua 5.1' then
+    local f = io.open('luac.out', 'w')
+    f:write(signature .. bin_version .. format)
+    f:close()
+    local cmd = luac .. [[ luac.out 2>&1]]
+    f = io.popen(cmd)
+    if _VERSION <= 'Lua 5.3' then
+        like(f:read'*l', "truncated precompiled chunk")
+    else
+        like(f:read'*l', "bad binary format %(truncated chunk%)")
+    end
+    f:close()
+end
+
+if _VERSION ~= 'Lua 5.1' then -- bad signature
+    local f = io.open('luac.out', 'w')
+    f:write("\x1bFoo" .. bin_version .. format .. data .. sizes .. "Foo")
+    f:close()
+    local cmd = luac .. [[ luac.out 2>&1]]
+    f = io.popen(cmd)
+    if _VERSION <= 'Lua 5.3' then
+        like(f:read'*l', "not a precompiled chunk", "bad signature")
+    else
+        like(f:read'*l', "bad binary format %(not a binary chunk%)", "bad signature")
+    end
+    f:close()
+end
+
+if _VERSION ~= 'Lua 5.1' then -- bad version
+    local f = io.open('luac.out', 'w')
+    f:write(signature .. "\x51" .. format .. data .. sizes .. "Foo")
+    f:close()
+    local cmd = luac .. [[ luac.out 2>&1]]
+    f = io.popen(cmd)
+    if _VERSION <= 'Lua 5.3' then
+        like(f:read'*l', "version mismatch in precompiled chunk", "bad version")
+    else
+        like(f:read'*l', "bad binary format %(version mismatch%)", "bad version")
+    end
+    f:close()
+end
+
+if _VERSION ~= 'Lua 5.1' then -- bad format
+    local f = io.open('luac.out', 'w')
+    f:write(signature .. bin_version .. "\x42" .. data .. sizes .. "Foo")
+    f:close()
+    local cmd = luac .. [[ luac.out 2>&1]]
+    f = io.popen(cmd)
+    if _VERSION == 'Lua 5.2' then
+        like(f:read'*l', "version mismatch in precompiled chunk", "bad format")
+    elseif _VERSION == 'Lua 5.3' then
+        like(f:read'*l', "format mismatch in precompiled chunk", "bad format")
+    else
+        like(f:read'*l', "bad binary format %(format mismatch%)", "bad format")
+    end
+    f:close()
+end
+
+if _VERSION == 'Lua 5.2' then -- bad sizes
+    local f = io.open('luac.out', 'w')
+    f:write(signature .. bin_version .. format .. "\xde\xad\xbe\xef\x00" .. data .. "Foo")
+    f:close()
+    local cmd = luac .. [[ luac.out 2>&1]]
+    f = io.popen(cmd)
+    like(f:read'*l', "incompatible precompiled chunk", "incompatible 5.2")
+    f:close()
+end
+
+if _VERSION == 'Lua 5.2' then -- bad data / tail
+    sizes = string.dump(load "a = 1"):sub(7, 12)
+    local f = io.open('luac.out', 'w')
+    f:write(signature .. bin_version .. format .. sizes .. "\x19\x99\r\n\x1a\n")
+    f:close()
+    local cmd = luac .. [[ luac.out 2>&1]]
+    f = io.popen(cmd)
+    like(f:read'*l', "corrupted precompiled chunk", "corrupted 5.2")
+    f:close()
+end
+
+if _VERSION == 'Lua 5.3' then -- bad data
+    local f = io.open('luac.out', 'w')
+    f:write(signature .. bin_version .. format .. "\x19\x99\r\n\x1a\n" .. sizes)
+    f:close()
+    local cmd = luac .. [[ luac.out 2>&1]]
+    f = io.popen(cmd)
+    like(f:read'*l', "corrupted precompiled chunk", "corrupted")
+    f:close()
+end
+
+if _VERSION == 'Lua 5.3' then -- bad sizes
+    local f = io.open('luac.out', 'w')
+    f:write(signature .. bin_version .. format .. data .. "\xde\xad\xbe\xef\x00")
+    f:close()
+    local cmd = luac .. [[ luac.out 2>&1]]
+    f = io.popen(cmd)
+    like(f:read'*l', "int size mismatch in precompiled chunk", "bad sizes")
+    f:close()
+end
+
+if _VERSION == 'Lua 5.3' then -- bad endianess
+    local f = io.open('luac.out', 'w')
+    f:write(signature .. bin_version .. format .. data .. sizes .. "\0\0\0\0\0\0\0\0")
+    f:close()
+    local cmd = luac .. [[ luac.out 2>&1]]
+    f = io.popen(cmd)
+    like(f:read'*l', "endianness mismatch in precompiled chunk", "bad endian")
+    f:close()
+end
+
+if _VERSION == 'Lua 5.3' then -- bad float format
+    local endian = string.dump(load "a = 1"):sub(18, 18 + string.packsize'n')
+    local f = io.open('luac.out', 'w')
+    f:write(signature .. bin_version .. format .. data .. sizes .. endian .. "\0\0\0\0\0\0\0\0")
+    f:close()
+    local cmd = luac .. [[ luac.out 2>&1]]
+    f = io.popen(cmd)
+    like(f:read'*l', "float format mismatch in precompiled chunk")
+    f:close()
+end
+
+do -- cover.lua
+    local f = io.open('cover-242.lua', 'w')
+    f:write([[
+local a = false
+b = a + 1
+pi = 3.14
+s = "all escaped \1\a\b\f\n\r\t\v\\\""
+local t = { "a", "b", "c", "d", [true] = 1 }
+local f = table.concat
+local function f ()
+    while true do
+        print(a)
+    end
+end
+local function g (...) -- segfault with Lua 5.4.0-beta
+    return {...}
+end
+s = nil
+]])
+    f:close()
+
+    local cmd = luac .. [[ -o cover-242.out cover-242.lua 2>&1]]
+    f = io.popen(cmd)
+    is(f:read'*l', nil, "-o cover-242.out cover-242.lua")
+    f:close()
+
+    cmd = luac .. [[ -l cover-242.out]]
+    f = io.popen(cmd)
+    is(f:read'*l', '', "-l cover-242.out")
+    like(f:read'*l', "^main")
+    f:close()
+
+    cmd = luac .. [[ -l -l cover-242.out]]
+    f = io.popen(cmd)
+    is(f:read'*l', '', "-l -l cover-242.out")
+    like(f:read'*l', "^main")
+    f:close()
+end
+
+os.remove('luac.out') -- clean up
+os.remove('cover-242.lua') -- clean up
+os.remove('cover-242.out') -- clean up
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/301-basic.t b/test/lua-Harness-tests/301-basic.t
new file mode 100755
index 0000000..f4f9235
--- /dev/null
+++ b/test/lua-Harness-tests/301-basic.t
@@ -0,0 +1,856 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Basic Library
+
+=head2 Synopsis
+
+    % prove 301-basic.t
+
+=head2 Description
+
+Tests Lua Basic Library
+
+See section "Basic Functions" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#5.1>,
+L<https://www.lua.org/manual/5.2/manual.html#6.1>,
+L<https://www.lua.org/manual/5.3/manual.html#6.1>,
+L<https://www.lua.org/manual/5.4/manual.html#6.1>
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local has_error53 = _VERSION >= 'Lua 5.3'
+local has_gcinfo = _VERSION == 'Lua 5.1'
+local has_getfenv = _VERSION == 'Lua 5.1'
+local has_ipairs53 = _VERSION >= 'Lua 5.3'
+local has_load52 = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local has_loadfile52 = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local has_loadstring = _VERSION == 'Lua 5.1'
+local has_alias_loadstring = profile.compat51
+local has_newproxy = _VERSION == 'Lua 5.1'
+local has_rawlen = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local has_unpack = _VERSION == 'Lua 5.1'
+local has_alias_unpack = profile.compat51
+local has_warn = _VERSION >= 'Lua 5.4'
+local has_xpcall52 = _VERSION >= 'Lua 5.2' or jit
+local has_xpcall53 = _VERSION >= 'Lua 5.3' or jit
+
+local lua = get_lua_binary_name()
+
+plan'no_plan'
+
+do -- assert
+    local v, msg = assert('text', "assert string")
+    is(v, 'text', "function assert")
+    is(msg, "assert string")
+    v, msg = assert({}, "assert table")
+    is(msg, "assert table")
+
+    error_like(function () assert(false, "ASSERTION TEST") end,
+               "^[^:]+:%d+: ASSERTION TEST",
+               "function assert(false, msg)")
+
+    error_like(function () assert(false) end,
+               "^[^:]+:%d+: assertion failed!",
+               "function assert(false)")
+
+    if has_error53 then
+        v, msg = pcall(function() assert(false, 42) end)
+        is(msg, 42, "function assert(false, 42)")
+    else
+        error_like(function () assert(false, 42) end,
+                   "^[^:]+:%d+: 42",
+                   "function assert(false, 42)")
+    end
+
+    if has_error53 then
+        local obj = {}
+        v, msg = pcall(function() assert(false, obj) end)
+        is(msg, obj, "function assert(false, {})")
+    else
+        diag("no assert with table")
+    end
+end
+
+-- collectgarbage
+if jit then
+    is(collectgarbage('stop'), 0, "function collectgarbage 'stop/restart/collect'")
+    is(collectgarbage('step'), false)
+    is(collectgarbage('restart'), 0)
+    is(collectgarbage('step'), false)
+    is(collectgarbage('collect'), 0)
+    is(collectgarbage('setpause', 10), 200)
+    is(collectgarbage('setstepmul', 200), 200)
+    is(collectgarbage(), 0)
+elseif _VERSION == 'Lua 5.1' then
+    is(collectgarbage('stop'), 0, "function collectgarbage 'stop/restart/collect'")
+    is(collectgarbage('restart'), 0)
+    is(collectgarbage('step'), false)
+    is(collectgarbage('collect'), 0)
+    is(collectgarbage(), 0)
+elseif _VERSION == 'Lua 5.2' then
+    is(collectgarbage('stop'), 0, "function collectgarbage 'stop/restart/collect'")
+    is(collectgarbage('isrunning'), false)
+    is(collectgarbage('step'), false)
+    is(collectgarbage('restart'), 0)
+    is(collectgarbage('isrunning'), true)
+    is(collectgarbage('step'), false)
+    is(collectgarbage('collect'), 0)
+    is(collectgarbage('setpause', 10), 200)
+    is(collectgarbage('setstepmul', 200), 200)
+    is(collectgarbage(), 0)
+    is(collectgarbage('generational'), 0)
+    is(collectgarbage('step'), false)
+    is(collectgarbage('incremental'), 0)
+    is(collectgarbage('setmajorinc'), 200)
+elseif _VERSION == 'Lua 5.3' then
+    is(collectgarbage('stop'), 0, "function collectgarbage 'stop/restart/collect'")
+    is(collectgarbage('isrunning'), false)
+    --is(collectgarbage('step'), false)
+    type_ok(collectgarbage('step'), 'boolean')
+    is(collectgarbage('restart'), 0)
+    is(collectgarbage('isrunning'), true)
+    is(collectgarbage('step'), false)
+    is(collectgarbage('collect'), 0)
+    is(collectgarbage('setpause', 10), 200)
+    is(collectgarbage('setstepmul', 200), 200)
+    is(collectgarbage(), 0)
+    is(collectgarbage('step'), false)
+elseif _VERSION == 'Lua 5.4' then
+    is(collectgarbage('stop'), 0, "function collectgarbage 'stop/restart/collect'")
+    is(collectgarbage('isrunning'), false)
+    is(collectgarbage('generational'), 'generational')
+    is(collectgarbage('incremental'), 'generational')
+    is(collectgarbage('incremental'), 'incremental')
+    is(collectgarbage('generational'), 'incremental')
+    is(collectgarbage('step'), false)
+    is(collectgarbage('restart'), 0)
+    is(collectgarbage('isrunning'), true)
+    is(collectgarbage('step'), false)
+    is(collectgarbage('collect'), 0)
+    is(collectgarbage('setpause', 10), 200)
+    is(collectgarbage('setstepmul', 200), 100)
+    is(collectgarbage(), 0)
+    is(collectgarbage('step'), false)
+end
+
+type_ok(collectgarbage('count'), 'number', "function collectgarbage 'count'")
+
+error_like(function () collectgarbage('unknown') end,
+           "^[^:]+:%d+: bad argument #1 to 'collectgarbage' %(invalid option 'unknown'%)",
+           "function collectgarbage (invalid)")
+
+do -- dofile
+    local f = io.open('lib-301.lua', 'w')
+    f:write[[
+function norm (x, y)
+    return (x^2 + y^2)^0.5
+end
+
+function twice (x)
+    return 2*x
+end
+]]
+    f:close()
+    dofile('lib-301.lua')
+    local n = norm(3.4, 1.0)
+    like(twice(n), '^7%.088', "function dofile")
+
+    os.remove('lib-301.lua') -- clean up
+
+    error_like(function () dofile('no_file-301.lua') end,
+               "cannot open no_file%-301%.lua: No such file or directory",
+               "function dofile (no file)")
+
+    f = io.open('foo-301.lua', 'w')
+    f:write[[?syntax error?]]
+    f:close()
+    error_like(function () dofile('foo-301.lua') end,
+               "^foo%-301%.lua:%d+:",
+               "function dofile (syntax error)")
+
+    os.remove('foo-301.lua') -- clean up
+end
+
+do -- error
+    error_like(function () error("ERROR TEST") end,
+               "^[^:]+:%d+: ERROR TEST",
+               "function error(msg)")
+
+    error_is(function () error("ERROR TEST", 0) end,
+             "ERROR TEST",
+             "function error(msg, 0)")
+
+    if has_error53 then
+        local v, msg = pcall(function() error(42) end)
+        is(msg, 42, "function error(42)")
+    else
+        error_like(function () error(42) end,
+                   "^[^:]+:%d+: 42",
+                   "function error(42)")
+    end
+
+    local obj = {}
+    local v, msg = pcall(function() error(obj) end)
+    is(msg, obj, "function error({})")
+
+    v, msg = pcall(function() error() end)
+    is(msg, nil, "function error()")
+end
+
+-- gcinfo
+if has_gcinfo then
+    type_ok(gcinfo(), 'number', "function gcinfo")
+else
+    is(gcinfo, nil, "no gcinfo (removed)")
+end
+
+-- getfenv
+if has_getfenv then
+    type_ok(getfenv(0), 'table', "function getfenv")
+    is(getfenv(0), _G)
+    is(getfenv(1), _G)
+    is(getfenv(), _G)
+    local function f () end
+    type_ok(getfenv(f), 'table')
+    is(getfenv(f), _G)
+    type_ok(getfenv(print), 'table')
+    is(getfenv(print), _G)
+
+    error_like(function () getfenv(-3) end,
+               "^[^:]+:%d+: bad argument #1 to 'getfenv' %(.-level.-%)",
+              "function getfenv (negative)")
+
+    error_like(function () getfenv(12) end,
+               "^[^:]+:%d+: bad argument #1 to 'getfenv' %(invalid level%)",
+               "function getfenv (too depth)")
+else
+    is(getfenv, nil, "no getfenv")
+end
+
+do -- getmetatable
+    is(getmetatable(true), nil, "boolean has no metatable by default")
+    is(getmetatable(getmetatable), nil, "function has no metatable by default")
+    is(getmetatable(nil), nil, "nil has no metatable by default")
+    is(getmetatable(3.14), nil, "number has no metatable by default")
+    is(getmetatable({}), nil, "table has no metatable by default")
+    local co = coroutine.create(function () return 1 end)
+    is(getmetatable(co), nil, "thread has no metatable by default")
+
+    type_ok(getmetatable('ABC'), 'table', "string has a metatable")
+    is(getmetatable('ABC'), getmetatable('abc'), "string has a shared metatable")
+end
+
+do -- ipairs
+    local a = {'a','b','c'}
+    if has_ipairs53 then
+        a = setmetatable({
+            [1] = 'a',
+            [3] = 'c',
+        }, {
+            __index = {
+               [2] = 'b',
+            }
+        })
+    end
+    local f, v, s = ipairs(a)
+    type_ok(f, 'function', "function ipairs")
+    type_ok(v, 'table')
+    is(s, 0)
+    s, v = f(a, s)
+    is(s, 1)
+    is(v, 'a')
+    s, v = f(a, s)
+    is(s, 2)
+    is(v, 'b')
+    s, v = f(a, s)
+    is(s, 3)
+    is(v, 'c')
+    s, v = f(a, s)
+    is(s, nil)
+    is(v, nil)
+end
+
+do -- load
+    local t = { [[
+function bar (x)
+    return x
+end
+]] }
+    local i = 0
+    local function reader ()
+        i = i + 1
+        return t[i]
+    end
+    local f, msg = load(reader)
+    if msg then
+        diag(msg)
+    end
+    type_ok(f, 'function', "function load(reader)")
+    is(bar, nil)
+    f()
+    is(bar('ok'), 'ok')
+    bar = nil
+
+    t = { [[
+function baz (x)
+    return x
+end
+]] }
+    i = -1
+    function reader ()
+        i = i + 1
+        return t[i]
+    end
+    f, msg = load(reader)
+    if msg then
+        diag(msg)
+    end
+    type_ok(f, 'function', "function load(pathological reader)")
+    f()
+    if _VERSION == 'Lua 5.1' and not jit then
+        todo("not with 5.1")
+    end
+    is(baz, nil)
+
+    t = { [[?syntax error?]] }
+    i = 0
+    f, msg = load(reader, "errorchunk")
+    is(f, nil, "function load(syntax error)")
+    like(msg, "^%[string \"errorchunk\"%]:%d+:")
+
+    f = load(function () return nil end)
+    type_ok(f, 'function', "when reader returns nothing")
+
+    f, msg = load(function () return {} end)
+    is(f, nil, "reader function must return a string")
+    like(msg, "reader function must return a string")
+
+    if has_load52 then
+        f = load([[
+function bar (x)
+    return x
+end
+]])
+        is(bar, nil, "function load(str)")
+        f()
+        is(bar('ok'), 'ok')
+        bar = nil
+
+        local env = {}
+        f = load([[
+function bar (x)
+    return x
+end
+]], "from string", 't', env)
+        is(env.bar, nil, "function load(str)")
+        f()
+        is(env.bar('ok'), 'ok')
+
+        f, msg = load([[?syntax error?]], "errorchunk")
+        is(f, nil, "function load(syntax error)")
+        like(msg, "^%[string \"errorchunk\"%]:%d+:")
+
+        f, msg = load([[print 'ok']], "chunk txt", 'b')
+        like(msg, "attempt to load")
+        is(f, nil, "mode")
+
+        f, msg = load("\x1bLua", "chunk bin", 't')
+        like(msg, "attempt to load")
+        is(f, nil, "mode")
+    else
+       diag("no load with string")
+    end
+end
+
+do -- loadfile
+    local f = io.open('foo-301.lua', 'w')
+    if _VERSION ~= 'Lua 5.1' or jit then
+        f:write'\xEF\xBB\xBF' -- BOM
+    end
+    f:write[[
+function foo (x)
+    return x
+end
+]]
+    f:close()
+    f = loadfile('foo-301.lua')
+    is(foo, nil, "function loadfile")
+    f()
+    is(foo('ok'), 'ok')
+
+    if has_loadfile52 then
+        local msg
+        f, msg = loadfile('foo-301.lua', 'b')
+        like(msg, "attempt to load")
+        is(f, nil, "mode")
+
+        local env = {}
+        f = loadfile('foo-301.lua', 't', env)
+        is(env.foo, nil, "function loadfile")
+        f()
+        is(env.foo('ok'), 'ok')
+    else
+        diag("no loadfile with mode & env")
+    end
+
+    os.remove('foo-301.lua') -- clean up
+
+    local msg
+    f, msg = loadfile('no_file-301.lua')
+    is(f, nil, "function loadfile (no file)")
+    is(msg, "cannot open no_file-301.lua: No such file or directory")
+
+    f = io.open('foo-301.lua', 'w')
+    f:write[[?syntax error?]]
+    f:close()
+    f, msg = loadfile('foo-301.lua')
+    is(f, nil, "function loadfile (syntax error)")
+    like(msg, '^foo%-301%.lua:%d+:')
+    os.remove('foo-301.lua') -- clean up
+end
+
+-- loadstring
+if has_loadstring then
+    local f = loadstring([[i = i + 1]])
+    i = 0
+    f()
+    is(i, 1, "function loadstring")
+    f()
+    is(i, 2)
+
+    i = 32
+    local i = 0
+    f = loadstring([[i = i + 1; return i]])
+    local g = function () i = i + 1; return i end
+    is(f(), 33, "function loadstring")
+    is(g(), 1)
+
+    local msg
+    f, msg = loadstring([[?syntax error?]])
+    is(f, nil, "function loadstring (syntax error)")
+    like(msg, '^%[string "%?syntax error%?"%]:%d+:')
+elseif has_alias_loadstring then
+    is(loadstring, load, "alias loadstring")
+else
+    is(loadstring, nil, "no loadstring")
+end
+
+-- newproxy
+if has_newproxy then
+    local proxy = newproxy(false)
+    type_ok(proxy, 'userdata', "function newproxy(false)")
+    is(getmetatable(proxy), nil, "without metatable")
+    proxy = newproxy(true)
+    type_ok(proxy, 'userdata', "function newproxy(true)")
+    type_ok(getmetatable(proxy), 'table', "with metatable")
+
+    local proxy2 = newproxy(proxy)
+    type_ok(proxy, 'userdata', "function newproxy(proxy)")
+    is(getmetatable(proxy2), getmetatable(proxy))
+
+    error_like(function () newproxy({}) end,
+               "^[^:]+:%d+: bad argument #1 to 'newproxy' %(boolean or proxy expected%)",
+               "function newproxy({})")
+else
+    is(newproxy, nil, "no newproxy")
+end
+
+do -- next
+    local t = {'a','b','c'}
+    local a = next(t, nil)
+    is(a, 1, "function next (array)")
+    a = next(t, 1)
+    is(a, 2)
+    a = next(t, 2)
+    is(a, 3)
+    a = next(t, 3)
+    is(a, nil)
+
+    error_like(function () a = next() end,
+               "^[^:]+:%d+: bad argument #1 to 'next' %(table expected, got no value%)",
+               "function next (no arg)")
+
+    error_like(function () a = next(t, 6) end,
+               "invalid key to 'next'",
+               "function next (invalid key)")
+
+    t = {'a','b','c'}
+    a = next(t, 2)
+    is(a, 3, "function next (unorderer)")
+    a = next(t, 1)
+    is(a, 2)
+    a = next(t, 3)
+    is(a, nil)
+
+    t = {}
+    a = next(t, nil)
+    is(a, nil, "function next (empty table)")
+end
+
+do -- pairs
+    local a = {'a','b','c'}
+    local f, v, s = pairs(a)
+    type_ok(f, 'function', "function pairs")
+    type_ok(v, 'table')
+    is(s, nil)
+    s = f(v, s)
+    is(s, 1)
+    s = f(v, s)
+    is(s, 2)
+    s = f(v, s)
+    is(s, 3)
+    s = f(v, s)
+    is(s, nil)
+end
+
+do -- pcall
+    local status, result = pcall(assert, 1)
+    is(status, true, "function pcall")
+    is(result, 1)
+    status, result = pcall(assert, false, 'catched')
+    is(status, false)
+    is(result, 'catched')
+    status = pcall(assert)
+    is(status, false)
+end
+
+do -- rawequal
+    local t = {}
+    local a = t
+    is(rawequal(nil, nil), true, "function rawequal -> true")
+    is(rawequal(false, false), true)
+    is(rawequal(3, 3), true)
+    is(rawequal('text', 'text'), true)
+    is(rawequal(t, a), true)
+    is(rawequal(print, print), true)
+
+    is(rawequal(nil, 2), false, "function rawequal -> false")
+    is(rawequal(false, true), false)
+    is(rawequal(false, 2), false)
+    is(rawequal(3, 2), false)
+    is(rawequal(3, '2'), false)
+    is(rawequal('text', '2'), false)
+    is(rawequal('text', 2), false)
+    is(rawequal(t, {}), false)
+    is(rawequal(t, 2), false)
+    is(rawequal(print, type), false)
+    is(rawequal(print, 2), false)
+end
+
+-- rawlen
+if has_rawlen then
+    is(rawlen("text"), 4, "function rawlen (string)")
+    is(rawlen({ 'a', 'b', 'c'}), 3, "function rawlen (table)")
+    error_like(function () local a = rawlen(true) end,
+               "^[^:]+:%d+: bad argument #1 to 'rawlen' %(table ",
+               "function rawlen (bad arg)")
+else
+    is(rawlen, nil, "no rawlen")
+end
+
+do -- rawget
+    local t = {a = 'letter a', b = 'letter b'}
+    is(rawget(t, 'a'), 'letter a', "function rawget")
+end
+
+do -- rawset
+    local t = {}
+    is(rawset(t, 'a', 'letter a'), t, "function rawset")
+    is(t.a, 'letter a')
+
+    error_like(function () t = {}; rawset(t, nil, 42) end,
+               "^table index is nil",
+               "function rawset (table index is nil)")
+end
+
+do -- select
+    is(select('#'), 0, "function select")
+    is(select('#','a','b','c'), 3)
+    eq_array({select(1,'a','b','c')}, {'a','b','c'})
+    eq_array({select(3,'a','b','c')}, {'c'})
+    eq_array({select(5,'a','b','c')}, {})
+    eq_array({select(-1,'a','b','c')}, {'c'})
+    eq_array({select(-2,'a','b','c')}, {'b', 'c'})
+    eq_array({select(-3,'a','b','c')}, {'a', 'b', 'c'})
+
+    error_like(function () select(0,'a','b','c') end,
+               "^[^:]+:%d+: bad argument #1 to 'select' %(index out of range%)",
+               "function select (out of range)")
+
+    error_like(function () select(-4,'a','b','c') end,
+               "^[^:]+:%d+: bad argument #1 to 'select' %(index out of range%)",
+               "function select (out of range)")
+end
+
+-- setfenv
+if has_getfenv then
+    local t = {}
+    local function f () end
+    is(setfenv(f, t), f, "function setfenv")
+    type_ok(getfenv(f), 'table')
+    is(getfenv(f), t)
+
+    save = getfenv(1)
+    a = 1
+    setfenv(1, {g = _G})
+    g.is(a, nil, "function setfenv")
+    g.is(g.a, 1)
+    g.setfenv(1, g.save) -- restore
+
+    save = getfenv(1)
+    a = 1
+    local newgt = {}        -- create new environment
+    setmetatable(newgt, {__index = _G})
+    setfenv(1, newgt)       -- set it
+    is(a, 1, "function setfenv")
+    a = 10
+    is(a, 10)
+    is(_G.a, 1)
+    _G.a = 20
+    is(_G.a, 20)
+    setfenv(1, save) -- restore
+
+    save = getfenv(1)
+    local function factory ()
+        return function ()
+                   return a    -- "global" a
+               end
+    end
+    a = 3
+    local f1 = factory()
+    local f2 = factory()
+    is(f1(), 3, "function setfenv")
+    is(f2(), 3)
+    setfenv(f1, {a = 10})
+    is(f1(), 10)
+    is(f2(), 3)
+    setfenv(1, save) -- restore
+
+    is(setfenv(0, _G), nil, "function setfenv(0)")
+
+    error_like(function () setfenv(-3, {}) end,
+               "^[^:]+:%d+: bad argument #1 to 'setfenv' %(.-level.-%)",
+               "function setfenv (negative)")
+
+    error_like(function () setfenv(12, {}) end,
+               "^[^:]+:%d+: bad argument #1 to 'setfenv' %(invalid level%)",
+               "function setfenv (too depth)")
+
+    t = {}
+    error_like(function () setfenv(t, {}) end,
+               "^[^:]+:%d+: bad argument #1 to 'setfenv' %(number expected, got table%)",
+               "function setfenv (bad arg)")
+
+    error_like(function () setfenv(print, {}) end,
+               "^[^:]+:%d+: 'setfenv' cannot change environment of given object",
+               "function setfenv (forbidden)")
+else
+    is(setfenv, nil, "no setfenv")
+end
+
+do -- setmetatable
+    local mt = {}
+    local t = {}
+    is(t, setmetatable(t, mt), "setmetatable")
+    is(getmetatable(t), mt)
+    is(t, setmetatable(t, nil))
+    is(getmetatable(t), nil)
+
+    error_like(function () setmetatable(t, true) end,
+               "^[^:]+:%d+: bad argument #2 to 'setmetatable' %(nil or table expected",
+               "function setmetatable (bad arg)")
+    error_like(function () setmetatable(true, mt) end,
+               "^[^:]+:%d+: bad argument #1 to 'setmetatable' %(table expected, got boolean%)",
+               "function setmetatable (bad arg)")
+end
+
+do -- type
+    is(type("Hello world"), 'string', "function type")
+    is(type(10.4*3), 'number')
+    is(type(print), 'function')
+    is(type(type), 'function')
+    is(type(true), 'boolean')
+    is(type(nil), 'nil')
+    is(type(io.stdin), 'userdata')
+    is(type(type(X)), 'string')
+
+    local a = nil
+    is(type(a), 'nil', "function type")
+    a = 10
+    is(type(a), 'number')
+    a = "a string!!"
+    is(type(a), 'string')
+    a = print
+    is(type(a), 'function')
+    is(type(function () end), 'function')
+
+    error_like(function () type() end,
+               "^[^:]+:%d+: bad argument #1 to 'type' %(value expected%)",
+               "function type (no arg)")
+end
+
+do -- tonumber
+    is(tonumber('text12'), nil, "function tonumber")
+    is(tonumber('12text'), nil)
+    is(tonumber(3.14), 3.14)
+    is(tonumber('3.14'), 3.14)
+    is(tonumber('  3.14  '), 3.14)
+    is(tonumber(tostring(111), 2), 7)
+    is(tonumber('111', 2), 7)
+    is(tonumber('  111  ', 2), 7)
+    local a = {}
+    is(tonumber(a), nil)
+
+    error_like(function () tonumber() end,
+               "^[^:]+:%d+: bad argument #1 to 'tonumber' %(value expected%)",
+               "function tonumber (no arg)")
+
+    error_like(function () tonumber('111', 200) end,
+               "^[^:]+:%d+: bad argument #2 to 'tonumber' %(base out of range%)",
+               "function tonumber (bad base)")
+end
+
+do -- tostring
+    is(tostring('text'), 'text', "function tostring")
+    is(tostring(3.14), '3.14')
+    is(tostring(nil), 'nil')
+    is(tostring(true), 'true')
+    is(tostring(false), 'false')
+    like(tostring({}), '^table: 0?[Xx]?%x+$')
+    like(tostring(print), '^function: 0?[Xx]?[builtin]*#?%x+$')
+
+    error_like(function () tostring() end,
+               "^[^:]+:%d+: bad argument #1 to 'tostring' %(value expected%)",
+               "function tostring (no arg)")
+end
+
+-- unpack
+if has_unpack then
+    eq_array({unpack({})}, {}, "function unpack")
+    eq_array({unpack({'a'})}, {'a'})
+    eq_array({unpack({'a','b','c'})}, {'a','b','c'})
+    eq_array({(unpack({'a','b','c'}))}, {'a'})
+    eq_array({unpack({'a','b','c','d','e'},2,4)}, {'b','c','d'})
+    eq_array({unpack({'a','b','c'},2,4)}, {'b','c'})
+elseif has_alias_unpack then
+    is(unpack, table.unpack, "alias unpack")
+else
+    is(unpack, nil, "no unpack")
+end
+
+-- warn
+if has_warn then
+    is(warn('foo'), nil, "function warn")
+
+    local r, f = pcall(io.popen, lua .. [[ -W -e "warn'foo'" 2>&1]])
+    if r then
+        is(f:read'*l', 'Lua warning: foo', "warn called with popen")
+        is(f:read'*l', nil)
+        is(f:close(), true)
+    else
+        diag("io.popen not supported")
+    end
+
+    r, f = pcall(io.popen, lua .. [[ -e "warn'@on'; warn'foo'" 2>&1]])
+    if r then
+        is(f:read'*l', 'Lua warning: foo', "warn called with popen")
+        is(f:read'*l', nil)
+        is(f:close(), true)
+    else
+        diag("io.popen not supported")
+    end
+
+    r, f = pcall(io.popen, lua .. [[ -e "warn'@on'; warn('foo', 'bar')" 2>&1]])
+    if r then
+        is(f:read'*l', 'Lua warning: foobar', "warn called with popen")
+        is(f:read'*l', nil)
+        is(f:close(), true)
+    else
+        diag("io.popen not supported")
+    end
+
+    error_like(function () warn('foo', warn) end,
+               "^[^:]+:%d+: bad argument #2 to 'warn' %(string expected, got function%)",
+               "function warn (no arg)")
+
+    error_like(function () warn() end,
+               "^[^:]+:%d+: bad argument #1 to 'warn' %(string expected, got no value%)",
+               "function warn (no arg)")
+else
+    is(warn, nil, "no warn")
+end
+
+do -- xpcall
+    local function err (obj)
+        return obj
+    end
+
+    local function backtrace ()
+        return 'not a back trace'
+    end
+
+    local status, result = xpcall(function () return assert(1) end, err)
+    is(status, true, "function xpcall")
+    is(result, 1)
+    status, result = xpcall(function () return assert(false, 'catched') end, err)
+    is(status, false)
+    if jit then
+        is(result, 'catched')
+    else
+        like(result, ':%d+: catched')
+    end
+    status, result = xpcall(function () return assert(false, 'catched') end, backtrace)
+    is(status, false)
+    is(result, 'not a back trace')
+
+    if has_xpcall52 then
+        status, result = xpcall(assert, err, 1)
+        is(status, true, "function xpcall with args")
+        is(result, 1)
+        status, result = xpcall(assert, err, false, 'catched')
+        is(status, false)
+        is(result, 'catched')
+        status, result = xpcall(assert, backtrace, false, 'catched')
+        is(status, false)
+        is(result, 'not a back trace')
+    end
+
+    error_like(function () xpcall(assert) end,
+               "bad argument #2 to 'xpcall' %(.-",
+               "function xpcall")
+
+    if has_xpcall53 then
+        error_like(function () xpcall(assert, 1) end,
+                   "bad argument #2 to 'xpcall' %(function expected, got number%)",
+                  "function xpcall")
+    else
+        is(xpcall(assert, nil), false, "function xpcall")
+    end
+end
+
+if jit and pcall(require, 'ffi') then
+    dofile'lexicojit/basic.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/303-package.t b/test/lua-Harness-tests/303-package.t
new file mode 100755
index 0000000..7e5216d
--- /dev/null
+++ b/test/lua-Harness-tests/303-package.t
@@ -0,0 +1,290 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Package Library
+
+=head2 Synopsis
+
+    % prove 303-package.t
+
+=head2 Description
+
+Tests Lua Package Library
+
+See section "Modules" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#5.3>,
+L<https://www.lua.org/manual/5.2/manual.html#6.3>,
+L<https://www.lua.org/manual/5.3/manual.html#6.3>,
+L<https://www.lua.org/manual/5.4/manual.html#6.3>
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
+local has_loaders = _VERSION == 'Lua 5.1'
+local has_alias_loaders = profile.compat51
+local has_loadlib52 = _VERSION >= 'Lua 5.2' or jit
+local has_module = _VERSION == 'Lua 5.1' or profile.compat51
+local has_searchers = _VERSION >= 'Lua 5.2'
+local has_alias_searchers = luajit21 and profile.luajit_compat52
+local has_searcherpath = _VERSION >= 'Lua 5.2' or jit
+local has_require54 = _VERSION >= 'Lua 5.4'
+
+plan'no_plan'
+
+
+type_ok(package.config, 'string')
+
+type_ok(package.cpath, 'string')
+
+type_ok(package.path, 'string')
+
+if has_loaders then
+    type_ok(package.loaders, 'table', "table package.loaders")
+elseif has_alias_loaders then
+    is(package.loaders, package.searchers, "alias package.loaders")
+else
+    is(package.loaders, nil, "no package.loaders")
+end
+
+if has_searchers then
+    type_ok(package.searchers, 'table', "table package.searchers")
+elseif has_alias_searchers then
+    is(package.searchers, package.loaders, "alias package.searchers")
+else
+    is(package.searchers, nil, "no package.searchers")
+end
+
+do -- loaded
+    ok(package.loaded._G, "table package.loaded")
+    ok(package.loaded.coroutine)
+    ok(package.loaded.io)
+    ok(package.loaded.math)
+    ok(package.loaded.os)
+    ok(package.loaded.package)
+    ok(package.loaded.string)
+    ok(package.loaded.table)
+
+    local m = require'os'
+    is(m, package.loaded['os'])
+end
+
+do -- preload
+    type_ok(package.preload, 'table', "table package.preload")
+    is(# package.preload, 0)
+
+    local foo = {}
+    foo.bar = 1234
+    local function foo_loader ()
+       return foo
+    end
+    package.preload.foo = foo_loader
+    local m = require 'foo'
+    assert(m == foo)
+    is(m.bar, 1234, "function require & package.preload")
+end
+
+do -- loadlib
+    local path_lpeg = package.searchpath and package.searchpath('lpeg', package.cpath)
+
+    local f, msg = package.loadlib('libbar', 'baz')
+    is(f, nil, "loadlib")
+    type_ok(msg, 'string')
+
+    if path_lpeg then
+        f, msg = package.loadlib(path_lpeg, 'baz')
+        is(f, nil, "loadlib")
+        like(msg, 'undefined symbol')
+
+        f = package.loadlib(path_lpeg, 'luaopen_lpeg')
+        type_ok(f, 'function', "loadlib ok")
+    else
+        skip("no lpeg path")
+    end
+
+    if has_loadlib52 then
+        f, msg = package.loadlib('libbar', '*')
+        is(f, nil, "loadlib '*'")
+        type_ok(msg, 'string')
+
+        if path_lpeg then
+            f = package.loadlib(path_lpeg, '*')
+            is(f, true, "loadlib '*'")
+        else
+            skip("no lpeg path")
+        end
+    end
+end
+
+-- searchpath
+if has_searcherpath then
+    local p = package.searchpath('tap', package.path)
+    type_ok(p, 'string', "searchpath")
+    p = package.searchpath('tap', 'bad path')
+    is(p, nil)
+else
+    is(package.searchpath, nil, "no package.searchpath")
+end
+
+do -- require
+    local f = io.open('complex.lua', 'w')
+    f:write [[
+complex = {}
+
+function complex.new (r, i) return {r=r, i=i} end
+
+--defines a constant 'i'
+complex.i = complex.new(0, 1)
+
+function complex.add (c1, c2)
+    return complex.new(c1.r + c2.r, c1.i + c2.i)
+end
+
+function complex.sub (c1, c2)
+    return complex.new(c1.r - c2.r, c1.i - c2.i)
+end
+
+function complex.mul (c1, c2)
+    return complex.new(c1.r*c2.r - c1.i*c2.i,
+                       c1.r*c2.i + c1.i*c2.r)
+end
+
+local function inv (c)
+    local n = c.r^2 + c.i^2
+    return complex.new(c.r/n, -c.i/n)
+end
+
+function complex.div (c1, c2)
+    return complex.mul(c1, inv(c2))
+end
+
+return complex
+]]
+    f:close()
+    if has_require54 then
+        local m1, path1 = require 'complex'
+        is(m1, complex, "function require")
+        is(path1, './complex.lua')
+        local m2, path2 = require 'complex'
+        is(m1, m2)
+        is(path2, nil)
+    else
+        local m1 = require 'complex'
+        is(m1, complex, "function require")
+        local m2 = require 'complex'
+        is(m1, m2)
+    end
+    is(complex.i.r, 0)
+    is(complex.i.i, 1)
+    os.remove('complex.lua') -- clean up
+
+    error_like(function () require('no_module') end,
+               "^[^:]+:%d+: module 'no_module' not found:",
+               "function require (no module)")
+
+    f = io.open('syntax.lua', 'w')
+    f:write [[?syntax error?]]
+    f:close()
+    error_like(function () require('syntax') end,
+               "^error loading module 'syntax' from file '%.[/\\]syntax%.lua':",
+               "function require (syntax error)")
+    os.remove('syntax.lua') -- clean up
+
+    f = io.open('bar.lua', 'w')
+    f:write [[
+    print("    in bar.lua", ...)
+    a = ...
+]]
+    f:close()
+    a = nil
+    require 'bar'
+    is(a, 'bar', "function require (arg)")
+    os.remove('bar.lua') -- clean up
+
+    f = io.open('cplx.lua', 'w')
+    f:write [[
+-- print('cplx.lua', ...)
+local _G = _G
+_ENV = nil
+local cplx = {}
+
+local function new (r, i) return {r=r, i=i} end
+cplx.new = new
+
+--defines a constant 'i'
+cplx.i = new(0, 1)
+
+function cplx.add (c1, c2)
+    return new(c1.r + c2.r, c1.i + c2.i)
+end
+
+function cplx.sub (c1, c2)
+    return new(c1.r - c2.r, c1.i - c2.i)
+end
+
+function cplx.mul (c1, c2)
+    return new(c1.r*c2.r - c1.i*c2.i,
+               c1.r*c2.i + c1.i*c2.r)
+end
+
+local function inv (c)
+    local n = c.r^2 + c.i^2
+    return new(c.r/n, -c.i/n)
+end
+
+function cplx.div (c1, c2)
+    return mul(c1, inv(c2))
+end
+
+_G.cplx = cplx
+return cplx
+]]
+    f:close()
+    require 'cplx'
+    is(cplx.i.r, 0, "function require & module")
+    is(cplx.i.i, 1)
+    os.remove('cplx.lua') -- clean up
+end
+
+-- module & seeall
+local done_testing = done_testing
+if has_module then
+    m = {}
+    package.seeall(m)
+    m.pass("function package.seeall")
+
+    is(mod, nil, "function module & seeall")
+    module('mod', package.seeall)
+    type_ok(mod, 'table')
+    is(mod, package.loaded.mod)
+
+    is(modz, nil, "function module")
+    local _G = _G
+    module('modz')
+    _G.type_ok(_G.modz, 'table')
+    _G.is(_G.modz, _G.package.loaded.modz)
+else
+    is(package.seeall, nil, "package.seeall (removed)")
+    is(module, nil, "module (removed)")
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/304-string.t b/test/lua-Harness-tests/304-string.t
new file mode 100755
index 0000000..991600a
--- /dev/null
+++ b/test/lua-Harness-tests/304-string.t
@@ -0,0 +1,633 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua String Library
+
+=head2 Synopsis
+
+    % prove 304-string.t
+
+=head2 Description
+
+Tests Lua String Library
+
+See section "String Manipulation" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#5.4>,
+L<https://www.lua.org/manual/5.2/manual.html#6.4>,
+L<https://www.lua.org/manual/5.3/manual.html#6.4>,
+L<https://www.lua.org/manual/5.4/manual.html#6.4>
+
+=cut
+
+]]
+
+require'tap'
+local profile = require'profile'
+local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
+local has_dump53 = _VERSION >= 'Lua 5.3' or jit
+local has_format_a = _VERSION >= 'Lua 5.3' or profile.has_string_format_a or jit
+local has_format_p = _VERSION >= 'Lua 5.4'
+local has_format_q52 = _VERSION >= 'Lua 5.2' or jit
+local has_format_q53 = _VERSION >= 'Lua 5.3'
+local has_format_q54 = _VERSION >= 'Lua 5.4'
+local has_gmatch54 = _VERSION >= 'Lua 5.4'
+local has_pack = _VERSION >= 'Lua 5.3' or (jit and jit.version:match'moonjit') or profile.pack
+local has_rep52 = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local has_class_g = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local loadstring = loadstring or load
+
+plan'no_plan'
+
+do -- metatable
+    local mt = getmetatable('ABC')
+    type_ok(mt, 'table', "metatable")
+    type_ok(mt.__index, 'table')
+
+    if not profile.nocvts2n and _VERSION >= 'Lua 5.4' then
+        type_ok(mt.__add, 'function')
+        type_ok(mt.__div, 'function')
+        type_ok(mt.__idiv, 'function')
+        type_ok(mt.__mul, 'function')
+        type_ok(mt.__mod, 'function')
+        type_ok(mt.__pow, 'function')
+        type_ok(mt.__sub, 'function')
+        type_ok(mt.__unm, 'function')
+    else
+        is(mt.__add, nil)
+        is(mt.__div, nil)
+        is(mt.__idiv, nil)
+        is(mt.__mul, nil)
+        is(mt.__mod, nil)
+        is(mt.__pow, nil)
+        is(mt.__sub, nil)
+        is(mt.__unm, nil)
+    end
+
+    is(mt.__index.byte, string.byte)
+    is(mt.__index.char, string.char)
+    is(mt.__index.dump, string.dump)
+    is(mt.__index.find, string.find)
+    is(mt.__index.format, string.format)
+    is(mt.__index.gmatch, string.gmatch)
+    is(mt.__index.gsub, string.gsub)
+    is(mt.__index.len, string.len)
+    is(mt.__index.lower, string.lower)
+    is(mt.__index.match, string.match)
+    is(mt.__index.rep, string.rep)
+    is(mt.__index.reverse, string.reverse)
+    is(mt.__index.sub, string.sub)
+    is(mt.__index.upper, string.upper)
+
+    if has_pack then
+        is(mt.__index.pack, string.pack)
+        is(mt.__index.packsize, string.packsize)
+        is(mt.__index.unpack, string.unpack)
+    else
+        is(mt.__index.pack, nil)
+        is(mt.__index.packsize, nil)
+        is(mt.__index.unpack, nil)
+    end
+end
+
+do -- byte
+    is(string.byte('ABC'), 65, "function byte")
+    is(string.byte('ABC', 2), 66)
+    is(string.byte('ABC', -1), 67)
+    is(string.byte('ABC', 4), nil)
+    is(string.byte('ABC', 0), nil)
+    eq_array({string.byte('ABC', 1, 3)}, {65, 66, 67})
+    eq_array({string.byte('ABC', 1, 4)}, {65, 66, 67})
+
+    local s = "ABC"
+    is(s:byte(2), 66, "method s:byte")
+end
+
+do -- char
+    is(string.char(65, 66, 67), 'ABC', "function char")
+    is(string.char(), '')
+
+    error_like(function () string.char(0, 'bad') end,
+               "^[^:]+:%d+: bad argument #2 to 'char' %(number expected, got string%)",
+               "function char (bad arg)")
+
+    error_like(function () string.char(0, 9999) end,
+               "^[^:]+:%d+: bad argument #2 to 'char' %(.-value.-%)",
+               "function char (invalid)")
+end
+
+do -- dump
+    local signature
+    if jit then
+        signature = "\x1bLJ"
+    elseif ravi then
+        signature = "\x1bRavi"
+    elseif _VERSION >= 'Lua 5.2' then
+        signature = "\x1bLua"
+    end
+
+    local function add (a, b)
+        return a + b
+    end
+
+    local d = string.dump(add)
+    type_ok(d, 'string', "function dump")
+    local f = loadstring(d)
+    type_ok(f, 'function')
+    is(f(1, 2), 3)
+
+    if signature then
+        local sig = d:sub(1, #signature)
+        is(sig, signature)
+    end
+
+    if has_dump53 then
+        local d2 = string.dump(add, true)
+        type_ok(d2, 'string', "function dump with strip")
+        f = loadstring(d2)
+        type_ok(f, 'function')
+        is(f(1, 2), 3)
+        isnt(d2:len(), d:len())
+
+        if signature then
+            local sig = d2:sub(1, #signature)
+            is(sig, signature)
+        end
+    end
+
+    error_like(function () string.dump(print) end,
+               "^[^:]+:%d+: unable to dump given function",
+               "function dump (C function)")
+end
+
+do -- find
+    local s = "hello world"
+    eq_array({string.find(s, "hello")}, {1, 5}, "function find (mode plain)")
+    eq_array({string.find(s, "hello", 1, true)}, {1, 5})
+    eq_array({string.find(s, "hello", 1)}, {1, 5})
+    is(string.sub(s, 1, 5), "hello")
+    eq_array({string.find(s, "world")}, {7, 11})
+    eq_array({string.find(s, "l")}, {3, 3})
+    is(string.find(s, "lll"), nil)
+    is(string.find(s, "hello", 2, true), nil)
+    eq_array({string.find(s, "world", 2, true)}, {7, 11})
+    is(string.find(s, "hello", 20), nil)
+
+    s = "hello world"
+    eq_array({string.find(s, "^h.ll.")}, {1, 5}, "function find (with regex & captures)")
+    eq_array({string.find(s, "w.rld", 2)}, {7, 11})
+    is(string.find(s, "W.rld"), nil)
+    eq_array({string.find(s, "^(h.ll.)")}, {1, 5, 'hello'})
+    eq_array({string.find(s, "^(h.)l(l.)")}, {1, 5, 'he', 'lo'})
+    s = "Deadline is 30/05/1999, firm"
+    local date = "%d%d/%d%d/%d%d%d%d"
+    is(string.sub(s, string.find(s, date)), "30/05/1999")
+    date = "%f[%S]%d%d/%d%d/%d%d%d%d"
+    is(string.sub(s, string.find(s, date)), "30/05/1999")
+
+    error_like(function () string.find(s, '%f') end,
+               "^[^:]+:%d+: missing '%[' after '%%f' in pattern",
+               "function find (invalid frontier)")
+end
+
+do -- format
+    is(string.format("pi = %.4f", math.pi), 'pi = 3.1416', "function format")
+    local d = 5; local m = 11; local y = 1990
+    is(string.format("%02d/%02d/%04d", d, m, y), "05/11/1990")
+    is(string.format("%X %x", 126, 126), "7E 7e")
+    local tag, title = "h1", "a title"
+    is(string.format("<%s>%s</%s>", tag, title, tag), "<h1>a title</h1>")
+
+    is(string.format('%q', 'a string with "quotes" and \n new line'), [["a string with \"quotes\" and \
+ new line"]], "function format %q")
+
+    if has_format_q52 then
+        is(string.format('%q', 'a string with \0 and \r.'), [["a string with \0 and \13."]], "function format %q")
+        is(string.format('%q', 'a string with \b and \b2'), [["a string with \8 and \0082"]], "function format %q")
+    else
+        is(string.format('%q', 'a string with \0 and \r.'), [["a string with \000 and \r."]], "function format %q")
+        is(string.format('%q', 'a string with \b and \b2'), '"a string with \b and \b2"', "function format %q")
+    end
+
+    if has_format_q53 then
+        is(string.format('%q', 1.5), '0x1.8p+0', "function format %q")
+        is(string.format('%q', 7), '7', "function format %q")
+    else
+        is(string.format('%q', 1.5), [["1.5"]], "function format %q")
+        is(string.format('%q', 7), [["7"]], "function format %q")
+    end
+
+    if has_format_q53 then
+        is(string.format('%q', nil), 'nil', "function format ('%q', nil)")
+    elseif luajit21 then
+        is(string.format('%q', nil), [["nil"]], "function format ('%q', nil)")
+    else
+        error_like(function () string.format("%q", nil) end,
+                   "^[^:]+:%d+: bad argument #2 to 'format' %(",
+                   "function format ('%q', nil)")
+    end
+
+    if has_format_q54 then
+        is(string.format('%q', 0/0), '(0/0)', "function format ('%q', NaN)")
+        is(string.format('%q', 1/0), '1e9999', "function format ('%q', +Inf)")
+        is(string.format('%q', -1/0), '-1e9999', "function format ('%q', -Inf)")
+
+        error_like(function () string.format("%-q", 0) end,
+                   "^[^:]+:%d+: specifier '%%q' cannot have modifiers",
+                   "function format '%-q'")
+    end
+
+    if luajit21 then
+        like(string.format('%q', {}), [[^"table: ]], "function format ('%q', {})")
+    else
+        error_like(function () string.format("%q", {}) end,
+                   "^[^:]+:%d+: bad argument #2 to 'format' %(",
+                   "function format ('%q', {})")
+    end
+
+    if has_format_a then
+        is(string.format('%a', 1.5), '0x1.8p+0', "function format %a")
+    end
+
+    if has_format_p then
+        is(string.format('table: %p', string), tostring(string), "function format %p")
+    end
+
+    is(string.format("%5s", 'foo'), '  foo', "function format (%5s)")
+
+    if _VERSION >= 'Lua 5.3' then
+        error_like(function () string.format("%5s", "foo\0bar") end,
+                   "^[^:]+:%d+: bad argument #2 to 'format' %(string contains zeros%)",
+                   "function format format (%5s with \\0)")
+    end
+
+    is(string.format("%s %s", 1, 2, 3), '1 2', "function format (too many arg)")
+
+    is(string.format("%% %c %%", 65), '% A %', "function format (%%)")
+
+    local r = string.rep("ab", 100)
+    is(string.format("%s %d", r, r:len()), r .. " 200")
+
+    error_like(function () string.format("%s %s", 1) end,
+               "^[^:]+:%d+: bad argument #3 to 'format' %(.-no value%)",
+               "function format (too few arg)")
+
+    error_like(function () string.format('%d', 'toto') end,
+               "^[^:]+:%d+: bad argument #2 to 'format' %(number expected, got string%)",
+               "function format (bad arg)")
+
+    error_like(function () string.format('%k', 'toto') end,
+               "^[^:]+:%d+: invalid .- '%%k' to 'format'",
+               "function format (invalid conversion)")
+
+    if luajit21 then
+        error_like(function () string.format('%111s', 'toto') end,
+                   "^[^:]+:%d+: invalid option '%%111' to 'format'",
+                   "function format (invalid format)")
+    else
+        error_like(function () string.format('%111s', 'toto') end,
+                   "^[^:]+:%d+: invalid format %(width or precision too long%)",
+                   "function format (invalid format)")
+
+        error_like(function () string.format('%------s', 'toto') end,
+                   "^[^:]+:%d+: invalid format %(repeated flags%)",
+                   "function format (invalid format)")
+    end
+
+    error_like(function () string.format('pi = %.123f', math.pi) end,
+               "^[^:]+:%d+: invalid ",
+               "function format (invalid format)")
+
+    error_like(function () string.format('% 123s', 'toto') end,
+               "^[^:]+:%d+: invalid ",
+               "function format (invalid format)")
+end
+
+do -- gmatch
+    local s = "hello"
+    local output = {}
+    for c in string.gmatch(s, '..') do
+        table.insert(output, c)
+    end
+    eq_array(output, {'he', 'll'}, "function gmatch")
+    if has_gmatch54 then
+        output = {}
+        for c in string.gmatch(s, '..', 2) do
+            table.insert(output, c)
+        end
+        eq_array(output, {'el', 'lo'})
+    end
+    output = {}
+    for c1, c2 in string.gmatch(s, '(.)(.)') do
+        table.insert(output, c1)
+        table.insert(output, c2)
+    end
+    eq_array(output, {'h', 'e', 'l', 'l'})
+    s = "hello world from Lua"
+    output = {}
+    for w in string.gmatch(s, '%a+') do
+        table.insert(output, w)
+    end
+    eq_array(output, {'hello', 'world', 'from', 'Lua'})
+    s = "from=world, to=Lua"
+    output = {}
+    for k, v in string.gmatch(s, '(%w+)=(%w+)') do
+        table.insert(output, k)
+        table.insert(output, v)
+    end
+    eq_array(output, {'from', 'world', 'to', 'Lua'})
+end
+
+do -- gsub
+    is(string.gsub("hello world", "(%w+)", "%1 %1"), "hello hello world world", "function gsub")
+    is(string.gsub("hello world", "%w+", "%0 %0", 1), "hello hello world")
+    is(string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1"), "world hello Lua from")
+    if _VERSION == 'Lua 5.1' then
+        todo("not with 5.1")
+    end
+    error_like(function () string.gsub("hello world", "%w+", "%e") end,
+               "^[^:]+:%d+: invalid use of '%%' in replacement string",
+               "function gsub (invalid replacement string)")
+    is(string.gsub("home = $HOME, user = $USER", "%$(%w+)", string.reverse), "home = EMOH, user = RESU")
+    is(string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) return tostring(loadstring(s)()) end), "4+5 = 9")
+    local t = {name='lua', version='5.1'}
+    is(string.gsub("$name-$version.tar.gz", "%$(%w+)", t), "lua-5.1.tar.gz")
+
+    is(string.gsub("Lua is cute", 'cute', 'great'), "Lua is great")
+    is(string.gsub("all lii", 'l', 'x'), "axx xii")
+    is(string.gsub("Lua is great", '^Sol', 'Sun'), "Lua is great")
+    is(string.gsub("all lii", 'l', 'x', 1), "axl lii")
+    is(string.gsub("all lii", 'l', 'x', 2), "axx lii")
+    is(select(2, string.gsub("string with 3 spaces", ' ', ' ')), 3)
+
+    eq_array({string.gsub("hello, up-down!", '%A', '.')}, {"hello..up.down.", 4})
+    eq_array({string.gsub("hello, up-down!", '%A', '%%')}, {"hello%%up%down%", 4})
+    local text = "hello world"
+    local nvow = select(2, string.gsub(text, '[AEIOUaeiou]', ''))
+    is(nvow, 3)
+    eq_array({string.gsub("one, and two; and three", '%a+', 'word')}, {"word, word word; word word", 5})
+    local test = "int x; /* x */  int y; /* y */"
+    eq_array({string.gsub(test, "/%*.*%*/", '<COMMENT>')}, {"int x; <COMMENT>", 1})
+    eq_array({string.gsub(test, "/%*.-%*/", '<COMMENT>')}, {"int x; <COMMENT>  int y; <COMMENT>", 2})
+    local s = "a (enclosed (in) parentheses) line"
+    eq_array({string.gsub(s, '%b()', '')}, {"a  line", 1})
+
+    error_like(function () string.gsub(s, '%b(', '') end,
+               "^[^:]+:%d+: .- pattern",
+               "function gsub (malformed pattern)")
+
+    eq_array({string.gsub("hello Lua!", "%a", "%0-%0")}, {"h-he-el-ll-lo-o L-Lu-ua-a!", 8})
+    eq_array({string.gsub("hello Lua", "(.)(.)", "%2%1")}, {"ehll ouLa", 4})
+
+    local function expand (str)
+        return (string.gsub(str, '$(%w+)', _G))
+    end
+    name = 'Lua'; status= 'great'
+    is(expand("$name is $status, isn't it?"), "Lua is great, isn't it?")
+    is(expand("$othername is $status, isn't it?"), "$othername is great, isn't it?")
+
+    function expand (str)
+        return (string.gsub(str, '$(%w+)', function (n)
+                                            return tostring(_G[n]), 1
+                                       end))
+    end
+    like(expand("print = $print; a = $a"), "^print = function: [0]?[Xx]?[builtin]*#?%x+; a = nil")
+
+    error_like(function () string.gsub("hello world", '(%w+)', '%2 %2') end,
+               "^[^:]+:%d+: invalid capture index",
+               "function gsub (invalid index)")
+
+    error_like(function () string.gsub("hello world", '(%w+)', true) end,
+               "^[^:]+:%d+: bad argument #3 to 'gsub' %(string/function/table expected",
+               "function gsub (bad type)")
+
+    error_like(function ()
+        function expand (str)
+           return (string.gsub(str, '$(%w+)', _G))
+        end
+
+        name = 'Lua'; status= true
+        expand("$name is $status, isn't it?")
+               end,
+               "^[^:]+:%d+: invalid replacement value %(a boolean%)",
+               "function gsub (invalid value)")
+
+    local function trim (str)
+        return (str:gsub('^%s*(.-)%s*$', '%1'))
+    end
+    is(trim('foo'), 'foo', "gsub trim")
+    is(trim('   foo  bar  '), 'foo  bar')
+end
+
+do -- len
+    is(string.len(''), 0, "function len")
+    is(string.len('test'), 4)
+    is(string.len("a\000b\000c"), 5)
+    is(string.len('"'), 1)
+end
+
+do -- lower
+    is(string.lower('Test'), 'test', "function lower")
+    is(string.lower('TeSt'), 'test')
+end
+
+do -- match
+    local s = "hello world"
+    is(string.match(s, '^hello'), 'hello', "function match")
+    is(string.match(s, 'world', 2), 'world')
+    is(string.match(s, 'World'), nil)
+    eq_array({string.match(s, '^(h.ll.)')}, {'hello'})
+    eq_array({string.match(s, '^(h.)l(l.)')}, {'he', 'lo'})
+    local date = "Today is 17/7/1990"
+    is(string.match(date, '%d+/%d+/%d+'), '17/7/1990')
+    eq_array({string.match(date, '(%d+)/(%d+)/(%d+)')}, {'17', '7', '1990'})
+    is(string.match("The number 1298 is even", '%d+'), '1298')
+    local pair = "name = Anna"
+    eq_array({string.match(pair, '(%a+)%s*=%s*(%a+)')}, {'name', 'Anna'})
+
+    s = [[then he said: "it's all right"!]]
+    eq_array({string.match(s, "([\"'])(.-)%1")}, {'"', "it's all right"}, "function match (back ref)")
+    local p = "%[(=*)%[(.-)%]%1%]"
+    s = "a = [=[[[ something ]] ]==]x]=]; print(a)"
+    eq_array({string.match(s, p)}, {'=', '[[ something ]] ]==]x'})
+
+    if has_class_g then
+        is(string.match(s, "%g"), "a", "match graphic char")
+    end
+
+    error_like(function () string.match("hello world", "%1") end,
+               "^[^:]+:%d+: invalid capture index",
+               "function match invalid capture")
+
+    error_like(function () string.match("hello world", "%w)") end,
+               "^[^:]+:%d+: invalid pattern capture",
+               "function match invalid capture")
+end
+
+-- pack
+if has_pack then
+    is(string.pack('b', 0x31), '\x31', "function pack")
+    is(string.pack('>b', 0x31), '\x31')
+    is(string.pack('=b', 0x31), '\x31')
+    is(string.pack('<b', 0x31), '\x31')
+    is(string.pack('>B', 0x91), '\x91')
+    is(string.pack('=B', 0x91), '\x91')
+    is(string.pack('<B', 0x91), '\x91')
+    is(string.byte(string.pack('<h', 1)), 1)
+    is(string.byte(string.pack('>h', 1):reverse()), 1)
+    is(string.byte(string.pack('<H', 1)), 1)
+    is(string.byte(string.pack('>H', 1):reverse()), 1)
+    is(string.byte(string.pack('<l', 1)), 1)
+    is(string.byte(string.pack('>l', 1):reverse()), 1)
+    is(string.byte(string.pack('<L', 1)), 1)
+    is(string.byte(string.pack('>L', 1):reverse()), 1)
+    is(string.byte(string.pack('<j', 1)), 1)
+    is(string.byte(string.pack('>j', 1):reverse()), 1)
+    is(string.byte(string.pack('<J', 1)), 1)
+    is(string.byte(string.pack('>J', 1):reverse()), 1)
+    is(string.byte(string.pack('<T', 1)), 1)
+    is(string.byte(string.pack('>T', 1):reverse()), 1)
+    is(string.byte(string.pack('<i', 1)), 1)
+    is(string.byte(string.pack('>i', 1):reverse()), 1)
+    is(string.byte(string.pack('<I', 1)), 1)
+    is(string.byte(string.pack('>I', 1):reverse()), 1)
+    is(string.pack('i1', 0):len(), 1)
+    is(string.pack('i2', 0):len(), 2)
+    is(string.pack('i4', 0):len(), 4)
+    is(string.pack('i8', 0):len(), 8)
+    is(string.pack('i16', 0):len(), 16)
+    error_like(function () string.pack('i20', 0) end,
+               "^[^:]+:%d+: integral size %(20%) out of limits %[1,16%]",
+               "function pack out limit")
+
+    is(string.pack('!2 i1 i4', 0, 0):len(), 6)
+    is(string.pack('i1 Xb i1', 0, 0):len(), 2)
+    is(string.pack('i1 x x i1', 0, 0):len(), 4)
+
+    is(string.pack('c3', 'foo'), 'foo')
+    is(string.pack('z', 'foo'), 'foo\0')
+    is(string.pack('c4', 'foo'), 'foo\0')   -- padding
+
+    error_like(function () string.pack('w', 0) end,
+               "^[^:]+:%d+: invalid format option 'w'",
+               "function pack invalid format")
+
+    error_like(function () string.pack('i1 Xz i1', 0, 0) end,
+               "^[^:]+:%d+: bad argument #1 to 'pack' %(invalid next option for option 'X'%)",
+               "function pack invalid next")
+
+    error_like(function () string.pack('i', 'foo') end,
+               "^[^:]+:%d+: bad argument #2 to 'pack' %(number expected, got string%)",
+              "function pack bad arg")
+else
+    is(string.pack, nil, "no string.pack");
+end
+
+-- packsize
+if has_pack then
+    is(string.packsize('b'), 1, "function packsize")
+
+    is(string.packsize(''), 0, "function packsize empty")
+
+    error_like(function () string.packsize('z') end,
+               "^[^:]+:%d+: bad argument #1 to 'packsize' %(variable%-length format%)",
+               "function packsize bad arg")
+else
+    is(string.packsize, nil, "no string.packsize");
+end
+
+do -- rep
+    is(string.rep('ab', 3), 'ababab', "function rep")
+    is(string.rep('ab', 0), '')
+    is(string.rep('ab', -1), '')
+    is(string.rep('', 5), '')
+    if has_rep52 then
+        is(string.rep('ab', 3, ','), 'ab,ab,ab', "with sep")
+        local n = 1e6
+        is(string.rep('a', n), string.rep('', n + 1, 'a'))
+    else
+        diag("no rep with separator")
+    end
+
+    if _VERSION >= 'Lua 5.3' then
+        error_like(function () string.rep('foo', 1e9) end,
+                   "^[^:]+:%d+: resulting string too large",
+                   "too large")
+    elseif luajit21 then
+        error_is(function () string.rep('foo', 1e9) end,
+                 "not enough memory",
+                 "too large")
+    end
+
+    if _VERSION >= 'Lua 5.4' or jit then
+        is(string.rep('', 1e8), '', "rep ''")
+    else
+        diag('too slow')
+    end
+end
+
+do -- reverse
+    is(string.reverse('abcde'), 'edcba', "function reverse")
+    is(string.reverse('abcd'), 'dcba')
+    is(string.reverse(''), '')
+end
+
+do -- sub
+    is(string.sub('abcde', 1, 2), 'ab', "function sub")
+    is(string.sub('abcde', 3, 4), 'cd')
+    is(string.sub('abcde', -2), 'de')
+    is(string.sub('abcde', 3, 2), '')
+end
+
+do -- upper
+    is(string.upper('Test'), 'TEST', "function upper")
+    is(string.upper('TeSt'), 'TEST')
+    is(string.upper(string.rep('Test', 10000)), string.rep('TEST', 10000))
+end
+
+-- unpack
+if has_pack then
+    is(string.unpack('<h', string.pack('>h', 1):reverse()), 1, "function unpack")
+    is(string.unpack('<H', string.pack('>H', 1):reverse()), 1)
+    is(string.unpack('<l', string.pack('>l', 1):reverse()), 1)
+    is(string.unpack('<L', string.pack('>L', 1):reverse()), 1)
+    is(string.unpack('<j', string.pack('>j', 1):reverse()), 1)
+    is(string.unpack('<J', string.pack('>J', 1):reverse()), 1)
+    is(string.unpack('<T', string.pack('>T', 1):reverse()), 1)
+    is(string.unpack('<i', string.pack('>i', 1):reverse()), 1)
+    is(string.unpack('<I', string.pack('>I', 1):reverse()), 1)
+    is(string.unpack('<f', string.pack('>f', 1.0):reverse()), 1.0)
+    is(string.unpack('<d', string.pack('>d', 1.0):reverse()), 1.0)
+    is(string.unpack('<n', string.pack('>n', 1.0):reverse()), 1.0)
+
+    is(string.unpack('c3', string.pack('c3', 'foo')), 'foo')
+    is(string.unpack('z', string.pack('z', 'foo')), 'foo')
+    is(string.unpack('s', string.pack('s', 'foo')), 'foo')
+
+    error_like(function () string.unpack('c4', 'foo') end,
+               "^[^:]+:%d+: bad argument #2 to 'unpack' %(data string too short%)",
+               "function unpack data too short")
+
+    error_like(function () string.unpack('c', 'foo') end,
+               "^[^:]+:%d+: missing size for format option 'c'",
+               "function unpack missing size")
+else
+    is(string.unpack, nil, "no string.unpack");
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/305-utf8.t b/test/lua-Harness-tests/305-utf8.t
new file mode 100755
index 0000000..4304b6c
--- /dev/null
+++ b/test/lua-Harness-tests/305-utf8.t
@@ -0,0 +1,55 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2014-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua UTF-8 support Library
+
+=head2 Synopsis
+
+    % prove 305-utf8.t
+
+=head2 Description
+
+Tests Lua UTF-8 Library
+
+This library was introduced in Lua 5.3.
+
+See section "UTF-8 support" in "Reference Manual"
+L<https://www.lua.org/manual/5.3/manual.html#6.5>,
+L<https://www.lua.org/manual/5.4/manual.html#6.5>
+
+=cut
+
+--]]
+
+require 'tap'
+
+local profile = require'profile'
+local has_utf8 = _VERSION >= 'Lua 5.3' or (jit and jit.version:match'moonjit') or profile.utf8
+
+if not utf8 then
+    plan(1)
+    nok(has_utf8, "no has_utf8")
+else
+    plan'no_plan'
+    dofile'lexico53/utf8.t'
+    if _VERSION >= 'Lua 5.4' then
+        dofile'lexico54/utf8.t'
+    end
+    done_testing()
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/306-table.t b/test/lua-Harness-tests/306-table.t
new file mode 100755
index 0000000..9836655
--- /dev/null
+++ b/test/lua-Harness-tests/306-table.t
@@ -0,0 +1,372 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Table Library
+
+=head2 Synopsis
+
+    % prove 305-table.t
+
+=head2 Description
+
+Tests Lua Table Library
+
+See section "Table Manipulation" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#5.5>,
+L<https://www.lua.org/manual/5.2/manual.html#6.5>,
+L<https://www.lua.org/manual/5.3/manual.html#6.6>,
+L<https://www.lua.org/manual/5.4/manual.html#6.6>
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
+local has_foreach = _VERSION == 'Lua 5.1'
+local has_foreachi = _VERSION == 'Lua 5.1'
+local has_getn = _VERSION == 'Lua 5.1'
+local has_setn_obsolete = _VERSION == 'Lua 5.1' and not jit
+local has_maxn = _VERSION == 'Lua 5.1' or profile.compat51 or profile.has_table_maxn
+local has_pack = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local has_move = _VERSION >= 'Lua 5.3' or  luajit21
+local has_unpack = _VERSION >= 'Lua 5.2'
+local has_alias_unpack = profile.luajit_compat52
+local nocvtn2s = profile.nocvtn2s
+
+plan'no_plan'
+
+do -- concat
+    local t = {'a','b','c','d','e'}
+    is(table.concat(t), 'abcde', "function concat")
+    is(table.concat(t, ','), 'a,b,c,d,e')
+    is(table.concat(t, ',',2), 'b,c,d,e')
+    is(table.concat(t, ',', 2, 4), 'b,c,d')
+    is(table.concat(t, ',', 4, 2), '')
+
+    t = {'a','b',3,'d','e'}
+    if nocvtn2s then
+        error_like(function () table.concat(t,',') end,
+               "^[^:]+:%d+: invalid value %(number%) at index 3 in table for 'concat'",
+               "function concat (number no conv)")
+    else
+        is(table.concat(t,','), 'a,b,3,d,e', "function concat (number)")
+    end
+
+    t = {'a','b','c','d','e'}
+    error_like(function () table.concat(t, ',', 2, 7) end,
+               "^[^:]+:%d+: invalid value %(nil%) at index 6 in table for 'concat'",
+               "function concat (out of range)")
+
+    t = {'a','b',true,'d','e'}
+    error_like(function () table.concat(t, ',') end,
+               "^[^:]+:%d+: invalid value %(boolean%) at index 3 in table for 'concat'",
+               "function concat (non-string)")
+end
+
+do -- insert
+    local a = {'10', '20', '30'}
+    table.insert(a, 1, '15')
+    is(table.concat(a,','), '15,10,20,30', "function insert")
+    local t = {}
+    table.insert(t, 'a')
+    is(table.concat(t, ','), 'a')
+    table.insert(t, 'b')
+    is(table.concat(t, ','), 'a,b')
+    table.insert(t, 1, 'c')
+    is(table.concat(t, ','), 'c,a,b')
+    table.insert(t, 2, 'd')
+    is(table.concat(t, ','), 'c,d,a,b')
+    table.insert(t, 5, 'e')
+    is(table.concat(t, ','), 'c,d,a,b,e')
+
+    if _VERSION == 'Lua 5.1' then
+        todo("not with 5.1", 2)
+    end
+    error_like(function () table.insert(t, 7, 'f') end,
+               "^[^:]+:%d+: bad argument #2 to 'insert' %(position out of bounds%)",
+               "function insert (out of bounds)")
+
+    error_like(function () table.insert(t, -9, 'f') end,
+               "^[^:]+:%d+: bad argument #2 to 'insert' %(position out of bounds%)",
+               "function insert (out of bounds)")
+
+    error_like(function () table.insert(t, 2, 'g', 'h')  end,
+               "^[^:]+:%d+: wrong number of arguments to 'insert'",
+               "function insert (too many arg)")
+end
+
+-- foreach 5.0
+if has_foreach then
+    local t = {a=10, b=100}
+    local output = {}
+    table.foreach(t, function (k, v) output[k] = v end)
+    eq_array(output, t, "function foreach (hash)")
+
+    t = {'a','b','c'}
+    output = {}
+    table.foreach(t, function (k, v)
+        table.insert(output, k)
+        table.insert(output, v)
+    end)
+    eq_array(output, {1, 'a', 2, 'b', 3, 'c'}, "function foreach (array)")
+else
+    is(table.foreach, nil, "no table.foreach");
+end
+
+-- foreachi 5.0
+if has_foreachi then
+    local t = {'a','b','c'}
+    local output = {}
+    table.foreachi(t, function (i, v)
+        table.insert(output, i)
+        table.insert(output, v)
+    end)
+    eq_array(output, {1, 'a', 2, 'b', 3, 'c'}, "function foreachi")
+else
+    is(table.foreachi, nil, "no table.foreachi");
+end
+
+if has_getn then
+    is(table.getn{10,2,4}, 3, "function getn")
+    is(table.getn{10,2,nil}, 2)
+else
+    is(table.getn, nil, "no table.getn");
+end
+
+-- maxn
+if has_maxn then
+    local t = {}
+    is(table.maxn(t), 0, "function maxn")
+    t[1] = 'a'
+    t[2] = 'b'
+    is(table.maxn(t), 2)
+    t[6] = 'g'
+    is(table.maxn(t), 6)
+
+    local a = {}
+    a[10000] = 1
+    is(table.maxn(a), 10000)
+else
+    is(table.maxn, nil, "no table.maxn");
+end
+
+-- move
+if has_move then
+    local a = {'a', 'b', 'c'}
+    local t = { 1, 2, 3, 4}
+    table.move(a, 1, 3, 1, t)
+    eq_array(t, {'a', 'b', 'c', 4}, "function move")
+    table.move(a, 1, 3, 3, t)
+    eq_array(t, {'a', 'b', 'a', 'b', 'c'})
+
+    table.move(a, 1, 3, 1)
+    eq_array(a, {'a', 'b', 'c'})
+    table.move(a, 1, 3, 3)
+    eq_array(a, {'a', 'b', 'a', 'b', 'c'})
+
+    error_like(function () table.move(a, 1, 2, 1, 2) end,
+               "^[^:]+:%d+: bad argument #5 to 'move' %(table expected",
+               "function move (bad arg)")
+
+    error_like(function () table.move(a, 1, 2) end,
+               "^[^:]+:%d+: bad argument #4 to 'move' %(number expected, got .-%)",
+               "function move (bad arg)")
+
+    error_like(function () table.move(a, 1) end,
+               "^[^:]+:%d+: bad argument #3 to 'move' %(number expected, got .-%)",
+               "function move (bad arg)")
+else
+    is(table.move, nil, "no table.move");
+end
+
+-- pack
+if has_pack then
+    local t = table.pack("abc", "def", "ghi")
+    eq_array(t, {
+        "abc",
+        "def",
+        "ghi"
+    }, "function pack")
+    is(t.n, 3)
+
+    t = table.pack()
+    eq_array(t, {}, "function pack (no element)")
+    is(t.n, 0)
+else
+    is(table.pack, nil, "no table.pack");
+end
+
+do -- remove
+    local t = {}
+    local a = table.remove(t)
+    is(a, nil, "function remove")
+    t = {'a','b','c','d','e'}
+    a = table.remove(t)
+    is(a, 'e')
+    is(table.concat(t, ','), 'a,b,c,d')
+    a = table.remove(t,3)
+    is(a, 'c')
+    is(table.concat(t, ','), 'a,b,d')
+    a = table.remove(t,1)
+    is(a, 'a')
+    is(table.concat(t, ','), 'b,d')
+
+    if _VERSION == 'Lua 5.1' then
+        todo("not with 5.1", 1)
+    end
+    error_like(function () table.remove(t,7) end,
+               "^[^:]+:%d+: bad argument #1 to 'remove' %(position out of bounds%)",
+               "function remove (out of bounds)")
+end
+
+-- setn obsolete
+if has_setn_obsolete then
+    local a = {}
+    error_like(function () table.setn(a, 10000) end,
+               "^[^:]+:%d+: 'setn' is obsolete",
+               "function setn")
+else
+    is(table.setn, nil, "no table.setn");
+end
+
+do -- sort
+    local lines = {
+        luaH_set = 10,
+        luaH_get = 24,
+        luaH_present = 48,
+    }
+
+    do
+        local a = {}
+        for n in pairs(lines) do a[#a + 1] = n end
+        table.sort(a)
+        local output = {}
+        for _, n in ipairs(a) do
+            table.insert(output, n)
+        end
+        eq_array(output, {'luaH_get', 'luaH_present', 'luaH_set'}, "function sort")
+    end
+
+    do
+        local function pairsByKeys (t, f)
+            local a = {}
+            for n in pairs(t) do a[#a + 1] = n end
+            table.sort(a, f)
+            local i = 0     -- iterator variable
+            return function ()  -- iterator function
+                i = i + 1
+                return a[i], t[a[i]]
+            end
+        end
+
+        local output = {}
+        for name, line in pairsByKeys(lines) do
+            table.insert(output, name)
+            table.insert(output, line)
+        end
+        eq_array(output, {'luaH_get', 24, 'luaH_present', 48, 'luaH_set', 10}, "function sort")
+
+        output = {}
+        for name, line in pairsByKeys(lines, function (a, b) return a < b end) do
+            table.insert(output, name)
+            table.insert(output, line)
+        end
+        eq_array(output, {'luaH_get', 24, 'luaH_present', 48, 'luaH_set', 10}, "function sort")
+    end
+
+    do
+        local function permgen (a, n)
+            n = n or #a
+            if n <= 1 then
+                coroutine.yield(a)
+            else
+                for i=1,n do
+                    a[n], a[i] = a[i], a[n]
+                    permgen(a, n - 1)
+                    a[n], a[i] = a[i], a[n]
+                end
+            end
+        end
+
+        local function permutations (a)
+            local co = coroutine.create(function () permgen(a) end)
+            return function ()
+                       local code, res = coroutine.resume(co)
+                       return res
+                    end
+        end
+
+        local t = {}
+        local output = {}
+        for _, v in ipairs{'a', 'b', 'c', 'd', 'e', 'f', 'g'} do
+            table.insert(t, v)
+            local ref = table.concat(t, ' ')
+            table.insert(output, ref)
+            local n = 0
+            for p in permutations(t) do
+                local c = {}
+                for i, vv in ipairs(p) do
+                    c[i] = vv
+                end
+                table.sort(c)
+                assert(ref == table.concat(c, ' '), table.concat(p, ' '))
+                n = n + 1
+            end
+            table.insert(output, n)
+        end
+
+        eq_array(output, {
+            'a', 1,
+            'a b', 2,
+            'a b c', 6,
+            'a b c d', 24,
+            'a b c d e', 120,
+            'a b c d e f', 720,
+            'a b c d e f g', 5040,
+        }, "function sort (all permutations)")
+    end
+
+    if _VERSION == 'Lua 5.1' and not jit then
+        todo("not with 5.1")
+    end
+    error_like(function ()
+                   local t = { 1 }
+                   table.sort( { t, t, t, t, }, function (a, b) return a[1] == b[1] end )
+               end,
+               "^[^:]+:%d+: invalid order function for sorting",
+               "function sort (bad func)")
+end
+
+-- unpack
+if has_unpack then
+    eq_array({table.unpack({})}, {}, "function unpack")
+    eq_array({table.unpack({'a'})}, {'a'})
+    eq_array({table.unpack({'a','b','c'})}, {'a','b','c'})
+    eq_array({(table.unpack({'a','b','c'}))}, {'a'})
+    eq_array({table.unpack({'a','b','c','d','e'},2,4)}, {'b','c','d'})
+    eq_array({table.unpack({'a','b','c'},2,4)}, {'b','c'})
+elseif has_alias_unpack then
+    is(table.unpack, unpack, "alias table.unpack");
+else
+    is(table.unpack, nil, "no table.unpack");
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/307-math.t b/test/lua-Harness-tests/307-math.t
new file mode 100755
index 0000000..8b51ed1
--- /dev/null
+++ b/test/lua-Harness-tests/307-math.t
@@ -0,0 +1,375 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Mathematic Library
+
+=head2 Synopsis
+
+    % prove 307-math.t
+
+=head2 Description
+
+Tests Lua Mathematic Library
+
+See section "Mathematical Functions" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#5.6>,
+L<https://www.lua.org/manual/5.2/manual.html#6.6>,
+L<https://www.lua.org/manual/5.3/manual.html#6.7>,
+L<https://www.lua.org/manual/5.4/manual.html#6.7>
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local has_integer = _VERSION >= 'Lua 5.3' or (jit and jit.version:match'moonjit') or profile.integer
+local has_mathx = _VERSION < 'Lua 5.3' or profile.compat52 or profile.compat53 or profile.has_mathx
+local has_log10 = _VERSION < 'Lua 5.2' or profile.compat51 or profile.has_math_log10 or
+                  profile.compat52 or profile.compat53 or profile.has_mathx
+local has_log_with_base = _VERSION >= 'Lua 5.2' or profile.compat52
+local has_mod = profile.has_math_mod or ujit
+local nocvts2n = profile.nocvts2n or jit
+
+plan'no_plan'
+
+do -- abs
+    is(math.abs(-12.34), 12.34, "function abs (float)")
+    is(math.abs(12.34), 12.34)
+    if math.type then
+        is(math.type(math.abs(-12.34)), 'float')
+    end
+    is(math.abs(-12), 12, "function abs (integer)")
+    is(math.abs(12), 12)
+    if math.type then
+        is(math.type(math.abs(-12)), 'integer')
+    end
+end
+
+do -- acos
+    like(math.acos(0.5), '^1%.047', "function acos")
+end
+
+do -- asin
+    like(math.asin(0.5), '^0%.523', "function asin")
+end
+
+do -- atan
+    like(math.atan(0.5), '^0%.463', "function atan")
+end
+
+-- atan2
+if has_mathx then
+    like(math.atan2(1.0, 2.0), '^0%.463', "function atan2")
+else
+    is(math.atan2, nil, "function atan2 (removed)")
+end
+
+do -- ceil
+    is(math.ceil(12.34), 13, "function ceil")
+    is(math.ceil(-12.34), -12)
+    is(math.ceil(-12), -12)
+    if math.type then
+        is(math.type(math.ceil(-12.34)), 'integer')
+    end
+end
+
+do -- cos
+    like(math.cos(1.0), '^0%.540', "function cos")
+end
+
+-- cosh
+if has_mathx then
+    like(math.cosh(1.0), '^1%.543', "function cosh")
+else
+    is(math.cosh, nil, "function cosh (removed)")
+end
+
+do -- deg
+    is(math.deg(math.pi), 180, "function deg")
+end
+
+do -- exp
+    like(math.exp(1.0), '^2%.718', "function exp")
+end
+
+do -- floor
+    is(math.floor(12.34), 12, "function floor")
+    is(math.floor(-12.34), -13)
+    is(math.floor(-12), -12)
+    if math.type then
+        is(math.type(math.floor(-12.34)), 'integer')
+    end
+end
+
+do -- fmod
+    like(math.fmod(7.0001, 0.3), '^0%.100', "function fmod (float)")
+    like(math.fmod(-7.0001, 0.3), '^-0%.100')
+    like(math.fmod(-7.0001, -0.3), '^-0%.100')
+    if math.type then
+        is(math.type(math.fmod(7.0, 0.3)), 'float')
+    end
+    is(math.fmod(7, 3), 1, "function fmod (integer)")
+    is(math.fmod(-7, 3), -1)
+    is(math.fmod(-7, -1), 0)
+    if math.type then
+        is(math.type(math.fmod(7, 3)), 'integer')
+    end
+    if _VERSION >= 'Lua 5.3' then
+        error_like(function () math.fmod(7, 0) end,
+                   "^[^:]+:%d+: bad argument #2 to 'fmod' %(zero%)",
+                   "function fmod 0")
+    else
+        diag"fmod by zero -> nan"
+    end
+end
+
+-- frexp
+if has_mathx then
+    eq_array({math.frexp(1.5)}, {0.75, 1}, "function frexp")
+else
+    is(math.frexp, nil, "function frexp (removed)")
+end
+
+do -- huge
+    type_ok(math.huge, 'number', "variable huge")
+    if math.type then
+        is(math.type(math.huge), 'float')
+    end
+end
+
+-- ldexp
+if has_mathx then
+    is(math.ldexp(1.2, 3), 9.6, "function ldexp")
+else
+    is(math.ldexp, nil, "function ldexp (removed)")
+end
+
+do -- log
+    like(math.log(47), '^3%.85', "function log")
+    if has_log_with_base then
+        like(math.log(47, math.exp(1)), '^3%.85', "function log (base e)")
+        like(math.log(47, 2), '^5%.554', "function log (base 2)")
+        like(math.log(47, 10), '^1%.672', "function log (base 10)")
+    end
+end
+
+-- log10
+if has_log10 then
+    like(math.log10(47.0), '^1%.672', "function log10")
+else
+    is(math.log10, nil, "function log10 (removed)")
+end
+
+do --max
+    is(math.max(1), 1, "function max")
+    is(math.max(1, 2), 2)
+    is(math.max(1, 2, 3, -4), 3)
+
+    error_like(function () math.max() end,
+               "^[^:]+:%d+: bad argument #1 to 'max' %(.- expected",
+               "function max 0")
+end
+
+-- maxinteger
+if has_integer then
+    type_ok(math.maxinteger, 'number', "variable maxinteger")
+    if math.type then
+        is(math.type(math.maxinteger), 'integer')
+    end
+else
+    is(math.maxinteger, nil, "no maxinteger")
+end
+
+do --min
+    is(math.min(1), 1, "function min")
+    is(math.min(1, 2), 1)
+    is(math.min(1, 2, 3, -4), -4)
+
+    error_like(function () math.min() end,
+               "^[^:]+:%d+: bad argument #1 to 'min' %(.- expected",
+               "function min 0")
+end
+
+-- mininteger
+if has_integer then
+    type_ok(math.mininteger, 'number', "variable mininteger")
+    if math.type then
+        is(math.type(math.mininteger), 'integer')
+    end
+else
+    is(math.mininteger, nil, "no mininteger")
+end
+
+-- mod (compat50)
+if has_mod then
+    is(math.mod, math.fmod, "function mod (alias fmod)")
+else
+    is(math.mod, nil, "function mod (alias removed)")
+end
+
+do -- modf
+    eq_array({math.modf(2.25)}, {2, 0.25}, "function modf")
+    eq_array({math.modf(2)}, {2, 0.0})
+end
+
+do -- pi
+    like(tostring(math.pi), '^3%.14', "variable pi")
+end
+
+-- pow
+if has_mathx then
+    is(math.pow(-2, 3), -8, "function pow")
+else
+    is(math.pow, nil, "function pow (removed)")
+end
+
+do -- rad
+    like(math.rad(180), '^3%.14', "function rad")
+end
+
+do -- random
+    like(math.random(), '^0%.%d+', "function random no arg")
+    if math.type then
+        is(math.type(math.random()), 'float')
+    end
+    like(math.random(9), '^%d$', "function random 1 arg")
+    if math.type then
+        is(math.type(math.random(9)), 'integer')
+    end
+    like(math.random(10, 19), '^1%d$', "function random 2 arg")
+    if math.type then
+        is(math.type(math.random(10, 19)), 'integer')
+    end
+    like(math.random(-19, -10), '^-1%d$', "function random 2 arg")
+
+    if _VERSION >= 'Lua 5.4' then
+        like(math.random(0), '^%-?%d+$', "function random 0")
+    else
+        if jit then
+            todo("LuaJIT intentional. Don't check empty interval.")
+        end
+        error_like(function () math.random(0) end,
+                   "^[^:]+:%d+: bad argument #1 to 'random' %(interval is empty%)",
+                  "function random empty interval")
+    end
+
+    if jit then
+        todo("LuaJIT intentional. Don't check empty interval.", 2)
+    end
+    error_like(function () math.random(-9) end,
+               "^[^:]+:%d+: bad argument #%d to 'random' %(interval is empty%)",
+               "function random empty interval")
+
+    error_like(function () math.random(19, 10) end,
+               "^[^:]+:%d+: bad argument #%d to 'random' %(interval is empty%)",
+               "function random empty interval")
+
+    if jit then
+        todo("LuaJIT intentional. Don't care about extra arguments.")
+    end
+    error_like(function () math.random(1, 2, 3) end,
+               "^[^:]+:%d+: wrong number of arguments",
+               "function random too many arg")
+end
+
+do -- randomseed
+    math.randomseed(42)
+    local a = math.random()
+    math.randomseed(42)
+    local b = math.random()
+    is(a, b, "function randomseed")
+end
+
+do -- sin
+    like(math.sin(1.0), '^0%.841', "function sin")
+end
+
+-- sinh
+if has_mathx then
+    like(math.sinh(1), '^1%.175', "function sinh")
+else
+    is(math.sinh, nil, "function sinh (removed)")
+end
+
+do -- sqrt
+    like(math.sqrt(2), '^1%.414', "function sqrt")
+end
+
+do -- tan
+    like(math.tan(1.0), '^1%.557', "function tan")
+end
+
+-- tanh
+if has_mathx then
+    like(math.tanh(1), '^0%.761', "function tanh")
+else
+    is(math.tanh, nil, "function tanh (removed)")
+end
+
+-- tointeger
+if has_integer then
+    is(math.tointeger(-12), -12, "function tointeger (number)")
+    is(math.tointeger(-12.0), -12)
+    is(math.tointeger(-12.34), nil)
+    if nocvts2n then
+        is(math.tointeger('-12'), nil, "function tointeger (string)")
+        is(math.tointeger('-12.0'), nil)
+    else
+        is(math.tointeger('-12'), -12, "function tointeger (string)")
+        is(math.tointeger('-12.0'), -12)
+    end
+    is(math.tointeger('-12.34'), nil)
+    is(math.tointeger('bad'), nil)
+    is(math.tointeger(true), nil, "function tointeger (boolean)")
+    is(math.tointeger({}), nil, "function tointeger (table)")
+else
+    is(math.tointeger, nil, "no math.tointeger")
+end
+
+-- type
+if has_integer then
+    is(math.type(3), 'integer', "function type")
+    is(math.type(3.14), 'float')
+    is(math.type('3.14'), nil)
+else
+    is(math.type, nil, "no math.type")
+end
+
+-- ult
+if has_integer then
+    is(math.ult(2, 3), true, "function ult")
+    is(math.ult(2, 2), false)
+    is(math.ult(2, 1), false)
+
+    error_like(function () math.ult(3.14) end,
+               "^%S+ bad argument #1 to 'ult' %(number has no integer representation%)",
+               "function ult (float)")
+    error_like(function () math.ult(2, 3.14) end,
+               "^%S+ bad argument #2 to 'ult' %(number has no integer representation%)")
+    error_like(function () math.ult(true) end,
+               "^[^:]+:%d+: bad argument #1 to 'ult' %(number expected, got boolean%)",
+               "function ult (boolean)")
+    error_like(function () math.ult(2, true) end,
+               "^[^:]+:%d+: bad argument #2 to 'ult' %(number expected, got boolean%)")
+else
+    is(math.ult, nil, "no math.ult")
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/308-io.t b/test/lua-Harness-tests/308-io.t
new file mode 100755
index 0000000..35d39c0
--- /dev/null
+++ b/test/lua-Harness-tests/308-io.t
@@ -0,0 +1,397 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Input/Output Library
+
+=head2 Synopsis
+
+    % prove 308-io.t
+
+=head2 Description
+
+Tests Lua Input/Output Library
+
+See section "Input and Output Facilities" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#5.7>,
+L<https://www.lua.org/manual/5.2/manual.html#6.8>,
+L<https://www.lua.org/manual/5.3/manual.html#6.8>,
+L<https://www.lua.org/manual/5.4/manual.html#6.8>
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
+local has_write51 = _VERSION == 'Lua 5.1' and (not profile.luajit_compat52 or ujit)
+local has_lines52 = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local has_read52 = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local has_read53 = _VERSION >= 'Lua 5.3' or luajit21
+local has_meta53 = _VERSION >= 'Lua 5.3'
+local has_meta54 = _VERSION >= 'Lua 5.4'
+
+local lua = get_lua_binary_name()
+
+plan'no_plan'
+
+do -- stdin
+    like(io.stdin, '^file %(0?[Xx]?%x+%)$', "variable stdin")
+end
+
+do -- stdout
+    like(io.stdout, '^file %(0?[Xx]?%x+%)$', "variable stdout")
+end
+
+do -- stderr
+    like(io.stderr, '^file %(0?[Xx]?%x+%)$', "variable stderr")
+end
+
+do -- metatable
+    local f = io.tmpfile()
+    local mt = getmetatable(f)
+    type_ok(mt, 'table', "metatable")
+
+    type_ok(mt.__gc, 'function')
+    type_ok(mt.__tostring, 'function')
+    type_ok(mt.__index, 'table')
+
+    if has_meta53 then
+        is(mt.__name, 'FILE*')
+    else
+        is(mt.__name, nil)
+    end
+
+    if has_meta54 then
+        type_ok(mt.__close, 'function')
+        type_ok(mt.__index, 'table')
+        is(mt.close, nil)
+        is(mt.flush, nil)
+        is(mt.lines, nil)
+        is(mt.read, nil)
+        is(mt.seek, nil)
+        is(mt.setvbuf, nil)
+        is(mt.write, nil)
+    else
+        is(mt.__close, nil)
+        is(mt.__index, mt)
+        type_ok(mt.close, 'function')
+        type_ok(mt.flush, 'function')
+        type_ok(mt.lines, 'function')
+        type_ok(mt.read, 'function')
+        type_ok(mt.seek, 'function')
+        type_ok(mt.setvbuf, 'function')
+        type_ok(mt.write, 'function')
+    end
+
+    type_ok(mt.__index.close, 'function')
+    type_ok(mt.__index.flush, 'function')
+    type_ok(mt.__index.lines, 'function')
+    type_ok(mt.__index.read, 'function')
+    type_ok(mt.__index.seek, 'function')
+    type_ok(mt.__index.setvbuf, 'function')
+    type_ok(mt.__index.write, 'function')
+end
+
+do -- close
+    local r, msg = io.close(io.stderr)
+    is(r, nil, "close (std)")
+    is(msg, "cannot close standard file")
+end
+
+do -- flush
+    is(io.flush(), true, "function flush")
+end
+
+do -- open
+    os.remove('file-308.no')
+    local f, msg = io.open("file-308.no")
+    is(f, nil, "function open")
+    is(msg, "file-308.no: No such file or directory")
+
+    os.remove('file-308.txt')
+    f = io.open('file-308.txt', 'w')
+    f:write("file with text\n")
+    f:close()
+    f = io.open('file-308.txt')
+    like(f, '^file %(0?[Xx]?%x+%)$', "function open")
+
+    is(io.close(f), true, "function close")
+
+    error_like(function () io.close(f) end,
+               "^[^:]+:%d+: attempt to use a closed file",
+               "function close (closed)")
+
+    if _VERSION == 'Lua 5.1' then
+        todo("not with 5.1")
+    end
+    error_like(function () io.open('file-308.txt', 'baz') end,
+               "^[^:]+:%d+: bad argument #2 to 'open' %(invalid mode%)",
+               "function open (bad mode)")
+end
+
+do -- type
+    is(io.type("not a file"), nil, "function type")
+    local f = io.open('file-308.txt')
+    is(io.type(f), 'file')
+    like(tostring(f), '^file %(0?[Xx]?%x+%)$')
+    io.close(f)
+    is(io.type(f), 'closed file')
+    is(tostring(f), 'file (closed)')
+end
+
+do -- input
+    is(io.stdin, io.input(), "function input")
+    is(io.stdin, io.input(nil))
+    local f = io.stdin
+    like(io.input('file-308.txt'), '^file %(0?[Xx]?%x+%)$')
+    is(f, io.input(f))
+end
+
+do -- output
+    is(io.output(), io.stdout, "function output")
+    is(io.output(nil), io.stdout)
+    local f = io.stdout
+    like(io.output('output.new'), '^file %(0?[Xx]?%x+%)$')
+    is(f, io.output(f))
+    os.remove('output.new')
+end
+
+do -- popen
+    local r, f = pcall(io.popen, lua .. [[ -e "print 'standard output'"]])
+    if r then
+        is(io.type(f), 'file', "popen (read)")
+        is(f:read(), "standard output")
+        is(io.close(f), true)
+    else
+        diag("io.popen not supported")
+    end
+
+    r, f = pcall(io.popen, lua .. [[ -e "for line in io.lines() do print((line:gsub('e', 'a'))) end"]], 'w')
+    if r then
+        is(io.type(f), 'file', "popen (write)")
+        f:write("# hello\n") -- not tested : hallo
+        is(io.close(f), true)
+    else
+        diag("io.popen not supported")
+    end
+end
+
+do -- lines
+    for line in io.lines('file-308.txt') do
+        is(line, "file with text", "function lines(filename)")
+    end
+
+    error_like(function () io.lines('file-308.no') end,
+               "No such file or directory",
+               "function lines(no filename)")
+end
+
+do -- tmpfile
+    local  f = io.tmpfile()
+    is(io.type(f), 'file', "function tmpfile")
+    f:write("some text")
+    f:close()
+end
+
+do -- write
+    io.write() -- not tested
+    io.write('# text', 12, "\n") -- not tested :  # text12
+end
+
+do -- :close
+    local r, msg = io.stderr:close()
+    is(r, nil, "method close (std)")
+    is(msg, "cannot close standard file")
+
+    local f = io.open('file-308.txt')
+    is(f:close(), true, "method close")
+end
+
+do -- :flush
+    is(io.stderr:flush(), true, "method flush")
+
+    local f = io.open('file-308.txt')
+    f:close()
+    error_like(function () f:flush() end,
+               "^[^:]+:%d+: attempt to use a closed file",
+               "method flush (closed)")
+end
+
+do -- :read & :write
+    local f = io.open('file-308.txt')
+    f:close()
+    error_like(function () f:read() end,
+               "^[^:]+:%d+: attempt to use a closed file",
+               "method read (closed)")
+
+    f = io.open('file-308.txt')
+    local s = f:read()
+    is(s:len(), 14, "method read")
+    is(s, "file with text")
+    s = f:read()
+    is(s, nil)
+    f:close()
+
+    f = io.open('file-308.txt')
+    error_like(function () f:read('*z') end,
+               "^[^:]+:%d+: bad argument #1 to 'read' %(invalid %w+%)",
+               "method read (invalid)")
+    f:close()
+
+    f = io.open('file-308.txt')
+    local s1, s2 = f:read('*l', '*l')
+    is(s1:len(), 14, "method read *l")
+    is(s1, "file with text")
+    is(s2, nil)
+    f:close()
+
+    if has_read52 then
+        f = io.open('file-308.txt')
+        s1, s2 = f:read('*L', '*L')
+        is(s1:len(), 15, "method read *L")
+        is(s1, "file with text\n")
+        is(s2, nil)
+        f:close()
+    else
+        diag("no read *L")
+    end
+
+    f = io.open('file-308.txt')
+    local n1, n2 = f:read('*n', '*n')
+    is(n1, nil, "method read *n")
+    is(n2, nil)
+    f:close()
+
+    f = io.open('file-308.num', 'w')
+    f:write('1\n')
+    f:write('0xFF\n')
+    f:write(string.rep('012', 90) .. '\n')
+    f:close()
+
+    f = io.open('file-308.num')
+    n1, n2 = f:read('*n', '*n')
+    is(n1, 1, "method read *n")
+    is(n2, 255, "method read *n")
+    local n = f:read('*n')
+    if _VERSION < 'Lua 5.3' then
+        type_ok(n, 'number')
+    else
+        is(n, nil, "method read *n too long")
+    end
+    f:close()
+
+    os.remove('file-308.num') -- clean up
+
+    f = io.open('file-308.txt')
+    s = f:read('*a')
+    is(s:len(), 15, "method read *a")
+    is(s, "file with text\n")
+    f:close()
+
+    if has_read53 then
+        f = io.open('file-308.txt')
+        s = f:read('a')
+        is(s:len(), 15, "method read a")
+        is(s, "file with text\n")
+        f:close()
+    else
+        diag("* mandatory")
+    end
+
+    f = io.open('file-308.txt')
+    is(f:read(0), '', "method read number")
+    eq_array({f:read(5, 5, 15)}, {'file ', 'with ', "text\n"})
+    f:close()
+end
+
+do -- :lines
+    local f = io.open('file-308.txt')
+    for line in f:lines() do
+        is(line, "file with text", "method lines")
+    end
+    is(io.type(f), 'file')
+    f:close()
+    is(io.type(f), 'closed file')
+
+    if has_lines52 then
+        f = io.open('file-308.txt')
+        for two_char in f:lines(2) do
+            is(two_char, "fi", "method lines (with read option)")
+            break
+        end
+        f:close()
+    else
+        diag("no lines with option")
+    end
+end
+
+do -- :seek
+    local f = io.open('file-308.txt')
+    f:close()
+
+    error_like(function () f:seek('end', 0) end,
+               "^[^:]+:%d+: attempt to use a closed file",
+               "method seek (closed)")
+
+    f = io.open('file-308.txt')
+    error_like(function () f:seek('bad', 0) end,
+               "^[^:]+:%d+: bad argument #1 to 'seek' %(invalid option 'bad'%)",
+               "method seek (invalid)")
+
+    f = io.open('file-308.bin', 'w')
+    f:write('ABCDE')
+    f:close()
+    f = io.open('file-308.bin')
+    is(f:seek('end', 0), 5, "method seek")
+    f:close()
+    os.remove('file-308.bin') --clean up
+end
+
+do -- :setvbuf
+    local  f = io.open('file-308.txt')
+     is(f:setvbuf('no'), true, "method setvbuf 'no'")
+
+    is(f:setvbuf('full', 4096), true, "method setvbuf 'full'")
+
+    is(f:setvbuf('line', 132), true, "method setvbuf 'line'")
+    f:close()
+end
+
+os.remove('file-308.txt') -- clean up
+
+do -- :write
+    local  f = io.open('file-308.out', 'w')
+    f:close()
+    error_like(function () f:write('end') end,
+               "^[^:]+:%d+: attempt to use a closed file",
+               "method write (closed)")
+
+    f = io.open('file-308.out', 'w')
+    if has_write51 then
+        is(f:write('end'), true, "method write")
+    else
+        is(f:write('end'), f, "method write")
+    end
+    f:close()
+
+    os.remove('file-308.out') --clean up
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/309-os.t b/test/lua-Harness-tests/309-os.t
new file mode 100755
index 0000000..a787b14
--- /dev/null
+++ b/test/lua-Harness-tests/309-os.t
@@ -0,0 +1,271 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Operating System Library
+
+=head2 Synopsis
+
+    % prove 309-os.t
+
+=head2 Description
+
+Tests Lua Operating System Library
+
+See section "Operating System Facilities" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#5.8>,
+L<https://www.lua.org/manual/5.2/manual.html#6.9>,
+L<https://www.lua.org/manual/5.3/manual.html#6.9>,
+L<https://www.lua.org/manual/5.4/manual.html#6.9>
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+local luajit20 = jit and (jit.version_num < 20100 and not jit.version:match'^RaptorJIT')
+local has_execute51 = _VERSION == 'Lua 5.1' and (not profile.luajit_compat52 or ujit)
+local lua = get_lua_binary_name()
+
+plan'no_plan'
+
+do -- clock
+    local clk = os.clock()
+    type_ok(clk, 'number', "function clock")
+    ok(clk <= os.clock())
+end
+
+do -- date
+    local d = os.date('!*t', 0)
+    is(d.year, 1970, "function date")
+    is(d.month, 1)
+    is(d.day, 1)
+    is(d.hour, 0)
+    is(d.min, 0)
+    is(d.sec, 0)
+    is(d.wday, 5)
+    is(d.yday, 1)
+    is(d.isdst, false)
+
+    is(os.date('!%d/%m/%y %H:%M:%S', 0), '01/01/70 00:00:00', "function date")
+
+    like(os.date('%H:%M:%S'), '^%d%d:%d%d:%d%d', "function date")
+
+    if (_VERSION == 'Lua 5.1' and not jit) or luajit20 then
+        todo("not with 5.1")
+    end
+    is(os.date('%Oy', 0), '70')
+
+    if _VERSION == 'Lua 5.1' then
+        todo("not with 5.1")
+    end
+    error_like(function () os.date('%Ja', 0) end,
+               "^[^:]+:%d+: bad argument #1 to 'date' %(invalid conversion specifier '%%Ja'%)",
+               "function date (invalid)")
+end
+
+do -- difftime
+    is(os.difftime(1234, 1200), 34, "function difftime")
+end
+
+do -- execute
+    if has_execute51 then
+        local res = os.execute()
+        is(res, 1, "function execute -> shell is available")
+
+        ok(os.execute('__IMPROBABLE__') > 0, "function execute __IMPROBABLE__")
+
+        local cmd = lua .. [[ -e "print '# hello from external Lua'"]]
+        is(os.execute(cmd), 0, "function execute")
+    else
+        local res = os.execute()
+        is(res, true, "function execute -> shell is available")
+
+        local r, s, n = os.execute('__IMPROBABLE__')
+        is(r, nil, "function execute __IMPROBABLE__")
+        is(s, 'exit')
+        type_ok(n, 'number')
+
+        local cmd = lua .. [[ -e "print '# hello from external Lua'"]]
+        r, s, n = os.execute(cmd)
+        is(r, true, "function execute")
+        is(s, 'exit')
+        is(n, 0)
+    end
+end
+
+do -- exit called with execute
+    if has_execute51 then
+        local cmd = lua .. [[ -e "print '# hello from external Lua'; os.exit(2)"]]
+        ok(os.execute(cmd) > 0, "function exit called with execute")
+    else
+        local cmd = lua .. [[ -e "print '# hello from external Lua'; os.exit(2)"]]
+        local r, s, n = os.execute(cmd)
+        is(r, nil, "function exit called with execute")
+        is(s, 'exit')
+        is(n, 2, "exit value")
+
+        cmd = lua .. [[ -e "print '# hello from external Lua'; os.exit(false)"]]
+        r, s, n = os.execute(cmd)
+        is(r, nil, "function exit called with execute")
+        is(s, 'exit')
+        is(n, 1, "exit value")
+
+        cmd = lua .. [[ -e "print '# hello from external Lua'; os.exit(true, true)"]]
+        r, s, n = os.execute(cmd)
+        is(r, true, "exit called with execute")
+        is(s, 'exit')
+        is(n, 0, "exit value")
+    end
+end
+
+do -- exit called with popen
+    local cmd = lua .. [[ -e "print 'reached'; os.exit(); print 'not reached';"]]
+    local res, f = pcall(io.popen, cmd)
+    if res then
+        is(f:read'*l', 'reached', "exit called with popen")
+        is(f:read'*l', nil)
+        if has_execute51 then
+            local code = f:close()
+            is(code, true, "exit code")
+        else
+            local r, s, n = f:close()
+            is(r, true)
+            is(s, 'exit', "exit code")
+            is(n, 0, "exit value")
+        end
+    else
+        diag("io.popen not supported")
+    end
+
+    cmd = lua .. [[ -e "print 'reached'; os.exit(3); print 'not reached';"]]
+    res, f = pcall(io.popen, cmd)
+    if res then
+        is(f:read'*l', 'reached', "exit called with popen")
+        is(f:read'*l', nil)
+        if has_execute51 then
+            local code = f:close()
+            is(code, true, "exit code")
+        else
+            local r, s, n = f:close()
+            is(r, nil)
+            is(s, 'exit', "exit code")
+            is(n, 3, "exit value")
+        end
+    else
+        diag("io.popen not supported")
+    end
+end
+
+do -- getenv
+    is(os.getenv('__IMPROBABLE__'), nil, "function getenv")
+
+    local user = os.getenv('LOGNAME') or os.getenv('USERNAME')
+    type_ok(user, 'string', "function getenv")
+end
+
+do -- remove
+    local f = io.open('file-309.rm', 'w')
+    f:write("file to remove")
+    f:close()
+    local r = os.remove("file-309.rm")
+    is(r, true, "function remove")
+
+    local msg
+    r, msg = os.remove('file-309.rm')
+    is(r, nil, "function remove")
+    like(msg, '^file%-309%.rm: No such file or directory')
+end
+
+do -- rename
+    local f = io.open('file-309.old', 'w')
+    f:write("file to rename")
+    f:close()
+    os.remove('file-309.new')
+    local r = os.rename('file-309.old', 'file-309.new')
+    is(r, true, "function rename")
+    os.remove('file-309.new') -- clean up
+
+    local msg
+    r, msg = os.rename('file-309.old', 'file-309.new')
+    is(r, nil, "function rename")
+    like(msg, 'No such file or directory')
+end
+
+do -- setlocale
+    is(os.setlocale('C', 'all'), 'C', "function setlocale")
+    is(os.setlocale(), 'C')
+    is(os.setlocale('unk_loc', 'all'), nil, "function setlocale (unknown locale)")
+end
+
+do -- time
+    like(os.time(), '^%d+%.?%d*$', "function time")
+    like(os.time(nil), '^%d+%.?%d*$', "function time")
+    like(os.time({
+        sec = 0,
+        min = 0,
+        hour = 0,
+        day = 1,
+        month = 1,
+        year = 2000,
+        isdst = false,
+    }), '^946%d+$', "function time")
+
+    error_like(function () os.time{} end,
+               "^[^:]+:%d+: field '%w+' missing in date table",
+               "function time (missing field)")
+
+    error_like(function () os.time({ day = 'bad', year = 'bad' }) end,
+               "^[^:]+:%d+: field '%w+'",
+               "function time (bad field)")
+
+    if _VERSION < 'Lua 5.3' then
+        todo("only with integer")
+    end
+    error_like(function () os.time({ day = 1.5, year = 1.5 }) end,
+               "^[^:]+:%d+: field '%w+' is not an integer",
+               "function time (not integer)")
+
+    if string.packsize and string.packsize('l') == 8 then
+        skip('64bit platforms')
+    else
+        if _VERSION < 'Lua 5.3' then
+            todo"only with 5.3"
+        end
+        error_like(function () os.time({
+            sec = 0,
+            min = 0,
+            hour = 0,
+            day = 1,
+            month = 1,
+            year = 1000,
+            isdst = false,
+        }) end,
+                   "^[^:]+:%d+: time result cannot be represented in this installation",
+                   "function time (invalid)")
+    end
+end
+
+do -- tmpname
+    local fname = os.tmpname()
+    type_ok(fname, 'string', "function tmpname")
+    ok(fname ~= os.tmpname())
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/310-debug.t b/test/lua-Harness-tests/310-debug.t
new file mode 100755
index 0000000..f78af03
--- /dev/null
+++ b/test/lua-Harness-tests/310-debug.t
@@ -0,0 +1,322 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Debug Library
+
+=head2 Synopsis
+
+    % prove 310-debug.t
+
+=head2 Description
+
+Tests Lua Debug Library
+
+See section "The Debug Library" in "Reference Manual"
+L<https://www.lua.org/manual/5.1/manual.html#5.9>,
+L<https://www.lua.org/manual/5.2/manual.html#6.10>,
+L<https://www.lua.org/manual/5.3/manual.html#6.10>,
+L<https://www.lua.org/manual/5.4/manual.html#6.10>
+
+=cut
+
+]]
+
+require 'tap'
+local profile = require'profile'
+local has_getfenv = _VERSION == 'Lua 5.1'
+local has_gethook54 = _VERSION >= 'Lua 5.4'
+local has_getlocal52 = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local has_getuservalue = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
+local has_getuservalue54 = _VERSION >= 'Lua 5.4'
+local has_setcstacklimit = _VERSION >= 'Lua 5.4'
+local has_setmetatable52 = _VERSION >= 'Lua 5.2' or (profile.luajit_compat52 and not ujit)
+local has_upvalueid = _VERSION >= 'Lua 5.2' or jit
+local has_upvaluejoin = _VERSION >= 'Lua 5.2' or jit
+
+local debug = require 'debug'
+
+if not debug then
+    skip_all("no debug")
+end
+
+plan'no_plan'
+
+-- getfenv
+if has_getfenv then
+    is(debug.getfenv(3.14), nil, "function getfenv")
+    local function f () end
+    type_ok(debug.getfenv(f), 'table')
+    is(debug.getfenv(f), _G)
+    type_ok(debug.getfenv(print), 'table')
+    is(debug.getfenv(print), _G)
+
+    local a = coroutine.create(function () return 1 end)
+    type_ok(debug.getfenv(a), 'table', "function getfenv (thread)")
+    is(debug.getfenv(a), _G)
+else
+    is(debug.getfenv, nil, "no debug.getfenv (removed)")
+end
+
+do -- getinfo
+    local info = debug.getinfo(is)
+    type_ok(info, 'table', "function getinfo (function)")
+    is(info.func, is, " .func")
+
+    info = debug.getinfo(is, 'L')
+    type_ok(info, 'table', "function getinfo (function, opt)")
+    type_ok(info.activelines, 'table')
+
+    info = debug.getinfo(1)
+    type_ok(info, 'table', "function getinfo (level)")
+    like(info.func, "^function: [0]?[Xx]?%x+", " .func")
+
+    is(debug.getinfo(12), nil, "function getinfo (too depth)")
+
+    error_like(function () debug.getinfo('bad') end,
+               "bad argument #1 to 'getinfo' %(.- expected",
+               "function getinfo (bad arg)")
+
+    error_like(function () debug.getinfo(is, 'X') end,
+               "bad argument #2 to 'getinfo' %(invalid option%)",
+               "function getinfo (bad opt)")
+end
+
+do -- getlocal
+    local name, value = debug.getlocal(0, 1)
+    type_ok(name, 'string', "function getlocal (level)")
+    is(value, 0)
+
+    error_like(function () debug.getlocal(42, 1) end,
+               "bad argument #1 to 'getlocal' %(level out of range%)",
+               "function getlocal (out of range)")
+
+    if has_getlocal52 then
+        name, value = debug.getlocal(like, 1)
+        type_ok(name, 'string', "function getlocal (func)")
+        is(value, nil)
+    else
+        diag("no getlocal with function")
+    end
+end
+
+do -- getmetatable
+    local t = {}
+    is(debug.getmetatable(t), nil, "function getmetatable")
+    local t1 = {}
+    debug.setmetatable(t, t1)
+    is(debug.getmetatable(t), t1)
+
+    local a = true
+    is(debug.getmetatable(a), nil)
+    debug.setmetatable(a, t1)
+    is(debug.getmetatable(t), t1)
+
+    a = 3.14
+    is(debug.getmetatable(a), nil)
+    debug.setmetatable(a, t1)
+    is(debug.getmetatable(t), t1)
+end
+
+do -- getregistry
+    local reg = debug.getregistry()
+    type_ok(reg, 'table', "function getregistry")
+    type_ok(reg._LOADED, 'table')
+end
+
+do -- getupvalue
+    local name = debug.getupvalue(plan, 1)
+    type_ok(name, 'string', "function getupvalue")
+end
+
+do -- gethook
+    debug.sethook()
+    local hook, mask, count
+    if has_gethook54 then
+        hook = debug.gethook()
+        is(hook, nil, "function gethook")
+    else
+        hook, mask, count = debug.gethook()
+        is(hook, nil, "function gethook")
+        is(mask, '')
+        is(count, 0)
+    end
+    local function f () end
+    debug.sethook(f, 'c', 42)
+    hook , mask, count = debug.gethook()
+    is(hook, f, "function gethook")
+    is(mask, 'c')
+    is(count, 42)
+
+    local co = coroutine.create(function () print "thread" end)
+    hook = debug.gethook(co)
+    if jit then
+        type_ok(hook, 'function', "function gethook(thread)")
+    else
+        is(hook, nil, "function gethook(thread)")
+    end
+end
+
+do -- setlocal
+    local name = debug.setlocal(0, 1, 0)
+    type_ok(name, 'string', "function setlocal (level)")
+
+    name = debug.setlocal(0, 42, 0)
+    is(name, nil, "function setlocal (level)")
+
+    error_like(function () debug.setlocal(42, 1, true) end,
+               "bad argument #1 to 'setlocal' %(level out of range%)",
+               "function setlocal (out of range)")
+end
+
+-- setcstacklimit
+if has_setcstacklimit then
+    type_ok(debug.setcstacklimit(200), 'number', "function setcstacklimit")
+    is(debug.setcstacklimit(1000), 200)
+
+    error_like(function () debug.setcstacklimit('bad') end,
+               "^[^:]+:%d+: bad argument #1 to 'setcstacklimit' %(number expected, got string%)",
+               "function setcstacklimit (bad arg)")
+else
+    is(debug.setcstacklimit, nil, "no debug.setcstacklimit")
+end
+
+-- setfenv
+if has_getfenv then
+    local t = {}
+    local function f () end
+    is(debug.setfenv(f, t), f, "function setfenv")
+    type_ok(debug.getfenv(f), 'table')
+    is(debug.getfenv(f), t)
+    is(debug.setfenv(print, t), print)
+    type_ok(debug.getfenv(print), 'table')
+    is(debug.getfenv(print), t)
+
+    t = {}
+    local a = coroutine.create(function () return 1 end)
+    is(debug.setfenv(a, t), a, "function setfenv (thread)")
+    type_ok(debug.getfenv(a), 'table')
+    is(debug.getfenv(a), t)
+
+    error_like(function () t = {}; debug.setfenv(t, t) end,
+               "^[^:]+:%d+: 'setfenv' cannot change environment of given object",
+               "function setfenv (forbidden)")
+else
+    is(debug.setfenv, nil, "no debug.setfenv (removed)")
+end
+
+do -- setmetatable
+    local t = {}
+    local t1 = {}
+    if has_setmetatable52 then
+        is(debug.setmetatable(t, t1), t, "function setmetatable")
+    else
+        is(debug.setmetatable(t, t1), true, "function setmetatable")
+    end
+    is(getmetatable(t), t1)
+
+    error_like(function () debug.setmetatable(t, true) end,
+               "^[^:]+:%d+: bad argument #2 to 'setmetatable' %(nil or table expected")
+end
+
+do -- setupvalue
+    local r, tb = pcall(require, 'Test.Builder')
+    local value = r and tb:new() or {}
+    local name = debug.setupvalue(plan, 1, value)
+    type_ok(name, 'string', "function setupvalue")
+
+    name = debug.setupvalue(plan, 42, true)
+    is(name, nil)
+end
+
+-- getuservalue / setuservalue
+if has_getuservalue54 then
+    local u = io.tmpfile()      -- lua_newuserdatauv(L, sizeof(LStream), 0);
+    is(debug.getuservalue(u, 0), nil, "function getuservalue")
+    is(debug.getuservalue(true), nil)
+
+    error_like(function () debug.getuservalue(u, 'foo') end,
+               "^[^:]+:%d+: bad argument #2 to 'getuservalue' %(number expected, got string%)")
+
+    local data = {}
+    is(debug.setuservalue(u, data, 42), nil, "function setuservalue")
+
+    error_like(function () debug.setuservalue({}, data) end,
+               "^[^:]+:%d+: bad argument #1 to 'setuservalue' %(userdata expected, got table%)")
+
+    error_like(function () debug.setuservalue(u, data, 'foo') end,
+               "^[^:]+:%d+: bad argument #3 to 'setuservalue' %(number expected, got string%)")
+elseif has_getuservalue then
+    local u = io.tmpfile()
+    local old = debug.getuservalue(u)
+    if jit then
+        type_ok(old, 'table', "function getuservalue")
+    else
+        is(old, nil, "function getuservalue")
+    end
+    is(debug.getuservalue(true), nil)
+
+    local data = {}
+    local r = debug.setuservalue(u, data)
+    is(r, u, "function setuservalue")
+    is(debug.getuservalue(u), data)
+    r = debug.setuservalue(u, old)
+    is(debug.getuservalue(u), old)
+
+    error_like(function () debug.setuservalue({}, data) end,
+               "^[^:]+:%d+: bad argument #1 to 'setuservalue' %(userdata expected, got table%)")
+else
+    is(debug.getuservalue, nil, "no getuservalue")
+    is(debug.setuservalue, nil, "no setuservalue")
+end
+
+do -- traceback
+    like(debug.traceback(), "^stack traceback:\n", "function traceback")
+
+    like(debug.traceback("message\n"), "^message\n\nstack traceback:\n", "function traceback with message")
+
+    like(debug.traceback(false), "false", "function traceback")
+end
+
+-- upvalueid
+if has_upvalueid then
+    local id = debug.upvalueid(plan, 1)
+    type_ok(id, 'userdata', "function upvalueid")
+else
+    is(debug.upvalueid, nil, "no upvalueid")
+end
+
+-- upvaluejoin
+if has_upvaluejoin and jit then
+    diag("jit upvaluejoin")
+    -- TODO
+elseif has_upvaluejoin then
+    debug.upvaluejoin(pass, 1, fail, 1)
+
+    error_like(function () debug.upvaluejoin(true, 1, nil, 1) end,
+               "bad argument #1 to 'upvaluejoin' %(function expected, got boolean%)",
+               "function upvaluejoin (bad arg)")
+
+    error_like(function () debug.upvaluejoin(pass, 1, true, 1) end,
+               "bad argument #3 to 'upvaluejoin' %(function expected, got boolean%)",
+               "function upvaluejoin (bad arg)")
+else
+    is(debug.upvaluejoin, nil, "no upvaluejoin")
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/311-bit32.t b/test/lua-Harness-tests/311-bit32.t
new file mode 100755
index 0000000..7023906
--- /dev/null
+++ b/test/lua-Harness-tests/311-bit32.t
@@ -0,0 +1,127 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2010-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Bitwise Library
+
+=head2 Synopsis
+
+    % prove 311-bit32.t
+
+=head2 Description
+
+Tests Lua Bitwise Library
+
+This library was introduced in Lua 5.2 and deprecated in Lua 5.3.
+
+See section "Bitwise Operations" in "Reference Manual"
+L<https://www.lua.org/manual/5.2/manual.html#6.7>
+
+=cut
+
+--]]
+
+require 'tap'
+local profile = require'profile'
+local has_bit32 = _VERSION == 'Lua 5.2' or profile.compat52 or profile.has_bit32
+
+if not bit32 then
+    plan(1)
+    nok(has_bit32, "no has_bit32")
+    os.exit(0)
+end
+
+plan(20)
+
+do -- arshift
+    is(bit32.arshift(0x06, 1), 0x03, "function arshift")
+    is(bit32.arshift(-3, 1), bit32.arshift(-6, 2), "function arshift")
+end
+
+do -- band
+    is(bit32.band(0x01, 0x03, 0x07), 0x01, "function band")
+end
+
+do -- bnot
+    if string.pack and #string.pack('n', 0) == 4 then
+        is(bit32.bnot(0x03), (-1 - 0x03), "function bnot")
+    else
+        is(bit32.bnot(0x03), (-1 - 0x03) % 2^32, "function bnot")
+    end
+end
+
+do -- bor
+    is(bit32.bor(0x01, 0x03, 0x07), 0x07, "function bor")
+end
+
+do -- btest
+    is(bit32.btest(0x01), true, "function btest")
+    is(bit32.btest(0x00), false, "function btest")
+end
+
+do -- bxor
+    is(bit32.bxor(0x01, 0x03, 0x07), 0x05, "function bxor")
+end
+
+do -- extract
+    is(bit32.extract(0xFFFF, 3, 3), 0x07, "function extract")
+
+    error_like(function () bit32.extract(0xFFFF, 99) end,
+               "^[^:]+:%d+: trying to access non%-existent bits",
+               "function extract (non-existent bits)")
+
+    error_like(function () bit32.extract(0xFFFF, -3) end,
+               "^[^:]+:%d+: bad argument #2 to 'extract' %(field cannot be negative%)",
+               "function extract (negatif field)")
+
+    error_like(function () bit32.extract(0xFFFF, 3, -3) end,
+               "^[^:]+:%d+: bad argument #3 to 'extract' %(width must be positive%)",
+               "function extract (negative width)")
+end
+
+do -- replace
+    is(bit32.replace(0x0000, 0xFFFF, 3, 3), 0x38, "function replace")
+
+    error_like(function () bit32.replace(0x0000, 0xFFFF, 99) end,
+               "^[^:]+:%d+: trying to access non%-existent bits",
+               "function replace (non-existent bits)")
+
+    error_like(function () bit32.replace(0x0000, 0xFFFF, -3) end,
+               "^[^:]+:%d+: bad argument #3 to 'replace' %(field cannot be negative%)",
+               "function replace (negatif field)")
+
+    error_like(function () bit32.replace(0x0000, 0xFFFF, 3, -3) end,
+               "^[^:]+:%d+: bad argument #4 to 'replace' %(width must be positive%)",
+               "function replace (negative width)")
+end
+
+do -- lrotate
+    is(bit32.lrotate(0x03, 2), 0x0C, "function lrotate")
+end
+
+do -- lshift
+    is(bit32.lshift(0x03, 2), 0x0C, "function lshift")
+end
+
+do -- rrotate
+    is(bit32.rrotate(0x06, 1), 0x03, "function rrotate")
+end
+
+do -- rshift
+    is(bit32.rshift(0x06, 1), 0x03, "function rshift")
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/314-regex.t b/test/lua-Harness-tests/314-regex.t
new file mode 100755
index 0000000..ad4554c
--- /dev/null
+++ b/test/lua-Harness-tests/314-regex.t
@@ -0,0 +1,222 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Regex Compiler
+
+=head2 Synopsis
+
+    % prove 314-regex.t
+
+=head2 Description
+
+Tests Lua Regex
+
+Individual tests are stored in the C<rx_*> files in the same directory;
+There is one test per line: each test consists of the following
+columns (separated by one *or more* tabs):
+
+=over 4
+
+=item pattern
+
+The Lua regex to test.
+
+=item target
+
+The string that will be matched against the pattern. Use '' to indicate
+an empty string.
+
+=item result
+
+The expected result of the match.
+
+=item description
+
+Description of the test.
+
+=back
+
+=cut
+
+--]]
+
+require'tap'
+local loadstring = loadstring or load
+
+plan(162)
+
+local test_files = {
+    'rx_captures',
+    'rx_charclass',
+    'rx_metachars',
+}
+
+local todo_info = {}
+
+if _VERSION == 'Lua 5.1' then
+    if not jit then
+        todo_info[130] = "printable. %g"
+        --todo_info[131] = "printable. %g"
+        todo_info[132] = "not printable. %G"
+        --todo_info[133] = "not printable. %G"
+    end
+    todo_info[147] = "embedded nul. \\0"
+    todo_info[149] = "embedded nul. \\0"
+    todo_info[151] = "embedded nul. [^\\0]"
+    todo_info[153] = "embedded nul. [^\\0]"
+end
+
+local function split (line)
+    local pattern, target, result, desc = '', '', '', ''
+    local idx = 1
+    local c = line:sub(idx, idx)
+    while (c ~= '' and c ~= "\t") do
+        if (c == '"') then
+            pattern = pattern .. "\\\""
+        else
+            pattern = pattern .. c
+        end
+        idx = idx + 1
+        c = line:sub(idx, idx)
+    end
+    if pattern == "''" then
+        pattern = ''
+    end
+    while (c ~= '' and c == "\t") do
+        idx = idx + 1
+        c = line:sub(idx, idx)
+    end
+    while (c ~= '' and c ~= "\t") do
+        if (c == '"') then
+            target = target .. "\\\""
+        else
+            target = target .. c
+        end
+        idx = idx + 1
+        c = line:sub(idx, idx)
+    end
+    if target == "''" then
+        target = ''
+    end
+    while (c ~= '' and c == "\t") do
+        idx = idx + 1
+        c = line:sub(idx, idx)
+    end
+    while (c ~= '' and c ~= "\t") do
+        if c == "\\" then
+            idx = idx + 1
+            c = line:sub(idx, idx)
+            if     c == 'f' then
+                result = result .. "\f"
+            elseif c == 'n' then
+                result = result .. "\n"
+            elseif c == 'r' then
+                result = result .. "\r"
+            elseif c == 't' then
+                result = result .. "\t"
+            elseif c == '0' then
+                idx = idx + 1
+                c = line:sub(idx, idx)
+                if     c == '1' then
+                    result = result .. "\01"
+                elseif c == '2' then
+                    result = result .. "\02"
+                elseif c == '3' then
+                    result = result .. "\03"
+                elseif c == '4' then
+                    result = result .. "\04"
+                else
+                    result = result .. "\0" .. c
+                end
+            elseif c == "\t" then
+                result = result .. "\\"
+            else
+                result = result .. "\\" .. c
+            end
+        else
+            result = result .. c
+        end
+        idx = idx + 1
+        c = line:sub(idx, idx)
+    end
+    if result == "''" then
+        result = ''
+    end
+    while (c ~= '' and c == "\t") do
+        idx = idx + 1
+        c = line:sub(idx, idx)
+    end
+    while (c ~= '' and c ~= "\t") do
+        desc = desc .. c
+        idx = idx + 1
+        c = line:sub(idx, idx)
+    end
+    return pattern, target, result, desc
+end
+
+local test_number = 0
+local dirname = arg[0]:sub(1, arg[0]:find'314' -1)
+for _, filename in ipairs(test_files) do
+    local f, msg = io.open(dirname .. filename, 'r')
+    if f == nil then
+        diag(msg)
+        break
+    else
+        for line in f:lines() do
+            if line:len() == 0 then
+                break
+            end
+            local pattern, target, result, desc = split(line)
+            test_number = test_number + 1
+            if todo_info[test_number] then
+                todo(todo_info[test_number])
+            end
+            local code = [[
+                    local t = {string.match("]] .. target .. [[", "]] .. pattern .. [[")}
+                    if #t== 0 then
+                        return 'nil'
+                    else
+                        for i = 1, #t do
+                            t[i] = tostring(t[i])
+                        end
+                        return table.concat(t, "\t")
+                    end
+            ]]
+            local compiled
+            compiled, msg = loadstring(code)
+            if not compiled then
+                error("can't compile : " .. code .. "\n" .. msg)
+            end
+            if result:sub(1, 1) == '/' then
+                pattern = result:sub(2, result:len() - 1)
+                error_like(compiled, pattern, desc)
+            else
+                local r, out
+                r, msg = pcall(function () out = compiled() end)
+                if r then
+                    is(out, result, desc)
+                else
+                    fail(desc)
+                    diag(msg)
+                end
+            end
+        end
+        f:close()
+    end
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/320-stdin.t b/test/lua-Harness-tests/320-stdin.t
new file mode 100755
index 0000000..4828285
--- /dev/null
+++ b/test/lua-Harness-tests/320-stdin.t
@@ -0,0 +1,133 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 Lua Library
+
+=head2 Synopsis
+
+    % prove 320-stdin.t
+
+=head2 Description
+
+Tests Lua Basic & IO Libraries with stdin
+
+=cut
+
+--]]
+
+require'tap'
+
+local lua = get_lua_binary_name()
+
+if not pcall(io.popen, lua .. [[ -e "a=1"]]) then
+    skip_all "io.popen not supported"
+end
+
+plan(12)
+
+do
+    local f = io.open('lib-320.lua', 'w')
+    f:write[[
+function norm (x, y)
+    return (x^2 + y^2)^0.5
+end
+
+function twice (x)
+    return 2*x
+end
+]]
+    f:close()
+
+    local cmd = lua .. [[ -e "dofile(); n = norm(3.4, 1.0); print(twice(n))" < lib-320.lua]]
+    f = io.popen(cmd)
+    like(f:read'*l', '^7%.088', "function dofile (stdin)")
+    f:close()
+
+    os.remove('lib-320.lua') -- clean up
+end
+
+do
+    local f = io.open('foo-320.lua', 'w')
+    f:write[[
+function foo (x)
+    return x
+end
+]]
+    f:close()
+
+    local cmd = lua .. [[ -e "f = loadfile(); print(foo); f(); print(foo('ok'))" < foo-320.lua]]
+    f = io.popen(cmd)
+    is(f:read'*l', 'nil', "function loadfile (stdin)")
+    is(f:read'*l', 'ok')
+    f:close()
+
+    os.remove('foo-320.lua') -- clean up
+end
+
+do
+    local f = io.open('file-320.txt', 'w')
+    f:write("file with text\n")
+    f:close()
+
+    local cmd = lua .. [[ -e "print(io.read'*l'); print(io.read'*l'); print(io.type(io.stdin))" < file-320.txt]]
+    f = io.popen(cmd)
+    is(f:read'*l', 'file with text', "function io.read *l")
+    is(f:read'*l', 'nil')
+    is(f:read'*l', 'file')
+    f:close()
+
+    cmd = lua .. [[ -e "for line in io.lines() do print(line) end" < file-320.txt]]
+    f = io.popen(cmd)
+    is(f:read'*l', 'file with text', "function io.lines")
+    is(f:read'*l', nil)
+    f:close()
+
+    os.remove('file-320.txt') -- clean up
+end
+
+do
+    local f = io.open('number-320.txt', 'w')
+    f:write("6.0     -3.23   15e3\n")
+    f:write("4.3     234     1000001\n")
+    f:close()
+
+    local cmd = lua .. [[ -e "while true do local n1, n2, n3 = io.read('*number', '*number', '*number'); if not n1 then break end; print(math.max(n1, n2, n3)) end" < number-320.txt]]
+    f = io.popen(cmd)
+    like(f:read'*l', '15000%.?', "function io:read *number")
+    is(f:read'*l', '1000001')
+    f:close()
+
+    os.remove('number-320.txt') -- clean up
+end
+
+do
+    local f = io.open('dbg-320.txt', 'w')
+    f:write("print 'ok'\n")
+    f:write("error 'dbg'\n")
+    f:write("cont\n")
+    f:close()
+
+    local cmd = lua .. [[ -e "debug.debug()" < dbg-320.txt]]
+    f = io.popen(cmd)
+    is(f:read'*l', 'ok', "function debug.debug")
+    is(f:read'*l', nil)
+    f:close()
+
+    os.remove('dbg-320.txt') -- clean up
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/401-bitop.t b/test/lua-Harness-tests/401-bitop.t
new file mode 100755
index 0000000..f95aebf
--- /dev/null
+++ b/test/lua-Harness-tests/401-bitop.t
@@ -0,0 +1,106 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 BitOp Library
+
+=head2 Synopsis
+
+    % prove 401-bitop.t
+
+=head2 Description
+
+See L<http://bitop.luajit.org/>.
+
+=cut
+
+--]]
+
+require 'tap'
+
+if not jit then
+    skip_all("only with LuaJIT")
+end
+
+plan(29)
+
+is(package.loaded.bit, _G.bit, "package.loaded")
+is(require'bit', bit, "require")
+
+do -- arshift
+    is(bit.arshift(256, 8), 1, "function arshift")
+    is(bit.arshift(-256, 8), -1)
+end
+
+do -- band
+    is(bit.band(0x12345678, 0xff), 0x00000078, "function band")
+end
+
+do -- bnot
+    is(bit.bnot(0), -1, "function bnot")
+    is(bit.bnot(-1), 0)
+    is(bit.bnot(0xffffffff), 0)
+end
+
+do -- bor
+    is(bit.bor(1, 2, 4, 8), 15, "function bor")
+end
+
+do -- bswap
+    is(bit.bswap(0x12345678), 0x78563412, "function bswap")
+    is(bit.bswap(0x78563412), 0x12345678)
+end
+
+do -- bxor
+    is(bit.bxor(0xa5a5f0f0, 0xaa55ff00), 0x0ff00ff0, "function bxor")
+end
+
+do -- lshift
+    is(bit.lshift(1, 0), 1, "function lshift")
+    is(bit.lshift(1, 8), 256)
+    is(bit.lshift(1, 40), 256)
+    is(bit.lshift(0x87654321, 12), 0x54321000)
+end
+
+do -- rol
+    is(bit.rol(0x12345678, 12), 0x45678123, "function rol")
+end
+
+do -- ror
+    is(bit.ror(0x12345678, 12), 0x67812345, "function ror")
+end
+
+do -- rshift
+    is(bit.rshift(256, 8), 1, "function rshift")
+    is(bit.rshift(-256, 8), 16777215)
+    is(bit.rshift(0x87654321, 12), 0x00087654)
+end
+
+do -- tobit
+    is(bit.tobit(0xffffffff + 1), 0, "function tobit")
+    is(bit.tobit(2^40 + 1234), 1234)
+end
+
+do -- tohex
+    is(bit.tohex(1), '00000001', "function tohex")
+    is(bit.tohex(-1), 'ffffffff')
+    is(bit.tohex(0xffffffff), 'ffffffff')
+    is(bit.tohex(-1, -8), 'FFFFFFFF')
+    is(bit.tohex(0x21, 4), '0021')
+    is(bit.tohex(0x87654321, 4), '4321')
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/402-ffi.t b/test/lua-Harness-tests/402-ffi.t
new file mode 100755
index 0000000..a2e32a5
--- /dev/null
+++ b/test/lua-Harness-tests/402-ffi.t
@@ -0,0 +1,142 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 FFI Library
+
+=head2 Synopsis
+
+    % prove 402-ffi.t
+
+=head2 Description
+
+See L<http://luajit.org/ext_ffi.html>.
+
+=cut
+
+--]]
+
+require 'tap'
+
+if not jit then
+    skip_all("only with LuaJIT")
+end
+
+if not pcall(require, 'ffi') then
+    plan(2)
+    is(_G.ffi, nil, "no FFI")
+    is(package.loaded.ffi, nil)
+    os.exit(0)
+end
+
+plan(33)
+
+is(_G.ffi, nil, "ffi not loaded by default")
+ffi = require'ffi'
+is(package.loaded.ffi, ffi, "package.loaded")
+is(require'ffi', ffi, "require")
+
+do -- C
+    type_ok(ffi.C, 'userdata', 'C')
+end
+
+do -- abi
+    type_ok(ffi.abi('32bit'), 'boolean', "abi")
+    type_ok(ffi.abi('64bit'), 'boolean')
+    type_ok(ffi.abi('le'), 'boolean')
+    type_ok(ffi.abi('be'), 'boolean')
+    type_ok(ffi.abi('fpu'), 'boolean')
+    type_ok(ffi.abi('softfp'), 'boolean')
+    type_ok(ffi.abi('hardfp'), 'boolean')
+    type_ok(ffi.abi('eabi'), 'boolean')
+    type_ok(ffi.abi('win'), 'boolean')
+    is(ffi.abi('bad'), false)
+    is(ffi.abi(0), false)
+
+    error_like(function () ffi.abi(true) end,
+               "^[^:]+:%d+: bad argument #1 to 'abi' %(string expected, got boolean%)",
+               "function unpack missing size")
+end
+
+do -- alignof
+    type_ok(ffi.alignof, 'function', "alignof")
+end
+
+do -- arch
+    is(ffi.arch, jit.arch, "alias arch")
+end
+
+do -- cast
+    type_ok(ffi.cast, 'function', "cast")
+end
+
+do -- cdef
+    type_ok(ffi.cdef, 'function', "cdef")
+end
+
+do -- copy
+    type_ok(ffi.copy, 'function', "copy")
+end
+
+do -- errno
+    type_ok(ffi.errno, 'function', "errno")
+end
+
+do -- fill
+    type_ok(ffi.fill, 'function', "fill")
+end
+
+do -- gc
+    type_ok(ffi.gc, 'function', "gc")
+end
+
+do -- istype
+    type_ok(ffi.istype, 'function', "istype")
+end
+
+do -- load
+    type_ok(ffi.load, 'function', "load")
+end
+
+do -- metatype
+    type_ok(ffi.metatype, 'function', "metatype")
+end
+
+do -- new
+    type_ok(ffi.new, 'function', "new")
+end
+
+do -- offsetof
+    type_ok(ffi.offsetof, 'function', "offsetof")
+end
+
+do -- os
+    is(ffi.os, jit.os, "alias os")
+end
+
+do -- sizeof
+    type_ok(ffi.sizeof, 'function', "sizeof")
+end
+
+do -- string
+    type_ok(ffi.string, 'function', "string")
+end
+
+do -- typeof
+    type_ok(ffi.typeof, 'function', "typeof")
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/403-jit.t b/test/lua-Harness-tests/403-jit.t
new file mode 100755
index 0000000..0073c90
--- /dev/null
+++ b/test/lua-Harness-tests/403-jit.t
@@ -0,0 +1,163 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2018-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 JIT Library
+
+=head2 Synopsis
+
+    % prove 403-jit.t
+
+=head2 Description
+
+See L<http://luajit.org/ext_jit.html>.
+
+=cut
+
+--]]
+
+require 'tap'
+local profile = require'profile'
+
+if not jit then
+    skip_all("only with LuaJIT")
+end
+
+local compiled_with_jit = jit.status()
+local luajit20 = jit.version_num < 20100 and not jit.version:match'RaptorJIT'
+local has_jit_opt = compiled_with_jit
+local has_jit_security = jit.security
+local has_jit_util = not ujit and not jit.version:match'RaptorJIT'
+
+plan'no_plan'
+
+is(package.loaded.jit, _G.jit, "package.loaded")
+is(require'jit', jit, "require")
+
+do -- arch
+    type_ok(jit.arch, 'string', "arch")
+end
+
+do -- flush
+    type_ok(jit.flush, 'function', "flush")
+end
+
+do -- off
+    jit.off()
+    is(jit.status(), false, "off")
+end
+
+-- on
+if compiled_with_jit then
+    jit.on()
+    is(jit.status(), true, "on")
+else
+    error_like(function () jit.on() end,
+               "^[^:]+:%d+: JIT compiler permanently disabled by build option",
+               "no jit.on")
+end
+
+-- opt
+if has_jit_opt then
+    type_ok(jit.opt, 'table', "opt.*")
+    type_ok(jit.opt.start, 'function', "opt.start")
+else
+    is(jit.opt, nil, "no jit.opt")
+end
+
+do -- os
+    type_ok(jit.os, 'string', "os")
+end
+
+-- prngstate
+if profile.openresty then
+    type_ok(jit.prngstate(), 'table', "prngstate")
+    local s1 = { 1, 2, 3, 4, 5, 6, 7, 8}
+    type_ok(jit.prngstate(s1), 'table')
+    local s2 = { 8, 7, 6, 5, 4, 3, 2, 1}
+    eq_array(jit.prngstate(s2), s1)
+    eq_array(jit.prngstate(), s2)
+
+    type_ok(jit.prngstate(32), 'table', "backward compat")
+    eq_array(jit.prngstate(5617), { 32, 0, 0, 0, 0, 0, 0, 0 })
+    eq_array(jit.prngstate(), { 5617, 0, 0, 0, 0, 0, 0, 0 })
+
+    error_like(function () jit.prngstate(-1) end,
+               "^[^:]+:%d+: bad argument #1 to 'prngstate' %(PRNG state must be an array with up to 8 integers or an integer%)")
+
+    error_like(function () jit.prngstate(false) end,
+               "^[^:]+:%d+: bad argument #1 to 'prngstate' %(table expected, got boolean%)")
+elseif jit.version:match'moonjit' then
+    is(jit.prngstate(), 0, "prngstate")
+else
+    is(jit.prngstate, nil, "no jit.prngstate");
+end
+
+-- security
+if has_jit_security then
+    type_ok(jit.security, 'function', "security")
+    type_ok(jit.security('prng'), 'number', "prng")
+    type_ok(jit.security('strhash'), 'number', "strhash")
+    type_ok(jit.security('strid'), 'number', "stdid")
+    type_ok(jit.security('mcode'), 'number', "mcode")
+
+    error_like(function () jit.security('foo') end,
+               "^[^:]+:%d+: bad argument #1 to 'security' %(invalid option 'foo'%)")
+else
+    is(jit.security, nil, "no jit.security")
+end
+
+do -- status
+    local status = { jit.status() }
+    type_ok(status[1], 'boolean', "status")
+    if compiled_with_jit then
+        for i = 2, #status do
+            type_ok(status[i], 'string', status[i])
+        end
+    else
+        is(#status, 1)
+    end
+end
+
+-- util
+if has_jit_util then
+    local jutil = require'jit.util'
+    type_ok(jutil, 'table', "util")
+    is(package.loaded['jit.util'], jutil)
+
+    if luajit20 then
+        is(jit.util, jutil, "util inside jit")
+    else
+        is(jit.util, nil, "no util inside jit")
+    end
+else
+    local r = pcall(require, 'jit.util')
+    is(r, false, "no jit.util")
+end
+
+do -- version
+    type_ok(jit.version, 'string', "version")
+    like(jit.version, '^%w+ %d%.%d%.%d')
+end
+
+do -- version_num
+    type_ok(jit.version_num, 'number', "version_num")
+    like(string.format("%06d", jit.version_num), '^0[12]0[012]%d%d$')
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/404-ext.t b/test/lua-Harness-tests/404-ext.t
new file mode 100755
index 0000000..22a52c7
--- /dev/null
+++ b/test/lua-Harness-tests/404-ext.t
@@ -0,0 +1,171 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2019-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 JIT Library extensions
+
+=head2 Synopsis
+
+    % prove 404-ext.t
+
+=head2 Description
+
+See L<http://luajit.org/ext_jit.html>.
+
+=cut
+
+--]]
+
+require 'tap'
+local profile = require'profile'
+
+local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
+if not luajit21 then
+    skip_all("only with LuaJIT 2.1")
+end
+
+plan'no_plan'
+
+do -- table.new
+    local r, new = pcall(require, 'table.new')
+    is(r, true, 'table.new')
+    type_ok(new, 'function')
+    is(package.loaded['table.new'], new)
+
+    type_ok(new(100, 0), 'table')
+    type_ok(new(0, 100), 'table')
+    type_ok(new(200, 200), 'table')
+
+    error_like(function () new(42) end,
+               "^[^:]+:%d+: bad argument #2 to 'new' %(number expected, got no value%)")
+end
+
+do -- table.clear
+    local r, clear = pcall(require, 'table.clear')
+    is(r, true, 'table.clear')
+    type_ok(clear, 'function')
+    is(package.loaded['table.clear'], clear)
+
+    local t = { 'foo', bar = 42 }
+    is(t[1], 'foo')
+    is(t.bar, 42)
+    clear(t)
+    is(t[1], nil)
+    is(t.bar, nil)
+
+    error_like(function () clear(42) end,
+               "^[^:]+:%d+: bad argument #1 to 'clear' %(table expected, got number%)")
+end
+
+-- table.clone
+if profile.openresty then
+    local r, clone = pcall(require, 'table.clone')
+    is(r, true, 'table.clone')
+    type_ok(clone, 'function')
+    is(package.loaded['table.clone'], clone)
+
+    local mt = {}
+    local t = setmetatable({ 'foo', bar = 42 }, mt)
+    is(t[1], 'foo')
+    is(t.bar, 42)
+    local t2 = clone(t)
+    type_ok(t2, 'table')
+    isnt(t2, t)
+    is(getmetatable(t2), nil)
+    is(t2[1], 'foo')
+    is(t2.bar, 42)
+
+    error_like(function () clone(42) end,
+               "^[^:]+:%d+: bad argument #1 to 'clone' %(table expected, got number%)")
+else
+    is(pcall(require, 'table.clone'), false, 'no table.clone')
+end
+
+-- table.isarray
+if profile.openresty then
+    local r, isarray = pcall(require, 'table.isarray')
+    is(r, true, 'table.isarray')
+    type_ok(isarray, 'function')
+    is(package.loaded['table.isarray'], isarray)
+
+    is(isarray({ [3] = 3, [5.3] = 4 }), false)
+    is(isarray({ [3] = 'a', [5] = true }), true)
+    is(isarray({ 'a', nil, true, 3.14 }), true)
+    is(isarray({}), true)
+    is(isarray({ ['1'] = 3, ['2'] = 4 }), false)
+    is(isarray({ ['dog'] = 3, ['cat'] = 4 }), false)
+    is(isarray({ 'dog', 'cat', true, ['bird'] = 3 }), false)
+
+    error_like(function () isarray(42) end,
+               "^[^:]+:%d+: bad argument #1 to 'isarray' %(table expected, got number%)")
+else
+    is(pcall(require, 'table.isarray'), false, 'no table.isarray')
+end
+
+-- table.isempty
+if profile.openresty then
+    local r, isempty = pcall(require, 'table.isempty')
+    is(r, true, 'table.isempty')
+    type_ok(isempty, 'function')
+    is(package.loaded['table.isempty'], isempty)
+
+    is(isempty({}), true)
+    is(isempty({ nil }), true)
+    is(isempty({ dogs = nil }), true)
+    is(isempty({ 3.1 }), false)
+    is(isempty({ 'a', 'b' }), false)
+    is(isempty({ nil, false }), false)
+    is(isempty({ dogs = 3 }), false)
+    is(isempty({ dogs = 3, cats = 4 }), false)
+    is(isempty({ dogs = 3, 5 }), false)
+
+    error_like(function () isempty(42) end,
+               "^[^:]+:%d+: bad argument #1 to 'isempty' %(table expected, got number%)")
+else
+    is(pcall(require, 'table.isempty'), false, 'no table.isempty')
+end
+
+-- table.nkeys
+if profile.openresty then
+    local r, nkeys = pcall(require, 'table.nkeys')
+    is(r, true, 'table.nkeys')
+    type_ok(nkeys, 'function')
+    is(package.loaded['table.nkeys'], nkeys)
+
+    is(nkeys({}), 0)
+    is(nkeys({ cats = 4 }), 1)
+    is(nkeys({ dogs = 3, cats = 4 }), 2)
+    is(nkeys({ dogs = nil, cats = 4 }), 1)
+    is(nkeys({ 'cats' }), 1)
+    is(nkeys({ 'dogs', 3, 'cats', 4 }), 4)
+    is(nkeys({ 'dogs', nil, 'cats', 4 }), 3)
+    is(nkeys({ cats = 4, 5, 6 }), 3)
+    is(nkeys({ nil, 'foo', dogs = 3, cats = 4 }), 3)
+
+    error_like(function () nkeys(42) end,
+               "^[^:]+:%d+: bad argument #1 to 'nkeys' %(table expected, got number%)")
+else
+    is(pcall(require, 'table.nkeys'), false, 'no table.nkeys')
+end
+
+-- thread.exdata
+if pcall(require, 'ffi') and (profile.openresty or jit.version:match'moonjit') then
+    dofile'lexicojit/ext.t'
+end
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/411-luajit.t b/test/lua-Harness-tests/411-luajit.t
new file mode 100755
index 0000000..feb752e
--- /dev/null
+++ b/test/lua-Harness-tests/411-luajit.t
@@ -0,0 +1,211 @@
+#! /usr/bin/lua
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2018-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+--[[
+
+=head1 LuaJIT Stand-alone
+
+=head2 Synopsis
+
+    % prove 411-luajit.t
+
+=head2 Description
+
+See L<http://luajit.org/running.html>
+
+=cut
+
+--]]
+
+require'tap'
+local profile = require'profile'
+
+if not jit or ujit then
+    skip_all("only with LuaJIT")
+end
+
+local lua = get_lua_binary_name()
+
+if not pcall(io.popen, lua .. [[ -e "a=1"]]) then
+    skip_all("io.popen not supported")
+end
+
+local compiled_with_jit = jit.status()
+local has_jutil = pcall(require, 'jit.util')
+local has_openresty_listing = profile.openresty or jit.version:match'moonjit'
+
+plan'no_plan'
+diag(lua)
+
+local f = io.open('hello-404.lua', 'w')
+f:write([[
+print 'Hello World'
+]])
+f:close()
+
+os.execute(lua .. " -b hello-404.lua hello-404.out")
+local cmd = lua .. " hello-404.out"
+f = io.popen(cmd)
+is(f:read'*l', 'Hello World', "-b")
+f:close()
+
+os.execute(lua .. " -bg hello-404.lua hello-404.out")
+cmd = lua .. " hello-404.out"
+f = io.popen(cmd)
+is(f:read'*l', 'Hello World', "-bg")
+f:close()
+
+os.execute(lua .. " -be 'print[[Hello World]]' hello-404.out")
+cmd = lua .. " hello-404.out"
+f = io.popen(cmd)
+is(f:read'*l', 'Hello World', "-be")
+f:close()
+
+os.remove('hello-404.out') -- clean up
+
+if has_jutil then
+    cmd = lua .. " -bl hello-404.lua"
+    f = io.popen(cmd)
+    like(f:read'*l', '^%-%- BYTECODE %-%- hello%-404%.lua', "-bl hello.lua")
+    if has_openresty_listing then
+        like(f:read'*l', '^KGC    0')
+        like(f:read'*l', '^KGC    1')
+    end
+    like(f:read'*l', '^0001    %u[%u%d]+%s+')
+    like(f:read'*l', '^0002    %u[%u%d]+%s+')
+    like(f:read'*l', '^0003    %u[%u%d]+%s+')
+    f:close()
+
+    os.execute(lua .. " -bl hello-404.lua hello-404.txt")
+    f = io.open('hello-404.txt', 'r')
+    like(f:read'*l', '^%-%- BYTECODE %-%- hello%-404%.lua', "-bl hello.lua hello.txt")
+    if has_openresty_listing then
+        like(f:read'*l', '^KGC    0')
+        like(f:read'*l', '^KGC    1')
+    end
+    like(f:read'*l', '^0001    %u[%u%d]+%s+')
+    like(f:read'*l', '^0002    %u[%u%d]+%s+')
+    like(f:read'*l', '^0003    %u[%u%d]+%s+')
+    f:close()
+end
+
+if has_openresty_listing then
+    cmd = lua .. " -bL hello-404.lua"
+    f = io.popen(cmd)
+    like(f:read'*l', '^%-%- BYTECODE %-%- hello%-404%.lua', "-bL hello.lua")
+    like(f:read'*l', '^KGC    0')
+    like(f:read'*l', '^KGC    1')
+    like(f:read'*l', '^0001     %[1%]    %u[%u%d]+%s+')
+    like(f:read'*l', '^0002     %[1%]    %u[%u%d]+%s+')
+    like(f:read'*l', '^0003     %[1%]    %u[%u%d]+%s+')
+    f:close()
+
+    os.execute(lua .. " -bL hello-404.lua hello-404.txt")
+    f = io.open('hello-404.txt', 'r')
+    like(f:read'*l', '^%-%- BYTECODE %-%- hello%-404%.lua', "-bL hello.lua hello.txt")
+    like(f:read'*l', '^KGC    0')
+    like(f:read'*l', '^KGC    1')
+    like(f:read'*l', '^0001     %[1%]    %u[%u%d]+%s+')
+    like(f:read'*l', '^0002     %[1%]    %u[%u%d]+%s+')
+    like(f:read'*l', '^0003     %[1%]    %u[%u%d]+%s+')
+    f:close()
+end
+
+os.remove('hello-404.txt') -- clean up
+
+os.execute(lua .. " -b hello-404.lua hello-404.c")
+f = io.open('hello-404.c', 'r')
+like(f:read'*l', '^#ifdef __?cplusplus$', "-b hello.lua hello.c")
+like(f:read'*l', '^extern "C"$')
+like(f:read'*l', '^#endif$')
+like(f:read'*l', '^#ifdef _WIN32$')
+like(f:read'*l', '^__declspec%(dllexport%)$')
+like(f:read'*l', '^#endif$')
+like(f:read'*l', '^const.- char luaJIT_BC_hello_404%[%] = {$')
+like(f:read'*l', '^%d+,%d+,%d+,')
+f:close()
+
+os.remove('hello-404.c') -- clean up
+
+os.execute(lua .. " -b hello-404.lua hello-404.h")
+f = io.open('hello-404.h', 'r')
+like(f:read'*l', '^#define luaJIT_BC_hello_404_SIZE %d+$', "-b hello.lua hello.h")
+like(f:read'*l', '^static const.- char luaJIT_BC_hello_404%[%] = {$')
+like(f:read'*l', '^%d+,%d+,%d+,')
+f:close()
+
+os.remove('hello-404.h') -- clean up
+
+cmd = lua .. " -j flush hello-404.lua"
+f = io.popen(cmd)
+is(f:read'*l', 'Hello World', "-j flush")
+f:close()
+
+cmd = lua .. " -joff hello-404.lua"
+f = io.popen(cmd)
+is(f:read'*l', 'Hello World', "-joff")
+f:close()
+
+cmd = lua .. " -jon hello-404.lua 2>&1"
+f = io.popen(cmd)
+if compiled_with_jit then
+    is(f:read'*l', 'Hello World', "-jon")
+else
+    like(f:read'*l', "^[^:]+: JIT compiler permanently disabled by build option", "no jit")
+end
+f:close()
+
+cmd = lua .. " -j bad hello-404.lua 2>&1"
+f = io.popen(cmd)
+like(f:read'*l', "^[^:]+: unknown luaJIT command or jit%.%* modules not installed", "-j bad")
+f:close()
+
+if compiled_with_jit then
+    cmd = lua .. " -O hello-404.lua"
+    f = io.popen(cmd)
+    is(f:read'*l', 'Hello World', "-O")
+    f:close()
+
+    cmd = lua .. " -O3 hello-404.lua"
+    f = io.popen(cmd)
+    is(f:read'*l', 'Hello World', "-O3")
+    f:close()
+
+    cmd = lua .. " -Ocse -O-dce -Ohotloop=10 hello-404.lua"
+    f = io.popen(cmd)
+    is(f:read'*l', 'Hello World', "-Ocse -O-dce -Ohotloop=10")
+    f:close()
+
+    cmd = lua .. " -O+cse,-dce,hotloop=10 hello-404.lua"
+    f = io.popen(cmd)
+    is(f:read'*l', 'Hello World', "-O+cse,-dce,hotloop=10")
+    f:close()
+
+    cmd = lua .. " -O+bad hello-404.lua 2>&1"
+    f = io.popen(cmd)
+    like(f:read'*l', "^[^:]+: unknown or malformed optimization flag '%+bad'", "-O+bad")
+    f:close()
+else
+    cmd = lua .. " -O0 hello-404.lua 2>&1"
+    f = io.popen(cmd)
+    like(f:read'*l', "^[^:]+: attempt to index a nil value")
+    f:close()
+end
+
+os.remove('hello-404.lua') -- clean up
+
+done_testing()
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/CMakeLists.txt b/test/lua-Harness-tests/CMakeLists.txt
new file mode 100644
index 0000000..9b35e5a
--- /dev/null
+++ b/test/lua-Harness-tests/CMakeLists.txt
@@ -0,0 +1,49 @@
+# Test suite that has been added from lua-Harness test suite
+# 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)
+
+find_program(PROVE prove)
+if(NOT PROVE)
+  message(WARNING "`prove' is not found, so lua-Harness-tests target is not generated")
+  return()
+endif()
+
+set(LUA_TEST_FLAGS --failures --shuffle)
+if(CMAKE_VERBOSE_MAKEFILE)
+  list(APPEND LUA_TEST_FLAGS --verbose)
+endif()
+
+string(CONCAT LUA_PATH
+  "./?.lua\;"
+  "${CMAKE_CURRENT_SOURCE_DIR}/?.lua\;"
+  "${LUAJIT_SOURCE_DIR}/?.lua\;"
+)
+
+string(CONCAT LUA_CPATH
+  "./?${CMAKE_SHARED_LIBRARY_SUFFIX}\;"
+  "${LUAJIT_SOURCE_DIR}/?${CMAKE_SHARED_LIBRARY_SUFFIX}\;"
+)
+
+add_custom_target(lua-Harness-tests DEPENDS ${LUAJIT_TEST_BINARY})
+
+add_custom_command(TARGET lua-Harness-tests
+  COMMENT "Running lua-Harness tests"
+  COMMAND
+  env
+    LUA_PATH="${LUA_PATH}\;"
+    LUA_CPATH="${LUA_CPATH}\;"
+    # Tarantool doesn't support LUA_INIT and most likely it
+    # never will.
+    # See https://github.com/tarantool/tarantool/issues/5744
+    # for more info.
+    # So use less preferable way for tests.
+    # See the root CMakeLists.txt for more info.
+    ${PROVE} ${CMAKE_CURRENT_SOURCE_DIR}
+      --exec '${LUAJIT_TEST_COMMAND} -l profile_luajit21'
+      ${LUA_TEST_FLAGS}
+  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+# vim: expandtab tabstop=2 shiftwidth=2
diff --git a/test/lua-Harness-tests/lexico52/lexico.t b/test/lua-Harness-tests/lexico52/lexico.t
new file mode 100644
index 0000000..ff6bb99
--- /dev/null
+++ b/test/lua-Harness-tests/lexico52/lexico.t
@@ -0,0 +1,45 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2012-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+is("\x41", "A")
+is("\x3d", "=")
+is("\x3D", "=")
+
+do
+    local f, msg = load [[a = "A\xyz"]]
+    like(msg, "^[^:]+:%d+: .- near")
+
+    f, msg = load [[a = "A\Z"]]
+    like(msg, "^[^:]+:%d+: .- escape .- near")
+end
+
+do
+    local a = 'alo\n123"'
+    is("alo\n\z
+    123\"", a)
+
+    local f, msg = load [[a = " escape \z unauthorized
+new line" ]]
+    like(msg, "^[^:]+:%d+: unfinished string near")
+end
+
+is(0x0.1E, 0x1E / 0x100)        -- 0.1171875
+is(0xA23p-4, 0xA23 / (2^4))     -- 162.1875
+if string.pack and #string.pack('n', 0) == 4 then
+    diag('Small Lua')
+else
+    is(0X1.921FB54442D18P+1, (1 + 0x921FB54442D18/0x10000000000000) * 2)
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico53/boolean.t b/test/lua-Harness-tests/lexico53/boolean.t
new file mode 100644
index 0000000..693ac76
--- /dev/null
+++ b/test/lua-Harness-tests/lexico53/boolean.t
@@ -0,0 +1,43 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+error_like(function () return ~true end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a boolean value",
+           "~true")
+
+error_like(function () return true // 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a boolean value",
+           "true // 3")
+
+error_like(function () return true & 7 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a boolean value",
+           "true & 7")
+
+error_like(function () return true | 1 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a boolean value",
+           "true | 1")
+
+error_like(function () return true ~ 4 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a boolean value",
+           "true ~ 4")
+
+error_like(function () return true >> 5 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a boolean value",
+           "true >> 5")
+
+error_like(function () return true << 2 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a boolean value",
+           "true << 2")
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico53/function.t b/test/lua-Harness-tests/lexico53/function.t
new file mode 100644
index 0000000..2471be6
--- /dev/null
+++ b/test/lua-Harness-tests/lexico53/function.t
@@ -0,0 +1,66 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2019, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+local f = function () return 1 end
+
+error_like(function () return ~f end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "~f")
+
+error_like(function () f = print; return ~f end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on")
+
+error_like(function () return f // 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "f // 3")
+
+error_like(function () f = print; return f // 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on")
+
+error_like(function () return f & 7 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "f & 7")
+
+error_like(function () f = print; return f & 7 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on")
+
+error_like(function () return f | 1 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "f | 1")
+
+error_like(function () f = print; return f | 1 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on")
+
+error_like(function () return f ~ 4 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "f ~ 4")
+
+error_like(function () f = print; return f ~ 4 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on")
+
+error_like(function () return f >> 5 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "f >> 5")
+
+error_like(function () f = print; return f >> 5 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on")
+
+error_like(function () return f << 2 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "f << 2")
+
+error_like(function () f = print; return f << 2 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on")
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico53/lexico.t b/test/lua-Harness-tests/lexico53/lexico.t
new file mode 100644
index 0000000..41b0d89
--- /dev/null
+++ b/test/lua-Harness-tests/lexico53/lexico.t
@@ -0,0 +1,30 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2015-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+is("\u{41}", "A")
+is("\u{20AC}", "\xE2\x82\xAC")
+is("\u{20ac}", "\xe2\x82\xac")
+
+do
+    local f, msg = load [[a = "A\u{yz}"]]
+    like(msg, "^[^:]+:%d+: .- near")
+
+    f, msg = load [[a = "A\u{41"]]
+    like(msg, "^[^:]+:%d+: .- near")
+
+    f, msg = load [[a = "A\u{FFFFFFFFFF}"]]
+    like(msg, "^[^:]+:%d+: .- near")
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico53/nil.t b/test/lua-Harness-tests/lexico53/nil.t
new file mode 100644
index 0000000..a6438e2
--- /dev/null
+++ b/test/lua-Harness-tests/lexico53/nil.t
@@ -0,0 +1,43 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+error_like(function () return ~nil end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a nil value",
+           "~nil")
+
+error_like(function () return  nil // 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a nil value",
+           "nil // 3")
+
+error_like(function () return nil & 7 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a nil value",
+           "nil & 7")
+
+error_like(function () return nil | 1 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a nil value",
+           "nil | 1")
+
+error_like(function () return nil ~ 4 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a nil value",
+           "nil ~ 4")
+
+error_like(function () return nil >> 5 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a nil value",
+           "nil >> 5")
+
+error_like(function () return nil << 2 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a nil value",
+           "nil << 2")
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico53/number.t b/test/lua-Harness-tests/lexico53/number.t
new file mode 100644
index 0000000..d205da3
--- /dev/null
+++ b/test/lua-Harness-tests/lexico53/number.t
@@ -0,0 +1,181 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2019, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+local profile = require'profile'
+
+is(~4, -5, "~4")
+
+error_like(function () return ~3.14 end,
+           "^[^:]+:%d+: number has no integer representation",
+           "~3.14")
+
+is(25.5 // 3.5, 7.0, "25.5 // 3.5")
+
+is(25 // 3, 8, "25 // 3")
+
+is(25 // -3, -9, "25 // -3")
+
+is(1 // -1, -1, "1 // -1")
+
+type_ok(1.0 // 0, 'number', "1.0 // 0")
+
+error_like(function () return 1 // 0 end,
+           "^[^:]+:%d+: attempt to divide by zero",
+           "1 // 0")
+
+is(3 & 7, 3, "3 & 7")
+
+is(4 | 1, 5, "4 | 1")
+
+is(7 ~ 1, 6, "7 ~ 1")
+
+is(100 >> 5, 3, "100 >> 5")
+
+is(3 << 2, 12, "3 << 2")
+
+error_like(function () return 25 // {} end,
+           "^[^:]+:%d+: attempt to perform arithmetic on a table value",
+           "25 // {}")
+
+error_like(function () return 3 & true end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a boolean value",
+           "3 & true")
+
+error_like(function () return 4 | true end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a boolean value",
+           "4 | true")
+
+error_like(function () return 7 ~ true end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a boolean value",
+           "7 ~ true")
+
+error_like(function () return 100 >> true end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a boolean value",
+           "100 >> true")
+
+error_like(function () return 3 << true end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a boolean value",
+           "3 << true")
+
+error_like(function () return 25 // 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "25 // 'text'")
+
+error_like(function () return 3 & 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "3 & 'text'")
+
+error_like(function () return 4 | 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "4 | 'text'")
+
+error_like(function () return 7 ~ 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "7 ~ 'text'")
+
+error_like(function () return 100 >> 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "100 >> 'text'")
+
+error_like(function () return 3 << 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "3 << 'text'")
+
+if profile.nocvts2n then
+    error_like(function () return 25.5 // '3.5' end,
+               "^[^:]+:%d+: attempt to",
+               "25.5 // '3.5'")
+
+    error_like(function () return 25 // '3' end,
+               "^[^:]+:%d+: attempt to",
+               "25 // '3'")
+else
+    is(25.5 // '3.5', 7.0, "25.5 // '3.5'")
+
+    is(25 // '3', 8, "25 // '3'")
+end
+
+if profile.nocvts2n or _VERSION >= 'Lua 5.4' then
+    error_like(function () return 3 & '7' end,
+               "^[^:]+:%d+: attempt to",
+               "3 & '7'")
+
+    error_like(function () return 4 | '1' end,
+               "^[^:]+:%d+: attempt to",
+               "4 | '1'")
+
+    error_like(function () return 7 ~ '1' end,
+               "^[^:]+:%d+: attempt to",
+               "7 ~ '1'")
+
+    error_like(function () return 100 >> '5' end,
+               "^[^:]+:%d+: attempt to",
+               "100 >> '5'")
+
+    error_like(function () return 3 << '2' end,
+               "^[^:]+:%d+: attempt to",
+               "3 << '2'")
+else
+    is(3 & '7', 3, "3 & '7'")
+
+    is(4 | '1', 5, "4 | '1'")
+
+    is(7 ~ '1', 6, "7 ~ '1'")
+
+    is(100 >> '5', 3, "100 >> '5'")
+
+    is(3 << '2', 12, "3 << '2'")
+end
+
+error_like(function () return 3.5 & 7 end,
+           "^[^:]+:%d+: number has no integer representation",
+           "3.5 & 7")
+
+error_like(function () return 3 & 7.5 end,
+           "^[^:]+:%d+: number has no integer representation",
+           "3 & 7.5")
+
+error_like(function () return 4.5 | 1 end,
+           "^[^:]+:%d+: number has no integer representation",
+           "4.5 | 1")
+
+error_like(function () return 4 | 1.5 end,
+           "^[^:]+:%d+: number has no integer representation",
+           "4 | 1.5")
+
+error_like(function () return 7.5 ~ 1 end,
+           "^[^:]+:%d+: number has no integer representation",
+           "7.5 ~ 1")
+
+error_like(function () return 7 ~ 1.5 end,
+           "^[^:]+:%d+: number has no integer representation",
+           "7 ~ 1.5")
+
+error_like(function () return 100.5 >> 5 end,
+           "^[^:]+:%d+: number has no integer representation",
+           "100.5 >> 5")
+
+error_like(function () return 100 >> 5.5 end,
+           "^[^:]+:%d+: number has no integer representation",
+           "100 >> 5.5")
+
+error_like(function () return 3.5 << 2 end,
+           "^[^:]+:%d+: number has no integer representation",
+           "3.5 << 2")
+
+error_like(function () return 3 << 2.5 end,
+           "^[^:]+:%d+: number has no integer representation",
+           "3 << 2.5")
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico53/string.t b/test/lua-Harness-tests/lexico53/string.t
new file mode 100644
index 0000000..eb74064
--- /dev/null
+++ b/test/lua-Harness-tests/lexico53/string.t
@@ -0,0 +1,169 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2019, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+local profile = require'profile'
+
+if profile.nocvts2n or _VERSION >= 'Lua 5.4' then
+    error_like(function () return ~'4' end,
+               "^[^:]+:%d+: attempt to",
+               "~'4'")
+else
+    is(~'4', -5, "~'4'")
+end
+
+error_like(function () return ~'text' end,
+           "^[^:]+:%d+: attempt to",
+           "~'text'")
+
+if profile.nocvts2n then
+    error_like(function () return '25.5' // 3.5 end,
+               "^[^:]+:%d+: attempt to",
+               "'25.5' // 3.5")
+
+    error_like(function () return '25' // 3 end,
+               "^[^:]+:%d+: attempt to",
+               "'25' // 3")
+else
+    is('25.5' // 3.5, 7.0, "'25.5' // 3.5")
+
+    is('25' // 3, 8, "'25' // 3")
+end
+
+if profile.nocvts2n or _VERSION >= 'Lua 5.4' then
+    error_like(function () return '3' & 7 end,
+               "^[^:]+:%d+: attempt to",
+               "'3' & 7")
+
+    error_like(function () return '4' | 1 end,
+               "^[^:]+:%d+: attempt to",
+               "'4' | 1")
+
+    error_like(function () return '7' ~ 1 end,
+               "^[^:]+:%d+: attempt to",
+               "'7' ~ 1")
+
+    error_like(function () return '100' >> 5 end,
+               "^[^:]+:%d+: attempt to",
+               "'100' >> 5")
+
+    error_like(function () return '3' << 2 end,
+               "^[^:]+:%d+: attempt to",
+               "'3' << 2")
+else
+    is('3' & 7, 3, "'3' & 7")
+
+    is('4' | 1, 5, "'4' | 1")
+
+    is('7' ~ 1, 6, "'7' ~ 1")
+
+    is('100' >> 5, 3, "'100' >> 5")
+
+    is('3' << 2, 12, "'3' << 2")
+end
+
+error_like(function () return '25' // {} end,
+           "^[^:]+:%d+: attempt to",
+           "'25' // {}")
+
+error_like(function () return '3' & true end,
+           "^[^:]+:%d+: attempt to",
+           "'3' & true")
+
+error_like(function () return '4' | true end,
+           "^[^:]+:%d+: attempt to",
+           "'4' | true")
+
+error_like(function () return '7' ~ true end,
+           "^[^:]+:%d+: attempt to",
+           "'7' ~ true")
+
+error_like(function () return '100' >> true end,
+           "^[^:]+:%d+: attempt to",
+           "'100' >> true")
+
+error_like(function () return '3' << true end,
+           "^[^:]+:%d+: attempt to",
+           "'3' << true")
+
+error_like(function () return '25' // 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'25' // 'text'")
+
+error_like(function () return '3' & 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'3' & 'text'")
+
+error_like(function () return '4' | 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'4' | 'text'")
+
+error_like(function () return '7' ~ 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'7' ~ 'text'")
+
+error_like(function () return '100' >> 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'100' >> 'text'")
+
+error_like(function () return '3' << 'text' end,
+           "^[^:]+:%d+: attempt to",
+           "'3' << 'text'")
+
+if profile.nocvts2n then
+    error_like(function () return '25.5' // '3.5' end,
+               "^[^:]+:%d+: attempt to",
+               "'25.5' // '3.5'")
+
+    error_like(function () return '25' // '3' end,
+               "^[^:]+:%d+: attempt to",
+               "'25' // '3'")
+else
+    is('25.5' // '3.5', 7.0, "'25.5' // '3.5'")
+
+     is('25' // '3', 8, "'25' // '3'")
+end
+
+if profile.nocvts2n or _VERSION >= 'Lua 5.4' then
+    error_like(function () return '3' & '7' end,
+               "^[^:]+:%d+: attempt to",
+               "'3' & '7'")
+
+    error_like(function () return '4' | '1' end,
+               "^[^:]+:%d+: attempt to",
+               "'4' | '1'")
+
+    error_like(function () return '7' ~ '1' end,
+               "^[^:]+:%d+: attempt to",
+               "'7' ~ '1'")
+
+    error_like(function () return '100' >> '5' end,
+               "^[^:]+:%d+: attempt to",
+               "'100' >> '5'")
+
+    error_like(function () return '3' << '2' end,
+               "^[^:]+:%d+: attempt to",
+               "'3' << '2'")
+else
+    is('3' & '7', 3, "'3' & '7'")
+
+    is('4' | '1', 5, "'4' | '1'")
+
+    is('7' ~ '1', 6, "'7' ~ '1'")
+
+    is('100' >> '5', 3, "'100' >> '5'")
+
+    is('3' << '2', 12, "'3' << 2")
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico53/table.t b/test/lua-Harness-tests/lexico53/table.t
new file mode 100644
index 0000000..007232d
--- /dev/null
+++ b/test/lua-Harness-tests/lexico53/table.t
@@ -0,0 +1,43 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+error_like(function () return ~{} end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a table value",
+           "~{}")
+
+error_like(function () return {} // 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "{} // 3")
+
+error_like(function () return {} & 7 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a table value",
+           "{} & 7")
+
+error_like(function () return {} | 1 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a table value",
+           "{} | 1")
+
+error_like(function () return {} ~ 4 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a table value",
+           "{} ~ 4")
+
+error_like(function () return {} >> 5 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a table value",
+           "{} >> 5")
+
+error_like(function () return {} << 2 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on a table value",
+           "{} << 2")
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico53/thread.t b/test/lua-Harness-tests/lexico53/thread.t
new file mode 100644
index 0000000..ef9e57b
--- /dev/null
+++ b/test/lua-Harness-tests/lexico53/thread.t
@@ -0,0 +1,45 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2019, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+local co = coroutine.create(function () return 1 end)
+
+error_like(function () return ~co end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "~co")
+
+error_like(function () return co // 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "co // 3")
+
+error_like(function () return co & 7 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "co & 7")
+
+error_like(function () return co | 1 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "co | 1")
+
+error_like(function () return co ~ 4 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "co ~ 4")
+
+error_like(function () return co >> 5 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "co >> 5")
+
+error_like(function () return co << 2 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "co << 2")
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico53/userdata.t b/test/lua-Harness-tests/lexico53/userdata.t
new file mode 100644
index 0000000..06b96f9
--- /dev/null
+++ b/test/lua-Harness-tests/lexico53/userdata.t
@@ -0,0 +1,45 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2009-2019, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+local u = io.stdin
+
+error_like(function () return ~u end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "~u")
+
+error_like(function () return u // 3 end,
+           "^[^:]+:%d+: attempt to perform arithmetic on",
+           "u // 3")
+
+error_like(function () return u & 7 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "u & 7")
+
+error_like(function () return u | 1 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "u | 1")
+
+error_like(function () return u ~ 4 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "u ~ 4")
+
+error_like(function () return u >> 5 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "u >> 5")
+
+error_like(function () return u << 2 end,
+           "^[^:]+:%d+: attempt to perform bitwise operation on",
+           "u << 2")
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico53/utf8.t b/test/lua-Harness-tests/lexico53/utf8.t
new file mode 100644
index 0000000..87d3f6d
--- /dev/null
+++ b/test/lua-Harness-tests/lexico53/utf8.t
@@ -0,0 +1,179 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2014-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+local has_char54 = _VERSION >= 'Lua 5.4'
+local has_charpattern54 = _VERSION >= 'Lua 5.4'
+
+do -- char
+    is(utf8.char(65, 66, 67), 'ABC', "function char")
+    is(utf8.char(0x20AC), '\u{20AC}')
+    is(utf8.char(), '')
+
+    is(utf8.char(0):len(), 1)
+    is(utf8.char(0x7F):len(), 1)
+    is(utf8.char(0x80):len(), 2)
+    is(utf8.char(0x7FF):len(), 2)
+    is(utf8.char(0x800):len(), 3)
+    is(utf8.char(0xFFFF):len(), 3)
+    is(utf8.char(0x10000):len(), 4)
+    is(utf8.char(0x10FFFF):len(), 4)
+    if has_char54 then
+        is(utf8.char(0x1FFFFF):len(), 4)
+        is(utf8.char(0x200000):len(), 5)
+        is(utf8.char(0x3FFFFFF):len(), 5)
+        is(utf8.char(0x4000000):len(), 6)
+        is(utf8.char(0x7FFFFFFF):len(), 6)
+    else
+        error_like(function () utf8.char(0x110000) end,
+                   "^[^:]+:%d+: bad argument #1 to 'char' %(value out of ",
+                   "function char (out of range)")
+    end
+
+    error_like(function () utf8.char(0, -1) end,
+               "^[^:]+:%d+: bad argument #2 to 'char' %(value out of ",
+               "function char (out of range)")
+
+     error_like(function () utf8.char(0, 'bad') end,
+                "^[^:]+:%d+: bad argument #2 to 'char' %(number expected, got string%)",
+                "function char (bad)")
+end
+
+do -- charpattern
+    if has_charpattern54 then
+        is(utf8.charpattern, "[\0-\x7F\xC2-\xFD][\x80-\xBF]*", "charpattern")
+    else
+        is(utf8.charpattern, "[\0-\x7F\xC2-\xF4][\x80-\xBF]*", "charpattern")
+    end
+end
+
+do -- codes
+    local ap = {}
+    local ac = {}
+    for p, c in utf8.codes("A\u{20AC}3") do
+        ap[#ap+1] = p
+        ac[#ac+1] = c
+    end
+    eq_array(ap, {1, 2, 5}, "function codes")
+    eq_array(ac, {0x41, 0x20AC, 0x33})
+
+    local empty = true
+    for p, c in utf8.codes('') do
+        empty = false
+    end
+    ok(empty, "codes (empty)")
+
+    error_like(function () utf8.codes() end,
+               "^[^:]+:%d+: bad argument #1 to 'codes' %(string expected, got no value%)",
+               "function codes ()")
+
+    error_like(function () utf8.codes(true) end,
+               "^[^:]+:%d+: bad argument #1 to 'codes' %(string expected, got boolean%)",
+               "function codes (true)")
+
+    error_like(function () for p, c in utf8.codes('invalid\xFF') do end end,
+               "^[^:]+:%d+: invalid UTF%-8 code",
+               "function codes (invalid)")
+end
+
+do -- codepoints
+    is(utf8.codepoint("A\u{20AC}3"), 0x41, "function codepoint")
+    is(utf8.codepoint("A\u{20AC}3", 2), 0x20AC)
+    is(utf8.codepoint("A\u{20AC}3", -1), 0x33)
+    is(utf8.codepoint("A\u{20AC}3", 5), 0x33)
+    eq_array({utf8.codepoint("A\u{20AC}3", 1, 5)}, {0x41, 0x20AC, 0x33})
+    eq_array({utf8.codepoint("A\u{20AC}3", 1, 4)}, {0x41, 0x20AC})
+
+    error_like(function () utf8.codepoint("A\u{20AC}3", 6) end,
+               "^[^:]+:%d+: bad argument #3 to 'codepoint' %(out of ",
+               "function codepoint (out of range)")
+
+    error_like(function () utf8.codepoint("A\u{20AC}3", 8) end,
+               "^[^:]+:%d+: bad argument #3 to 'codepoint' %(out of ",
+               "function codepoint (out of range)")
+
+    error_like(function () utf8.codepoint("invalid\xFF", 8) end,
+               "^[^:]+:%d+: invalid UTF%-8 code",
+               "function codepoint (invalid)")
+end
+
+do -- len
+    is(utf8.len('A'), 1, "function len")
+    is(utf8.len(''), 0)
+    is(utf8.len("\u{41}\u{42}\u{43}"), 3)
+    is(utf8.len("A\u{20AC}3"), 3)
+
+    is(utf8.len('A', 1), 1)
+    is(utf8.len('A', 2), 0)
+    is(utf8.len('ABC', 1, 1), 1)
+    is(utf8.len('ABC', 2, 2), 1)
+    is(utf8.len('ABC', -1), 1)
+    is(utf8.len('ABC', -2), 2)
+
+    error_like(function () utf8.len('A', 3) end,
+               "^[^:]+:%d+: bad argument #2 to 'len' %(initial position out of ",
+               "function len (out of range)")
+
+    local len, pos = utf8.len('invalid\xFF')
+    is(len, nil, "function len (invalid)")
+    is(pos, 8)
+end
+
+do -- offset
+    is(utf8.offset("A\u{20AC}3", 1), 1, "function offset")
+    is(utf8.offset("A\u{20AC}3", 2), 2)
+    is(utf8.offset("A\u{20AC}3", 3), 5)
+    is(utf8.offset("A\u{20AC}3", 4), 6)
+    is(utf8.offset("A\u{20AC}3", 5), nil)
+    is(utf8.offset("A\u{20AC}3", 6), nil)
+    is(utf8.offset("A\u{20AC}3", -1), 5)
+    is(utf8.offset("A\u{20AC}3", 1, 2), 2)
+    is(utf8.offset("A\u{20AC}3", 2, 2), 5)
+    is(utf8.offset("A\u{20AC}3", 3, 2), 6)
+    is(utf8.offset("A\u{20AC}3", 4, 2), nil)
+    is(utf8.offset("A\u{20AC}3", -1, 2), 1)
+    is(utf8.offset("A\u{20AC}3", -2, 2), nil)
+    is(utf8.offset("A\u{20AC}3", 1, 5), 5)
+    is(utf8.offset("A\u{20AC}3", 2, 5), 6)
+    is(utf8.offset("A\u{20AC}3", 3, 5), nil)
+    is(utf8.offset("A\u{20AC}3", -1, 5), 2)
+    is(utf8.offset("A\u{20AC}3", -2, 5), 1)
+    is(utf8.offset("A\u{20AC}3", -3, 5), nil)
+    is(utf8.offset("A\u{20AC}3", 1, 6), 6)
+    is(utf8.offset("A\u{20AC}3", 2, 6), nil)
+    is(utf8.offset("A\u{20AC}3", 1, -1), 5)
+    is(utf8.offset("A\u{20AC}3", -1, -1), 2)
+    is(utf8.offset("A\u{20AC}3", -2, -1), 1)
+    is(utf8.offset("A\u{20AC}3", -3, -1), nil)
+    is(utf8.offset("A\u{20AC}3", 1, -4), 2)
+    is(utf8.offset("A\u{20AC}3", 2, -4), 5)
+    is(utf8.offset("A\u{20AC}3", -1, -4), 1)
+    is(utf8.offset("A\u{20AC}3", -2, -4), nil)
+
+    is(utf8.offset("A\u{20AC}3", 0, 1), 1)
+    is(utf8.offset("A\u{20AC}3", 0, 2), 2)
+    is(utf8.offset("A\u{20AC}3", 0, 3), 2)
+    is(utf8.offset("A\u{20AC}3", 0, 4), 2)
+    is(utf8.offset("A\u{20AC}3", 0, 5), 5)
+    is(utf8.offset("A\u{20AC}3", 0, 6), 6)
+
+    error_like(function () utf8.offset("A\u{20AC}3", 1, 7) end,
+               "^[^:]+:%d+: bad argument #3 to 'offset' %(position out of ",
+              "function offset (out of range)")
+
+    error_like(function () utf8.offset("\x80", 1) end,
+               "^[^:]+:%d+: initial position is a continuation byte",
+               "function offset (continuation byte)")
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico54/lexico.t b/test/lua-Harness-tests/lexico54/lexico.t
new file mode 100644
index 0000000..4523a51
--- /dev/null
+++ b/test/lua-Harness-tests/lexico54/lexico.t
@@ -0,0 +1,19 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2019, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+is("\u{10000}", "\xF0\x90\x80\x80")
+is("\u{200000}", "\xF8\x88\x80\x80\x80")
+is("\u{4000000}", "\xFC\x84\x80\x80\x80\x80")
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico54/metatable.t b/test/lua-Harness-tests/lexico54/metatable.t
new file mode 100644
index 0000000..4685b34
--- /dev/null
+++ b/test/lua-Harness-tests/lexico54/metatable.t
@@ -0,0 +1,38 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2019-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+do -- toclose
+    local called = false
+    do
+        local foo <close> = setmetatable({}, { __close = function () called = true end })
+        type_ok(foo, 'table', "toclose")
+        is(called, false)
+    end
+    is(called, true)
+
+    error_like(function () do local foo <close> = {} end end,
+               "^[^:]+:%d+: variable 'foo' got a non%-closable value")
+
+    lives_ok(function ()
+        local var1 <const> = nil
+        local var2 <const> = nil
+        do
+            local var3 <close> = setmetatable({}, { __close = function () end })
+        end
+        local var4 = true
+        -- attempt to close non-closable variable 'var4'
+    end, "blocker bug 5.4.0-rc3")
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexico54/utf8.t b/test/lua-Harness-tests/lexico54/utf8.t
new file mode 100644
index 0000000..1aa70cc
--- /dev/null
+++ b/test/lua-Harness-tests/lexico54/utf8.t
@@ -0,0 +1,54 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2019, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+do -- codes
+    local ap = {}
+    local ac = {}
+    for p, c in utf8.codes("A\u{200000}3", true) do
+        ap[#ap+1] = p
+        ac[#ac+1] = c
+    end
+    eq_array(ap, {1, 2, 7}, "function codes lax")
+    eq_array(ac, {0x41, 0x200000, 0x33})
+
+    error_like(function () for _ in utf8.codes("A\u{200000}3", false) do end end,
+               "^[^:]+:%d+: invalid UTF%-8 code")
+
+    error_like(function () for _ in utf8.codes("A\u{200000}3") do end end,
+               "^[^:]+:%d+: invalid UTF%-8 code")
+end
+
+do -- codepoints
+    eq_array({utf8.codepoint("A\u{200000}3", 1, 7, true)}, {0x41, 0x200000, 0x33}, "function codepoint lax")
+
+    error_like(function () utf8.codepoint("A\u{200000}3", 1, 7, false) end,
+               "^[^:]+:%d+: invalid UTF%-8 code")
+
+    error_like(function () utf8.codepoint("A\u{200000}3", 1, 7) end,
+               "^[^:]+:%d+: invalid UTF%-8 code")
+end
+
+do -- len
+    is(utf8.len('A\u{200000}C', 1, -1, true), 3, "function len lax")
+
+    local len, pos = utf8.len('A\u{200000}C')
+    is(len, nil)
+    is(pos, 2)
+
+    len, pos = utf8.len('A\u{200000}C', 1, -1, false)
+    is(len, nil)
+    is(pos, 2)
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexicojit/basic.t b/test/lua-Harness-tests/lexicojit/basic.t
new file mode 100644
index 0000000..8ad3a59
--- /dev/null
+++ b/test/lua-Harness-tests/lexicojit/basic.t
@@ -0,0 +1,27 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+do -- tonumber
+    is(tonumber(42uLL), 42, "function tonumber (cdata)")
+    is(tonumber(42LL), 42)
+end
+
+do -- tostring
+    is(tostring(42uLL), '42ULL', "function tostring (cdata)")
+    is(tostring(42LL), '42LL')
+    is(tostring(1i), '0+1i')
+    is(tostring(12.5i), '0+12.5i')
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexicojit/ext.t b/test/lua-Harness-tests/lexicojit/ext.t
new file mode 100644
index 0000000..8c44b99
--- /dev/null
+++ b/test/lua-Harness-tests/lexicojit/ext.t
@@ -0,0 +1,52 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2019-2020, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+local profile = require'profile'
+
+do -- thread.exdata
+    local r, exdata = pcall(require, 'thread.exdata')
+    is(r, true, 'thread.exdata')
+    type_ok(exdata, 'function')
+    is(package.loaded['thread.exdata'], exdata)
+
+    local ffi = require'ffi'
+    local u64 = ffi.new('uintptr_t', 0xefdeaddeadbeefLL)
+    local ptr = ffi.cast('void *', u64)
+    exdata(u64)  -- set
+    is(exdata(), ptr) -- get
+
+    error_like(function () exdata(42) end,
+               "^[^:]+:%d+: bad argument #1 to 'exdata' %(cdata expected, got number%)")
+end
+
+-- thread.exdata2
+if profile.openresty then
+    local r, exdata2 = pcall(require, 'thread.exdata2')
+    is(r, true, 'thread.exdata2')
+    type_ok(exdata2, 'function')
+    is(package.loaded['thread.exdata2'], exdata2)
+
+    local ffi = require'ffi'
+    local u64 = ffi.new('uintptr_t', 0xefdeaddeadbeefLL)
+    local ptr = ffi.cast('void *', u64)
+    exdata2(u64)  -- set
+    is(exdata2(), ptr) -- get
+
+    error_like(function () exdata2(42) end,
+               "^[^:]+:%d+: bad argument #1 to 'exdata2' %(cdata expected, got number%)")
+else
+    is(pcall(require, 'thread.exdata2'), false, 'no thread.exdata2')
+end
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/lexicojit/lexico.t b/test/lua-Harness-tests/lexicojit/lexico.t
new file mode 100644
index 0000000..1a973b5
--- /dev/null
+++ b/test/lua-Harness-tests/lexicojit/lexico.t
@@ -0,0 +1,32 @@
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+-- Copyright (C) 2018, Perrad Francois
+--
+-- This code is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
+
+type_ok(42LL, 'cdata', "42LL")
+type_ok(42ULL, 'cdata', "42ULL")
+type_ok(42uLL, 'cdata', "42uLL")
+type_ok(42ull, 'cdata', "42ull")
+
+type_ok(0x2aLL, 'cdata', "0x2aLL")
+type_ok(0x2aULL, 'cdata', "0x2aULL")
+type_ok(0x2auLL, 'cdata', "0x2auLL")
+type_ok(0x2aull, 'cdata', "0x2aull")
+
+type_ok(12.5i, 'cdata', '12.5i')
+type_ok(12.5I, 'cdata', '12.5I')
+type_ok(1i, 'cdata', '1i')
+type_ok(1I, 'cdata', '1I')
+type_ok(0i, 'cdata', '0i')
+type_ok(0I, 'cdata', '0I')
+
+-- Local Variables:
+--   mode: lua
+--   lua-indent-level: 4
+--   fill-column: 100
+-- End:
+-- vim: ft=lua expandtab shiftwidth=4:
diff --git a/test/lua-Harness-tests/profile.lua b/test/lua-Harness-tests/profile.lua
new file mode 100644
index 0000000..50c0c11
--- /dev/null
+++ b/test/lua-Harness-tests/profile.lua
@@ -0,0 +1,53 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = true,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = true,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+    compat53 = false,
+--[[
+    has_math_log10 = true,
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_lua51.lua b/test/lua-Harness-tests/profile_lua51.lua
new file mode 100644
index 0000000..8625b23
--- /dev/null
+++ b/test/lua-Harness-tests/profile_lua51.lua
@@ -0,0 +1,46 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+-- [[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_lua51_strict.lua b/test/lua-Harness-tests/profile_lua51_strict.lua
new file mode 100644
index 0000000..d8d1efd
--- /dev/null
+++ b/test/lua-Harness-tests/profile_lua51_strict.lua
@@ -0,0 +1,46 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_lua52.lua b/test/lua-Harness-tests/profile_lua52.lua
new file mode 100644
index 0000000..fbc2fc4
--- /dev/null
+++ b/test/lua-Harness-tests/profile_lua52.lua
@@ -0,0 +1,46 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = true,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_lua52_strict.lua b/test/lua-Harness-tests/profile_lua52_strict.lua
new file mode 100644
index 0000000..d8d1efd
--- /dev/null
+++ b/test/lua-Harness-tests/profile_lua52_strict.lua
@@ -0,0 +1,46 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_lua53.lua b/test/lua-Harness-tests/profile_lua53.lua
new file mode 100644
index 0000000..ed1b91f
--- /dev/null
+++ b/test/lua-Harness-tests/profile_lua53.lua
@@ -0,0 +1,52 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = true,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+    compat53 = false,
+--[[
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_lua53_noconv.lua b/test/lua-Harness-tests/profile_lua53_noconv.lua
new file mode 100644
index 0000000..c4500b3
--- /dev/null
+++ b/test/lua-Harness-tests/profile_lua53_noconv.lua
@@ -0,0 +1,55 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = true,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+    nocvtn2s = true,
+    nocvts2n = true,
+
+    compat53 = false,
+--[[
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_lua53_strict.lua b/test/lua-Harness-tests/profile_lua53_strict.lua
new file mode 100644
index 0000000..399282b
--- /dev/null
+++ b/test/lua-Harness-tests/profile_lua53_strict.lua
@@ -0,0 +1,52 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+    compat53 = false,
+--[[
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_lua54.lua b/test/lua-Harness-tests/profile_lua54.lua
new file mode 100644
index 0000000..ef4daa3
--- /dev/null
+++ b/test/lua-Harness-tests/profile_lua54.lua
@@ -0,0 +1,52 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+    compat53 = true,
+--[[
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_lua54_noconv.lua b/test/lua-Harness-tests/profile_lua54_noconv.lua
new file mode 100644
index 0000000..b9e17c3
--- /dev/null
+++ b/test/lua-Harness-tests/profile_lua54_noconv.lua
@@ -0,0 +1,55 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+    nocvtn2s = true,
+    nocvts2n = true,
+
+    compat53 = true,
+--[[
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_lua54_strict.lua b/test/lua-Harness-tests/profile_lua54_strict.lua
new file mode 100644
index 0000000..9fcfb79
--- /dev/null
+++ b/test/lua-Harness-tests/profile_lua54_strict.lua
@@ -0,0 +1,53 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+    compat53 = false,
+--[[
+    has_math_log10 = true,
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_luajit20.lua b/test/lua-Harness-tests/profile_luajit20.lua
new file mode 100644
index 0000000..75461c2
--- /dev/null
+++ b/test/lua-Harness-tests/profile_luajit20.lua
@@ -0,0 +1,53 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+-- [[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+    compat53 = false,
+--[[
+    has_math_log10 = true,
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+-- [[ luajit
+    luajit_compat52 = false,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_luajit20_compat52.lua b/test/lua-Harness-tests/profile_luajit20_compat52.lua
new file mode 100644
index 0000000..7064470
--- /dev/null
+++ b/test/lua-Harness-tests/profile_luajit20_compat52.lua
@@ -0,0 +1,53 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = false,
+    has_metamethod_ipairs = true,
+--]]
+
+    compat53 = false,
+--[[
+    has_math_log10 = true,
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+-- [[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_luajit21.lua b/test/lua-Harness-tests/profile_luajit21.lua
new file mode 100644
index 0000000..f24e85e
--- /dev/null
+++ b/test/lua-Harness-tests/profile_luajit21.lua
@@ -0,0 +1,53 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+    compat53 = false,
+--[[
+    has_math_log10 = true,
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+-- [[ luajit
+    luajit_compat52 = false,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_luajit21_compat52.lua b/test/lua-Harness-tests/profile_luajit21_compat52.lua
new file mode 100644
index 0000000..7064470
--- /dev/null
+++ b/test/lua-Harness-tests/profile_luajit21_compat52.lua
@@ -0,0 +1,53 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = false,
+    has_metamethod_ipairs = true,
+--]]
+
+    compat53 = false,
+--[[
+    has_math_log10 = true,
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+-- [[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_openresty.lua b/test/lua-Harness-tests/profile_openresty.lua
new file mode 100644
index 0000000..c151a39
--- /dev/null
+++ b/test/lua-Harness-tests/profile_openresty.lua
@@ -0,0 +1,53 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = false,
+    has_metamethod_ipairs = true,
+--]]
+
+    compat53 = false,
+--[[
+    has_math_log10 = true,
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+-- [[ luajit
+    luajit_compat52 = true,
+    openresty = true,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_ravi.lua b/test/lua-Harness-tests/profile_ravi.lua
new file mode 100644
index 0000000..8cd2464
--- /dev/null
+++ b/test/lua-Harness-tests/profile_ravi.lua
@@ -0,0 +1,58 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+-- luacheck: globals _VERSION
+_VERSION = 'Lua 5.3'    -- instead of 'Ravi 5.3'
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = true,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = true,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+    nocvtn2s = false,
+    nocvts2n = false,
+
+    compat53 = false,
+--[[
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+--[[ luajit
+    luajit_compat52 = true,
+    openresty = false,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/profile_tiny_fork.lua b/test/lua-Harness-tests/profile_tiny_fork.lua
new file mode 100644
index 0000000..f0df77b
--- /dev/null
+++ b/test/lua-Harness-tests/profile_tiny_fork.lua
@@ -0,0 +1,60 @@
+---
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+---
+
+require'compat53.math'
+-- luacheck: globals utf8
+utf8 = require'compat53.utf8'
+
+local profile = {
+
+--[[ compat 5.0
+    has_string_gfind = true,
+    has_math_mod = true,
+--]]
+
+    compat51 = false,
+--[[
+    has_unpack = true,
+    has_package_loaders = true,
+    has_math_log10 = true,
+    has_loadstring = true,
+    has_table_maxn = true,
+    has_module = true,
+    has_package_seeall = true,
+--]]
+
+    compat52 = false,
+--[[
+    has_mathx = true,
+    has_bit32 = true,
+    has_metamethod_ipairs = true,
+--]]
+
+    compat53 = false,
+--[[
+    has_math_log10 = true,
+    has_mathx = true,
+    has_metamethod_ipairs = true,
+--]]
+
+-- [[ luajit
+    luajit_compat52 = false,
+    openresty = false,
+    pack = true,
+    integer = true,
+    utf8 = true,
+--]]
+
+}
+
+package.loaded.profile = profile        -- prevents loading of default profile
+
+return profile
+
+--
+-- Copyright (c) 2018-2019 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
diff --git a/test/lua-Harness-tests/rx_captures b/test/lua-Harness-tests/rx_captures
new file mode 100644
index 0000000..e209d26
--- /dev/null
+++ b/test/lua-Harness-tests/rx_captures
@@ -0,0 +1,13 @@
+(a.)..(..)		zzzabcdefzzz	ab\tef			basic match
+(a(b(c))(d))		abcd		abcd\tbc\tc\td		nested match
+((%w+))			abcd		abcd\tabcd		nested match
+(a*(.)%w(%s*))		aa!b c		aa!b \t!\t 		nested match
+(a?)..			abcd		a			opt
+(A?)..			abcd		''			opt
+()aa()			flaaap		3\t5			empty capture
+(.)%1			bookkeeper	o			backreference
+(%w+)%s+%1		hello hello	hello			backreference
+(.*)x			123x		123			repeated dot capture
+$(%w+)			$abc=		abc			not escaped
+
+## vim: noexpandtab tabstop=4 shiftwidth=4
diff --git a/test/lua-Harness-tests/rx_charclass b/test/lua-Harness-tests/rx_charclass
new file mode 100644
index 0000000..af5cb45
--- /dev/null
+++ b/test/lua-Harness-tests/rx_charclass
@@ -0,0 +1,38 @@
+[c]			abcdef		c		character class
+^[a]			abcdef		a		anchored character class
+[^e]			abcdef		a		negated character class
+^[a]?			abcdef		a		anchored optional character class
+[^e]?			abcdef		a		negated optional character class
+^[^e]			abcdef		a		anchored negated character class
+^[^a]			abcdef		nil		anchored negated character class
+[b-d]			abcdef		b		character range
+[b-d]			abxxef		b		character range
+[b-d]			axcxef		c		character range
+[b-d]			axxdef		d		character range
+[b-d]			axxxef		nil		character range
+[^b-d]			abcdef		a		negated character range
+[^b-d]			bbccdd		nil		negated character range
+[-]			ab-def		-		unescaped hyphen
+[%-]			ab-def		-		escaped hyphen
+[%-]			abcdef		nil		escaped hyphen
+[^%-]			---x--		x		negated escaped hyphen
+[^%-]			------		nil		negated escaped hyphen
+[%-+]			ab-def		-		escaped hyphen in range
+[%-+]			ab+def		+		escaped hyphen in range
+[%-+]			abcdef		nil		escaped hyphen in range
+[+%-]			ab-def		-		escaped hyphen in range
+[+%-]			ab+def		+		escaped hyphen in range
+[+%-]			abcdef		nil		escaped hyphen in range
+[^%-+]			---x--		x		negated escaped hyphen in range
+[^%-+]			------		nil		negated escaped hyphen in range
+[^+%-]			---x--		x		negated escaped hyphen in range
+[^+%-]			------		nil		negated escaped hyphen in range
+["\\]			\\		\		escaped backslash
+[%]]			]		]		escaped close bracket
+[%]			\\]]		/malformed pattern %(missing ']'%)/	unescaped backslash (or no closing brace)
+ab\\cd			ab\092cd	ab\cd		literal match with backslash
+%?			ab<?		?		literal match with question mark
+[A-Z0-9]		abcdef		nil		two enumerated ranges
+[A-Z0-9]		abcDef		D		two enumerated ranges
+
+## vim: noexpandtab tabstop=4 shiftwidth=4
diff --git a/test/lua-Harness-tests/rx_metachars b/test/lua-Harness-tests/rx_metachars
new file mode 100644
index 0000000..8716ca1
--- /dev/null
+++ b/test/lua-Harness-tests/rx_metachars
@@ -0,0 +1,117 @@
+.			a		a		dot (.)
+.			\n		\n		dot (.)
+.			''		nil		dot (.)
+a%s+f			abcdef		nil		whitespace (%s)
+ab%s+cdef		ab  cdef	ab  cdef	whitespace (%s)
+a%S+f			abcdef		abcdef		not whitespace (%S)
+a%S+f			ab cdef		nil		not whitespace (%S)
+^abc			abcdef		abc		start and end of string (^)
+^abc			abc\ndef	abc		start and end of string (^)
+^abc			def\nabc	nil		start and end of string (^)
+def\n^abc		def\nabc	nil		start and end of string (^)
+def$			abcdef		def		start and end of string ($)
+def$			abc\ndef	def		start and end of string ($)
+def$			def\nabc	nil		start and end of string ($)
+def$\nabc		def\nabc	nil		start and end of string (^)
+abc\n$			abc\n		abc\n		end of string ($)
+abc$			abc\n		nil		end of string ($)
+c\nd			abc\ndef	c\nd		newline (\n)
+c\nd			abc\010def	c\nd		newline (\n)
+c\n+d			abc\n\ndef	c\n\nd		newline (\n)
+a\n+f			abcdef		nil		newline (\n)
+b\nc			abc\ndef	nil		newline (\n)
+c\td			abc\tdef	c\td		horizontal tab (\t)
+c\td			abc\09def	c\td		horizontal tab (\t)
+c\t+d			abc\t\tdef	c\t\td		horizontal tab (\t)
+a\t+f			abcdef		nil		horizontal tab (\t)
+b\tc			abc\tdef	nil		horizontal tab (\t)
+c\rd			abc\rdef	c\rd		return (\r)
+c\rd			abc\013def	c\rd		return (\r)
+c\r+d			abc\r\rdef	c\r\rd		return (\r)
+a\r+f			abcdef		nil		return (\r)
+b\rc			abc\rdef	nil		return (\r)
+c\fd			abc\fdef	c\fd		formfeed (\f)
+c\fd			abc\012def	c\fd		formfeed (\f)
+c\f+d			abc\f\fdef	c\f\fd		formfeed (\f)
+a\f+f			abcdef		nil		formfeed (\f)
+b\fc			abc\fdef	nil		formfeed (\f)
+c\033d			abc!def		c!d		dec (\0)
+c\033d			abc\033def	c!d		dec (\0)
+c\033+d			abc!!def	c!!d		dec (\0)
+a\033+f			abcdef		nil		dec (\0)
+b\033c			abc!def		nil		dec (\0)
+a%^d			a^d		a^d		escaped (useless)
+a^d			a^d		a^d		not escaped
+%^d			^d		^d		escaped
+a%$d			a$d		a$d		escaped (useless)
+a$d			a$d		a$d		not escaped
+a%$			a$		a$		escaped
+a%(d			a(d		a(d		escaped
+a%)d			a)d		a)d		escaped
+a%%d			a%d		a%d		escaped
+a%			a%		/malformed pattern %(ends with '%%'%)/	not escaped
+a%.d			a.d		a.d		escaped
+a%.d			abd		nil		escaped
+a%[d			a[d		a[d		escaped
+a%]d			a]d		a]d		escaped
+a%*d			a*d		a*d		escaped
+*ad			*ad		*ad		not escaped
+a%+d			a+d		a+d		escaped
+a%-d			a-d		a-d		escaped
+a%?d			a?d		a?d		escaped
+a%yd			ayd		ayd		escaped
+a%w+f			a=[ *f		nil		word character
+a%w+f			abcdef		abcdef		word character
+a%W+f			a&%- f		a&%- f		not word character
+a%W+f			abcdef		nil		not word character
+a%d+f			abcdef		nil		digit
+ab%d+cdef		ab42cdef	ab42cdef	digit
+a%D+f			abcdef		abcdef		not digit
+a%D+f			ab0cdef		nil		not digit
+a%l+f			aBCDEf		nil		lowercase letter
+a%l+f			abcdef		abcdef		lowercase letter
+a%L+f			a&2D f		a&2D f		not lowercase letter
+a%L+f			aBCdEf		nil		not lowercase letter
+a%u+f			abcdef		nil		uppercase letter
+a%u+f			aBCDEf		aBCDEf		uppercase letter
+a%U+f			a&2d f		a&2d f		not uppercase letter
+a%U+f			a&2D f		nil		not uppercase letter
+a%a+f			aBcDef		aBcDef		all letter
+a%a+f			a=[ *f		nil		all letter
+a%A+f			a&%- f		a&%- f		not all letter
+a%A+f			abcdef		nil		not all letter
+a%g+f			aBcDef		aBcDef		printable
+a%g+f			a=[ *f		nil		printable
+a%G+f			a \nf		a \nf		not printable
+a%G+f			abcdef		nil		not printable
+a%p+f			abcdef		nil		ponctuation
+a%p+f			a,;:!f		a,;:!f		ponctuation
+a%P+f			abcdef		abcdef		not ponctuation
+a%P+f			adc:ef		nil		not ponctuation
+a%c+f			abcdef		nil		control character
+a%c+f			a\04\03\02f	a\04\03\02f	control character
+a%C+f			abcdef		abcdef		not control character
+a%C+f			abc\01ef	nil		not control character
+a%x+f			axyzef		nil		hexadecimal
+a%x+f			ab3Def		ab3Def		hexadecimal
+a%X+f			abcdef		nil		not hexadecimal
+a%X+f			axy;Zf		axy;Zf		not hexadecimal
+a%z+f			abcdef		nil		zero (deprecated)
+a\0+f			abcdef		nil		zero
+a%z+f			a\0f		a\0f		zero (deprecated)
+a\0+f			a\0f		a\0f		zero
+a%Z+f			abcdef		abcdef		not zero (deprecated)
+a[^\0]+f		abcdef		abcdef		not zero
+a%Z+f			abc\0ef		nil		not zero (deprecated)
+a[^\0]+f		abc\0ef		nil		not zero
+a%b()f			a(bcde)f	a(bcde)f	balanced
+a%b()f			a(b(de)f	nil		balanced
+a%b()f			a(b(d)e)f	a(b(d)e)f	balanced
+a%b''f			a'bcde'f	a'bcde'f	balanced
+a%b""f			a"bcde"f	a"bcde"f	balanced
+%f[b]bc			abcdef		bc		frontier
+%f[b]c			abcdef		nil		frontier
+%f[^ab]c		abacdef		c		frontier
+%f[^ab]d		abacdef		nil		frontier
+
+## vim: noexpandtab tabstop=4 shiftwidth=4
diff --git a/test/lua-Harness-tests/tap.lua b/test/lua-Harness-tests/tap.lua
new file mode 100644
index 0000000..5ce95e6
--- /dev/null
+++ b/test/lua-Harness-tests/tap.lua
@@ -0,0 +1,212 @@
+
+--
+-- lua-Harness : <https://fperrad.frama.io/lua-Harness/>
+--
+
+--[[
+
+        Test Anything Protocol : minimalist version
+
+]]
+
+if pcall(require, 'Test.More') then
+    diag 'Test.More loaded'
+    return
+end
+
+local os = os
+local pcall = pcall
+local print = print
+local require = require
+local tostring = tostring
+local type = type
+
+local curr_test = 0
+local expected_tests = 0
+local todo_upto = 0
+local todo_reason
+
+function plan (arg)
+    if arg ~= 'no_plan' then
+        expected_tests = arg
+        print("1.." .. tostring(arg))
+    end
+end
+
+function done_testing ()
+    print("1.." .. tostring(curr_test))
+end
+
+function skip_all (reason)
+    out = "1..0"
+    if reason then
+        out = out .. " # SKIP " .. reason
+    end
+    print(out)
+    os.exit(0)
+end
+
+function ok (test, name)
+    curr_test = curr_test + 1
+    local out = ''
+    if not test then
+        out = "not "
+    end
+    out = out .. "ok " .. tostring(curr_test)
+    if name then
+        out = out .. " - " .. name
+    end
+    if todo_reason and todo_upto >= curr_test then
+        out = out .. " # TODO # " .. todo_reason
+    end
+    print(out)
+end
+
+function nok (test, name)
+    ok(not test, name)
+end
+
+function is (got, expected, name)
+    local pass = got == expected
+    ok(pass, name)
+    if not pass then
+        diag("         got: " .. tostring(got))
+        diag("    expected: " .. tostring(expected))
+    end
+end
+
+function isnt (got, not_expected, name)
+    local pass = got ~= not_expected
+    ok(pass, name)
+    if not pass then
+        diag("         got: " .. tostring(got))
+        diag("    expected: anything else")
+    end
+end
+
+function like (got, pattern, name)
+    local pass = tostring(got):match(pattern)
+    ok(pass, name)
+    if not pass then
+        diag("                  " .. tostring(got))
+        diag("    doesn't match '" .. tostring(pattern) .. "'")
+    end
+end
+
+function type_ok (val, t, name)
+    if type(val) == t then
+        ok(true, name)
+    else
+        ok(false, name)
+        diag("    " .. tostring(val) .. " isn't a '" .. t .."' it's '" .. type(val) .. "'")
+    end
+end
+
+function pass (name)
+    ok(true, name)
+end
+
+function fail (name)
+    ok(false, name)
+end
+
+function require_ok (mod)
+    local r, msg = pcall(require, mod)
+    ok(r, "require '" .. mod .. "'")
+    if not r then
+        diag("    " .. msg)
+    end
+    return r
+end
+
+function eq_array (got, expected, name)
+    for i = 1, #expected do
+        local v = expected[i]
+        local val = got[i]
+        if val ~= v then
+            ok(false, name)
+            diag("    at index: " .. tostring(i))
+            diag("         got: " .. tostring(val))
+            diag("    expected: " .. tostring(v))
+            return
+        end
+    end
+    local extra = #got - #expected
+    if extra ~= 0 then
+        ok(false, name)
+        diag("    " .. tostring(extra) .. " unexpected item(s)")
+    else
+        ok(true, name)
+    end
+end
+
+function error_is (code, expected, name)
+    local r, msg = pcall(code)
+    if r then
+        ok(false, name)
+        diag("    unexpected success")
+        diag("    expected: " .. tostring(pattern))
+    else
+        is(msg, expected, name)
+    end
+end
+
+function error_like (code, pattern, name)
+    local r, msg = pcall(code)
+    if r then
+        ok(false, name)
+        diag("    unexpected success")
+        diag("    expected: " .. tostring(pattern))
+    else
+        like(msg, pattern, name)
+    end
+end
+
+function lives_ok (code, name)
+    local r, msg = pcall(code)
+    ok(r, name)
+    if not r then
+        diag("    " .. msg)
+    end
+end
+
+function diag (msg)
+    print("# " .. msg)
+end
+
+function skip (reason, count)
+    count = count or 1
+    local name = "# skip"
+    if reason then
+        name = name .. " " ..reason
+    end
+    for i = 1, count do
+        ok(true, name)
+    end
+end
+
+function skip_rest (reason)
+    skip(reason, expected_tests - curr_test)
+end
+
+function todo (reason, count)
+    count = count or 1
+    todo_upto = curr_test + count
+    todo_reason = reason
+end
+
+-- The last arg element is guaranteed name of tested binary.
+function get_lua_binary_name ()
+    local i = 0
+    while arg[i] do
+        i = i - 1
+    end
+    return arg[i + 1]
+end
+
+--
+-- Copyright (c) 2009-2018 Francois Perrad
+--
+-- This library is licensed under the terms of the MIT/X11 license,
+-- like Lua itself.
+--
-- 
2.28.0


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

* [Tarantool-patches] [PATCH luajit 2/6] test: adjust lua-Harness test suite for Tarantool
  2021-03-12  5:27 [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite Sergey Kaplun via Tarantool-patches
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 1/6] test: add " Sergey Kaplun via Tarantool-patches
@ 2021-03-12  5:27 ` Sergey Kaplun via Tarantool-patches
  2021-03-13 18:41   ` Sergey Ostanevich via Tarantool-patches
  2021-03-15 13:22   ` Igor Munkin via Tarantool-patches
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 3/6] test: disable 305-utf8 of lua-Harness suite Sergey Kaplun via Tarantool-patches
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-12  5:27 UTC (permalink / raw)
  To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches

This patch makes it possible to run lua-Harness test suite using
Tarantool.

Tarantool has its own loaded tap built in so need to change name to
another one.

203-lexico.t and 301-basic.t is adjusted to valid working with
out-of-source build in Tarantool CI.

Also creates additional list of files provided to prove via stdin.
This is required to avoid tests hungs via Tarantool's binary.
Partially this problem is descripted in tarantool/tarantool#5040.

Part of tarantool/tarantool#5844
Part of tarantool/tarantool#4473
---
Author: Mergen Imeev <imeevma@gmail.com>

 .gitignore                                      |  1 +
 test/lua-Harness-tests/090-tap.t                |  2 +-
 test/lua-Harness-tests/091-profile.t            |  2 +-
 test/lua-Harness-tests/101-boolean.t            |  2 +-
 test/lua-Harness-tests/102-function.t           |  2 +-
 test/lua-Harness-tests/103-nil.t                |  2 +-
 test/lua-Harness-tests/104-number.t             |  2 +-
 test/lua-Harness-tests/105-string.t             |  2 +-
 test/lua-Harness-tests/106-table.t              |  2 +-
 test/lua-Harness-tests/107-thread.t             |  2 +-
 test/lua-Harness-tests/108-userdata.t           |  2 +-
 test/lua-Harness-tests/200-examples.t           |  2 +-
 test/lua-Harness-tests/201-assign.t             |  2 +-
 test/lua-Harness-tests/202-expr.t               |  2 +-
 test/lua-Harness-tests/203-lexico.t             | 14 +++++++++-----
 test/lua-Harness-tests/204-grammar.t            |  2 +-
 test/lua-Harness-tests/211-scope.t              |  2 +-
 test/lua-Harness-tests/212-function.t           |  2 +-
 test/lua-Harness-tests/213-closure.t            |  2 +-
 test/lua-Harness-tests/214-coroutine.t          |  2 +-
 test/lua-Harness-tests/221-table.t              |  2 +-
 test/lua-Harness-tests/222-constructor.t        |  2 +-
 test/lua-Harness-tests/223-iterator.t           |  2 +-
 test/lua-Harness-tests/231-metatable.t          |  2 +-
 test/lua-Harness-tests/232-object.t             |  2 +-
 test/lua-Harness-tests/241-standalone.t         | 10 +++++-----
 test/lua-Harness-tests/242-luac.t               |  2 +-
 test/lua-Harness-tests/301-basic.t              |  7 +++++--
 test/lua-Harness-tests/303-package.t            |  6 +++---
 test/lua-Harness-tests/304-string.t             |  2 +-
 test/lua-Harness-tests/305-utf8.t               |  2 +-
 test/lua-Harness-tests/306-table.t              |  2 +-
 test/lua-Harness-tests/307-math.t               |  2 +-
 test/lua-Harness-tests/308-io.t                 |  2 +-
 test/lua-Harness-tests/309-os.t                 |  2 +-
 test/lua-Harness-tests/310-debug.t              |  2 +-
 test/lua-Harness-tests/311-bit32.t              |  2 +-
 test/lua-Harness-tests/314-regex.t              |  2 +-
 test/lua-Harness-tests/320-stdin.t              |  2 +-
 test/lua-Harness-tests/401-bitop.t              |  2 +-
 test/lua-Harness-tests/402-ffi.t                |  2 +-
 test/lua-Harness-tests/403-jit.t                |  2 +-
 test/lua-Harness-tests/404-ext.t                |  2 +-
 test/lua-Harness-tests/411-luajit.t             |  2 +-
 test/lua-Harness-tests/CMakeLists.txt           | 17 +++++++++++++++--
 .../{tap.lua => tap_harness.lua}                |  0
 46 files changed, 77 insertions(+), 56 deletions(-)
 rename test/lua-Harness-tests/{tap.lua => tap_harness.lua} (100%)

diff --git a/.gitignore b/.gitignore
index 2103a30..1fb81bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,4 @@ compile_commands.json
 install_manifest.txt
 luajit-parse-memprof
 luajit.pc
+tests_list
diff --git a/test/lua-Harness-tests/090-tap.t b/test/lua-Harness-tests/090-tap.t
index 92f04d8..99932f2 100755
--- a/test/lua-Harness-tests/090-tap.t
+++ b/test/lua-Harness-tests/090-tap.t
@@ -22,7 +22,7 @@
 
 ]]
 
-require'tap'
+require'tap_harness'
 
 plan(3)
 ok( true, 'ok' )
diff --git a/test/lua-Harness-tests/091-profile.t b/test/lua-Harness-tests/091-profile.t
index db47438..ebc142d 100755
--- a/test/lua-Harness-tests/091-profile.t
+++ b/test/lua-Harness-tests/091-profile.t
@@ -22,7 +22,7 @@
 
 ]]
 
-require'tap'
+require'tap_harness'
 
 plan'no_plan'
 
diff --git a/test/lua-Harness-tests/101-boolean.t b/test/lua-Harness-tests/101-boolean.t
index 0033eff..653509f 100755
--- a/test/lua-Harness-tests/101-boolean.t
+++ b/test/lua-Harness-tests/101-boolean.t
@@ -22,7 +22,7 @@
 
 ]]
 
-require'tap'
+require'tap_harness'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/102-function.t b/test/lua-Harness-tests/102-function.t
index 48ed814..cb7e9d0 100755
--- a/test/lua-Harness-tests/102-function.t
+++ b/test/lua-Harness-tests/102-function.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap'
+require'tap_harness'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/103-nil.t b/test/lua-Harness-tests/103-nil.t
index 561b101..a74c491 100755
--- a/test/lua-Harness-tests/103-nil.t
+++ b/test/lua-Harness-tests/103-nil.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap'
+require'tap_harness'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/104-number.t b/test/lua-Harness-tests/104-number.t
index 0d4d3fd..634d22a 100755
--- a/test/lua-Harness-tests/104-number.t
+++ b/test/lua-Harness-tests/104-number.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
diff --git a/test/lua-Harness-tests/105-string.t b/test/lua-Harness-tests/105-string.t
index cd8c88b..f2ea067 100755
--- a/test/lua-Harness-tests/105-string.t
+++ b/test/lua-Harness-tests/105-string.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
diff --git a/test/lua-Harness-tests/106-table.t b/test/lua-Harness-tests/106-table.t
index 0c0ba49..4a66f69 100755
--- a/test/lua-Harness-tests/106-table.t
+++ b/test/lua-Harness-tests/106-table.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap'
+require'tap_harness'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/107-thread.t b/test/lua-Harness-tests/107-thread.t
index 3d4af18..e67ef36 100755
--- a/test/lua-Harness-tests/107-thread.t
+++ b/test/lua-Harness-tests/107-thread.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap'
+require'tap_harness'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/108-userdata.t b/test/lua-Harness-tests/108-userdata.t
index b1e3641..687b1b8 100755
--- a/test/lua-Harness-tests/108-userdata.t
+++ b/test/lua-Harness-tests/108-userdata.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap'
+require'tap_harness'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/200-examples.t b/test/lua-Harness-tests/200-examples.t
index 362aae3..cb06a80 100755
--- a/test/lua-Harness-tests/200-examples.t
+++ b/test/lua-Harness-tests/200-examples.t
@@ -24,7 +24,7 @@ First tests in order to check infrastructure.
 
 --]]
 
-require'tap'
+require'tap_harness'
 
 plan(5)
 
diff --git a/test/lua-Harness-tests/201-assign.t b/test/lua-Harness-tests/201-assign.t
index 7d023d8..f7ed472 100755
--- a/test/lua-Harness-tests/201-assign.t
+++ b/test/lua-Harness-tests/201-assign.t
@@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#3.3.3>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local has_env = _VERSION >= 'Lua 5.2'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/202-expr.t b/test/lua-Harness-tests/202-expr.t
index 2576750..f03d5ea 100755
--- a/test/lua-Harness-tests/202-expr.t
+++ b/test/lua-Harness-tests/202-expr.t
@@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#3.4>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local nocvtn2s = profile.nocvtn2s
 local nocvts2n = profile.nocvts2n
diff --git a/test/lua-Harness-tests/203-lexico.t b/test/lua-Harness-tests/203-lexico.t
index c1abebf..0a73f8c 100755
--- a/test/lua-Harness-tests/203-lexico.t
+++ b/test/lua-Harness-tests/203-lexico.t
@@ -31,7 +31,7 @@ L<https://www.lua.org/manual/5.4/manual.html#3.1>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local loadstring = loadstring or load
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 
@@ -117,20 +117,24 @@ do
     like(msg, "^[^:]+:%d+: unfinished long comment .-near")
 end
 
+-- Adapt tests 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') .. '/'
+
 if _VERSION >= 'Lua 5.2' or jit then
-    dofile'lexico52/lexico.t'
+    dofile(path_to_sources .. 'lexico52/lexico.t')
 end
 
 if _VERSION >= 'Lua 5.3' or luajit21 then
-    dofile'lexico53/lexico.t'
+    dofile(path_to_sources .. 'lexico53/lexico.t')
 end
 
 if _VERSION >= 'Lua 5.4' then
-    dofile'lexico54/lexico.t'
+    dofile(path_to_sources .. 'lexico54/lexico.t')
 end
 
 if jit and pcall(require, 'ffi') then
-    dofile'lexicojit/lexico.t'
+    dofile(path_to_sources .. 'lexicojit/lexico.t')
 end
 
 done_testing()
diff --git a/test/lua-Harness-tests/204-grammar.t b/test/lua-Harness-tests/204-grammar.t
index d9ae3a6..03580f4 100755
--- a/test/lua-Harness-tests/204-grammar.t
+++ b/test/lua-Harness-tests/204-grammar.t
@@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#9>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local has_goto = _VERSION >= 'Lua 5.2' or jit
 local has_attr = _VERSION >= 'Lua 5.4'
diff --git a/test/lua-Harness-tests/211-scope.t b/test/lua-Harness-tests/211-scope.t
index 64eed52..8e26a6f 100755
--- a/test/lua-Harness-tests/211-scope.t
+++ b/test/lua-Harness-tests/211-scope.t
@@ -30,7 +30,7 @@ See section "Local Variables and Blocks" in "Programming in Lua".
 
 --]]
 
-require'tap'
+require'tap_harness'
 
 plan(10)
 
diff --git a/test/lua-Harness-tests/212-function.t b/test/lua-Harness-tests/212-function.t
index 2851053..405035e 100755
--- a/test/lua-Harness-tests/212-function.t
+++ b/test/lua-Harness-tests/212-function.t
@@ -30,7 +30,7 @@ See section "Functions" in "Programming in Lua".
 
 --]]
 
-require'tap'
+require'tap_harness'
 local loadstring = loadstring or load
 
 plan(68)
diff --git a/test/lua-Harness-tests/213-closure.t b/test/lua-Harness-tests/213-closure.t
index fc3bd29..16a8a21 100755
--- a/test/lua-Harness-tests/213-closure.t
+++ b/test/lua-Harness-tests/213-closure.t
@@ -24,7 +24,7 @@ See section "Closures" in "Programming in Lua".
 
 --]]
 
-require'tap'
+require'tap_harness'
 
 plan(15)
 
diff --git a/test/lua-Harness-tests/214-coroutine.t b/test/lua-Harness-tests/214-coroutine.t
index 92929e1..1ca1cb5 100755
--- a/test/lua-Harness-tests/214-coroutine.t
+++ b/test/lua-Harness-tests/214-coroutine.t
@@ -30,7 +30,7 @@ See section "Coroutines" in "Programming in Lua".
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 local has_coroutine52 = _VERSION >= 'Lua 5.2' or jit
diff --git a/test/lua-Harness-tests/221-table.t b/test/lua-Harness-tests/221-table.t
index c064a33..07ac952 100755
--- a/test/lua-Harness-tests/221-table.t
+++ b/test/lua-Harness-tests/221-table.t
@@ -24,7 +24,7 @@ See section "Tables" in "Programming in Lua".
 
 --]]
 
-require'tap'
+require'tap_harness'
 
 plan(25)
 
diff --git a/test/lua-Harness-tests/222-constructor.t b/test/lua-Harness-tests/222-constructor.t
index a01be2e..28037bf 100755
--- a/test/lua-Harness-tests/222-constructor.t
+++ b/test/lua-Harness-tests/222-constructor.t
@@ -30,7 +30,7 @@ See section "Table Constructors" in "Programming in Lua".
 
 --]]
 
-require'tap'
+require'tap_harness'
 
 plan(16)
 
diff --git a/test/lua-Harness-tests/223-iterator.t b/test/lua-Harness-tests/223-iterator.t
index 777ad73..073f3cd 100755
--- a/test/lua-Harness-tests/223-iterator.t
+++ b/test/lua-Harness-tests/223-iterator.t
@@ -25,7 +25,7 @@ section "Coroutines as Iterators" in "Programming in Lua".
 
 --]]
 
-require'tap'
+require'tap_harness'
 
 plan(8)
 
diff --git a/test/lua-Harness-tests/231-metatable.t b/test/lua-Harness-tests/231-metatable.t
index a2c6499..b94f608 100755
--- a/test/lua-Harness-tests/231-metatable.t
+++ b/test/lua-Harness-tests/231-metatable.t
@@ -30,7 +30,7 @@ See section "Metatables and Metamethods" in "Programming in Lua".
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local has_metamethod52 = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
 local has_metamethod_ipairs = _VERSION == 'Lua 5.2' or profile.compat52 or profile.luajit_compat52
diff --git a/test/lua-Harness-tests/232-object.t b/test/lua-Harness-tests/232-object.t
index 0d87572..0d22232 100755
--- a/test/lua-Harness-tests/232-object.t
+++ b/test/lua-Harness-tests/232-object.t
@@ -24,7 +24,7 @@ See section "Object-Oriented Programming" in "Programming in Lua".
 
 --]]
 
-require'tap'
+require'tap_harness'
 
 plan(18)
 
diff --git a/test/lua-Harness-tests/241-standalone.t b/test/lua-Harness-tests/241-standalone.t
index c5237ee..33d5159 100755
--- a/test/lua-Harness-tests/241-standalone.t
+++ b/test/lua-Harness-tests/241-standalone.t
@@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#7>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local has_bytecode = not ujit and not ravi
 local has_error52 = _VERSION >= 'Lua 5.2'
 local has_error53 = _VERSION >= 'Lua 5.3'
@@ -228,14 +228,14 @@ end
 like(f:read'*l', "^usage: ", "no file")
 f:close()
 
-cmd = lua .. [[ -ltap -e "print(type(ok))"]]
+cmd = lua .. [[ -ltap_harness -e "print(type(ok))"]]
 f = io.popen(cmd)
-is(f:read'*l', 'function', "-ltap")
+is(f:read'*l', 'function', "-ltap_harness")
 f:close()
 
-cmd = lua .. [[ -l tap -e "print(type(ok))"]]
+cmd = lua .. [[ -l tap_harness -e "print(type(ok))"]]
 f = io.popen(cmd)
-is(f:read'*l', 'function', "-l tap")
+is(f:read'*l', 'function', "-l tap_harness")
 f:close()
 
 cmd = lua .. [[ -l lpeg -e "print(1)" 2>&1]]
diff --git a/test/lua-Harness-tests/242-luac.t b/test/lua-Harness-tests/242-luac.t
index a95a334..9a3a3c3 100755
--- a/test/lua-Harness-tests/242-luac.t
+++ b/test/lua-Harness-tests/242-luac.t
@@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#7>
 
 --]]
 
-require'tap'
+require'tap_harness'
 
 if jit then
     skip_all("LuaJIT")
diff --git a/test/lua-Harness-tests/301-basic.t b/test/lua-Harness-tests/301-basic.t
index f4f9235..13472cd 100755
--- a/test/lua-Harness-tests/301-basic.t
+++ b/test/lua-Harness-tests/301-basic.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.1>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local has_error53 = _VERSION >= 'Lua 5.3'
 local has_gcinfo = _VERSION == 'Lua 5.1'
@@ -843,7 +843,10 @@ do -- xpcall
 end
 
 if jit and pcall(require, 'ffi') then
-    dofile'lexicojit/basic.t'
+    -- 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(path_to_sources .. '/lexicojit/basic.t')
 end
 
 done_testing()
diff --git a/test/lua-Harness-tests/303-package.t b/test/lua-Harness-tests/303-package.t
index 7e5216d..996ce22 100755
--- a/test/lua-Harness-tests/303-package.t
+++ b/test/lua-Harness-tests/303-package.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.3>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 local has_loaders = _VERSION == 'Lua 5.1'
@@ -130,9 +130,9 @@ end
 
 -- searchpath
 if has_searcherpath then
-    local p = package.searchpath('tap', package.path)
+    local p = package.searchpath('tap_harness', package.path)
     type_ok(p, 'string', "searchpath")
-    p = package.searchpath('tap', 'bad path')
+    p = package.searchpath('tap_harness', 'bad path')
     is(p, nil)
 else
     is(package.searchpath, nil, "no package.searchpath")
diff --git a/test/lua-Harness-tests/304-string.t b/test/lua-Harness-tests/304-string.t
index 991600a..293fd8e 100755
--- a/test/lua-Harness-tests/304-string.t
+++ b/test/lua-Harness-tests/304-string.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.4>
 
 ]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 local has_dump53 = _VERSION >= 'Lua 5.3' or jit
diff --git a/test/lua-Harness-tests/305-utf8.t b/test/lua-Harness-tests/305-utf8.t
index 4304b6c..59a2e6b 100755
--- a/test/lua-Harness-tests/305-utf8.t
+++ b/test/lua-Harness-tests/305-utf8.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.5>
 
 --]]
 
-require 'tap'
+require'tap_harness'
 
 local profile = require'profile'
 local has_utf8 = _VERSION >= 'Lua 5.3' or (jit and jit.version:match'moonjit') or profile.utf8
diff --git a/test/lua-Harness-tests/306-table.t b/test/lua-Harness-tests/306-table.t
index 9836655..6e76492 100755
--- a/test/lua-Harness-tests/306-table.t
+++ b/test/lua-Harness-tests/306-table.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.6>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 local has_foreach = _VERSION == 'Lua 5.1'
diff --git a/test/lua-Harness-tests/307-math.t b/test/lua-Harness-tests/307-math.t
index 8b51ed1..762567f 100755
--- a/test/lua-Harness-tests/307-math.t
+++ b/test/lua-Harness-tests/307-math.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.7>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local has_integer = _VERSION >= 'Lua 5.3' or (jit and jit.version:match'moonjit') or profile.integer
 local has_mathx = _VERSION < 'Lua 5.3' or profile.compat52 or profile.compat53 or profile.has_mathx
diff --git a/test/lua-Harness-tests/308-io.t b/test/lua-Harness-tests/308-io.t
index 35d39c0..1945ce3 100755
--- a/test/lua-Harness-tests/308-io.t
+++ b/test/lua-Harness-tests/308-io.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.8>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 local has_write51 = _VERSION == 'Lua 5.1' and (not profile.luajit_compat52 or ujit)
diff --git a/test/lua-Harness-tests/309-os.t b/test/lua-Harness-tests/309-os.t
index a787b14..f94db00 100755
--- a/test/lua-Harness-tests/309-os.t
+++ b/test/lua-Harness-tests/309-os.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.9>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 local luajit20 = jit and (jit.version_num < 20100 and not jit.version:match'^RaptorJIT')
 local has_execute51 = _VERSION == 'Lua 5.1' and (not profile.luajit_compat52 or ujit)
diff --git a/test/lua-Harness-tests/310-debug.t b/test/lua-Harness-tests/310-debug.t
index f78af03..63194ac 100755
--- a/test/lua-Harness-tests/310-debug.t
+++ b/test/lua-Harness-tests/310-debug.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.10>
 
 ]]
 
-require 'tap'
+require'tap_harness'
 local profile = require'profile'
 local has_getfenv = _VERSION == 'Lua 5.1'
 local has_gethook54 = _VERSION >= 'Lua 5.4'
diff --git a/test/lua-Harness-tests/311-bit32.t b/test/lua-Harness-tests/311-bit32.t
index 7023906..a314f47 100755
--- a/test/lua-Harness-tests/311-bit32.t
+++ b/test/lua-Harness-tests/311-bit32.t
@@ -29,7 +29,7 @@ L<https://www.lua.org/manual/5.2/manual.html#6.7>
 
 --]]
 
-require 'tap'
+require'tap_harness'
 local profile = require'profile'
 local has_bit32 = _VERSION == 'Lua 5.2' or profile.compat52 or profile.has_bit32
 
diff --git a/test/lua-Harness-tests/314-regex.t b/test/lua-Harness-tests/314-regex.t
index ad4554c..ac7ad80 100755
--- a/test/lua-Harness-tests/314-regex.t
+++ b/test/lua-Harness-tests/314-regex.t
@@ -49,7 +49,7 @@ Description of the test.
 
 --]]
 
-require'tap'
+require'tap_harness'
 local loadstring = loadstring or load
 
 plan(162)
diff --git a/test/lua-Harness-tests/320-stdin.t b/test/lua-Harness-tests/320-stdin.t
index 4828285..a0eabcb 100755
--- a/test/lua-Harness-tests/320-stdin.t
+++ b/test/lua-Harness-tests/320-stdin.t
@@ -24,7 +24,7 @@ Tests Lua Basic & IO Libraries with stdin
 
 --]]
 
-require'tap'
+require'tap_harness'
 
 local lua = get_lua_binary_name()
 
diff --git a/test/lua-Harness-tests/401-bitop.t b/test/lua-Harness-tests/401-bitop.t
index f95aebf..d1225bd 100755
--- a/test/lua-Harness-tests/401-bitop.t
+++ b/test/lua-Harness-tests/401-bitop.t
@@ -24,7 +24,7 @@ See L<http://bitop.luajit.org/>.
 
 --]]
 
-require 'tap'
+require'tap_harness'
 
 if not jit then
     skip_all("only with LuaJIT")
diff --git a/test/lua-Harness-tests/402-ffi.t b/test/lua-Harness-tests/402-ffi.t
index a2e32a5..2423b2e 100755
--- a/test/lua-Harness-tests/402-ffi.t
+++ b/test/lua-Harness-tests/402-ffi.t
@@ -24,7 +24,7 @@ See L<http://luajit.org/ext_ffi.html>.
 
 --]]
 
-require 'tap'
+require'tap_harness'
 
 if not jit then
     skip_all("only with LuaJIT")
diff --git a/test/lua-Harness-tests/403-jit.t b/test/lua-Harness-tests/403-jit.t
index 0073c90..6c0870a 100755
--- a/test/lua-Harness-tests/403-jit.t
+++ b/test/lua-Harness-tests/403-jit.t
@@ -24,7 +24,7 @@ See L<http://luajit.org/ext_jit.html>.
 
 --]]
 
-require 'tap'
+require'tap_harness'
 local profile = require'profile'
 
 if not jit then
diff --git a/test/lua-Harness-tests/404-ext.t b/test/lua-Harness-tests/404-ext.t
index 22a52c7..906ed51 100755
--- a/test/lua-Harness-tests/404-ext.t
+++ b/test/lua-Harness-tests/404-ext.t
@@ -24,7 +24,7 @@ See L<http://luajit.org/ext_jit.html>.
 
 --]]
 
-require 'tap'
+require'tap_harness'
 local profile = require'profile'
 
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
diff --git a/test/lua-Harness-tests/411-luajit.t b/test/lua-Harness-tests/411-luajit.t
index feb752e..b8cb547 100755
--- a/test/lua-Harness-tests/411-luajit.t
+++ b/test/lua-Harness-tests/411-luajit.t
@@ -24,7 +24,7 @@ See L<http://luajit.org/running.html>
 
 --]]
 
-require'tap'
+require'tap_harness'
 local profile = require'profile'
 
 if not jit or ujit then
diff --git a/test/lua-Harness-tests/CMakeLists.txt b/test/lua-Harness-tests/CMakeLists.txt
index 9b35e5a..e28cadd 100644
--- a/test/lua-Harness-tests/CMakeLists.txt
+++ b/test/lua-Harness-tests/CMakeLists.txt
@@ -26,7 +26,17 @@ string(CONCAT LUA_CPATH
   "${LUAJIT_SOURCE_DIR}/?${CMAKE_SHARED_LIBRARY_SUFFIX}\;"
 )
 
-add_custom_target(lua-Harness-tests DEPENDS ${LUAJIT_TEST_BINARY})
+# FIXME: Until https://github.com/tarantool/tarantool/issues/5040
+# is resolved, Tarantool enters interactive mode if prove input
+# is not stdin. As a result test hungs and not run at all.
+# This part should be dropped, and argument to prove is passed
+# as directory.
+file(GLOB TESTS_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.t)
+string(REPLACE ";" "\n" TESTS_LIST "${TESTS_LIST}")
+set(LIST_FILE ${CMAKE_CURRENT_BINARY_DIR}/tests_list)
+file(WRITE ${LIST_FILE} ${TESTS_LIST})
+
+add_custom_target(lua-Harness-tests DEPENDS ${LUAJIT_TEST_BINARY} ${LIST_FILE})
 
 add_custom_command(TARGET lua-Harness-tests
   COMMENT "Running lua-Harness tests"
@@ -40,7 +50,10 @@ add_custom_command(TARGET lua-Harness-tests
     # for more info.
     # So use less preferable way for tests.
     # See the root CMakeLists.txt for more info.
-    ${PROVE} ${CMAKE_CURRENT_SOURCE_DIR}
+    # XXX: Adapt to run test witht Tarantool on read-only
+    # file systems with dofile(CUR_SOURCE_DIR..filename).
+    CUR_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
+    ${PROVE} - < ${LIST_FILE}
       --exec '${LUAJIT_TEST_COMMAND} -l profile_luajit21'
       ${LUA_TEST_FLAGS}
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
diff --git a/test/lua-Harness-tests/tap.lua b/test/lua-Harness-tests/tap_harness.lua
similarity index 100%
rename from test/lua-Harness-tests/tap.lua
rename to test/lua-Harness-tests/tap_harness.lua
-- 
2.28.0


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

* [Tarantool-patches] [PATCH luajit 3/6] test: disable 305-utf8 of lua-Harness suite
  2021-03-12  5:27 [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite Sergey Kaplun via Tarantool-patches
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 1/6] test: add " Sergey Kaplun via Tarantool-patches
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 2/6] test: adjust lua-Harness test suite for Tarantool Sergey Kaplun via Tarantool-patches
@ 2021-03-12  5:27 ` Sergey Kaplun via Tarantool-patches
  2021-03-13 18:45   ` Sergey Ostanevich via Tarantool-patches
  2021-03-15 12:45   ` Igor Munkin via Tarantool-patches
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 4/6] test: disable 241-standalone " Sergey Kaplun via Tarantool-patches
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-12  5:27 UTC (permalink / raw)
  To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches

This patch disables 305-utf8.t from the lua-Harness test suite, because
the built-in utf8 module in Tarantool does not work as expected in the
test.

Partially the problem mentioned in tarantool/tarantool#5241.

Part of tarantool/tarantool#5844
Part of tarantool/tarantool#4473
---
 test/lua-Harness-tests/{305-utf8.t => 305-utf8.t.disabled} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename test/lua-Harness-tests/{305-utf8.t => 305-utf8.t.disabled} (100%)

diff --git a/test/lua-Harness-tests/305-utf8.t b/test/lua-Harness-tests/305-utf8.t.disabled
similarity index 100%
rename from test/lua-Harness-tests/305-utf8.t
rename to test/lua-Harness-tests/305-utf8.t.disabled
-- 
2.28.0


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

* [Tarantool-patches] [PATCH luajit 4/6] test: disable 241-standalone of lua-Harness suite
  2021-03-12  5:27 [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite Sergey Kaplun via Tarantool-patches
                   ` (2 preceding siblings ...)
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 3/6] test: disable 305-utf8 of lua-Harness suite Sergey Kaplun via Tarantool-patches
@ 2021-03-12  5:27 ` Sergey Kaplun via Tarantool-patches
  2021-03-13 18:45   ` Sergey Ostanevich via Tarantool-patches
  2021-03-15 12:47   ` Igor Munkin via Tarantool-patches
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 5/6] test: disable 411-luajit " Sergey Kaplun via Tarantool-patches
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-12  5:27 UTC (permalink / raw)
  To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches

This patch disables 241-standalone.t from the lua-Harness test suite,
because some flags in Tarantool and LuaJIT work differently, or they are
not present at all in Tarantool. For example, -i, -b, -j.
See tarantool/tarantool#5541.

Part of tarantool/tarantool#5844
Part of tarantool/tarantool#4473
---
 .../{241-standalone.t => 241-standalone.t.disabled}               | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename test/lua-Harness-tests/{241-standalone.t => 241-standalone.t.disabled} (100%)

diff --git a/test/lua-Harness-tests/241-standalone.t b/test/lua-Harness-tests/241-standalone.t.disabled
similarity index 100%
rename from test/lua-Harness-tests/241-standalone.t
rename to test/lua-Harness-tests/241-standalone.t.disabled
-- 
2.28.0


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

* [Tarantool-patches] [PATCH luajit 5/6] test: disable 411-luajit of lua-Harness suite
  2021-03-12  5:27 [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite Sergey Kaplun via Tarantool-patches
                   ` (3 preceding siblings ...)
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 4/6] test: disable 241-standalone " Sergey Kaplun via Tarantool-patches
@ 2021-03-12  5:27 ` Sergey Kaplun via Tarantool-patches
  2021-03-13 18:46   ` Sergey Ostanevich via Tarantool-patches
  2021-03-15 12:48   ` Igor Munkin via Tarantool-patches
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 6/6] test: skip test for getenv in 309-os.t Sergey Kaplun via Tarantool-patches
  2021-03-13 18:22 ` [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite Sergey Ostanevich via Tarantool-patches
  6 siblings, 2 replies; 19+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-12  5:27 UTC (permalink / raw)
  To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches

This patch disables 411-luajit.t from the lua-Harness test suite,
because Tarantool does not support -b and -j flags.
See tarantool/tarantool#5541.

Part of tarantool/tarantool#5844
Part of tarantool/tarantool#4473
---
 test/lua-Harness-tests/{411-luajit.t => 411-luajit.t.disabled} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename test/lua-Harness-tests/{411-luajit.t => 411-luajit.t.disabled} (100%)

diff --git a/test/lua-Harness-tests/411-luajit.t b/test/lua-Harness-tests/411-luajit.t.disabled
similarity index 100%
rename from test/lua-Harness-tests/411-luajit.t
rename to test/lua-Harness-tests/411-luajit.t.disabled
-- 
2.28.0


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

* [Tarantool-patches] [PATCH luajit 6/6] test: skip test for getenv in 309-os.t
  2021-03-12  5:27 [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite Sergey Kaplun via Tarantool-patches
                   ` (4 preceding siblings ...)
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 5/6] test: disable 411-luajit " Sergey Kaplun via Tarantool-patches
@ 2021-03-12  5:27 ` Sergey Kaplun via Tarantool-patches
  2021-03-13 18:50   ` Sergey Ostanevich via Tarantool-patches
  2021-03-13 18:22 ` [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite Sergey Ostanevich via Tarantool-patches
  6 siblings, 1 reply; 19+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2021-03-12  5:27 UTC (permalink / raw)
  To: Sergey Ostanevich, Igor Munkin; +Cc: tarantool-patches

Inside Tarantool's GiHub-CI there is not defined variable LOGNAME nor
USERNAME. This leads to failed test inside CI, because a string is
expected.

This test is skipped when this variable is `nil`.

Part of tarantool/tarantool#5844
Part of tarantool/tarantool#4473
---
 test/lua-Harness-tests/309-os.t | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/test/lua-Harness-tests/309-os.t b/test/lua-Harness-tests/309-os.t
index f94db00..6b3ea4d 100755
--- a/test/lua-Harness-tests/309-os.t
+++ b/test/lua-Harness-tests/309-os.t
@@ -170,7 +170,11 @@ do -- getenv
     is(os.getenv('__IMPROBABLE__'), nil, "function getenv")
 
     local user = os.getenv('LOGNAME') or os.getenv('USERNAME')
-    type_ok(user, 'string', "function getenv")
+    if not user then
+        skip("no LOGNAME and USERNAME")
+    else
+        type_ok(user, 'string', "function getenv")
+    end
 end
 
 do -- remove
-- 
2.28.0


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

* Re: [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite
  2021-03-12  5:27 [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite Sergey Kaplun via Tarantool-patches
                   ` (5 preceding siblings ...)
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 6/6] test: skip test for getenv in 309-os.t Sergey Kaplun via Tarantool-patches
@ 2021-03-13 18:22 ` Sergey Ostanevich via Tarantool-patches
  6 siblings, 0 replies; 19+ messages in thread
From: Sergey Ostanevich via Tarantool-patches @ 2021-03-13 18:22 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Hi!

Thanks for the patch!

I believe it’s no good to put the initial test suit commit different from the
original. Namely: the ’tap.lua’ was renamed. Test suite is not runnable as a 
result. Then all tests were changed to use the renamed version in a separate
commit. I believe the rename should belong there - in rename patch - hence keep
consistency in testability.

Regards,
Sergos


> On 12 Mar 2021, at 08:27, Sergey Kaplun <skaplun@tarantool.org> wrote:
> 
> In this patchset lua-Harness test suite is adapted for the LuaJIT fork
> and Tarantool.
> 
> Branch: https://github.com/tarantool/luajit/tree/skaplun/gh-5844-adapt-lua-harness-test-suite
> Tarantool's branch for tests:
> https://github.com/tarantool/tarantool/tree/skaplun/gh-5844-adapt-lua-harness-test-suite
> Issues:
> * https://github.com/tarantool/tarantool/issues/5844
> * https://github.com/tarantool/tarantool/issues/5473
> 
> You can check the accuracy of the first patch with the following commands:
> | $ cd ~/tmp/lua-Harness && git remote -v && echo $(git log -n1) && cd -
> | origin  https://framagit.org/fperrad/lua-Harness.git (fetch)
> | origin  https://framagit.org/fperrad/lua-Harness.git (push)
> | commit a74be274d299dc299228dc7a09052759da9ceac4 Author: Francois Perrad <francois.perrad@gadz.org> Date: Wed Mar 3 15:15:59 2021 +0100 Makefile for lua-5.4.3-rc1
> |
> | $ diff --color -ur ~/tmp/lua-Harness/test_lua/ test/lua-Harness-tests/
> 
> Mergen Imeev (2):
>  test: add lua-Harness test suite
>  test: adjust lua-Harness test suite for Tarantool
> 
> Sergey Kaplun (4):
>  test: disable 305-utf8 of lua-Harness suite
>  test: disable 241-standalone of lua-Harness suite
>  test: disable 411-luajit of lua-Harness suite
>  test: skip test for getenv in 309-os.t
> 
> .gitignore                                    |   1 +
> .luacheckrc                                   |   1 +
> test/CMakeLists.txt                           |   4 +-
> test/lua-Harness-tests/000-sanity.t           |  54 ++
> test/lua-Harness-tests/001-if.t               |  88 ++
> test/lua-Harness-tests/002-table.t            |  67 ++
> test/lua-Harness-tests/011-while.t            |  89 ++
> test/lua-Harness-tests/012-repeat.t           |  85 ++
> test/lua-Harness-tests/014-fornum.t           | 151 +++
> test/lua-Harness-tests/015-forlist.t          | 111 +++
> test/lua-Harness-tests/090-tap.t              |  37 +
> test/lua-Harness-tests/091-profile.t          |  45 +
> test/lua-Harness-tests/101-boolean.t          | 127 +++
> test/lua-Harness-tests/102-function.t         | 206 +++++
> test/lua-Harness-tests/103-nil.t              | 127 +++
> test/lua-Harness-tests/104-number.t           | 246 +++++
> test/lua-Harness-tests/105-string.t           | 277 ++++++
> test/lua-Harness-tests/106-table.t            | 135 +++
> test/lua-Harness-tests/107-thread.t           | 135 +++
> test/lua-Harness-tests/108-userdata.t         | 132 +++
> test/lua-Harness-tests/200-examples.t         | 104 +++
> test/lua-Harness-tests/201-assign.t           | 150 +++
> test/lua-Harness-tests/202-expr.t             | 157 ++++
> test/lua-Harness-tests/203-lexico.t           | 147 +++
> test/lua-Harness-tests/204-grammar.t          | 233 +++++
> test/lua-Harness-tests/211-scope.t            |  86 ++
> test/lua-Harness-tests/212-function.t         | 288 ++++++
> test/lua-Harness-tests/213-closure.t          |  98 ++
> test/lua-Harness-tests/214-coroutine.t        | 244 +++++
> test/lua-Harness-tests/221-table.t            | 120 +++
> test/lua-Harness-tests/222-constructor.t      | 119 +++
> test/lua-Harness-tests/223-iterator.t         | 203 +++++
> test/lua-Harness-tests/231-metatable.t        | 602 ++++++++++++
> test/lua-Harness-tests/232-object.t           | 314 +++++++
> .../241-standalone.t.disabled                 | 269 ++++++
> test/lua-Harness-tests/242-luac.t             | 341 +++++++
> test/lua-Harness-tests/301-basic.t            | 859 ++++++++++++++++++
> test/lua-Harness-tests/303-package.t          | 290 ++++++
> test/lua-Harness-tests/304-string.t           | 633 +++++++++++++
> test/lua-Harness-tests/305-utf8.t.disabled    |  55 ++
> test/lua-Harness-tests/306-table.t            | 372 ++++++++
> test/lua-Harness-tests/307-math.t             | 375 ++++++++
> test/lua-Harness-tests/308-io.t               | 397 ++++++++
> test/lua-Harness-tests/309-os.t               | 275 ++++++
> test/lua-Harness-tests/310-debug.t            | 322 +++++++
> test/lua-Harness-tests/311-bit32.t            | 127 +++
> test/lua-Harness-tests/314-regex.t            | 222 +++++
> test/lua-Harness-tests/320-stdin.t            | 133 +++
> test/lua-Harness-tests/401-bitop.t            | 106 +++
> test/lua-Harness-tests/402-ffi.t              | 142 +++
> test/lua-Harness-tests/403-jit.t              | 163 ++++
> test/lua-Harness-tests/404-ext.t              | 171 ++++
> test/lua-Harness-tests/411-luajit.t.disabled  | 211 +++++
> test/lua-Harness-tests/CMakeLists.txt         |  62 ++
> test/lua-Harness-tests/lexico52/lexico.t      |  45 +
> test/lua-Harness-tests/lexico53/boolean.t     |  43 +
> test/lua-Harness-tests/lexico53/function.t    |  66 ++
> test/lua-Harness-tests/lexico53/lexico.t      |  30 +
> test/lua-Harness-tests/lexico53/nil.t         |  43 +
> test/lua-Harness-tests/lexico53/number.t      | 181 ++++
> test/lua-Harness-tests/lexico53/string.t      | 169 ++++
> test/lua-Harness-tests/lexico53/table.t       |  43 +
> test/lua-Harness-tests/lexico53/thread.t      |  45 +
> test/lua-Harness-tests/lexico53/userdata.t    |  45 +
> test/lua-Harness-tests/lexico53/utf8.t        | 179 ++++
> test/lua-Harness-tests/lexico54/lexico.t      |  19 +
> test/lua-Harness-tests/lexico54/metatable.t   |  38 +
> test/lua-Harness-tests/lexico54/utf8.t        |  54 ++
> test/lua-Harness-tests/lexicojit/basic.t      |  27 +
> test/lua-Harness-tests/lexicojit/ext.t        |  52 ++
> test/lua-Harness-tests/lexicojit/lexico.t     |  32 +
> test/lua-Harness-tests/profile.lua            |  53 ++
> test/lua-Harness-tests/profile_lua51.lua      |  46 +
> .../profile_lua51_strict.lua                  |  46 +
> test/lua-Harness-tests/profile_lua52.lua      |  46 +
> .../profile_lua52_strict.lua                  |  46 +
> test/lua-Harness-tests/profile_lua53.lua      |  52 ++
> .../profile_lua53_noconv.lua                  |  55 ++
> .../profile_lua53_strict.lua                  |  52 ++
> test/lua-Harness-tests/profile_lua54.lua      |  52 ++
> .../profile_lua54_noconv.lua                  |  55 ++
> .../profile_lua54_strict.lua                  |  53 ++
> test/lua-Harness-tests/profile_luajit20.lua   |  53 ++
> .../profile_luajit20_compat52.lua             |  53 ++
> test/lua-Harness-tests/profile_luajit21.lua   |  53 ++
> .../profile_luajit21_compat52.lua             |  53 ++
> test/lua-Harness-tests/profile_openresty.lua  |  53 ++
> test/lua-Harness-tests/profile_ravi.lua       |  58 ++
> test/lua-Harness-tests/profile_tiny_fork.lua  |  60 ++
> test/lua-Harness-tests/rx_captures            |  13 +
> test/lua-Harness-tests/rx_charclass           |  38 +
> test/lua-Harness-tests/rx_metachars           | 117 +++
> test/lua-Harness-tests/tap_harness.lua        | 212 +++++
> 93 files changed, 12937 insertions(+), 1 deletion(-)
> create mode 100755 test/lua-Harness-tests/000-sanity.t
> create mode 100755 test/lua-Harness-tests/001-if.t
> create mode 100755 test/lua-Harness-tests/002-table.t
> create mode 100755 test/lua-Harness-tests/011-while.t
> create mode 100755 test/lua-Harness-tests/012-repeat.t
> create mode 100755 test/lua-Harness-tests/014-fornum.t
> create mode 100755 test/lua-Harness-tests/015-forlist.t
> create mode 100755 test/lua-Harness-tests/090-tap.t
> create mode 100755 test/lua-Harness-tests/091-profile.t
> create mode 100755 test/lua-Harness-tests/101-boolean.t
> create mode 100755 test/lua-Harness-tests/102-function.t
> create mode 100755 test/lua-Harness-tests/103-nil.t
> create mode 100755 test/lua-Harness-tests/104-number.t
> create mode 100755 test/lua-Harness-tests/105-string.t
> create mode 100755 test/lua-Harness-tests/106-table.t
> create mode 100755 test/lua-Harness-tests/107-thread.t
> create mode 100755 test/lua-Harness-tests/108-userdata.t
> create mode 100755 test/lua-Harness-tests/200-examples.t
> create mode 100755 test/lua-Harness-tests/201-assign.t
> create mode 100755 test/lua-Harness-tests/202-expr.t
> create mode 100755 test/lua-Harness-tests/203-lexico.t
> create mode 100755 test/lua-Harness-tests/204-grammar.t
> create mode 100755 test/lua-Harness-tests/211-scope.t
> create mode 100755 test/lua-Harness-tests/212-function.t
> create mode 100755 test/lua-Harness-tests/213-closure.t
> create mode 100755 test/lua-Harness-tests/214-coroutine.t
> create mode 100755 test/lua-Harness-tests/221-table.t
> create mode 100755 test/lua-Harness-tests/222-constructor.t
> create mode 100755 test/lua-Harness-tests/223-iterator.t
> create mode 100755 test/lua-Harness-tests/231-metatable.t
> create mode 100755 test/lua-Harness-tests/232-object.t
> create mode 100755 test/lua-Harness-tests/241-standalone.t.disabled
> create mode 100755 test/lua-Harness-tests/242-luac.t
> create mode 100755 test/lua-Harness-tests/301-basic.t
> create mode 100755 test/lua-Harness-tests/303-package.t
> create mode 100755 test/lua-Harness-tests/304-string.t
> create mode 100755 test/lua-Harness-tests/305-utf8.t.disabled
> create mode 100755 test/lua-Harness-tests/306-table.t
> create mode 100755 test/lua-Harness-tests/307-math.t
> create mode 100755 test/lua-Harness-tests/308-io.t
> create mode 100755 test/lua-Harness-tests/309-os.t
> create mode 100755 test/lua-Harness-tests/310-debug.t
> create mode 100755 test/lua-Harness-tests/311-bit32.t
> create mode 100755 test/lua-Harness-tests/314-regex.t
> create mode 100755 test/lua-Harness-tests/320-stdin.t
> create mode 100755 test/lua-Harness-tests/401-bitop.t
> create mode 100755 test/lua-Harness-tests/402-ffi.t
> create mode 100755 test/lua-Harness-tests/403-jit.t
> create mode 100755 test/lua-Harness-tests/404-ext.t
> create mode 100755 test/lua-Harness-tests/411-luajit.t.disabled
> create mode 100644 test/lua-Harness-tests/CMakeLists.txt
> create mode 100644 test/lua-Harness-tests/lexico52/lexico.t
> create mode 100644 test/lua-Harness-tests/lexico53/boolean.t
> create mode 100644 test/lua-Harness-tests/lexico53/function.t
> create mode 100644 test/lua-Harness-tests/lexico53/lexico.t
> create mode 100644 test/lua-Harness-tests/lexico53/nil.t
> create mode 100644 test/lua-Harness-tests/lexico53/number.t
> create mode 100644 test/lua-Harness-tests/lexico53/string.t
> create mode 100644 test/lua-Harness-tests/lexico53/table.t
> create mode 100644 test/lua-Harness-tests/lexico53/thread.t
> create mode 100644 test/lua-Harness-tests/lexico53/userdata.t
> create mode 100644 test/lua-Harness-tests/lexico53/utf8.t
> create mode 100644 test/lua-Harness-tests/lexico54/lexico.t
> create mode 100644 test/lua-Harness-tests/lexico54/metatable.t
> create mode 100644 test/lua-Harness-tests/lexico54/utf8.t
> create mode 100644 test/lua-Harness-tests/lexicojit/basic.t
> create mode 100644 test/lua-Harness-tests/lexicojit/ext.t
> create mode 100644 test/lua-Harness-tests/lexicojit/lexico.t
> create mode 100644 test/lua-Harness-tests/profile.lua
> create mode 100644 test/lua-Harness-tests/profile_lua51.lua
> create mode 100644 test/lua-Harness-tests/profile_lua51_strict.lua
> create mode 100644 test/lua-Harness-tests/profile_lua52.lua
> create mode 100644 test/lua-Harness-tests/profile_lua52_strict.lua
> create mode 100644 test/lua-Harness-tests/profile_lua53.lua
> create mode 100644 test/lua-Harness-tests/profile_lua53_noconv.lua
> create mode 100644 test/lua-Harness-tests/profile_lua53_strict.lua
> create mode 100644 test/lua-Harness-tests/profile_lua54.lua
> create mode 100644 test/lua-Harness-tests/profile_lua54_noconv.lua
> create mode 100644 test/lua-Harness-tests/profile_lua54_strict.lua
> create mode 100644 test/lua-Harness-tests/profile_luajit20.lua
> create mode 100644 test/lua-Harness-tests/profile_luajit20_compat52.lua
> create mode 100644 test/lua-Harness-tests/profile_luajit21.lua
> create mode 100644 test/lua-Harness-tests/profile_luajit21_compat52.lua
> create mode 100644 test/lua-Harness-tests/profile_openresty.lua
> create mode 100644 test/lua-Harness-tests/profile_ravi.lua
> create mode 100644 test/lua-Harness-tests/profile_tiny_fork.lua
> create mode 100644 test/lua-Harness-tests/rx_captures
> create mode 100644 test/lua-Harness-tests/rx_charclass
> create mode 100644 test/lua-Harness-tests/rx_metachars
> create mode 100644 test/lua-Harness-tests/tap_harness.lua
> 
> -- 
> 2.28.0
> 


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

* Re: [Tarantool-patches] [PATCH luajit 2/6] test: adjust lua-Harness test suite for Tarantool
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 2/6] test: adjust lua-Harness test suite for Tarantool Sergey Kaplun via Tarantool-patches
@ 2021-03-13 18:41   ` Sergey Ostanevich via Tarantool-patches
  2021-03-15 13:22   ` Igor Munkin via Tarantool-patches
  1 sibling, 0 replies; 19+ messages in thread
From: Sergey Ostanevich via Tarantool-patches @ 2021-03-13 18:41 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Hi!

Thanks for the patch!

LGTM.

Sergos.

> On 12 Mar 2021, at 08:27, Sergey Kaplun <skaplun@tarantool.org> wrote:
> 
> This patch makes it possible to run lua-Harness test suite using
> Tarantool.
> 
> Tarantool has its own loaded tap built in so need to change name to
> another one.
> 
> 203-lexico.t and 301-basic.t is adjusted to valid working with
> out-of-source build in Tarantool CI.
> 
> Also creates additional list of files provided to prove via stdin.
> This is required to avoid tests hungs via Tarantool's binary.
> Partially this problem is descripted in tarantool/tarantool#5040.
> 
> Part of tarantool/tarantool#5844
> Part of tarantool/tarantool#4473
> ---
> Author: Mergen Imeev <imeevma@gmail.com>
> 
> .gitignore                                      |  1 +
> test/lua-Harness-tests/090-tap.t                |  2 +-
> test/lua-Harness-tests/091-profile.t            |  2 +-
> test/lua-Harness-tests/101-boolean.t            |  2 +-
> test/lua-Harness-tests/102-function.t           |  2 +-
> test/lua-Harness-tests/103-nil.t                |  2 +-
> test/lua-Harness-tests/104-number.t             |  2 +-
> test/lua-Harness-tests/105-string.t             |  2 +-
> test/lua-Harness-tests/106-table.t              |  2 +-
> test/lua-Harness-tests/107-thread.t             |  2 +-
> test/lua-Harness-tests/108-userdata.t           |  2 +-
> test/lua-Harness-tests/200-examples.t           |  2 +-
> test/lua-Harness-tests/201-assign.t             |  2 +-
> test/lua-Harness-tests/202-expr.t               |  2 +-
> test/lua-Harness-tests/203-lexico.t             | 14 +++++++++-----
> test/lua-Harness-tests/204-grammar.t            |  2 +-
> test/lua-Harness-tests/211-scope.t              |  2 +-
> test/lua-Harness-tests/212-function.t           |  2 +-
> test/lua-Harness-tests/213-closure.t            |  2 +-
> test/lua-Harness-tests/214-coroutine.t          |  2 +-
> test/lua-Harness-tests/221-table.t              |  2 +-
> test/lua-Harness-tests/222-constructor.t        |  2 +-
> test/lua-Harness-tests/223-iterator.t           |  2 +-
> test/lua-Harness-tests/231-metatable.t          |  2 +-
> test/lua-Harness-tests/232-object.t             |  2 +-
> test/lua-Harness-tests/241-standalone.t         | 10 +++++-----
> test/lua-Harness-tests/242-luac.t               |  2 +-
> test/lua-Harness-tests/301-basic.t              |  7 +++++--
> test/lua-Harness-tests/303-package.t            |  6 +++---
> test/lua-Harness-tests/304-string.t             |  2 +-
> test/lua-Harness-tests/305-utf8.t               |  2 +-
> test/lua-Harness-tests/306-table.t              |  2 +-
> test/lua-Harness-tests/307-math.t               |  2 +-
> test/lua-Harness-tests/308-io.t                 |  2 +-
> test/lua-Harness-tests/309-os.t                 |  2 +-
> test/lua-Harness-tests/310-debug.t              |  2 +-
> test/lua-Harness-tests/311-bit32.t              |  2 +-
> test/lua-Harness-tests/314-regex.t              |  2 +-
> test/lua-Harness-tests/320-stdin.t              |  2 +-
> test/lua-Harness-tests/401-bitop.t              |  2 +-
> test/lua-Harness-tests/402-ffi.t                |  2 +-
> test/lua-Harness-tests/403-jit.t                |  2 +-
> test/lua-Harness-tests/404-ext.t                |  2 +-
> test/lua-Harness-tests/411-luajit.t             |  2 +-
> test/lua-Harness-tests/CMakeLists.txt           | 17 +++++++++++++++--
> .../{tap.lua => tap_harness.lua}                |  0
> 46 files changed, 77 insertions(+), 56 deletions(-)
> rename test/lua-Harness-tests/{tap.lua => tap_harness.lua} (100%)
> 
> diff --git a/.gitignore b/.gitignore
> index 2103a30..1fb81bc 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -20,3 +20,4 @@ compile_commands.json
> install_manifest.txt
> luajit-parse-memprof
> luajit.pc
> +tests_list
> diff --git a/test/lua-Harness-tests/090-tap.t b/test/lua-Harness-tests/090-tap.t
> index 92f04d8..99932f2 100755
> --- a/test/lua-Harness-tests/090-tap.t
> +++ b/test/lua-Harness-tests/090-tap.t
> @@ -22,7 +22,7 @@
> 
> ]]
> 
> -require'tap'
> +require'tap_harness'
> 
> plan(3)
> ok( true, 'ok' )
> diff --git a/test/lua-Harness-tests/091-profile.t b/test/lua-Harness-tests/091-profile.t
> index db47438..ebc142d 100755
> --- a/test/lua-Harness-tests/091-profile.t
> +++ b/test/lua-Harness-tests/091-profile.t
> @@ -22,7 +22,7 @@
> 
> ]]
> 
> -require'tap'
> +require'tap_harness'
> 
> plan'no_plan'
> 
> diff --git a/test/lua-Harness-tests/101-boolean.t b/test/lua-Harness-tests/101-boolean.t
> index 0033eff..653509f 100755
> --- a/test/lua-Harness-tests/101-boolean.t
> +++ b/test/lua-Harness-tests/101-boolean.t
> @@ -22,7 +22,7 @@
> 
> ]]
> 
> -require'tap'
> +require'tap_harness'
> local has_op53 = _VERSION >= 'Lua 5.3'
> 
> plan'no_plan'
> diff --git a/test/lua-Harness-tests/102-function.t b/test/lua-Harness-tests/102-function.t
> index 48ed814..cb7e9d0 100755
> --- a/test/lua-Harness-tests/102-function.t
> +++ b/test/lua-Harness-tests/102-function.t
> @@ -22,7 +22,7 @@
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local has_op53 = _VERSION >= 'Lua 5.3'
> 
> plan'no_plan'
> diff --git a/test/lua-Harness-tests/103-nil.t b/test/lua-Harness-tests/103-nil.t
> index 561b101..a74c491 100755
> --- a/test/lua-Harness-tests/103-nil.t
> +++ b/test/lua-Harness-tests/103-nil.t
> @@ -22,7 +22,7 @@
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local has_op53 = _VERSION >= 'Lua 5.3'
> 
> plan'no_plan'
> diff --git a/test/lua-Harness-tests/104-number.t b/test/lua-Harness-tests/104-number.t
> index 0d4d3fd..634d22a 100755
> --- a/test/lua-Harness-tests/104-number.t
> +++ b/test/lua-Harness-tests/104-number.t
> @@ -22,7 +22,7 @@
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local has_op53 = _VERSION >= 'Lua 5.3'
> 
> diff --git a/test/lua-Harness-tests/105-string.t b/test/lua-Harness-tests/105-string.t
> index cd8c88b..f2ea067 100755
> --- a/test/lua-Harness-tests/105-string.t
> +++ b/test/lua-Harness-tests/105-string.t
> @@ -22,7 +22,7 @@
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local has_op53 = _VERSION >= 'Lua 5.3'
> 
> diff --git a/test/lua-Harness-tests/106-table.t b/test/lua-Harness-tests/106-table.t
> index 0c0ba49..4a66f69 100755
> --- a/test/lua-Harness-tests/106-table.t
> +++ b/test/lua-Harness-tests/106-table.t
> @@ -22,7 +22,7 @@
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local has_op53 = _VERSION >= 'Lua 5.3'
> 
> plan'no_plan'
> diff --git a/test/lua-Harness-tests/107-thread.t b/test/lua-Harness-tests/107-thread.t
> index 3d4af18..e67ef36 100755
> --- a/test/lua-Harness-tests/107-thread.t
> +++ b/test/lua-Harness-tests/107-thread.t
> @@ -22,7 +22,7 @@
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local has_op53 = _VERSION >= 'Lua 5.3'
> 
> plan'no_plan'
> diff --git a/test/lua-Harness-tests/108-userdata.t b/test/lua-Harness-tests/108-userdata.t
> index b1e3641..687b1b8 100755
> --- a/test/lua-Harness-tests/108-userdata.t
> +++ b/test/lua-Harness-tests/108-userdata.t
> @@ -22,7 +22,7 @@
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local has_op53 = _VERSION >= 'Lua 5.3'
> 
> plan'no_plan'
> diff --git a/test/lua-Harness-tests/200-examples.t b/test/lua-Harness-tests/200-examples.t
> index 362aae3..cb06a80 100755
> --- a/test/lua-Harness-tests/200-examples.t
> +++ b/test/lua-Harness-tests/200-examples.t
> @@ -24,7 +24,7 @@ First tests in order to check infrastructure.
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> 
> plan(5)
> 
> diff --git a/test/lua-Harness-tests/201-assign.t b/test/lua-Harness-tests/201-assign.t
> index 7d023d8..f7ed472 100755
> --- a/test/lua-Harness-tests/201-assign.t
> +++ b/test/lua-Harness-tests/201-assign.t
> @@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#3.3.3>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local has_env = _VERSION >= 'Lua 5.2'
> 
> plan'no_plan'
> diff --git a/test/lua-Harness-tests/202-expr.t b/test/lua-Harness-tests/202-expr.t
> index 2576750..f03d5ea 100755
> --- a/test/lua-Harness-tests/202-expr.t
> +++ b/test/lua-Harness-tests/202-expr.t
> @@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#3.4>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local nocvtn2s = profile.nocvtn2s
> local nocvts2n = profile.nocvts2n
> diff --git a/test/lua-Harness-tests/203-lexico.t b/test/lua-Harness-tests/203-lexico.t
> index c1abebf..0a73f8c 100755
> --- a/test/lua-Harness-tests/203-lexico.t
> +++ b/test/lua-Harness-tests/203-lexico.t
> @@ -31,7 +31,7 @@ L<https://www.lua.org/manual/5.4/manual.html#3.1>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local loadstring = loadstring or load
> local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
> 
> @@ -117,20 +117,24 @@ do
>     like(msg, "^[^:]+:%d+: unfinished long comment .-near")
> end
> 
> +-- Adapt tests 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') .. '/'
> +
> if _VERSION >= 'Lua 5.2' or jit then
> -    dofile'lexico52/lexico.t'
> +    dofile(path_to_sources .. 'lexico52/lexico.t')
> end
> 
> if _VERSION >= 'Lua 5.3' or luajit21 then
> -    dofile'lexico53/lexico.t'
> +    dofile(path_to_sources .. 'lexico53/lexico.t')
> end
> 
> if _VERSION >= 'Lua 5.4' then
> -    dofile'lexico54/lexico.t'
> +    dofile(path_to_sources .. 'lexico54/lexico.t')
> end
> 
> if jit and pcall(require, 'ffi') then
> -    dofile'lexicojit/lexico.t'
> +    dofile(path_to_sources .. 'lexicojit/lexico.t')
> end
> 
> done_testing()
> diff --git a/test/lua-Harness-tests/204-grammar.t b/test/lua-Harness-tests/204-grammar.t
> index d9ae3a6..03580f4 100755
> --- a/test/lua-Harness-tests/204-grammar.t
> +++ b/test/lua-Harness-tests/204-grammar.t
> @@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#9>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local has_goto = _VERSION >= 'Lua 5.2' or jit
> local has_attr = _VERSION >= 'Lua 5.4'
> diff --git a/test/lua-Harness-tests/211-scope.t b/test/lua-Harness-tests/211-scope.t
> index 64eed52..8e26a6f 100755
> --- a/test/lua-Harness-tests/211-scope.t
> +++ b/test/lua-Harness-tests/211-scope.t
> @@ -30,7 +30,7 @@ See section "Local Variables and Blocks" in "Programming in Lua".
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> 
> plan(10)
> 
> diff --git a/test/lua-Harness-tests/212-function.t b/test/lua-Harness-tests/212-function.t
> index 2851053..405035e 100755
> --- a/test/lua-Harness-tests/212-function.t
> +++ b/test/lua-Harness-tests/212-function.t
> @@ -30,7 +30,7 @@ See section "Functions" in "Programming in Lua".
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local loadstring = loadstring or load
> 
> plan(68)
> diff --git a/test/lua-Harness-tests/213-closure.t b/test/lua-Harness-tests/213-closure.t
> index fc3bd29..16a8a21 100755
> --- a/test/lua-Harness-tests/213-closure.t
> +++ b/test/lua-Harness-tests/213-closure.t
> @@ -24,7 +24,7 @@ See section "Closures" in "Programming in Lua".
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> 
> plan(15)
> 
> diff --git a/test/lua-Harness-tests/214-coroutine.t b/test/lua-Harness-tests/214-coroutine.t
> index 92929e1..1ca1cb5 100755
> --- a/test/lua-Harness-tests/214-coroutine.t
> +++ b/test/lua-Harness-tests/214-coroutine.t
> @@ -30,7 +30,7 @@ See section "Coroutines" in "Programming in Lua".
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
> local has_coroutine52 = _VERSION >= 'Lua 5.2' or jit
> diff --git a/test/lua-Harness-tests/221-table.t b/test/lua-Harness-tests/221-table.t
> index c064a33..07ac952 100755
> --- a/test/lua-Harness-tests/221-table.t
> +++ b/test/lua-Harness-tests/221-table.t
> @@ -24,7 +24,7 @@ See section "Tables" in "Programming in Lua".
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> 
> plan(25)
> 
> diff --git a/test/lua-Harness-tests/222-constructor.t b/test/lua-Harness-tests/222-constructor.t
> index a01be2e..28037bf 100755
> --- a/test/lua-Harness-tests/222-constructor.t
> +++ b/test/lua-Harness-tests/222-constructor.t
> @@ -30,7 +30,7 @@ See section "Table Constructors" in "Programming in Lua".
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> 
> plan(16)
> 
> diff --git a/test/lua-Harness-tests/223-iterator.t b/test/lua-Harness-tests/223-iterator.t
> index 777ad73..073f3cd 100755
> --- a/test/lua-Harness-tests/223-iterator.t
> +++ b/test/lua-Harness-tests/223-iterator.t
> @@ -25,7 +25,7 @@ section "Coroutines as Iterators" in "Programming in Lua".
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> 
> plan(8)
> 
> diff --git a/test/lua-Harness-tests/231-metatable.t b/test/lua-Harness-tests/231-metatable.t
> index a2c6499..b94f608 100755
> --- a/test/lua-Harness-tests/231-metatable.t
> +++ b/test/lua-Harness-tests/231-metatable.t
> @@ -30,7 +30,7 @@ See section "Metatables and Metamethods" in "Programming in Lua".
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local has_metamethod52 = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
> local has_metamethod_ipairs = _VERSION == 'Lua 5.2' or profile.compat52 or profile.luajit_compat52
> diff --git a/test/lua-Harness-tests/232-object.t b/test/lua-Harness-tests/232-object.t
> index 0d87572..0d22232 100755
> --- a/test/lua-Harness-tests/232-object.t
> +++ b/test/lua-Harness-tests/232-object.t
> @@ -24,7 +24,7 @@ See section "Object-Oriented Programming" in "Programming in Lua".
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> 
> plan(18)
> 
> diff --git a/test/lua-Harness-tests/241-standalone.t b/test/lua-Harness-tests/241-standalone.t
> index c5237ee..33d5159 100755
> --- a/test/lua-Harness-tests/241-standalone.t
> +++ b/test/lua-Harness-tests/241-standalone.t
> @@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#7>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local has_bytecode = not ujit and not ravi
> local has_error52 = _VERSION >= 'Lua 5.2'
> local has_error53 = _VERSION >= 'Lua 5.3'
> @@ -228,14 +228,14 @@ end
> like(f:read'*l', "^usage: ", "no file")
> f:close()
> 
> -cmd = lua .. [[ -ltap -e "print(type(ok))"]]
> +cmd = lua .. [[ -ltap_harness -e "print(type(ok))"]]
> f = io.popen(cmd)
> -is(f:read'*l', 'function', "-ltap")
> +is(f:read'*l', 'function', "-ltap_harness")
> f:close()
> 
> -cmd = lua .. [[ -l tap -e "print(type(ok))"]]
> +cmd = lua .. [[ -l tap_harness -e "print(type(ok))"]]
> f = io.popen(cmd)
> -is(f:read'*l', 'function', "-l tap")
> +is(f:read'*l', 'function', "-l tap_harness")
> f:close()
> 
> cmd = lua .. [[ -l lpeg -e "print(1)" 2>&1]]
> diff --git a/test/lua-Harness-tests/242-luac.t b/test/lua-Harness-tests/242-luac.t
> index a95a334..9a3a3c3 100755
> --- a/test/lua-Harness-tests/242-luac.t
> +++ b/test/lua-Harness-tests/242-luac.t
> @@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#7>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> 
> if jit then
>     skip_all("LuaJIT")
> diff --git a/test/lua-Harness-tests/301-basic.t b/test/lua-Harness-tests/301-basic.t
> index f4f9235..13472cd 100755
> --- a/test/lua-Harness-tests/301-basic.t
> +++ b/test/lua-Harness-tests/301-basic.t
> @@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.1>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local has_error53 = _VERSION >= 'Lua 5.3'
> local has_gcinfo = _VERSION == 'Lua 5.1'
> @@ -843,7 +843,10 @@ do -- xpcall
> end
> 
> if jit and pcall(require, 'ffi') then
> -    dofile'lexicojit/basic.t'
> +    -- 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(path_to_sources .. '/lexicojit/basic.t')
> end
> 
> done_testing()
> diff --git a/test/lua-Harness-tests/303-package.t b/test/lua-Harness-tests/303-package.t
> index 7e5216d..996ce22 100755
> --- a/test/lua-Harness-tests/303-package.t
> +++ b/test/lua-Harness-tests/303-package.t
> @@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.3>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
> local has_loaders = _VERSION == 'Lua 5.1'
> @@ -130,9 +130,9 @@ end
> 
> -- searchpath
> if has_searcherpath then
> -    local p = package.searchpath('tap', package.path)
> +    local p = package.searchpath('tap_harness', package.path)
>     type_ok(p, 'string', "searchpath")
> -    p = package.searchpath('tap', 'bad path')
> +    p = package.searchpath('tap_harness', 'bad path')
>     is(p, nil)
> else
>     is(package.searchpath, nil, "no package.searchpath")
> diff --git a/test/lua-Harness-tests/304-string.t b/test/lua-Harness-tests/304-string.t
> index 991600a..293fd8e 100755
> --- a/test/lua-Harness-tests/304-string.t
> +++ b/test/lua-Harness-tests/304-string.t
> @@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.4>
> 
> ]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
> local has_dump53 = _VERSION >= 'Lua 5.3' or jit
> diff --git a/test/lua-Harness-tests/305-utf8.t b/test/lua-Harness-tests/305-utf8.t
> index 4304b6c..59a2e6b 100755
> --- a/test/lua-Harness-tests/305-utf8.t
> +++ b/test/lua-Harness-tests/305-utf8.t
> @@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.5>
> 
> --]]
> 
> -require 'tap'
> +require'tap_harness'
> 
> local profile = require'profile'
> local has_utf8 = _VERSION >= 'Lua 5.3' or (jit and jit.version:match'moonjit') or profile.utf8
> diff --git a/test/lua-Harness-tests/306-table.t b/test/lua-Harness-tests/306-table.t
> index 9836655..6e76492 100755
> --- a/test/lua-Harness-tests/306-table.t
> +++ b/test/lua-Harness-tests/306-table.t
> @@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.6>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
> local has_foreach = _VERSION == 'Lua 5.1'
> diff --git a/test/lua-Harness-tests/307-math.t b/test/lua-Harness-tests/307-math.t
> index 8b51ed1..762567f 100755
> --- a/test/lua-Harness-tests/307-math.t
> +++ b/test/lua-Harness-tests/307-math.t
> @@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.7>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local has_integer = _VERSION >= 'Lua 5.3' or (jit and jit.version:match'moonjit') or profile.integer
> local has_mathx = _VERSION < 'Lua 5.3' or profile.compat52 or profile.compat53 or profile.has_mathx
> diff --git a/test/lua-Harness-tests/308-io.t b/test/lua-Harness-tests/308-io.t
> index 35d39c0..1945ce3 100755
> --- a/test/lua-Harness-tests/308-io.t
> +++ b/test/lua-Harness-tests/308-io.t
> @@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.8>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
> local has_write51 = _VERSION == 'Lua 5.1' and (not profile.luajit_compat52 or ujit)
> diff --git a/test/lua-Harness-tests/309-os.t b/test/lua-Harness-tests/309-os.t
> index a787b14..f94db00 100755
> --- a/test/lua-Harness-tests/309-os.t
> +++ b/test/lua-Harness-tests/309-os.t
> @@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.9>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> local luajit20 = jit and (jit.version_num < 20100 and not jit.version:match'^RaptorJIT')
> local has_execute51 = _VERSION == 'Lua 5.1' and (not profile.luajit_compat52 or ujit)
> diff --git a/test/lua-Harness-tests/310-debug.t b/test/lua-Harness-tests/310-debug.t
> index f78af03..63194ac 100755
> --- a/test/lua-Harness-tests/310-debug.t
> +++ b/test/lua-Harness-tests/310-debug.t
> @@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.10>
> 
> ]]
> 
> -require 'tap'
> +require'tap_harness'
> local profile = require'profile'
> local has_getfenv = _VERSION == 'Lua 5.1'
> local has_gethook54 = _VERSION >= 'Lua 5.4'
> diff --git a/test/lua-Harness-tests/311-bit32.t b/test/lua-Harness-tests/311-bit32.t
> index 7023906..a314f47 100755
> --- a/test/lua-Harness-tests/311-bit32.t
> +++ b/test/lua-Harness-tests/311-bit32.t
> @@ -29,7 +29,7 @@ L<https://www.lua.org/manual/5.2/manual.html#6.7>
> 
> --]]
> 
> -require 'tap'
> +require'tap_harness'
> local profile = require'profile'
> local has_bit32 = _VERSION == 'Lua 5.2' or profile.compat52 or profile.has_bit32
> 
> diff --git a/test/lua-Harness-tests/314-regex.t b/test/lua-Harness-tests/314-regex.t
> index ad4554c..ac7ad80 100755
> --- a/test/lua-Harness-tests/314-regex.t
> +++ b/test/lua-Harness-tests/314-regex.t
> @@ -49,7 +49,7 @@ Description of the test.
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local loadstring = loadstring or load
> 
> plan(162)
> diff --git a/test/lua-Harness-tests/320-stdin.t b/test/lua-Harness-tests/320-stdin.t
> index 4828285..a0eabcb 100755
> --- a/test/lua-Harness-tests/320-stdin.t
> +++ b/test/lua-Harness-tests/320-stdin.t
> @@ -24,7 +24,7 @@ Tests Lua Basic & IO Libraries with stdin
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> 
> local lua = get_lua_binary_name()
> 
> diff --git a/test/lua-Harness-tests/401-bitop.t b/test/lua-Harness-tests/401-bitop.t
> index f95aebf..d1225bd 100755
> --- a/test/lua-Harness-tests/401-bitop.t
> +++ b/test/lua-Harness-tests/401-bitop.t
> @@ -24,7 +24,7 @@ See L<http://bitop.luajit.org/>.
> 
> --]]
> 
> -require 'tap'
> +require'tap_harness'
> 
> if not jit then
>     skip_all("only with LuaJIT")
> diff --git a/test/lua-Harness-tests/402-ffi.t b/test/lua-Harness-tests/402-ffi.t
> index a2e32a5..2423b2e 100755
> --- a/test/lua-Harness-tests/402-ffi.t
> +++ b/test/lua-Harness-tests/402-ffi.t
> @@ -24,7 +24,7 @@ See L<http://luajit.org/ext_ffi.html>.
> 
> --]]
> 
> -require 'tap'
> +require'tap_harness'
> 
> if not jit then
>     skip_all("only with LuaJIT")
> diff --git a/test/lua-Harness-tests/403-jit.t b/test/lua-Harness-tests/403-jit.t
> index 0073c90..6c0870a 100755
> --- a/test/lua-Harness-tests/403-jit.t
> +++ b/test/lua-Harness-tests/403-jit.t
> @@ -24,7 +24,7 @@ See L<http://luajit.org/ext_jit.html>.
> 
> --]]
> 
> -require 'tap'
> +require'tap_harness'
> local profile = require'profile'
> 
> if not jit then
> diff --git a/test/lua-Harness-tests/404-ext.t b/test/lua-Harness-tests/404-ext.t
> index 22a52c7..906ed51 100755
> --- a/test/lua-Harness-tests/404-ext.t
> +++ b/test/lua-Harness-tests/404-ext.t
> @@ -24,7 +24,7 @@ See L<http://luajit.org/ext_jit.html>.
> 
> --]]
> 
> -require 'tap'
> +require'tap_harness'
> local profile = require'profile'
> 
> local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
> diff --git a/test/lua-Harness-tests/411-luajit.t b/test/lua-Harness-tests/411-luajit.t
> index feb752e..b8cb547 100755
> --- a/test/lua-Harness-tests/411-luajit.t
> +++ b/test/lua-Harness-tests/411-luajit.t
> @@ -24,7 +24,7 @@ See L<http://luajit.org/running.html>
> 
> --]]
> 
> -require'tap'
> +require'tap_harness'
> local profile = require'profile'
> 
> if not jit or ujit then
> diff --git a/test/lua-Harness-tests/CMakeLists.txt b/test/lua-Harness-tests/CMakeLists.txt
> index 9b35e5a..e28cadd 100644
> --- a/test/lua-Harness-tests/CMakeLists.txt
> +++ b/test/lua-Harness-tests/CMakeLists.txt
> @@ -26,7 +26,17 @@ string(CONCAT LUA_CPATH
>   "${LUAJIT_SOURCE_DIR}/?${CMAKE_SHARED_LIBRARY_SUFFIX}\;"
> )
> 
> -add_custom_target(lua-Harness-tests DEPENDS ${LUAJIT_TEST_BINARY})
> +# FIXME: Until https://github.com/tarantool/tarantool/issues/5040
> +# is resolved, Tarantool enters interactive mode if prove input
> +# is not stdin. As a result test hungs and not run at all.
> +# This part should be dropped, and argument to prove is passed
> +# as directory.
> +file(GLOB TESTS_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.t)
> +string(REPLACE ";" "\n" TESTS_LIST "${TESTS_LIST}")
> +set(LIST_FILE ${CMAKE_CURRENT_BINARY_DIR}/tests_list)
> +file(WRITE ${LIST_FILE} ${TESTS_LIST})
> +
> +add_custom_target(lua-Harness-tests DEPENDS ${LUAJIT_TEST_BINARY} ${LIST_FILE})
> 
> add_custom_command(TARGET lua-Harness-tests
>   COMMENT "Running lua-Harness tests"
> @@ -40,7 +50,10 @@ add_custom_command(TARGET lua-Harness-tests
>     # for more info.
>     # So use less preferable way for tests.
>     # See the root CMakeLists.txt for more info.
> -    ${PROVE} ${CMAKE_CURRENT_SOURCE_DIR}
> +    # XXX: Adapt to run test witht Tarantool on read-only
> +    # file systems with dofile(CUR_SOURCE_DIR..filename).
> +    CUR_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
> +    ${PROVE} - < ${LIST_FILE}
>       --exec '${LUAJIT_TEST_COMMAND} -l profile_luajit21'
>       ${LUA_TEST_FLAGS}
>   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> diff --git a/test/lua-Harness-tests/tap.lua b/test/lua-Harness-tests/tap_harness.lua
> similarity index 100%
> rename from test/lua-Harness-tests/tap.lua
> rename to test/lua-Harness-tests/tap_harness.lua
> -- 
> 2.28.0
> 


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

* Re: [Tarantool-patches] [PATCH luajit 3/6] test: disable 305-utf8 of lua-Harness suite
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 3/6] test: disable 305-utf8 of lua-Harness suite Sergey Kaplun via Tarantool-patches
@ 2021-03-13 18:45   ` Sergey Ostanevich via Tarantool-patches
  2021-03-15 12:45   ` Igor Munkin via Tarantool-patches
  1 sibling, 0 replies; 19+ messages in thread
From: Sergey Ostanevich via Tarantool-patches @ 2021-03-13 18:45 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Hi!

LGTM.

Sergos.

> On 12 Mar 2021, at 08:27, Sergey Kaplun <skaplun@tarantool.org> wrote:
> 
> This patch disables 305-utf8.t from the lua-Harness test suite, because
> the built-in utf8 module in Tarantool does not work as expected in the
> test.
> 
> Partially the problem mentioned in tarantool/tarantool#5241.
> 
> Part of tarantool/tarantool#5844
> Part of tarantool/tarantool#4473
> ---
> test/lua-Harness-tests/{305-utf8.t => 305-utf8.t.disabled} | 0
> 1 file changed, 0 insertions(+), 0 deletions(-)
> rename test/lua-Harness-tests/{305-utf8.t => 305-utf8.t.disabled} (100%)
> 
> diff --git a/test/lua-Harness-tests/305-utf8.t b/test/lua-Harness-tests/305-utf8.t.disabled
> similarity index 100%
> rename from test/lua-Harness-tests/305-utf8.t
> rename to test/lua-Harness-tests/305-utf8.t.disabled
> -- 
> 2.28.0
> 


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

* Re: [Tarantool-patches] [PATCH luajit 4/6] test: disable 241-standalone of lua-Harness suite
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 4/6] test: disable 241-standalone " Sergey Kaplun via Tarantool-patches
@ 2021-03-13 18:45   ` Sergey Ostanevich via Tarantool-patches
  2021-03-15 12:47   ` Igor Munkin via Tarantool-patches
  1 sibling, 0 replies; 19+ messages in thread
From: Sergey Ostanevich via Tarantool-patches @ 2021-03-13 18:45 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Hi!

LGTM.

Sergos


> On 12 Mar 2021, at 08:27, Sergey Kaplun <skaplun@tarantool.org> wrote:
> 
> This patch disables 241-standalone.t from the lua-Harness test suite,
> because some flags in Tarantool and LuaJIT work differently, or they are
> not present at all in Tarantool. For example, -i, -b, -j.
> See tarantool/tarantool#5541.
> 
> Part of tarantool/tarantool#5844
> Part of tarantool/tarantool#4473
> ---
> .../{241-standalone.t => 241-standalone.t.disabled}               | 0
> 1 file changed, 0 insertions(+), 0 deletions(-)
> rename test/lua-Harness-tests/{241-standalone.t => 241-standalone.t.disabled} (100%)
> 
> diff --git a/test/lua-Harness-tests/241-standalone.t b/test/lua-Harness-tests/241-standalone.t.disabled
> similarity index 100%
> rename from test/lua-Harness-tests/241-standalone.t
> rename to test/lua-Harness-tests/241-standalone.t.disabled
> -- 
> 2.28.0
> 


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

* Re: [Tarantool-patches] [PATCH luajit 5/6] test: disable 411-luajit of lua-Harness suite
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 5/6] test: disable 411-luajit " Sergey Kaplun via Tarantool-patches
@ 2021-03-13 18:46   ` Sergey Ostanevich via Tarantool-patches
  2021-03-15 12:48   ` Igor Munkin via Tarantool-patches
  1 sibling, 0 replies; 19+ messages in thread
From: Sergey Ostanevich via Tarantool-patches @ 2021-03-13 18:46 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Hi!

LGTM.

Sergos


> On 12 Mar 2021, at 08:27, Sergey Kaplun <skaplun@tarantool.org> wrote:
> 
> This patch disables 411-luajit.t from the lua-Harness test suite,
> because Tarantool does not support -b and -j flags.
> See tarantool/tarantool#5541.
> 
> Part of tarantool/tarantool#5844
> Part of tarantool/tarantool#4473
> ---
> test/lua-Harness-tests/{411-luajit.t => 411-luajit.t.disabled} | 0
> 1 file changed, 0 insertions(+), 0 deletions(-)
> rename test/lua-Harness-tests/{411-luajit.t => 411-luajit.t.disabled} (100%)
> 
> diff --git a/test/lua-Harness-tests/411-luajit.t b/test/lua-Harness-tests/411-luajit.t.disabled
> similarity index 100%
> rename from test/lua-Harness-tests/411-luajit.t
> rename to test/lua-Harness-tests/411-luajit.t.disabled
> -- 
> 2.28.0
> 


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

* Re: [Tarantool-patches] [PATCH luajit 6/6] test: skip test for getenv in 309-os.t
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 6/6] test: skip test for getenv in 309-os.t Sergey Kaplun via Tarantool-patches
@ 2021-03-13 18:50   ` Sergey Ostanevich via Tarantool-patches
  2021-03-15 10:22     ` Igor Munkin via Tarantool-patches
  0 siblings, 1 reply; 19+ messages in thread
From: Sergey Ostanevich via Tarantool-patches @ 2021-03-13 18:50 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Hi!

Thanks for the patch!

Shall we consider an environment being set in cmake dedicated to the Tarantool’s
testing?

Regards,
Sergos


> On 12 Mar 2021, at 08:27, Sergey Kaplun <skaplun@tarantool.org> wrote:
> 
> Inside Tarantool's GiHub-CI there is not defined variable LOGNAME nor
                      t               ^^^ no 
> USERNAME. This leads to failed test inside CI, because a string is
                          test failure
> expected.
> 
> This test is skipped when this variable is `nil`.
> 
> Part of tarantool/tarantool#5844
> Part of tarantool/tarantool#4473
> ---
> test/lua-Harness-tests/309-os.t | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/test/lua-Harness-tests/309-os.t b/test/lua-Harness-tests/309-os.t
> index f94db00..6b3ea4d 100755
> --- a/test/lua-Harness-tests/309-os.t
> +++ b/test/lua-Harness-tests/309-os.t
> @@ -170,7 +170,11 @@ do -- getenv
>     is(os.getenv('__IMPROBABLE__'), nil, "function getenv")
> 
>     local user = os.getenv('LOGNAME') or os.getenv('USERNAME')
> -    type_ok(user, 'string', "function getenv")
> +    if not user then
> +        skip("no LOGNAME and USERNAME")
> +    else
> +        type_ok(user, 'string', "function getenv")
> +    end
> end
> 
> do -- remove
> -- 
> 2.28.0
> 


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

* Re: [Tarantool-patches] [PATCH luajit 6/6] test: skip test for getenv in 309-os.t
  2021-03-13 18:50   ` Sergey Ostanevich via Tarantool-patches
@ 2021-03-15 10:22     ` Igor Munkin via Tarantool-patches
  0 siblings, 0 replies; 19+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-03-15 10:22 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Sergey,

On 13.03.21, Sergey Ostanevich wrote:
> Hi!
> 
> Thanks for the patch!
> 
> Shall we consider an environment being set in cmake dedicated to the Tarantool’s
> testing?

Totally agree with Sergos: this patch is excess (we even lose one test
case from the suite) and the issue can be resolved within Tarantool
build system (either cmake/luajit.cmake or test/CMakeLists.txt).

> 
> Regards,
> Sergos
> 
> 

<snipped>

> 

-- 
Best regards,
IM

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

* Re: [Tarantool-patches] [PATCH luajit 3/6] test: disable 305-utf8 of lua-Harness suite
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 3/6] test: disable 305-utf8 of lua-Harness suite Sergey Kaplun via Tarantool-patches
  2021-03-13 18:45   ` Sergey Ostanevich via Tarantool-patches
@ 2021-03-15 12:45   ` Igor Munkin via Tarantool-patches
  1 sibling, 0 replies; 19+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-03-15 12:45 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Sergey,

Thanks for the patch, but it is excess. The issue does not relates to
utf8.* functions per se (the are none of them provided by LuaJIT), but
rather the way UTF-8 support is checked in the test: if there is "falsy"
value stored in <utf8> global, then test simply checks that UTF-8
support is not expected considering to the loaded profile. Hence, simply
make <utf8> nil in test/luajit-init-test.lua (you can also "unload" it
from package.loaded, but this is not obliged, since utf8 is not
required in the test) and leave the test itself unmasked.

On 12.03.21, Sergey Kaplun wrote:
> This patch disables 305-utf8.t from the lua-Harness test suite, because
> the built-in utf8 module in Tarantool does not work as expected in the
> test.
> 
> Partially the problem mentioned in tarantool/tarantool#5241.
> 
> Part of tarantool/tarantool#5844
> Part of tarantool/tarantool#4473
> ---
>  test/lua-Harness-tests/{305-utf8.t => 305-utf8.t.disabled} | 0
>  1 file changed, 0 insertions(+), 0 deletions(-)
>  rename test/lua-Harness-tests/{305-utf8.t => 305-utf8.t.disabled} (100%)
> 
> diff --git a/test/lua-Harness-tests/305-utf8.t b/test/lua-Harness-tests/305-utf8.t.disabled
> similarity index 100%
> rename from test/lua-Harness-tests/305-utf8.t
> rename to test/lua-Harness-tests/305-utf8.t.disabled
> -- 
> 2.28.0
> 

-- 
Best regards,
IM

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

* Re: [Tarantool-patches] [PATCH luajit 4/6] test: disable 241-standalone of lua-Harness suite
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 4/6] test: disable 241-standalone " Sergey Kaplun via Tarantool-patches
  2021-03-13 18:45   ` Sergey Ostanevich via Tarantool-patches
@ 2021-03-15 12:47   ` Igor Munkin via Tarantool-patches
  1 sibling, 0 replies; 19+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-03-15 12:47 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Sergey,

Thanks for the patch, LGTM! Feel free to squash it with the next one,
since they are related to the one issue.

On 12.03.21, Sergey Kaplun wrote:
> This patch disables 241-standalone.t from the lua-Harness test suite,
> because some flags in Tarantool and LuaJIT work differently, or they are
> not present at all in Tarantool. For example, -i, -b, -j.
> See tarantool/tarantool#5541.
> 
> Part of tarantool/tarantool#5844
> Part of tarantool/tarantool#4473
> ---
>  .../{241-standalone.t => 241-standalone.t.disabled}               | 0
>  1 file changed, 0 insertions(+), 0 deletions(-)
>  rename test/lua-Harness-tests/{241-standalone.t => 241-standalone.t.disabled} (100%)
> 
> diff --git a/test/lua-Harness-tests/241-standalone.t b/test/lua-Harness-tests/241-standalone.t.disabled
> similarity index 100%
> rename from test/lua-Harness-tests/241-standalone.t
> rename to test/lua-Harness-tests/241-standalone.t.disabled
> -- 
> 2.28.0
> 

-- 
Best regards,
IM

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

* Re: [Tarantool-patches] [PATCH luajit 5/6] test: disable 411-luajit of lua-Harness suite
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 5/6] test: disable 411-luajit " Sergey Kaplun via Tarantool-patches
  2021-03-13 18:46   ` Sergey Ostanevich via Tarantool-patches
@ 2021-03-15 12:48   ` Igor Munkin via Tarantool-patches
  1 sibling, 0 replies; 19+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-03-15 12:48 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Sergey,

Thanks for the patch, LGTM! Feel free to squash it with the previous
one, since they are related to the same issue.

On 12.03.21, Sergey Kaplun wrote:
> This patch disables 411-luajit.t from the lua-Harness test suite,
> because Tarantool does not support -b and -j flags.
> See tarantool/tarantool#5541.
> 
> Part of tarantool/tarantool#5844
> Part of tarantool/tarantool#4473
> ---
>  test/lua-Harness-tests/{411-luajit.t => 411-luajit.t.disabled} | 0
>  1 file changed, 0 insertions(+), 0 deletions(-)
>  rename test/lua-Harness-tests/{411-luajit.t => 411-luajit.t.disabled} (100%)
> 
> diff --git a/test/lua-Harness-tests/411-luajit.t b/test/lua-Harness-tests/411-luajit.t.disabled
> similarity index 100%
> rename from test/lua-Harness-tests/411-luajit.t
> rename to test/lua-Harness-tests/411-luajit.t.disabled
> -- 
> 2.28.0
> 

-- 
Best regards,
IM

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

* Re: [Tarantool-patches] [PATCH luajit 1/6] test: add lua-Harness test suite
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 1/6] test: add " Sergey Kaplun via Tarantool-patches
@ 2021-03-15 13:05   ` Igor Munkin via Tarantool-patches
  0 siblings, 0 replies; 19+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-03-15 13:05 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Sergey,

This patch doesn't respect the process we were talking many times: the
first commit moves the suite intact, to be sure we are testing against
the right suite. Furthermore, please specify the exact path and revision
checked to our source tree like it is done here[1].

On 12.03.21, Sergey Kaplun wrote:
> This patch adds lua-Harness test suite:
> https://fperrad.frama.io/lua-Harness/
> 
> For lua binary name detection the new function `get_lua_binary_name()`
> is introduced. It is necessary because LUAJIT_TEST_COMMAND
> always extends an amount of line argument by two and a new universal
> way to detect program name is required.
> 
> Some tests may fail after this commit. They will be disabled
> or adapted in the next patches.
> 
> Part of tarantool/tarantool#5844
> Part of tarantool/tarantool#4473
> ---
> Author: Mergen Imeev <imeevma@gmail.com>
> 

<snipped>

> -- 
> 2.28.0
> 

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

-- 
Best regards,
IM

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

* Re: [Tarantool-patches] [PATCH luajit 2/6] test: adjust lua-Harness test suite for Tarantool
  2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 2/6] test: adjust lua-Harness test suite for Tarantool Sergey Kaplun via Tarantool-patches
  2021-03-13 18:41   ` Sergey Ostanevich via Tarantool-patches
@ 2021-03-15 13:22   ` Igor Munkin via Tarantool-patches
  1 sibling, 0 replies; 19+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2021-03-15 13:22 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Sergey,

Thanks for the patch, though it's almost excess...

On 12.03.21, Sergey Kaplun wrote:
> This patch makes it possible to run lua-Harness test suite using
> Tarantool.
> 
> Tarantool has its own loaded tap built in so need to change name to
> another one.

You can simply remove Tarantool TAP module from package.loaded in
test/luajit-test-init.lua (and move it out of the Debug condition
preliminary). See the incremental patches for both LuaJIT and Tarantool
repos at the end.

> 
> 203-lexico.t and 301-basic.t is adjusted to valid working with
> out-of-source build in Tarantool CI.

Your solution works, but it's too specific for our case. Consider the
following: one need to run lua-Harness suite outside from its source
tree. He faces the same issue, so I believe it's better to tweak the
test the next way (the patch is incremental for your branch).

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

diff --git a/test/lua-Harness-tests/203-lexico.t b/test/lua-Harness-tests/203-lexico.t
index be67a440..8ac140b2 100755
--- a/test/lua-Harness-tests/203-lexico.t
+++ b/test/lua-Harness-tests/203-lexico.t
@@ -117,24 +117,26 @@ do
     like(msg, "^[^:]+:%d+: unfinished long comment .-near")
 end
 
--- Adapt tests 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') .. '/'
+-- XXX: If this test is run out of the tests source tree, the
+-- relative paths below become invalid. Hence, we need to prepend
+-- the directory from the script (i.e. test) name to the auxiliary
+-- files to be loaded and executed.
+local cwd = arg[0]:gsub('([^/]+)%.t$', '')
 
 if _VERSION >= 'Lua 5.2' or jit then
-    dofile(path_to_sources .. 'lexico52/lexico.t')
+    dofile(cwd .. 'lexico52/lexico.t')
 end
 
 if _VERSION >= 'Lua 5.3' or luajit21 then
-    dofile(path_to_sources .. 'lexico53/lexico.t')
+    dofile(cwd .. 'lexico53/lexico.t')
 end
 
 if _VERSION >= 'Lua 5.4' then
-    dofile(path_to_sources .. 'lexico54/lexico.t')
+    dofile(cwd .. 'lexico54/lexico.t')
 end
 
 if jit and pcall(require, 'ffi') then
-    dofile(path_to_sources .. 'lexicojit/lexico.t')
+    dofile(cwd .. 'lexicojit/lexico.t')
 end
 
 done_testing()
diff --git a/test/lua-Harness-tests/301-basic.t b/test/lua-Harness-tests/301-basic.t
index 0489c707..55b10ce7 100755
--- a/test/lua-Harness-tests/301-basic.t
+++ b/test/lua-Harness-tests/301-basic.t
@@ -843,10 +843,11 @@ do -- xpcall
 end
 
 if jit and pcall(require, 'ffi') then
-    -- 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(path_to_sources .. '/lexicojit/basic.t')
+    -- XXX: If this test is run out of the tests source tree, the
+    -- relative paths below become invalid. Hence, we need to
+    -- prepend the directory from the script (i.e. test) name to
+    -- the auxiliary files to be loaded and executed.
+    dofile(arg[0]:gsub('([^/]+)%.t$', '') .. 'lexicojit/basic.t')
 end
 
 done_testing()
diff --git a/test/lua-Harness-tests/CMakeLists.txt b/test/lua-Harness-tests/CMakeLists.txt
index e62f2d12..77ad9c21 100644
--- a/test/lua-Harness-tests/CMakeLists.txt
+++ b/test/lua-Harness-tests/CMakeLists.txt
@@ -42,9 +42,6 @@ add_custom_command(TARGET lua-Harness-tests
     # for more info.
     # So use less preferable way for tests.
     # See the root CMakeLists.txt for more info.
-    # XXX: Adapt to run test witht Tarantool on read-only
-    # file systems with dofile(CUR_SOURCE_DIR..filename).
-    CUR_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
     ${PROVE} ${CMAKE_CURRENT_SOURCE_DIR}
       --exec '${LUAJIT_TEST_COMMAND} -l profile_luajit21'
       --ext ${LUA_TEST_SUFFIX}

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

Tres bien, n'est-ce pas? You can also propose the patch to Francois in
lua-Harness repo[1].

> 
> Also creates additional list of files provided to prove via stdin.
> This is required to avoid tests hungs via Tarantool's binary.
> Partially this problem is descripted in tarantool/tarantool#5040.

I removed the related changes and rebased the branch on the current
master with resolved #5040 (considering #5040 fixes the issue for all
long-term branches) and CI[2] is green (except the known issues). See
the incremental patches for both LuaJIT and Tarantool repos below.

> 
> Part of tarantool/tarantool#5844
> Part of tarantool/tarantool#4473
> ---
> Author: Mergen Imeev <imeevma@gmail.com>
> 
>  .gitignore                                      |  1 +
>  test/lua-Harness-tests/090-tap.t                |  2 +-
>  test/lua-Harness-tests/091-profile.t            |  2 +-
>  test/lua-Harness-tests/101-boolean.t            |  2 +-
>  test/lua-Harness-tests/102-function.t           |  2 +-
>  test/lua-Harness-tests/103-nil.t                |  2 +-
>  test/lua-Harness-tests/104-number.t             |  2 +-
>  test/lua-Harness-tests/105-string.t             |  2 +-
>  test/lua-Harness-tests/106-table.t              |  2 +-
>  test/lua-Harness-tests/107-thread.t             |  2 +-
>  test/lua-Harness-tests/108-userdata.t           |  2 +-
>  test/lua-Harness-tests/200-examples.t           |  2 +-
>  test/lua-Harness-tests/201-assign.t             |  2 +-
>  test/lua-Harness-tests/202-expr.t               |  2 +-
>  test/lua-Harness-tests/203-lexico.t             | 14 +++++++++-----
>  test/lua-Harness-tests/204-grammar.t            |  2 +-
>  test/lua-Harness-tests/211-scope.t              |  2 +-
>  test/lua-Harness-tests/212-function.t           |  2 +-
>  test/lua-Harness-tests/213-closure.t            |  2 +-
>  test/lua-Harness-tests/214-coroutine.t          |  2 +-
>  test/lua-Harness-tests/221-table.t              |  2 +-
>  test/lua-Harness-tests/222-constructor.t        |  2 +-
>  test/lua-Harness-tests/223-iterator.t           |  2 +-
>  test/lua-Harness-tests/231-metatable.t          |  2 +-
>  test/lua-Harness-tests/232-object.t             |  2 +-
>  test/lua-Harness-tests/241-standalone.t         | 10 +++++-----
>  test/lua-Harness-tests/242-luac.t               |  2 +-
>  test/lua-Harness-tests/301-basic.t              |  7 +++++--
>  test/lua-Harness-tests/303-package.t            |  6 +++---
>  test/lua-Harness-tests/304-string.t             |  2 +-
>  test/lua-Harness-tests/305-utf8.t               |  2 +-
>  test/lua-Harness-tests/306-table.t              |  2 +-
>  test/lua-Harness-tests/307-math.t               |  2 +-
>  test/lua-Harness-tests/308-io.t                 |  2 +-
>  test/lua-Harness-tests/309-os.t                 |  2 +-
>  test/lua-Harness-tests/310-debug.t              |  2 +-
>  test/lua-Harness-tests/311-bit32.t              |  2 +-
>  test/lua-Harness-tests/314-regex.t              |  2 +-
>  test/lua-Harness-tests/320-stdin.t              |  2 +-
>  test/lua-Harness-tests/401-bitop.t              |  2 +-
>  test/lua-Harness-tests/402-ffi.t                |  2 +-
>  test/lua-Harness-tests/403-jit.t                |  2 +-
>  test/lua-Harness-tests/404-ext.t                |  2 +-
>  test/lua-Harness-tests/411-luajit.t             |  2 +-
>  test/lua-Harness-tests/CMakeLists.txt           | 17 +++++++++++++++--
>  .../{tap.lua => tap_harness.lua}                |  0
>  46 files changed, 77 insertions(+), 56 deletions(-)
>  rename test/lua-Harness-tests/{tap.lua => tap_harness.lua} (100%)
> 

<snipped>

> diff --git a/test/lua-Harness-tests/241-standalone.t b/test/lua-Harness-tests/241-standalone.t
> index c5237ee..33d5159 100755
> --- a/test/lua-Harness-tests/241-standalone.t
> +++ b/test/lua-Harness-tests/241-standalone.t

<snipped>

> @@ -228,14 +228,14 @@ end
>  like(f:read'*l', "^usage: ", "no file")
>  f:close()
>  
> -cmd = lua .. [[ -ltap -e "print(type(ok))"]]
> +cmd = lua .. [[ -ltap_harness -e "print(type(ok))"]]

Side note: "Unloading" hack works here, since nothing tap-specific is
used in this test: it checks only third party module loading and nothing
more. BTW, this test is masked in the following patch.

>  f = io.popen(cmd)
> -is(f:read'*l', 'function', "-ltap")
> +is(f:read'*l', 'function', "-ltap_harness")
>  f:close()
>  
> -cmd = lua .. [[ -l tap -e "print(type(ok))"]]
> +cmd = lua .. [[ -l tap_harness -e "print(type(ok))"]]
>  f = io.popen(cmd)
> -is(f:read'*l', 'function', "-l tap")
> +is(f:read'*l', 'function', "-l tap_harness")
>  f:close()
>  
>  cmd = lua .. [[ -l lpeg -e "print(1)" 2>&1]]

<snipped>

> -- 
> 2.28.0

The incremental patch for LuaJIT reverting the renaming:

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

diff --git a/.gitignore b/.gitignore
index 1fb81bc9..2103a30f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,4 +20,3 @@ compile_commands.json
 install_manifest.txt
 luajit-parse-memprof
 luajit.pc
-tests_list
diff --git a/test/lua-Harness-tests/090-tap.t b/test/lua-Harness-tests/090-tap.t
index 99932f2e..92f04d8e 100755
--- a/test/lua-Harness-tests/090-tap.t
+++ b/test/lua-Harness-tests/090-tap.t
@@ -22,7 +22,7 @@
 
 ]]
 
-require'tap_harness'
+require'tap'
 
 plan(3)
 ok( true, 'ok' )
diff --git a/test/lua-Harness-tests/091-profile.t b/test/lua-Harness-tests/091-profile.t
index ebc142da..db474384 100755
--- a/test/lua-Harness-tests/091-profile.t
+++ b/test/lua-Harness-tests/091-profile.t
@@ -22,7 +22,7 @@
 
 ]]
 
-require'tap_harness'
+require'tap'
 
 plan'no_plan'
 
diff --git a/test/lua-Harness-tests/101-boolean.t b/test/lua-Harness-tests/101-boolean.t
index 653509f0..0033eff0 100755
--- a/test/lua-Harness-tests/101-boolean.t
+++ b/test/lua-Harness-tests/101-boolean.t
@@ -22,7 +22,7 @@
 
 ]]
 
-require'tap_harness'
+require'tap'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/102-function.t b/test/lua-Harness-tests/102-function.t
index cb7e9d05..48ed814e 100755
--- a/test/lua-Harness-tests/102-function.t
+++ b/test/lua-Harness-tests/102-function.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap_harness'
+require'tap'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/103-nil.t b/test/lua-Harness-tests/103-nil.t
index a74c491f..561b1018 100755
--- a/test/lua-Harness-tests/103-nil.t
+++ b/test/lua-Harness-tests/103-nil.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap_harness'
+require'tap'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/104-number.t b/test/lua-Harness-tests/104-number.t
index 634d22a0..0d4d3fdb 100755
--- a/test/lua-Harness-tests/104-number.t
+++ b/test/lua-Harness-tests/104-number.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
diff --git a/test/lua-Harness-tests/105-string.t b/test/lua-Harness-tests/105-string.t
index f2ea067f..cd8c88bf 100755
--- a/test/lua-Harness-tests/105-string.t
+++ b/test/lua-Harness-tests/105-string.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
diff --git a/test/lua-Harness-tests/106-table.t b/test/lua-Harness-tests/106-table.t
index 4a66f694..0c0ba49b 100755
--- a/test/lua-Harness-tests/106-table.t
+++ b/test/lua-Harness-tests/106-table.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap_harness'
+require'tap'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/107-thread.t b/test/lua-Harness-tests/107-thread.t
index e67ef363..3d4af18d 100755
--- a/test/lua-Harness-tests/107-thread.t
+++ b/test/lua-Harness-tests/107-thread.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap_harness'
+require'tap'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/108-userdata.t b/test/lua-Harness-tests/108-userdata.t
index 687b1b81..b1e3641a 100755
--- a/test/lua-Harness-tests/108-userdata.t
+++ b/test/lua-Harness-tests/108-userdata.t
@@ -22,7 +22,7 @@
 
 --]]
 
-require'tap_harness'
+require'tap'
 local has_op53 = _VERSION >= 'Lua 5.3'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/200-examples.t b/test/lua-Harness-tests/200-examples.t
index cb06a80e..362aae3a 100755
--- a/test/lua-Harness-tests/200-examples.t
+++ b/test/lua-Harness-tests/200-examples.t
@@ -24,7 +24,7 @@ First tests in order to check infrastructure.
 
 --]]
 
-require'tap_harness'
+require'tap'
 
 plan(5)
 
diff --git a/test/lua-Harness-tests/201-assign.t b/test/lua-Harness-tests/201-assign.t
index f7ed4725..7d023d8e 100755
--- a/test/lua-Harness-tests/201-assign.t
+++ b/test/lua-Harness-tests/201-assign.t
@@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#3.3.3>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local has_env = _VERSION >= 'Lua 5.2'
 
 plan'no_plan'
diff --git a/test/lua-Harness-tests/202-expr.t b/test/lua-Harness-tests/202-expr.t
index f03d5ea3..25767507 100755
--- a/test/lua-Harness-tests/202-expr.t
+++ b/test/lua-Harness-tests/202-expr.t
@@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#3.4>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local nocvtn2s = profile.nocvtn2s
 local nocvts2n = profile.nocvts2n
diff --git a/test/lua-Harness-tests/203-lexico.t b/test/lua-Harness-tests/203-lexico.t
index 0a73f8cf..be67a440 100755
--- a/test/lua-Harness-tests/203-lexico.t
+++ b/test/lua-Harness-tests/203-lexico.t
@@ -31,7 +31,7 @@ L<https://www.lua.org/manual/5.4/manual.html#3.1>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local loadstring = loadstring or load
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 
diff --git a/test/lua-Harness-tests/204-grammar.t b/test/lua-Harness-tests/204-grammar.t
index 03580f48..d9ae3a6f 100755
--- a/test/lua-Harness-tests/204-grammar.t
+++ b/test/lua-Harness-tests/204-grammar.t
@@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#9>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local has_goto = _VERSION >= 'Lua 5.2' or jit
 local has_attr = _VERSION >= 'Lua 5.4'
diff --git a/test/lua-Harness-tests/211-scope.t b/test/lua-Harness-tests/211-scope.t
index 8e26a6fe..64eed521 100755
--- a/test/lua-Harness-tests/211-scope.t
+++ b/test/lua-Harness-tests/211-scope.t
@@ -30,7 +30,7 @@ See section "Local Variables and Blocks" in "Programming in Lua".
 
 --]]
 
-require'tap_harness'
+require'tap'
 
 plan(10)
 
diff --git a/test/lua-Harness-tests/212-function.t b/test/lua-Harness-tests/212-function.t
index 405035e2..28510537 100755
--- a/test/lua-Harness-tests/212-function.t
+++ b/test/lua-Harness-tests/212-function.t
@@ -30,7 +30,7 @@ See section "Functions" in "Programming in Lua".
 
 --]]
 
-require'tap_harness'
+require'tap'
 local loadstring = loadstring or load
 
 plan(68)
diff --git a/test/lua-Harness-tests/213-closure.t b/test/lua-Harness-tests/213-closure.t
index 16a8a215..fc3bd29c 100755
--- a/test/lua-Harness-tests/213-closure.t
+++ b/test/lua-Harness-tests/213-closure.t
@@ -24,7 +24,7 @@ See section "Closures" in "Programming in Lua".
 
 --]]
 
-require'tap_harness'
+require'tap'
 
 plan(15)
 
diff --git a/test/lua-Harness-tests/214-coroutine.t b/test/lua-Harness-tests/214-coroutine.t
index 1ca1cb57..92929e1b 100755
--- a/test/lua-Harness-tests/214-coroutine.t
+++ b/test/lua-Harness-tests/214-coroutine.t
@@ -30,7 +30,7 @@ See section "Coroutines" in "Programming in Lua".
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 local has_coroutine52 = _VERSION >= 'Lua 5.2' or jit
diff --git a/test/lua-Harness-tests/221-table.t b/test/lua-Harness-tests/221-table.t
index 07ac9521..c064a339 100755
--- a/test/lua-Harness-tests/221-table.t
+++ b/test/lua-Harness-tests/221-table.t
@@ -24,7 +24,7 @@ See section "Tables" in "Programming in Lua".
 
 --]]
 
-require'tap_harness'
+require'tap'
 
 plan(25)
 
diff --git a/test/lua-Harness-tests/222-constructor.t b/test/lua-Harness-tests/222-constructor.t
index 28037bfc..a01be2ec 100755
--- a/test/lua-Harness-tests/222-constructor.t
+++ b/test/lua-Harness-tests/222-constructor.t
@@ -30,7 +30,7 @@ See section "Table Constructors" in "Programming in Lua".
 
 --]]
 
-require'tap_harness'
+require'tap'
 
 plan(16)
 
diff --git a/test/lua-Harness-tests/223-iterator.t b/test/lua-Harness-tests/223-iterator.t
index 073f3cdc..777ad73d 100755
--- a/test/lua-Harness-tests/223-iterator.t
+++ b/test/lua-Harness-tests/223-iterator.t
@@ -25,7 +25,7 @@ section "Coroutines as Iterators" in "Programming in Lua".
 
 --]]
 
-require'tap_harness'
+require'tap'
 
 plan(8)
 
diff --git a/test/lua-Harness-tests/231-metatable.t b/test/lua-Harness-tests/231-metatable.t
index b94f608a..a2c6499b 100755
--- a/test/lua-Harness-tests/231-metatable.t
+++ b/test/lua-Harness-tests/231-metatable.t
@@ -30,7 +30,7 @@ See section "Metatables and Metamethods" in "Programming in Lua".
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local has_metamethod52 = _VERSION >= 'Lua 5.2' or profile.luajit_compat52
 local has_metamethod_ipairs = _VERSION == 'Lua 5.2' or profile.compat52 or profile.luajit_compat52
diff --git a/test/lua-Harness-tests/232-object.t b/test/lua-Harness-tests/232-object.t
index 0d222324..0d875729 100755
--- a/test/lua-Harness-tests/232-object.t
+++ b/test/lua-Harness-tests/232-object.t
@@ -24,7 +24,7 @@ See section "Object-Oriented Programming" in "Programming in Lua".
 
 --]]
 
-require'tap_harness'
+require'tap'
 
 plan(18)
 
diff --git a/test/lua-Harness-tests/241-standalone.t.disabled b/test/lua-Harness-tests/241-standalone.t.disabled
index 33d5159c..c5237eed 100755
--- a/test/lua-Harness-tests/241-standalone.t.disabled
+++ b/test/lua-Harness-tests/241-standalone.t.disabled
@@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#7>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local has_bytecode = not ujit and not ravi
 local has_error52 = _VERSION >= 'Lua 5.2'
 local has_error53 = _VERSION >= 'Lua 5.3'
@@ -228,14 +228,14 @@ end
 like(f:read'*l', "^usage: ", "no file")
 f:close()
 
-cmd = lua .. [[ -ltap_harness -e "print(type(ok))"]]
+cmd = lua .. [[ -ltap -e "print(type(ok))"]]
 f = io.popen(cmd)
-is(f:read'*l', 'function', "-ltap_harness")
+is(f:read'*l', 'function', "-ltap")
 f:close()
 
-cmd = lua .. [[ -l tap_harness -e "print(type(ok))"]]
+cmd = lua .. [[ -l tap -e "print(type(ok))"]]
 f = io.popen(cmd)
-is(f:read'*l', 'function', "-l tap_harness")
+is(f:read'*l', 'function', "-l tap")
 f:close()
 
 cmd = lua .. [[ -l lpeg -e "print(1)" 2>&1]]
diff --git a/test/lua-Harness-tests/242-luac.t b/test/lua-Harness-tests/242-luac.t
index 9a3a3c3b..a95a334a 100755
--- a/test/lua-Harness-tests/242-luac.t
+++ b/test/lua-Harness-tests/242-luac.t
@@ -28,7 +28,7 @@ L<https://www.lua.org/manual/5.4/manual.html#7>
 
 --]]
 
-require'tap_harness'
+require'tap'
 
 if jit then
     skip_all("LuaJIT")
diff --git a/test/lua-Harness-tests/301-basic.t b/test/lua-Harness-tests/301-basic.t
index 13472cd2..0489c707 100755
--- a/test/lua-Harness-tests/301-basic.t
+++ b/test/lua-Harness-tests/301-basic.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.1>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local has_error53 = _VERSION >= 'Lua 5.3'
 local has_gcinfo = _VERSION == 'Lua 5.1'
diff --git a/test/lua-Harness-tests/303-package.t b/test/lua-Harness-tests/303-package.t
index 996ce226..7e5216d8 100755
--- a/test/lua-Harness-tests/303-package.t
+++ b/test/lua-Harness-tests/303-package.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.3>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 local has_loaders = _VERSION == 'Lua 5.1'
@@ -130,9 +130,9 @@ end
 
 -- searchpath
 if has_searcherpath then
-    local p = package.searchpath('tap_harness', package.path)
+    local p = package.searchpath('tap', package.path)
     type_ok(p, 'string', "searchpath")
-    p = package.searchpath('tap_harness', 'bad path')
+    p = package.searchpath('tap', 'bad path')
     is(p, nil)
 else
     is(package.searchpath, nil, "no package.searchpath")
diff --git a/test/lua-Harness-tests/304-string.t b/test/lua-Harness-tests/304-string.t
index 293fd8e5..991600a7 100755
--- a/test/lua-Harness-tests/304-string.t
+++ b/test/lua-Harness-tests/304-string.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.4>
 
 ]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 local has_dump53 = _VERSION >= 'Lua 5.3' or jit
diff --git a/test/lua-Harness-tests/305-utf8.t.disabled b/test/lua-Harness-tests/305-utf8.t.disabled
index 59a2e6bd..4304b6c5 100755
--- a/test/lua-Harness-tests/305-utf8.t.disabled
+++ b/test/lua-Harness-tests/305-utf8.t.disabled
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.5>
 
 --]]
 
-require'tap_harness'
+require 'tap'
 
 local profile = require'profile'
 local has_utf8 = _VERSION >= 'Lua 5.3' or (jit and jit.version:match'moonjit') or profile.utf8
diff --git a/test/lua-Harness-tests/306-table.t b/test/lua-Harness-tests/306-table.t
index 6e764922..98366556 100755
--- a/test/lua-Harness-tests/306-table.t
+++ b/test/lua-Harness-tests/306-table.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.6>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 local has_foreach = _VERSION == 'Lua 5.1'
diff --git a/test/lua-Harness-tests/307-math.t b/test/lua-Harness-tests/307-math.t
index 762567fc..8b51ed16 100755
--- a/test/lua-Harness-tests/307-math.t
+++ b/test/lua-Harness-tests/307-math.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.7>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local has_integer = _VERSION >= 'Lua 5.3' or (jit and jit.version:match'moonjit') or profile.integer
 local has_mathx = _VERSION < 'Lua 5.3' or profile.compat52 or profile.compat53 or profile.has_mathx
diff --git a/test/lua-Harness-tests/308-io.t b/test/lua-Harness-tests/308-io.t
index 1945ce3e..35d39c02 100755
--- a/test/lua-Harness-tests/308-io.t
+++ b/test/lua-Harness-tests/308-io.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.8>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
 local has_write51 = _VERSION == 'Lua 5.1' and (not profile.luajit_compat52 or ujit)
diff --git a/test/lua-Harness-tests/309-os.t b/test/lua-Harness-tests/309-os.t
index 6b3ea4d1..87b41ca5 100755
--- a/test/lua-Harness-tests/309-os.t
+++ b/test/lua-Harness-tests/309-os.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.9>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 local luajit20 = jit and (jit.version_num < 20100 and not jit.version:match'^RaptorJIT')
 local has_execute51 = _VERSION == 'Lua 5.1' and (not profile.luajit_compat52 or ujit)
diff --git a/test/lua-Harness-tests/310-debug.t b/test/lua-Harness-tests/310-debug.t
index 63194ac3..f78af03f 100755
--- a/test/lua-Harness-tests/310-debug.t
+++ b/test/lua-Harness-tests/310-debug.t
@@ -30,7 +30,7 @@ L<https://www.lua.org/manual/5.4/manual.html#6.10>
 
 ]]
 
-require'tap_harness'
+require 'tap'
 local profile = require'profile'
 local has_getfenv = _VERSION == 'Lua 5.1'
 local has_gethook54 = _VERSION >= 'Lua 5.4'
diff --git a/test/lua-Harness-tests/311-bit32.t b/test/lua-Harness-tests/311-bit32.t
index a314f479..7023906e 100755
--- a/test/lua-Harness-tests/311-bit32.t
+++ b/test/lua-Harness-tests/311-bit32.t
@@ -29,7 +29,7 @@ L<https://www.lua.org/manual/5.2/manual.html#6.7>
 
 --]]
 
-require'tap_harness'
+require 'tap'
 local profile = require'profile'
 local has_bit32 = _VERSION == 'Lua 5.2' or profile.compat52 or profile.has_bit32
 
diff --git a/test/lua-Harness-tests/314-regex.t b/test/lua-Harness-tests/314-regex.t
index ac7ad80e..ad4554cd 100755
--- a/test/lua-Harness-tests/314-regex.t
+++ b/test/lua-Harness-tests/314-regex.t
@@ -49,7 +49,7 @@ Description of the test.
 
 --]]
 
-require'tap_harness'
+require'tap'
 local loadstring = loadstring or load
 
 plan(162)
diff --git a/test/lua-Harness-tests/320-stdin.t b/test/lua-Harness-tests/320-stdin.t
index a0eabcb1..4828285d 100755
--- a/test/lua-Harness-tests/320-stdin.t
+++ b/test/lua-Harness-tests/320-stdin.t
@@ -24,7 +24,7 @@ Tests Lua Basic & IO Libraries with stdin
 
 --]]
 
-require'tap_harness'
+require'tap'
 
 local lua = get_lua_binary_name()
 
diff --git a/test/lua-Harness-tests/401-bitop.t b/test/lua-Harness-tests/401-bitop.t
index d1225bd0..f95aebf3 100755
--- a/test/lua-Harness-tests/401-bitop.t
+++ b/test/lua-Harness-tests/401-bitop.t
@@ -24,7 +24,7 @@ See L<http://bitop.luajit.org/>.
 
 --]]
 
-require'tap_harness'
+require 'tap'
 
 if not jit then
     skip_all("only with LuaJIT")
diff --git a/test/lua-Harness-tests/402-ffi.t b/test/lua-Harness-tests/402-ffi.t
index 2423b2ea..a2e32a54 100755
--- a/test/lua-Harness-tests/402-ffi.t
+++ b/test/lua-Harness-tests/402-ffi.t
@@ -24,7 +24,7 @@ See L<http://luajit.org/ext_ffi.html>.
 
 --]]
 
-require'tap_harness'
+require 'tap'
 
 if not jit then
     skip_all("only with LuaJIT")
diff --git a/test/lua-Harness-tests/403-jit.t b/test/lua-Harness-tests/403-jit.t
index 6c0870a2..0073c90d 100755
--- a/test/lua-Harness-tests/403-jit.t
+++ b/test/lua-Harness-tests/403-jit.t
@@ -24,7 +24,7 @@ See L<http://luajit.org/ext_jit.html>.
 
 --]]
 
-require'tap_harness'
+require 'tap'
 local profile = require'profile'
 
 if not jit then
diff --git a/test/lua-Harness-tests/404-ext.t b/test/lua-Harness-tests/404-ext.t
index 906ed512..22a52c72 100755
--- a/test/lua-Harness-tests/404-ext.t
+++ b/test/lua-Harness-tests/404-ext.t
@@ -24,7 +24,7 @@ See L<http://luajit.org/ext_jit.html>.
 
 --]]
 
-require'tap_harness'
+require 'tap'
 local profile = require'profile'
 
 local luajit21 = jit and (jit.version_num >= 20100 or jit.version:match'^RaptorJIT')
diff --git a/test/lua-Harness-tests/411-luajit.t.disabled b/test/lua-Harness-tests/411-luajit.t.disabled
index b8cb5475..feb752eb 100755
--- a/test/lua-Harness-tests/411-luajit.t.disabled
+++ b/test/lua-Harness-tests/411-luajit.t.disabled
@@ -24,7 +24,7 @@ See L<http://luajit.org/running.html>
 
 --]]
 
-require'tap_harness'
+require'tap'
 local profile = require'profile'
 
 if not jit or ujit then
diff --git a/test/lua-Harness-tests/CMakeLists.txt b/test/lua-Harness-tests/CMakeLists.txt
index e28cadd9..e62f2d12 100644
--- a/test/lua-Harness-tests/CMakeLists.txt
+++ b/test/lua-Harness-tests/CMakeLists.txt
@@ -10,7 +10,10 @@ if(NOT PROVE)
   return()
 endif()
 
+set(LUA_TEST_SUFFIX .t)
 set(LUA_TEST_FLAGS --failures --shuffle)
+file(GLOB TEST_DEPS ${CMAKE_CURRENT_SOURCE_DIR}/*${LUA_TEST_SUFFIX})
+
 if(CMAKE_VERBOSE_MAKEFILE)
   list(APPEND LUA_TEST_FLAGS --verbose)
 endif()
@@ -26,18 +29,7 @@ string(CONCAT LUA_CPATH
   "${LUAJIT_SOURCE_DIR}/?${CMAKE_SHARED_LIBRARY_SUFFIX}\;"
 )
 
-# FIXME: Until https://github.com/tarantool/tarantool/issues/5040
-# is resolved, Tarantool enters interactive mode if prove input
-# is not stdin. As a result test hungs and not run at all.
-# This part should be dropped, and argument to prove is passed
-# as directory.
-file(GLOB TESTS_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.t)
-string(REPLACE ";" "\n" TESTS_LIST "${TESTS_LIST}")
-set(LIST_FILE ${CMAKE_CURRENT_BINARY_DIR}/tests_list)
-file(WRITE ${LIST_FILE} ${TESTS_LIST})
-
-add_custom_target(lua-Harness-tests DEPENDS ${LUAJIT_TEST_BINARY} ${LIST_FILE})
-
+add_custom_target(lua-Harness-tests DEPENDS ${LUAJIT_TEST_BINARY} ${TEST_DEPS})
 add_custom_command(TARGET lua-Harness-tests
   COMMENT "Running lua-Harness tests"
   COMMAND
@@ -53,8 +45,9 @@ add_custom_command(TARGET lua-Harness-tests
     # XXX: Adapt to run test witht Tarantool on read-only
     # file systems with dofile(CUR_SOURCE_DIR..filename).
     CUR_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
-    ${PROVE} - < ${LIST_FILE}
+    ${PROVE} ${CMAKE_CURRENT_SOURCE_DIR}
       --exec '${LUAJIT_TEST_COMMAND} -l profile_luajit21'
+      --ext ${LUA_TEST_SUFFIX}
       ${LUA_TEST_FLAGS}
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
 )
diff --git a/test/lua-Harness-tests/tap_harness.lua b/test/lua-Harness-tests/tap.lua
similarity index 100%
rename from test/lua-Harness-tests/tap_harness.lua
rename to test/lua-Harness-tests/tap.lua

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

The incremental patch for Tarantool "unloading" its tap:

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

diff --git a/cmake/luajit.cmake b/cmake/luajit.cmake
index 1c05e085b..e00817a8f 100644
--- a/cmake/luajit.cmake
+++ b/cmake/luajit.cmake
@@ -40,16 +40,18 @@ set(LUAJIT_TEST_BINARY $<TARGET_FILE:tarantool> CACHE STRING
 set(LUAJIT_USE_TEST OFF CACHE BOOL
     "Generate <test> target" FORCE)
 
-# Enable internal LuaJIT assertions for Tarantool Debug build.
 # XXX: There is <strict> module enabled by default in Tarantool
 # built in Debug, so we need to tweak LuaJIT testing environment.
+# TODO: Drop a few words regarding TAP.
+set(LUAJIT_TEST_INIT "${PROJECT_SOURCE_DIR}/test/luajit-test-init.lua"
+    CACHE STRING "Lua code need to be run before tests are started" FORCE)
+
+# Enable internal LuaJIT assertions for Tarantool Debug build.
 if(CMAKE_BUILD_TYPE STREQUAL "Debug")
     set(LUAJIT_USE_APICHECK ON CACHE BOOL
         "Assertions for the Lua/C API" FORCE)
     set(LUAJIT_USE_ASSERT ON CACHE BOOL
         "Assertions for the whole LuaJIT VM" FORCE)
-    set(LUAJIT_TEST_INIT "${PROJECT_SOURCE_DIR}/test/luajit-test-init.lua"
-        CACHE STRING "Lua code need to be run before tests are started" FORCE)
 endif()
 
 # Valgrind can be used only with the system allocator. For more
diff --git a/test/luajit-test-init.lua b/test/luajit-test-init.lua
index a529e9d8a..199d34f3f 100644
--- a/test/luajit-test-init.lua
+++ b/test/luajit-test-init.lua
@@ -1,6 +1,9 @@
 -- Disable strict for Tarantool.
 require("strict").off()
 
+-- TODO: Drop a few words regarding this.
+package.loaded.tap = nil
+
 -- Add `strict.off()` to `progname` command, that runs child tests
 -- in some LuaJIT test suites to disable strict there too.
 -- Quotes type is important.

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

> 

[1]: https://framagit.org/fperrad/lua-Harness
[2]: https://github.com/tarantool/tarantool/commit/b4f2911

-- 
Best regards,
IM

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

end of thread, other threads:[~2021-03-15 13:22 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-12  5:27 [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite Sergey Kaplun via Tarantool-patches
2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 1/6] test: add " Sergey Kaplun via Tarantool-patches
2021-03-15 13:05   ` Igor Munkin via Tarantool-patches
2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 2/6] test: adjust lua-Harness test suite for Tarantool Sergey Kaplun via Tarantool-patches
2021-03-13 18:41   ` Sergey Ostanevich via Tarantool-patches
2021-03-15 13:22   ` Igor Munkin via Tarantool-patches
2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 3/6] test: disable 305-utf8 of lua-Harness suite Sergey Kaplun via Tarantool-patches
2021-03-13 18:45   ` Sergey Ostanevich via Tarantool-patches
2021-03-15 12:45   ` Igor Munkin via Tarantool-patches
2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 4/6] test: disable 241-standalone " Sergey Kaplun via Tarantool-patches
2021-03-13 18:45   ` Sergey Ostanevich via Tarantool-patches
2021-03-15 12:47   ` Igor Munkin via Tarantool-patches
2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 5/6] test: disable 411-luajit " Sergey Kaplun via Tarantool-patches
2021-03-13 18:46   ` Sergey Ostanevich via Tarantool-patches
2021-03-15 12:48   ` Igor Munkin via Tarantool-patches
2021-03-12  5:27 ` [Tarantool-patches] [PATCH luajit 6/6] test: skip test for getenv in 309-os.t Sergey Kaplun via Tarantool-patches
2021-03-13 18:50   ` Sergey Ostanevich via Tarantool-patches
2021-03-15 10:22     ` Igor Munkin via Tarantool-patches
2021-03-13 18:22 ` [Tarantool-patches] [PATCH luajit 0/6] Adapt lua-Harness test suite 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