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 8A52B4DD247; Wed, 7 Jun 2023 19:25:48 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 8A52B4DD247 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1686155148; bh=D0b32KkYQ1trEyE3U4fdzKj+6tFRM+rimicdyqeHGis=; 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=Ns06V+YXC3Ab+ADMwoNNicZDviN8FKPnY1pFH+PgKb4r0aBib5w+VeW6pjumWyyXF r7jvmhTjKIyY0zk0/galZXRTWckXwqqR1UP4Zh+gqhJdGR2P0OewI9XRyt2D6p00/k 1zQRNpCmfUr81l8OaO3zrQwHwFnBcn43QJJj6Z8I= Received: from smtp56.i.mail.ru (smtp56.i.mail.ru [95.163.41.94]) (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 BD5494DD247 for ; Wed, 7 Jun 2023 19:25:46 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org BD5494DD247 Received: by smtp56.i.mail.ru with esmtpa (envelope-from ) id 1q6vyj-00D5De-CF; Wed, 07 Jun 2023 19:25:46 +0300 Message-ID: <232ac2a1-efec-45c4-9a68-b9c59c1fd3fc@tarantool.org> Date: Wed, 7 Jun 2023 19:25:44 +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: In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Mailru-Src: smtp X-4EC0790: 10 X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD93D74B10BAB639DE302E1C0119B995D3D6F61403B2504378A00894C459B0CD1B9B4B47883509EA4E7C4589085BF5A51FF36E96C74CFF3B7DF5E522EEE8CA89B86 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7CB1C1CF81BFF4FD8EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637DD92412F72BDCE938638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D849EDC8F9DB0AB99342DA9B9153F9DC8B117882F4460429724CE54428C33FAD305F5C1EE8F4F765FC55D5BE2F85BDEC5FA471835C12D1D9774AD6D5ED66289B52BA9C0B312567BB23117882F4460429728776938767073520CCD848CCB6FE560C6FD1C55BDD38FC3FD2E47CDBA5A96583BA9C0B312567BB2376E601842F6C81A19E625A9149C048EE38D4DC57D478E688148812EF9080FC94D8FC6C240DEA7642DBF02ECDB25306B2B78CF848AE20165D0A6AB1C7CE11FEE3706E30CA5231861903F1AB874ED89028C4224003CC836476E2F48590F00D11D6E2021AF6380DFAD1A18204E546F3947CB11811A4A51E3B096D1867E19FE1407959CC434672EE6371089D37D7C0E48F6C8AA50765F7900637BBEA499411984DA1EFF80C71ABB335746BA297DBC24807EABDAD6C7F3747799A X-B7AD71C0: 4965CFDFE0519134C1FE400A9E48C5401DD40DE57556AFB266D16FC5F53507A1816E0A2A8F779BBED8D40077074E805C66D16FC5F53507A117535B0CF9F6D0C3EE9D5CB6078CC77CAE6527C5EC657E48146EF582D857B11F X-C1DE0DAB: 0D63561A33F958A59351C148544B65B481558B329FC336D35F7DD79AB5A655D8F87CCE6106E1FC07E67D4AC08A07B9B0CE135D2742255B35CB5012B2E24CD356 X-C8649E89: 1C3962B70DF3F0AD75DCE07D45A749953FED46C3ACD6F73ED3581295AF09D3DF87807E0823442EA2ED31085941D9CD0AF7F820E7B07EA4CF25038D2404A273CBC76C8F24AE42C3F0C9C4572512C0FDE69871A0D93E4FC417A96D85E4AF70DF37588A46A5EBCE8E37A9A25D4C10157A30CF90FD33F53920E1A74DFFEFA5DC0E7F02C26D483E81D6BE0DBAE6F56676BC7117BB6831D7356A2DEC5B5AD62611EEC62B5AFB4261A09AF0 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojC5OBK/dlsGMPuU6S9IUl4w== X-Mailru-Sender: C4F68CFF4024C8867DFDF7C7F25884586BA439E9ABDE282B03FC9B4D96FC90A22BCC59BF2CB9878F282EC151BADDC1D3523A6D01B4765B2DFB59E2DDD9FE06B14FA522850F29BC30B0DAF586E7D11B3E67EA787935ED9F1B X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH v3 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! LGTM On 6/5/23 13:41, 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. > > Part of tarantool/tarantool#7900 > --- > src/CMakeLists.txt | 2 + > .../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 -------------- > 6 files changed, 383 insertions(+), 317 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/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-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..724b551a > --- /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, "misclib-getmetrics-capi-script.lua"); > + 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; > -}