Skip to content

Commit 8e6716c

Browse files
committed
tests/lapi: add bitop tests
The patch adds initial infrastructure for Lua API tests and changes existed infrastructure for running these tests. The patch reqires commit "cmake: allow to set a Lua library outside" in `luzer` project. The patch adds a fuzzing tests for Lua bitwise operations. In LuaJIT, these operations are implemented as a Lua functions in BitOp module [1], that later became a part of LuaJIT. In PUC Rio Lua, bitwise operations were added since version 5.2 [2] in "bit32" library. In Lua 5.3 the bit32 library has been deprecated and its operations were replaced by bitwise operations. 1. http://bitop.luajit.org/ 2. https://www.lua.org/manual/5.2/manual.html#6.7 3. https://www.lua.org/manual/5.3/manual.html#3.4.2 4. https://www.lua.org/manual/5.3/manual.html#8.2 5. ligurio/luzer@4ce52a6
1 parent 49a1ccc commit 8e6716c

18 files changed

+568
-3
lines changed

cmake/BuildLua.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ macro(build_lua LUA_VERSION)
55
set(LUA_PATCH_PATH ${PROJECT_SOURCE_DIR}/patches/puc-rio-lua.patch)
66

77
set(CFLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer")
8+
set(CFLAGS "${CMAKE_C_FLAGS} -DLUA_USE_DLOPEN")
89
if (ENABLE_LUA_ASSERT)
910
set(CFLAGS "${CFLAGS} -DLUAI_ASSERT")
1011
endif (ENABLE_LUA_ASSERT)
@@ -56,6 +57,9 @@ macro(build_lua LUA_VERSION)
5657
set(LDFLAGS "${LDFLAGS} -fprofile-instr-generate -fprofile-arcs -fcoverage-mapping -ftest-coverage")
5758
endif (ENABLE_COV)
5859

60+
# "relocation R_X86_64_PC32 against symbol `lua_isnumber' can
61+
# not be used when making a shared object; recompile with -fPIC".
62+
set(CFLAGS "${CFLAGS} -fPIC")
5963

6064
include(ExternalProject)
6165

cmake/BuildLuaJIT.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ macro(build_luajit LJ_VERSION)
8080
set(LDFLAGS "${LDFLAGS} -fprofile-instr-generate -fprofile-arcs -fcoverage-mapping -ftest-coverage")
8181
endif (ENABLE_COV)
8282

83+
# "relocation R_X86_64_PC32 against symbol `lua_isnumber' can
84+
# not be used when making a shared object; recompile with -fPIC".
85+
set(CFLAGS "${CFLAGS} -fPIC")
8386

8487
include(ExternalProject)
8588

cmake/BuildLuzer.cmake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ macro(build_luzer)
99

1010
include(ExternalProject)
1111

12+
get_target_property(LUA_LIBRARIES_LOCATION ${LUA_LIBRARIES} LOCATION)
13+
1214
ExternalProject_Add(bundled-luzer
1315
GIT_REPOSITORY https://github.com/ligurio/luzer
1416
GIT_TAG 649289aa945b7d6c1e2c29edccc83fd3fbe70568
@@ -23,6 +25,10 @@ macro(build_luzer)
2325
-G ${CMAKE_GENERATOR} ${BENCHMARK_CMAKE_FLAGS}
2426
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
2527
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
28+
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
29+
30+
-DLUA_INCLUDE_DIR=${LUA_INCLUDE_DIR}
31+
-DLUA_LIBRARIES=${LUA_LIBRARIES_LOCATION}
2632
BUILD_COMMAND cd <BINARY_DIR> && ${CMAKE_MAKE_PROGRAM}
2733
INSTALL_COMMAND ""
2834
CMAKE_GENERATOR ${CMAKE_GENERATOR}
@@ -34,6 +40,7 @@ macro(build_luzer)
3440
set_target_properties(luzer-library PROPERTIES
3541
IMPORTED_LOCATION "${LUZER_LIBRARIES}")
3642
add_dependencies(luzer-library bundled-luzer)
43+
add_dependencies(bundled-luzer bundled-liblua)
3744

3845
set(LUZER_LUA_PATH ${LUZER_DIR}/source/?/init.lua)
3946
set(LUZER_LUA_PATH ${LUZER_LUA_PATH} PARENT_SCOPE)

tests/CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
add_subdirectory(capi)
2-
if (ENABLE_BONUS_TESTS)
3-
add_subdirectory(lapi)
4-
endif()
2+
add_subdirectory(lapi)

tests/lapi/CMakeLists.txt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
include(BuildLuzer)
2+
build_luzer()
3+
include(MakeLuaPath)
4+
5+
if(NOT LUA_EXECUTABLE)
6+
message(FATAL_ERROR "${LUA_EXECUTABLE} is not found.")
7+
endif()
8+
9+
make_lua_path(LUA_CPATH
10+
PATHS
11+
${LUZER_LUA_CPATH}
12+
)
13+
14+
make_lua_path(LUA_PATH
15+
PATHS
16+
${LUZER_LUA_PATH}
17+
${CMAKE_CURRENT_SOURCE_DIR}/?.lua
18+
)
19+
20+
function(create_test)
21+
cmake_parse_arguments(
22+
FUZZ
23+
""
24+
"FILENAME"
25+
""
26+
${ARGN}
27+
)
28+
get_filename_component(test_name ${FUZZ_FILENAME} NAME_WE)
29+
string(REPLACE "_test" "" test_prefix ${test_name})
30+
set(dict_path ${PROJECT_SOURCE_DIR}/corpus/${test_prefix}.dict)
31+
set(corpus_path ${PROJECT_SOURCE_DIR}/corpus/${test_prefix})
32+
add_test(NAME ${test_name}
33+
COMMAND ${LUA_EXECUTABLE} -e "${LUA_OPT}" "${FUZZ_FILENAME}"
34+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
35+
)
36+
set_tests_properties(${test_name} PROPERTIES
37+
LABELS "lapi"
38+
ENVIRONMENT "LUA_PATH=${LUA_PATH};LUA_CPATH=${LUA_CPATH};ASAN_OPTIONS=detect_odr_violation=0"
39+
DEPENDS ${LUA_EXECUTABLE} ${LUZER_LIBRARY}
40+
)
41+
string(REPLACE "_test" "" test_prefix ${test_name})
42+
endfunction()
43+
44+
message(STATUS "Add Lua API test suite")
45+
file(GLOB tests LIST_DIRECTORIES false ${CMAKE_CURRENT_SOURCE_DIR} *_test.lua)
46+
foreach(filename ${tests})
47+
get_filename_component(test_name ${filename} NAME_WE)
48+
create_test(FILENAME ${filename})
49+
endforeach()

tests/lapi/bitop_arshift_test.lua

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
Synopsis: bit32.arshift (x, disp)
6+
]]
7+
8+
local luzer = require("luzer")
9+
local test_lib = require("lib")
10+
11+
if test_lib.version() ~= "LuaJIT" then
12+
os.exit(0)
13+
end
14+
15+
local bitop = require("bit")
16+
local arshift = bitop.arshift
17+
18+
local function TestOneInput(buf)
19+
local fdp = luzer.FuzzedDataProvider(buf)
20+
local x = test_lib.random_number(fdp)
21+
local y = test_lib.random_number(fdp)
22+
arshift(x, y)
23+
end
24+
25+
local args = {
26+
max_len = 4096,
27+
max_total_time = 10,
28+
artifact_prefix = "bitop_arshift_",
29+
}
30+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/bitop_band_test.lua

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
Wrong code generation for constants in bitwise operations,
6+
https://github.com/lua/lua/commit/c764ca71a639f5585b5f466bea25dc42b855a4b0
7+
8+
Inconsistent behaviour of bit ops in DUALNUM mode,
9+
https://github.com/LuaJIT/LuaJIT/issues/1273
10+
11+
Synopsis: bit32.band (...)
12+
]]
13+
14+
local luzer = require("luzer")
15+
local test_lib = require("lib")
16+
17+
local band
18+
if test_lib.version() == "LuaJIT" then
19+
local bitop = require("bit")
20+
band = bitop.band
21+
else
22+
band = test_lib.bitwise_op("&")
23+
end
24+
25+
local function TestOneInput(buf)
26+
local fdp = luzer.FuzzedDataProvider(buf)
27+
local x = test_lib.random_number(fdp)
28+
local y = test_lib.random_number(fdp)
29+
local z = test_lib.random_number(fdp)
30+
31+
assert(band(x, band(y, z)) ==
32+
band(band(x, y), z), "x & (y & z) ~= (x & y) & z")
33+
assert(band(x, 0) == 0, "x & 0 ~= 0, where x = " .. x)
34+
35+
-- Broken?
36+
-- assert(band(x, 0xffff) == x, "x & 0xFFFF ~= x")
37+
-- assert(band(x, y) == band(y, z), "x & y ~= y & x")
38+
-- assert(band(x, x) == x, "x & x ~= x, where x = " .. x)
39+
end
40+
41+
local args = {
42+
max_len = 4096,
43+
max_total_time = 10,
44+
artifact_prefix = "bitop_band_",
45+
}
46+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/bitop_bnot_test.lua

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
Synopsis: bit32.bnot (x)
6+
]]
7+
8+
local luzer = require("luzer")
9+
local test_lib = require("lib")
10+
11+
local bnot
12+
if test_lib.version() == "LuaJIT" then
13+
local bitop = require("bit")
14+
bnot = bitop.bnot
15+
else
16+
bnot = test_lib.bitwise_op("~")
17+
end
18+
19+
local function TestOneInput(buf)
20+
local fdp = luzer.FuzzedDataProvider(buf)
21+
local x = test_lib.random_number(fdp)
22+
bnot(x)
23+
24+
-- For any integer x, the following identity holds [1]:
25+
-- 1. https://www.lua.org/manual/5.2/manual.html
26+
-- assert(bnot(x) == (-1 - x) % 2^32)
27+
28+
-- FIXME
29+
-- assert(bnot(bnot(x)) == x, "~(~x) ~= x")
30+
end
31+
32+
local args = {
33+
max_len = 4096,
34+
max_total_time = 10,
35+
artifact_prefix = "bitop_bnot_",
36+
}
37+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/bitop_bor_test.lua

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
ARM64: Should not fuse sign-extension into logical operands,
6+
can fuse rotations though,
7+
https://github.com/LuaJIT/LuaJIT/issues/1076
8+
9+
Wrong code generation for constants in bitwise operations,
10+
https://github.com/lua/lua/commit/c764ca71a639f5585b5f466bea25dc42b855a4b0
11+
12+
Synopsis: bit32.bor (···)
13+
]]
14+
15+
local luzer = require("luzer")
16+
local test_lib = require("lib")
17+
18+
local bor
19+
if test_lib.version() == "LuaJIT" then
20+
local bitop = require("bit")
21+
bor = bitop.bor
22+
else
23+
bor = test_lib.bitwise_op("|")
24+
end
25+
26+
local function TestOneInput(buf)
27+
local fdp = luzer.FuzzedDataProvider(buf)
28+
local x = test_lib.random_number(fdp)
29+
local y = test_lib.random_number(fdp)
30+
local z = test_lib.random_number(fdp)
31+
bor(x, y)
32+
33+
assert(bor(x, y) == bor(y, x), "x | y ~= y | x")
34+
assert(bor(x, bor(y, z)) == bor(bor(x, y), z),
35+
"x | (y | z) ~= (x | y) | z")
36+
37+
-- FIXME
38+
-- assert(bor(x, 0) == x, "x | 0 ~= x")
39+
-- assert(bor(x, 0xffff) == 0xffff, "x | 0xFFFF ~= 0xFFFF")
40+
-- assert(bor(x, x) == x, "x | x ~= x")
41+
end
42+
43+
local args = {
44+
max_len = 4096,
45+
max_total_time = 10,
46+
artifact_prefix = "bitop_bor_",
47+
}
48+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/bitop_bswap_test.lua

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
]]
5+
6+
local luzer = require("luzer")
7+
local test_lib = require("lib")
8+
9+
if test_lib.version() ~= "LuaJIT" then
10+
os.exit(0)
11+
end
12+
13+
local bitop = require("bit")
14+
local bswap = bitop.bswap
15+
16+
local function TestOneInput(buf)
17+
local fdp = luzer.FuzzedDataProvider(buf)
18+
local x = test_lib.random_number(fdp)
19+
local y = test_lib.random_number(fdp)
20+
bswap(x, y)
21+
end
22+
23+
local args = {
24+
max_len = 4096,
25+
max_total_time = 10,
26+
artifact_prefix = "bitop_bswap_",
27+
}
28+
luzer.Fuzz(TestOneInput, nil, args)

0 commit comments

Comments
 (0)