From: Sergey Bronnikov via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: Sergey Kaplun <skaplun@tarantool.org>, Igor Munkin <imun@tarantool.org>, Maxim Kokryashkin <m.kokryashkin@tarantool.org> Cc: tarantool-patches@dev.tarantool.org Subject: Re: [Tarantool-patches] [PATCH v2 luajit 4/6] test: rewrite misclib-getmetrics-capi test in C Date: Mon, 29 May 2023 19:15:18 +0300 [thread overview] Message-ID: <93782bbf-c742-8c81-cad5-ae53dcd680ee@tarantool.org> (raw) In-Reply-To: <0ceed30db5259087a6733c429ed5a2502468ce40.1684442182.git.skaplun@tarantool.org> Hi, Sergey see my comments below On 5/18/23 23:44, Sergey Kaplun wrote: > This patch rewrites the aforementioned test with the usage libtest, > recently introduced. Since we still stand in need of a Lua helper script > for generation of traces, the original test file is reworked as a > standalone script, which returns the table with helper functions. Each > helper function is named the same as the test where it will be used. Now > single quotes are used according to our Lua code style. > > In C part all asserts from glibc are replaced with the corresponding > assert_{cond} from the libtest. Now tests return `TEST_EXIT_SUCCESS` at > the finish. Also, the stack check for the amount of return results from > the helper function is slightly changed, since there is one more stack > slot in use (table with these functions). `snap_restores()` C function > duplicates 4 times for each subtest. Common helper > `check_snap_restores()` is used for each of them. Each error throwing is > replaced with `bail_out()` call. > > NB: `lua_pop()` to clear the Lua stack after a call should be done before > any possible assertion, which would exit from the test leaving the stack > uncleaned. > > All skipconds use macros defined in <lj_arch.h>, so it is included in > the test. As far as this test initializes the LuaJIT VM manually, there > is no need to check `jit.status()` result; checking `LJ_HASJIT` is > enough. Now, only JIT-related tests are skipped, when compiled without > JIT. Nevertheless, all tests are skipped for *BSD arches. > > Also, this patch sets the new CMake variable named `LUAJIT_LIBRARY` > equal to `LUAJIT_LIB` in `PARENT_SCOPE` to be used in tarantool-c-tests > linking. > > Also, .c_test suffix is added to the <.gitignore>. > > Part of tarantool/tarantool#7900 > --- > .gitignore | 1 + > src/CMakeLists.txt | 2 + > test/tarantool-c-tests/CMakeLists.txt | 32 +- > .../misclib-getmetrics-capi-script.lua} | 83 ++--- > .../misclib-getmetrics-capi.test.c | 343 ++++++++++++++++++ > test/tarantool-tests/CMakeLists.txt | 1 - > .../misclib-getmetrics-capi/CMakeLists.txt | 1 - > .../misclib-getmetrics-capi/testgetmetrics.c | 270 -------------- > 8 files changed, 412 insertions(+), 321 deletions(-) > rename test/{tarantool-tests/misclib-getmetrics-capi.test.lua => tarantool-c-tests/misclib-getmetrics-capi-script.lua} (68%) > create mode 100644 test/tarantool-c-tests/misclib-getmetrics-capi.test.c > delete mode 100644 test/tarantool-tests/misclib-getmetrics-capi/CMakeLists.txt > delete mode 100644 test/tarantool-tests/misclib-getmetrics-capi/testgetmetrics.c > > diff --git a/.gitignore b/.gitignore > index b7908aee..dc5ea5fc 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -24,3 +24,4 @@ install_manifest.txt > luajit-parse-memprof > luajit-parse-sysprof > luajit.pc > +*.c_test > diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt > index dffc0a4d..fed4c38d 100644 > --- a/src/CMakeLists.txt > +++ b/src/CMakeLists.txt > @@ -325,6 +325,8 @@ if(NOT BUILDMODE STREQUAL "dynamic") > set(LUAJIT_BIN luajit_static) > set(LUAJIT_LIB libluajit_static) > endif() > +# Need for the test linking, so the PARENT_SCOPE option is used. > +set(LUAJIT_LIBRARY ${LUAJIT_LIB} PARENT_SCOPE) > set(LIBLUAJIT_DEPS ${LIBLUAJIT_STATIC_DEPS} ${LIBLUAJIT_SHARED_DEPS}) > > add_executable(${LUAJIT_BIN} EXCLUDE_FROM_ALL ${CLI_SOURCES}) > diff --git a/test/tarantool-c-tests/CMakeLists.txt b/test/tarantool-c-tests/CMakeLists.txt > index c6b7cd30..c9d75d6c 100644 > --- a/test/tarantool-c-tests/CMakeLists.txt > +++ b/test/tarantool-c-tests/CMakeLists.txt > @@ -22,13 +22,37 @@ set_target_properties(libtest PROPERTIES > LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" > ) > > -# XXX: For now, just build libtest. The tests to be depended on > -# will be added in the next commit. > +# TARGET_C_FLAGS is required here to be sure that headers like > +# lj_arch.h in compiled test are consistent with the LuaJIT library > +# to link. > +AppendFlags(TESTS_C_FLAGS ${TARGET_C_FLAGS}) > + > +set(CTEST_SRC_SUFFIX ".test.c") > +file(GLOB tests "${CMAKE_CURRENT_SOURCE_DIR}/*${CTEST_SRC_SUFFIX}") > +foreach(test_source ${tests}) > + string(REGEX REPLACE ".+/([^/]+)${CTEST_SRC_SUFFIX}" "\\1" exe ${test_source}) Please replace with get_filename_component [1]: --- a/test/tarantool-c-tests/CMakeLists.txt +++ b/test/tarantool-c-tests/CMakeLists.txt @@ -31,7 +31,7 @@ set(CTEST_SRC_SUFFIX ".test.c") file(GLOB tests "${CMAKE_CURRENT_SOURCE_DIR}/*${CTEST_SRC_SUFFIX}") foreach(test_source ${tests}) # Get test name without suffix. Needed to set OUTPUT_NAME. - string(REGEX REPLACE ".+/([^/]+)${CTEST_SRC_SUFFIX}" "\\1" exe ${test_source}) + get_filename_component(exe ${test_source} NAME_WE) add_executable(${exe} EXCLUDE_FROM_ALL ${test_source}) target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} 1: https://cmake.org/cmake/help/latest/command/get_filename_component.html > + add_executable(${exe} EXCLUDE_FROM_ALL ${test_source}) > + target_include_directories(${exe} PRIVATE > + ${CMAKE_CURRENT_SOURCE_DIR} > + ${LUAJIT_SOURCE_DIR} > + ) > + set_target_properties(${exe} PROPERTIES > + # `__FILE__` macro may not represnt absolute path to the Typo: represnt > + # source file, depening on cmake version or Typo: depening > + # -fmacro-prefix-map flag value. > + # Use custom macro. > + COMPILE_FLAGS "${TESTS_C_FLAGS} -D__ABS_FILENAME__='\"${test_source}\"'" > + OUTPUT_NAME "${exe}${C_TEST_SUFFIX}" > + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" > + ) > + target_link_libraries(${exe} libtest ${LUAJIT_LIBRARY}) > + LIST(APPEND TESTS_COMPILED ${exe}) > +endforeach() > + > add_custom_target(tarantool-c-tests > - DEPENDS libluajit libtest > + DEPENDS libluajit libtest ${TESTS_COMPILED} > ) > > -# XXX: For now, run 0 tests. Just verify that libtest was built. > add_custom_command(TARGET tarantool-c-tests > COMMENT "Running Tarantool C tests" > COMMAND > diff --git a/test/tarantool-tests/misclib-getmetrics-capi.test.lua b/test/tarantool-c-tests/misclib-getmetrics-capi-script.lua > similarity index 68% > rename from test/tarantool-tests/misclib-getmetrics-capi.test.lua > rename to test/tarantool-c-tests/misclib-getmetrics-capi-script.lua > index 654e5545..2f0ee5cf 100644 > --- a/test/tarantool-tests/misclib-getmetrics-capi.test.lua > +++ b/test/tarantool-c-tests/misclib-getmetrics-capi-script.lua > @@ -1,32 +1,26 @@ > -local tap = require('tap') > -local test = tap.test("clib-misc-getmetrics"):skipcond({ > - ['Test requires JIT enabled'] = not jit.status(), > - ['Disabled on *BSD due to #4819'] = jit.os == 'BSD', > -}) > +local ffi = require('ffi') > > -test:plan(11) > +-- Auxiliary script to provide Lua functions to be used in tests > +-- for `getmetrics()` C API inside the test > +-- <misclib-getmetrics-capi.test.c>. > +local M = {} > > -local path = arg[0]:gsub('%.test%.lua', '') > -local suffix = package.cpath:match('?.(%a+);') > -package.cpath = ('%s/?.%s;'):format(path, suffix)..package.cpath > +-- XXX: Max nins is limited by max IRRef, that equals to > +-- REF_DROP - REF_BIAS. Unfortunately, these constants are not > +-- provided to Lua space, so we ought to make some math: > +-- * REF_DROP = 0xffff > +-- * REF_BIAS = 0x8000 > +-- See <src/lj_ir.h> for details. > +local MAXNINS = 0xffff - 0x8000 > > -local MAXNINS = require('utils').const.maxnins > local jit_opt_default = { > 3, -- level > - "hotloop=56", > - "hotexit=10", > - "minstitch=0", > + 'hotloop=56', > + 'hotexit=10', > + 'minstitch=0', > } > > -local testgetmetrics = require("testgetmetrics") > - > -test:ok(testgetmetrics.base()) > -test:ok(testgetmetrics.gc_allocated_freed()) > -test:ok(testgetmetrics.gc_steps()) > - > -test:ok(testgetmetrics.objcount(function(iterations) > - local ffi = require("ffi") > - > +M.objcount = function(iterations) > jit.opt.start(0) > > local placeholder = { > @@ -51,35 +45,34 @@ test:ok(testgetmetrics.objcount(function(iterations) > > for _ = 1, iterations do > -- Check counting of VLA/VLS/aligned cdata. > - table.insert(placeholder.cdata, ffi.new("char[?]", 4)) > + table.insert(placeholder.cdata, ffi.new('char[?]', 4)) > end > > for _ = 1, iterations do > -- Check counting of non-VLA/VLS/aligned cdata. > - table.insert(placeholder.cdata, ffi.new("uint64_t", _)) > + table.insert(placeholder.cdata, ffi.new('uint64_t', _)) > end > > placeholder = nil -- luacheck: no unused > -- Restore default jit settings. > jit.opt.start(unpack(jit_opt_default)) > -end)) > +end > > -test:ok(testgetmetrics.objcount_cdata_decrement(function() > +M.objcount_cdata_decrement = function() > -- gc_cdatanum decrement test. > -- See https://github.com/tarantool/tarantool/issues/5820. > - local ffi = require("ffi") > local function nop() end > - ffi.gc(ffi.cast("void *", 0), nop) > + ffi.gc(ffi.cast('void *', 0), nop) > -- Does not collect the cdata, but resurrects the object and > -- removes LJ_GC_CDATA_FIN flag. > collectgarbage() > -- Collects the cdata. > collectgarbage() > -end)) > +end > > -- Compiled loop with a direct exit to the interpreter. > -test:ok(testgetmetrics.snap_restores(function() > - jit.opt.start(0, "hotloop=1") > +M.snap_restores_direct_exit = function() > + jit.opt.start(0, 'hotloop=1') > > local sum = 0 > for i = 1, 20 do > @@ -91,11 +84,11 @@ test:ok(testgetmetrics.snap_restores(function() > > -- A single snapshot restoration happened on loop finish. > return 1 > -end)) > +end > > -- Compiled loop with a side exit which does not get compiled. > -test:ok(testgetmetrics.snap_restores(function() > - jit.opt.start(0, "hotloop=1", "hotexit=2", ("minstitch=%d"):format(MAXNINS)) > +M.snap_restores_side_exit_not_compiled = function() > + jit.opt.start(0, 'hotloop=1', 'hotexit=2', ('minstitch=%d'):format(MAXNINS)) > > local function foo(i) > -- math.fmod is not yet compiled! > @@ -112,13 +105,13 @@ test:ok(testgetmetrics.snap_restores(function() > > -- Side exits from the root trace could not get compiled. > return 5 > -end)) > +end > > -- Compiled loop with a side exit which gets compiled. > -test:ok(testgetmetrics.snap_restores(function() > +M.snap_restores_side_exit_compiled = function() > -- Optimization level is important here as `loop` optimization > -- may unroll the loop body and insert +1 side exit. > - jit.opt.start(0, "hotloop=1", "hotexit=5") > + jit.opt.start(0, 'hotloop=1', 'hotexit=5') > > local function foo(i) > return i <= 10 and i or tostring(i) > @@ -136,13 +129,13 @@ test:ok(testgetmetrics.snap_restores(function() > -- and compiled > -- 1 side exit on loop end > return 6 > -end)) > +end > > -- Compiled scalar trace with a direct exit to the interpreter. > -test:ok(testgetmetrics.snap_restores(function() > +M.snap_restores_direct_exit_scalar = function() > -- For calls it will be 2 * hotloop (see lj_dispatch.{c,h} > -- and hotcall@vm_*.dasc). > - jit.opt.start(3, "hotloop=2", "hotexit=3") > + jit.opt.start(3, 'hotloop=2', 'hotexit=3') > > local function foo(i) > return i <= 15 and i or tostring(i) > @@ -167,15 +160,15 @@ test:ok(testgetmetrics.snap_restores(function() > jit.opt.start(unpack(jit_opt_default)) > > return 2 > -end)) > +end > > -test:ok(testgetmetrics.strhash()) > - > -test:ok(testgetmetrics.tracenum_base(function() > +M.tracenum_base = function() > local sum = 0 > for i = 1, 200 do > sum = sum + i > end > -- Compiled only 1 loop as new trace. > return 1 > -end)) > +end > + > +return M > diff --git a/test/tarantool-c-tests/misclib-getmetrics-capi.test.c b/test/tarantool-c-tests/misclib-getmetrics-capi.test.c > new file mode 100644 > index 00000000..202cd395 > --- /dev/null > +++ b/test/tarantool-c-tests/misclib-getmetrics-capi.test.c > @@ -0,0 +1,343 @@ > +#include "lua.h" > +#include "luajit.h" > +#include "lauxlib.h" > +#include "lmisclib.h" > + > +#include "test.h" > +#include "utils.h" > + > +/* Need for skipcond for BSD and JIT. */ > +#include "lj_arch.h" > + > +static int base(void *test_state) > +{ > + lua_State *L = test_state; > + struct luam_Metrics metrics; > + luaM_metrics(L, &metrics); > + > + /* > + * Just check structure format, not values that fields > + * contain. > + */ > + (void)metrics.strhash_hit; > + (void)metrics.strhash_miss; > + > + (void)metrics.gc_strnum; > + (void)metrics.gc_tabnum; > + (void)metrics.gc_udatanum; > + (void)metrics.gc_cdatanum; > + > + (void)metrics.gc_total; > + (void)metrics.gc_freed; > + (void)metrics.gc_allocated; > + > + (void)metrics.gc_steps_pause; > + (void)metrics.gc_steps_propagate; > + (void)metrics.gc_steps_atomic; > + (void)metrics.gc_steps_sweepstring; > + (void)metrics.gc_steps_sweep; > + (void)metrics.gc_steps_finalize; > + > + (void)metrics.jit_snap_restore; > + (void)metrics.jit_trace_abort; > + (void)metrics.jit_mcode_size; > + (void)metrics.jit_trace_num; > + > + return TEST_EXIT_SUCCESS; > +} > + > +static int gc_allocated_freed(void *test_state) > +{ > + lua_State *L = test_state; > + struct luam_Metrics oldm, newm; > + /* Force up garbage collect all dead objects. */ > + lua_gc(L, LUA_GCCOLLECT, 0); > + > + luaM_metrics(L, &oldm); > + /* Simple garbage generation. */ > + if (luaL_dostring(L, "local i = 0 for j = 1, 10 do i = i + j end")) > + bail_out("failed to translate Lua code snippet"); > + lua_gc(L, LUA_GCCOLLECT, 0); > + luaM_metrics(L, &newm); > + assert_true(newm.gc_allocated - oldm.gc_allocated > 0); > + assert_true(newm.gc_freed - oldm.gc_freed > 0); > + > + return TEST_EXIT_SUCCESS; > +} > + > +static int gc_steps(void *test_state) > +{ > + lua_State *L = test_state; > + struct luam_Metrics oldm, newm; > + /* > + * Some garbage has already happened before the next line, > + * i.e. during frontend processing Lua test chunk. > + * Let's put a full garbage collection cycle on top > + * of that, and confirm that non-null values are reported > + * (we are not yet interested in actual numbers): > + */ > + lua_gc(L, LUA_GCCOLLECT, 0); > + > + luaM_metrics(L, &oldm); > + assert_true(oldm.gc_steps_pause > 0); > + assert_true(oldm.gc_steps_propagate > 0); > + assert_true(oldm.gc_steps_atomic > 0); > + assert_true(oldm.gc_steps_sweepstring > 0); > + assert_true(oldm.gc_steps_sweep > 0); > + /* Nothing to finalize, skipped. */ > + assert_true(oldm.gc_steps_finalize == 0); > + > + /* > + * As long as we don't create new Lua objects > + * consequent call should return the same values: > + */ > + luaM_metrics(L, &newm); > + assert_sizet_equal(newm.gc_steps_pause, oldm.gc_steps_pause); > + assert_sizet_equal(newm.gc_steps_propagate, oldm.gc_steps_propagate); > + assert_sizet_equal(newm.gc_steps_atomic, oldm.gc_steps_atomic); > + assert_sizet_equal(newm.gc_steps_sweepstring, > + oldm.gc_steps_sweepstring); > + assert_sizet_equal(newm.gc_steps_sweep, oldm.gc_steps_sweep); > + /* Nothing to finalize, skipped. */ > + assert_true(newm.gc_steps_finalize == 0); > + oldm = newm; > + > + /* > + * Now the last phase: run full GC once and make sure that > + * everything is being reported as expected: > + */ > + lua_gc(L, LUA_GCCOLLECT, 0); > + luaM_metrics(L, &newm); > + assert_true(newm.gc_steps_pause - oldm.gc_steps_pause == 1); > + assert_true(newm.gc_steps_propagate - oldm.gc_steps_propagate >= 1); > + assert_true(newm.gc_steps_atomic - oldm.gc_steps_atomic == 1); > + assert_true(newm.gc_steps_sweepstring - oldm.gc_steps_sweepstring >= 1); > + assert_true(newm.gc_steps_sweep - oldm.gc_steps_sweep >= 1); > + /* Nothing to finalize, skipped. */ > + assert_true(newm.gc_steps_finalize == 0); > + oldm = newm; > + > + /* > + * Now let's run three GC cycles to ensure that > + * increment was not a lucky coincidence. > + */ > + lua_gc(L, LUA_GCCOLLECT, 0); > + lua_gc(L, LUA_GCCOLLECT, 0); > + lua_gc(L, LUA_GCCOLLECT, 0); > + luaM_metrics(L, &newm); > + assert_true(newm.gc_steps_pause - oldm.gc_steps_pause == 3); > + assert_true(newm.gc_steps_propagate - oldm.gc_steps_propagate >= 3); > + assert_true(newm.gc_steps_atomic - oldm.gc_steps_atomic == 3); > + assert_true(newm.gc_steps_sweepstring - oldm.gc_steps_sweepstring >= 3); > + assert_true(newm.gc_steps_sweep - oldm.gc_steps_sweep >= 3); > + /* Nothing to finalize, skipped. */ > + assert_true(newm.gc_steps_finalize == 0); > + > + return TEST_EXIT_SUCCESS; > +} > + > +static int objcount(void *test_state) > +{ > + lua_State *L = test_state; > + struct luam_Metrics oldm, newm; > + if (!LJ_HASJIT) > + return skip("Test requires JIT enabled"); > + > + utils_get_aux_lfunc(L); > + > + /* Force up garbage collect all dead objects. */ > + lua_gc(L, LUA_GCCOLLECT, 0); > + > + luaM_metrics(L, &oldm); > + /* Generate garbage. Argument is iterations amount. */ > + lua_pushnumber(L, 1000); > + lua_call(L, 1, 0); > + lua_gc(L, LUA_GCCOLLECT, 0); > + luaM_metrics(L, &newm); > + assert_sizet_equal(newm.gc_strnum, oldm.gc_strnum); > + assert_sizet_equal(newm.gc_tabnum, oldm.gc_tabnum); > + assert_sizet_equal(newm.gc_udatanum, oldm.gc_udatanum); > + assert_sizet_equal(newm.gc_cdatanum, oldm.gc_cdatanum); > + > + return TEST_EXIT_SUCCESS; > +} > + > +static int objcount_cdata_decrement(void *test_state) > +{ > + lua_State *L = test_state; > + /* > + * cdata decrement test. > + * See https://github.com/tarantool/tarantool/issues/5820. > + */ > + struct luam_Metrics oldm, newm; > + utils_get_aux_lfunc(L); > + > + /* Force up garbage collect all dead objects. */ > + lua_gc(L, LUA_GCCOLLECT, 0); > + > + luaM_metrics(L, &oldm); > + /* > + * The function generates and collects cdata with > + * LJ_GC_CDATA_FIN flag. > + */ > + lua_call(L, 0, 0); > + luaM_metrics(L, &newm); > + assert_sizet_equal(newm.gc_cdatanum, oldm.gc_cdatanum); > + > + return TEST_EXIT_SUCCESS; > +} > + > +/* > + * Get function to call to generate the corresponding snapshot > + * restores on top of the Lua stack. Function returns the amount > + * of snapshot restorations expected. > + * Clear stack after call. > + */ > +static void check_snap_restores(lua_State *L) > +{ > + struct luam_Metrics oldm, newm; > + luaM_metrics(L, &oldm); > + /* Generate snapshots. */ > + lua_call(L, 0, 1); > + int n = lua_gettop(L); > + /* > + * The first value is the table with functions, > + * the second is number of snapshot restores. > + */ > + if (n != 2 || !lua_isnumber(L, -1)) > + bail_out("incorrect return value: 1 number is required"); > + size_t snap_restores = lua_tonumber(L, -1); > + luaM_metrics(L, &newm); > + /* > + * Remove `snap_restores` from stack. > + * Must be done before potiential assert and exit from > + * the test. > + */ > + lua_pop(L, 1); > + assert_true(newm.jit_snap_restore - oldm.jit_snap_restore > + == snap_restores); > +} > + > +static int snap_restores_direct_exit(void *test_state) > +{ > + lua_State *L = test_state; > + utils_get_aux_lfunc(L); > + check_snap_restores(L); > + return TEST_EXIT_SUCCESS; > +} > + > +static int snap_restores_direct_exit_scalar(void *test_state) > +{ > + lua_State *L = test_state; > + utils_get_aux_lfunc(L); > + check_snap_restores(L); > + return TEST_EXIT_SUCCESS; > +} > + > +static int snap_restores_side_exit_compiled(void *test_state) > +{ > + lua_State *L = test_state; > + utils_get_aux_lfunc(L); > + check_snap_restores(L); > + return TEST_EXIT_SUCCESS; > +} > + > +static int snap_restores_side_exit_not_compiled(void *test_state) > +{ > + lua_State *L = test_state; > + utils_get_aux_lfunc(L); > + check_snap_restores(L); > + return TEST_EXIT_SUCCESS; > +} > + > +static int snap_restores_group(void *test_state) > +{ > + if (!LJ_HASJIT) > + return skip("Test requires JIT enabled"); > + const struct test_unit tgroup[] = { > + test_unit_new(snap_restores_direct_exit), > + test_unit_new(snap_restores_direct_exit_scalar), > + test_unit_new(snap_restores_side_exit_compiled), > + test_unit_new(snap_restores_side_exit_not_compiled) > + }; > + return test_run_group(tgroup, test_state); > +} > + > +static int strhash(void *test_state) > +{ > + lua_State *L = test_state; > + struct luam_Metrics oldm, newm; > + lua_pushstring(L, "strhash_hit"); > + luaM_metrics(L, &oldm); > + lua_pushstring(L, "strhash_hit"); > + lua_pushstring(L, "new_str"); > + luaM_metrics(L, &newm); > + /* Remove pushed strings. */ > + lua_pop(L, 3); > + assert_true(newm.strhash_hit - oldm.strhash_hit == 1); > + assert_true(newm.strhash_miss - oldm.strhash_miss == 1); > + return TEST_EXIT_SUCCESS; > +} > + > +static int tracenum_base(void *test_state) > +{ > + lua_State *L = test_state; > + if (!LJ_HASJIT) > + return skip("Test requires JIT enabled"); > + struct luam_Metrics metrics; > + utils_get_aux_lfunc(L); > + > + luaJIT_setmode(L, 0, LUAJIT_MODE_FLUSH); > + /* Force up garbage collect all dead objects. */ > + lua_gc(L, LUA_GCCOLLECT, 0); > + > + luaM_metrics(L, &metrics); > + assert_true(metrics.jit_trace_num == 0); > + > + /* Generate traces. */ > + lua_call(L, 0, 1); > + int n = lua_gettop(L); > + /* > + * The first value is the table with functions, > + * the second is the amount of traces. > + */ > + if (n != 2 || !lua_isnumber(L, -1)) > + bail_out("incorrect return value: 1 number is required"); > + size_t jit_trace_num = lua_tonumber(L, -1); > + luaM_metrics(L, &metrics); > + /* Remove `jit_trace_num` from Lua stack. */ > + lua_pop(L, 1); > + > + assert_sizet_equal(metrics.jit_trace_num, jit_trace_num); > + > + luaJIT_setmode(L, 0, LUAJIT_MODE_FLUSH); > + /* Force up garbage collect all dead objects. */ > + lua_gc(L, LUA_GCCOLLECT, 0); > + luaM_metrics(L, &metrics); > + assert_true(metrics.jit_trace_num == 0); > + > + return TEST_EXIT_SUCCESS; > +} > + > +int main(void) > +{ > + if (LUAJIT_OS == LUAJIT_OS_BSD) > + return skip_all("Disabled on *BSD due to #4819"); > + > + lua_State *L = utils_lua_init(); > + > + utils_load_aux_script(L); > + const struct test_unit tgroup[] = { > + test_unit_new(base), > + test_unit_new(gc_allocated_freed), > + test_unit_new(gc_steps), > + test_unit_new(objcount), > + test_unit_new(objcount_cdata_decrement), > + test_unit_new(snap_restores_group), > + test_unit_new(strhash), > + test_unit_new(tracenum_base) > + }; > + const int test_result = test_run_group(tgroup, L); > + utils_lua_close(L); > + return test_result; > +} > diff --git a/test/tarantool-tests/CMakeLists.txt b/test/tarantool-tests/CMakeLists.txt > index 38d6ae49..b4ce39d3 100644 > --- a/test/tarantool-tests/CMakeLists.txt > +++ b/test/tarantool-tests/CMakeLists.txt > @@ -66,7 +66,6 @@ add_subdirectory(lj-416-xor-before-jcc) > add_subdirectory(lj-601-fix-gc-finderrfunc) > add_subdirectory(lj-727-lightuserdata-itern) > add_subdirectory(lj-flush-on-trace) > -add_subdirectory(misclib-getmetrics-capi) > add_subdirectory(misclib-sysprof-capi) > > # The part of the memory profiler toolchain is located in tools > diff --git a/test/tarantool-tests/misclib-getmetrics-capi/CMakeLists.txt b/test/tarantool-tests/misclib-getmetrics-capi/CMakeLists.txt > deleted file mode 100644 > index 60eb5bbb..00000000 > --- a/test/tarantool-tests/misclib-getmetrics-capi/CMakeLists.txt > +++ /dev/null > @@ -1 +0,0 @@ > -BuildTestCLib(testgetmetrics testgetmetrics.c) > diff --git a/test/tarantool-tests/misclib-getmetrics-capi/testgetmetrics.c b/test/tarantool-tests/misclib-getmetrics-capi/testgetmetrics.c > deleted file mode 100644 > index 67776338..00000000 > --- a/test/tarantool-tests/misclib-getmetrics-capi/testgetmetrics.c > +++ /dev/null > @@ -1,270 +0,0 @@ > -#include <lua.h> > -#include <luajit.h> > -#include <lauxlib.h> > - > -#include <lmisclib.h> > - > -#undef NDEBUG > -#include <assert.h> > - > -static int base(lua_State *L) > -{ > - struct luam_Metrics metrics; > - luaM_metrics(L, &metrics); > - > - /* Just check structure format, not values that fields contain. */ > - (void)metrics.strhash_hit; > - (void)metrics.strhash_miss; > - > - (void)metrics.gc_strnum; > - (void)metrics.gc_tabnum; > - (void)metrics.gc_udatanum; > - (void)metrics.gc_cdatanum; > - > - (void)metrics.gc_total; > - (void)metrics.gc_freed; > - (void)metrics.gc_allocated; > - > - (void)metrics.gc_steps_pause; > - (void)metrics.gc_steps_propagate; > - (void)metrics.gc_steps_atomic; > - (void)metrics.gc_steps_sweepstring; > - (void)metrics.gc_steps_sweep; > - (void)metrics.gc_steps_finalize; > - > - (void)metrics.jit_snap_restore; > - (void)metrics.jit_trace_abort; > - (void)metrics.jit_mcode_size; > - (void)metrics.jit_trace_num; > - > - lua_pushboolean(L, 1); > - return 1; > -} > - > -static int gc_allocated_freed(lua_State *L) > -{ > - struct luam_Metrics oldm, newm; > - /* Force up garbage collect all dead objects. */ > - lua_gc(L, LUA_GCCOLLECT, 0); > - > - luaM_metrics(L, &oldm); > - /* Simple garbage generation. */ > - if (luaL_dostring(L, "local i = 0 for j = 1, 10 do i = i + j end")) > - luaL_error(L, "failed to translate Lua code snippet"); > - lua_gc(L, LUA_GCCOLLECT, 0); > - luaM_metrics(L, &newm); > - assert(newm.gc_allocated - oldm.gc_allocated > 0); > - assert(newm.gc_freed - oldm.gc_freed > 0); > - > - lua_pushboolean(L, 1); > - return 1; > -} > - > -static int gc_steps(lua_State *L) > -{ > - struct luam_Metrics oldm, newm; > - /* > - * Some garbage has already happened before the next line, > - * i.e. during frontend processing Lua test chunk. > - * Let's put a full garbage collection cycle on top > - * of that, and confirm that non-null values are reported > - * (we are not yet interested in actual numbers): > - */ > - lua_gc(L, LUA_GCCOLLECT, 0); > - > - luaM_metrics(L, &oldm); > - assert(oldm.gc_steps_pause > 0); > - assert(oldm.gc_steps_propagate > 0); > - assert(oldm.gc_steps_atomic > 0); > - assert(oldm.gc_steps_sweepstring > 0); > - assert(oldm.gc_steps_sweep > 0); > - /* Nothing to finalize, skipped. */ > - assert(oldm.gc_steps_finalize == 0); > - > - /* > - * As long as we don't create new Lua objects > - * consequent call should return the same values: > - */ > - luaM_metrics(L, &newm); > - assert(newm.gc_steps_pause - oldm.gc_steps_pause == 0); > - assert(newm.gc_steps_propagate - oldm.gc_steps_propagate == 0); > - assert(newm.gc_steps_atomic - oldm.gc_steps_atomic == 0); > - assert(newm.gc_steps_sweepstring - oldm.gc_steps_sweepstring == 0); > - assert(newm.gc_steps_sweep - oldm.gc_steps_sweep == 0); > - /* Nothing to finalize, skipped. */ > - assert(newm.gc_steps_finalize == 0); > - oldm = newm; > - > - /* > - * Now the last phase: run full GC once and make sure that > - * everything is being reported as expected: > - */ > - lua_gc(L, LUA_GCCOLLECT, 0); > - luaM_metrics(L, &newm); > - assert(newm.gc_steps_pause - oldm.gc_steps_pause == 1); > - assert(newm.gc_steps_propagate - oldm.gc_steps_propagate >= 1); > - assert(newm.gc_steps_atomic - oldm.gc_steps_atomic == 1); > - assert(newm.gc_steps_sweepstring - oldm.gc_steps_sweepstring >= 1); > - assert(newm.gc_steps_sweep - oldm.gc_steps_sweep >= 1); > - /* Nothing to finalize, skipped. */ > - assert(newm.gc_steps_finalize == 0); > - oldm = newm; > - > - /* > - * Now let's run three GC cycles to ensure that > - * increment was not a lucky coincidence. > - */ > - lua_gc(L, LUA_GCCOLLECT, 0); > - lua_gc(L, LUA_GCCOLLECT, 0); > - lua_gc(L, LUA_GCCOLLECT, 0); > - luaM_metrics(L, &newm); > - assert(newm.gc_steps_pause - oldm.gc_steps_pause == 3); > - assert(newm.gc_steps_propagate - oldm.gc_steps_propagate >= 3); > - assert(newm.gc_steps_atomic - oldm.gc_steps_atomic == 3); > - assert(newm.gc_steps_sweepstring - oldm.gc_steps_sweepstring >= 3); > - assert(newm.gc_steps_sweep - oldm.gc_steps_sweep >= 3); > - /* Nothing to finalize, skipped. */ > - assert(newm.gc_steps_finalize == 0); > - > - lua_pushboolean(L, 1); > - return 1; > -} > - > -static int objcount(lua_State *L) > -{ > - struct luam_Metrics oldm, newm; > - int n = lua_gettop(L); > - if (n != 1 || !lua_isfunction(L, 1)) > - luaL_error(L, "incorrect argument: 1 function is required"); > - > - /* Force up garbage collect all dead objects. */ > - lua_gc(L, LUA_GCCOLLECT, 0); > - > - luaM_metrics(L, &oldm); > - /* Generate garbage. Argument is iterations amount. */ > - lua_pushnumber(L, 1000); > - lua_call(L, 1, 0); > - lua_gc(L, LUA_GCCOLLECT, 0); > - luaM_metrics(L, &newm); > - assert(newm.gc_strnum - oldm.gc_strnum == 0); > - assert(newm.gc_tabnum - oldm.gc_tabnum == 0); > - assert(newm.gc_udatanum - oldm.gc_udatanum == 0); > - assert(newm.gc_cdatanum - oldm.gc_cdatanum == 0); > - > - lua_pushboolean(L, 1); > - return 1; > -} > - > -static int objcount_cdata_decrement(lua_State *L) > -{ > - /* > - * cdata decrement test. > - * See https://github.com/tarantool/tarantool/issues/5820. > - */ > - struct luam_Metrics oldm, newm; > - int n = lua_gettop(L); > - if (n != 1 || !lua_isfunction(L, 1)) > - luaL_error(L, "incorrect argument: 1 function is required"); > - > - /* Force up garbage collect all dead objects. */ > - lua_gc(L, LUA_GCCOLLECT, 0); > - > - luaM_metrics(L, &oldm); > - /* > - * The function generates and collects cdata with > - * LJ_GC_CDATA_FIN flag. > - */ > - lua_call(L, 0, 0); > - luaM_metrics(L, &newm); > - assert(newm.gc_cdatanum - oldm.gc_cdatanum == 0); > - > - lua_pushboolean(L, 1); > - return 1; > -} > - > -static int snap_restores(lua_State *L) > -{ > - struct luam_Metrics oldm, newm; > - int n = lua_gettop(L); > - if (n != 1 || !lua_isfunction(L, 1)) > - luaL_error(L, "incorrect arguments: 1 function is required"); > - > - luaM_metrics(L, &oldm); > - /* Generate snapshots. */ > - lua_call(L, 0, 1); > - n = lua_gettop(L); > - if (n != 1 || !lua_isnumber(L, 1)) > - luaL_error(L, "incorrect return value: 1 number is required"); > - size_t snap_restores = lua_tonumber(L, 1); > - luaM_metrics(L, &newm); > - assert(newm.jit_snap_restore - oldm.jit_snap_restore == snap_restores); > - > - lua_pushboolean(L, 1); > - return 1; > -} > - > -static int strhash(lua_State *L) > -{ > - struct luam_Metrics oldm, newm; > - lua_pushstring(L, "strhash_hit"); > - luaM_metrics(L, &oldm); > - lua_pushstring(L, "strhash_hit"); > - lua_pushstring(L, "new_str"); > - luaM_metrics(L, &newm); > - assert(newm.strhash_hit - oldm.strhash_hit == 1); > - assert(newm.strhash_miss - oldm.strhash_miss == 1); > - lua_pop(L, 3); > - lua_pushboolean(L, 1); > - return 1; > -} > - > -static int tracenum_base(lua_State *L) > -{ > - struct luam_Metrics metrics; > - int n = lua_gettop(L); > - if (n != 1 || !lua_isfunction(L, 1)) > - luaL_error(L, "incorrect arguments: 1 function is required"); > - > - luaJIT_setmode(L, 0, LUAJIT_MODE_FLUSH); > - /* Force up garbage collect all dead objects. */ > - lua_gc(L, LUA_GCCOLLECT, 0); > - > - luaM_metrics(L, &metrics); > - assert(metrics.jit_trace_num == 0); > - > - /* Generate traces. */ > - lua_call(L, 0, 1); > - n = lua_gettop(L); > - if (n != 1 || !lua_isnumber(L, 1)) > - luaL_error(L, "incorrect return value: 1 number is required"); > - size_t jit_trace_num = lua_tonumber(L, 1); > - luaM_metrics(L, &metrics); > - assert(metrics.jit_trace_num == jit_trace_num); > - > - luaJIT_setmode(L, 0, LUAJIT_MODE_FLUSH); > - /* Force up garbage collect all dead objects. */ > - lua_gc(L, LUA_GCCOLLECT, 0); > - luaM_metrics(L, &metrics); > - assert(metrics.jit_trace_num == 0); > - > - lua_pushboolean(L, 1); > - return 1; > -} > - > -static const struct luaL_Reg testgetmetrics[] = { > - {"base", base}, > - {"gc_allocated_freed", gc_allocated_freed}, > - {"gc_steps", gc_steps}, > - {"objcount", objcount}, > - {"objcount_cdata_decrement", objcount_cdata_decrement}, > - {"snap_restores", snap_restores}, > - {"strhash", strhash}, > - {"tracenum_base", tracenum_base}, > - {NULL, NULL} > -}; > - > -LUA_API int luaopen_testgetmetrics(lua_State *L) > -{ > - luaL_register(L, "testgetmetrics", testgetmetrics); > - return 1; > -}
next prev parent reply other threads:[~2023-05-29 16:15 UTC|newest] Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top 2023-05-18 20:44 [Tarantool-patches] [PATCH v2 luajit 0/6] Revorking C tests Sergey Kaplun via Tarantool-patches 2023-05-18 20:44 ` [Tarantool-patches] [PATCH v2 luajit 1/6] test: fix setting of {DY}LD_LIBRARY_PATH variables Sergey Kaplun via Tarantool-patches 2023-05-19 11:23 ` Maxim Kokryashkin via Tarantool-patches 2023-05-22 11:03 ` Sergey Bronnikov via Tarantool-patches 2023-05-23 6:47 ` Sergey Kaplun via Tarantool-patches 2023-05-29 14:37 ` Sergey Bronnikov via Tarantool-patches 2023-05-18 20:44 ` [Tarantool-patches] [PATCH v2 luajit 2/6] test: introduce module for C tests Sergey Kaplun via Tarantool-patches 2023-05-19 11:46 ` Maxim Kokryashkin via Tarantool-patches 2023-05-22 12:33 ` Sergey Bronnikov via Tarantool-patches 2023-05-24 6:41 ` Sergey Kaplun via Tarantool-patches 2023-05-25 17:33 ` Sergey Bronnikov via Tarantool-patches 2023-05-29 10:03 ` Sergey Kaplun via Tarantool-patches 2023-05-29 14:38 ` Sergey Bronnikov via Tarantool-patches 2023-05-31 13:32 ` Sergey Kaplun via Tarantool-patches 2023-05-18 20:44 ` [Tarantool-patches] [PATCH v2 luajit 3/6] test: introduce utils.h helper " Sergey Kaplun via Tarantool-patches 2023-05-19 11:58 ` Maxim Kokryashkin via Tarantool-patches 2023-05-20 7:52 ` Sergey Kaplun via Tarantool-patches 2023-05-29 15:26 ` Sergey Bronnikov via Tarantool-patches 2023-05-18 20:44 ` [Tarantool-patches] [PATCH v2 luajit 4/6] test: rewrite misclib-getmetrics-capi test in C Sergey Kaplun via Tarantool-patches 2023-05-19 12:17 ` Maxim Kokryashkin via Tarantool-patches 2023-05-20 8:08 ` Sergey Kaplun via Tarantool-patches 2023-05-29 16:15 ` Sergey Bronnikov via Tarantool-patches [this message] 2023-05-18 20:44 ` [Tarantool-patches] [PATCH v2 luajit 5/6] test: rewrite misclib-sysprof-capi " Sergey Kaplun via Tarantool-patches 2023-05-19 13:00 ` Maxim Kokryashkin via Tarantool-patches 2023-05-20 7:28 ` Sergey Kaplun via Tarantool-patches 2023-05-18 20:44 ` [Tarantool-patches] [PATCH v2 luajit 6/6] test: rewrite lj-49-bad-lightuserdata " Sergey Kaplun via Tarantool-patches 2023-05-19 12:40 ` Maxim Kokryashkin via Tarantool-patches 2023-05-19 14:29 ` [Tarantool-patches] [PATCH v2 luajit 0/6] Revorking C tests Maxim Kokryashkin via Tarantool-patches 2023-05-20 8:38 ` Sergey Kaplun via Tarantool-patches
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=93782bbf-c742-8c81-cad5-ae53dcd680ee@tarantool.org \ --to=tarantool-patches@dev.tarantool.org \ --cc=imun@tarantool.org \ --cc=m.kokryashkin@tarantool.org \ --cc=sergeyb@tarantool.org \ --cc=skaplun@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v2 luajit 4/6] test: rewrite misclib-getmetrics-capi test in C' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox