From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 8EA6947E8EB; Mon, 29 May 2023 19:15:22 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 8EA6947E8EB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1685376922; bh=jiAT9FYs04RMUnmxZ+LX0MvVJMRvo8EQ3VdFxv86UG8=; h=Date:To:Cc:References:In-Reply-To:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=Hl2Vhk6H6cP8EI6iGuszrf7DJ4e5gSZ6N+bxnwuCjAdGzVyBG1xS51tN1JmhyX7II fH7mXOBXrqd9GtwWTxo1HvZqkemUVNKftUyDOVecw5BLI4QbH8AsHg9o19sBxHuXcE Jqr6buhCmLS1RIkZCsFmlQPUb3NvcvLLUNYFlfGE= Received: from smtp50.i.mail.ru (smtp50.i.mail.ru [95.163.41.92]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id C6E4647E8EB for ; Mon, 29 May 2023 19:15:20 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org C6E4647E8EB Received: by smtp50.i.mail.ru with esmtpa (envelope-from ) id 1q3fWh-00EacZ-9F; Mon, 29 May 2023 19:15:20 +0300 Message-ID: <93782bbf-c742-8c81-cad5-ae53dcd680ee@tarantool.org> Date: Mon, 29 May 2023 19:15:18 +0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0 Content-Language: en-US To: Sergey Kaplun , Igor Munkin , Maxim Kokryashkin Cc: tarantool-patches@dev.tarantool.org References: <0ceed30db5259087a6733c429ed5a2502468ce40.1684442182.git.skaplun@tarantool.org> In-Reply-To: <0ceed30db5259087a6733c429ed5a2502468ce40.1684442182.git.skaplun@tarantool.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Mailru-Src: smtp X-4EC0790: 10 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD9FA9FE7958A526B773B5D1199AD0FAA30688DC8E9E56BDE9F00894C459B0CD1B9DEBBAF9B99E8543F6C8146639373FBD0A283591F6C1149142DF3BC933CAA2D70 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7A8E2F8CB64581590EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637801520E8C0CFD3888638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D897E9CFC5E7566A7AB3113CBEA705B000117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCB816BE3345416868389733CBF5DBD5E9C8A9BA7A39EFB766F5D81C698A659EA7CC7F00164DA146DA9985D098DBDEAEC886D40F53BA192295F6B57BC7E6449061A352F6E88A58FB86F5D81C698A659EA73AA81AA40904B5D9A18204E546F3947CF3F7A3D03CB1379C302FCEF25BFAB3454AD6D5ED66289B52698AB9A7B718F8C46E0066C2D8992A16725E5C173C3A84C3D376232643AC164BBA3038C0950A5D36B5C8C57E37DE458B330BD67F2E7D9AF16D1867E19FE14079C09775C1D3CA48CF3D321E7403792E342EB15956EA79C166A417C69337E82CC275ECD9A6C639B01B78DA827A17800CE74ABCC139FF3F849B731C566533BA786AA5CC5B56E945C8DA X-C1DE0DAB: 0D63561A33F958A5A92047E8AC2C5C66BA741D999270650AF1536C887D6127A3F87CCE6106E1FC07E67D4AC08A07B9B0CE135D2742255B35CB5012B2E24CD356 X-C8649E89: 1C3962B70DF3F0ADE00A9FD3E00BEEDF3FED46C3ACD6F73ED3581295AF09D3DF87807E0823442EA2ED31085941D9CD0AF7F820E7B07EA4CF106FA600371CAA5AFCA4A4DD520194F329FB61B27BEDB23B0F0992DC8ABE511D01EE030787A60D78A0A56A47F2C7DF6420B7C8F0C6013DFC26B7453E227F16F2F4E8A8FB6BF8EBF5 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojjwJ7vqadnRvlA929OrWBcg== X-Mailru-Sender: 11C2EC085EDE56FAC07928AF2646A7695C73EEB4EF2AE2B5F46BFBAC707C41346565FCDE7E403FA1EBA65886582A37BD66FEC6BF5C9C28D98A98C1125256619760D574B6FC815AB872D6B4FCE48DF648AE208404248635DF X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH v2 luajit 4/6] test: rewrite misclib-getmetrics-capi test in C X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Sergey Bronnikov via Tarantool-patches Reply-To: Sergey Bronnikov Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" 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 , 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 > +-- . > +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 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 > -#include > -#include > - > -#include > - > -#undef NDEBUG > -#include > - > -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; > -}