From 08f5667a9a93ed2793b9cb1a2ee774c76659052c Mon Sep 17 00:00:00 2001 From: Sergey Bronnikov Date: Thu, 26 Jun 2025 10:00:49 +0300 Subject: [PATCH] tests/lapi: add sysprof tests The patch adds tests for sysprof built into LuaJIT and Tarantool's sysprof. --- tests/lapi/jit_p_test.lua | 69 ++++++++++++++++++++++++++++++++ tests/lapi/misc_sysprof_test.lua | 41 +++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 tests/lapi/jit_p_test.lua create mode 100644 tests/lapi/misc_sysprof_test.lua diff --git a/tests/lapi/jit_p_test.lua b/tests/lapi/jit_p_test.lua new file mode 100644 index 0000000..9eeb5ed --- /dev/null +++ b/tests/lapi/jit_p_test.lua @@ -0,0 +1,69 @@ +--[[ +SPDX-License-Identifier: ISC +Copyright (c) 2025, Sergey Bronnikov. + +LuaJIT profiler, +https://luajit.org/ext_profiler.html +]] + +local luzer = require("luzer") +local test_lib = require("lib") + +if test_lib.lua_version() ~= "LuaJIT" then + print("Unsupported version.") + os.exit(0) +end + +local sysprof = require("jit.profile") + +local MAX_INT = test_lib.MAX_INT +local MIN_INT = test_lib.MIN_INT + +local SYSPROF_DEFAULT_INTERVAL = 1 -- ms + +local SYSPROF_OPTIONS = { + "f", -- Profile with precision down to the function level. + "l", -- Profile with precision down to the line level. + "i", -- Sampling interval in milliseconds (default 10ms). +} + +local DUMPSTACK_FMT = { + "p", -- Preserve the full path for module names. + "f", -- Dump the function name if it can be derived. + "F", -- Ditto, but dump module:name. + "l", -- Dump module:line. + "Z", -- Zap the following characters for the last dumped frame. +} + +local function sysprof_dumpstack(fdp) + local fmt = fdp:oneof(DUMPSTACK_FMT) + local depth = fdp:consume_integer(MIN_INT, MAX_INT) + local dump = sysprof.dumpstack(fmt, depth) + assert(dump) +end + +local function TestOneInput(buf) + local fdp = luzer.FuzzedDataProvider(buf) + local chunk = fdp:consume_string(test_lib.MAX_STR_LEN) + -- LuaJIT ASSERT lj_bcread.c:123: bcread_byte: buffer read + -- overflow. + local func = load(chunk, "luzer", "t") + + local sysprof_option = fdp:oneof(SYSPROF_OPTIONS) + if sysprof_option == "i" then + sysprof_option = ("i%d"):format(SYSPROF_DEFAULT_INTERVAL) + end + local cb = function(_thread, _samples, _vmstate) + -- Nope. + end + + sysprof.start(sysprof_option, cb) + pcall(func) + sysprof_dumpstack(fdp) + sysprof.stop() +end + +local args = { + artifact_prefix = "jit_p_test", +} +luzer.Fuzz(TestOneInput, nil, args) diff --git a/tests/lapi/misc_sysprof_test.lua b/tests/lapi/misc_sysprof_test.lua new file mode 100644 index 0000000..18cc163 --- /dev/null +++ b/tests/lapi/misc_sysprof_test.lua @@ -0,0 +1,41 @@ +--[[ +SPDX-License-Identifier: ISC +Copyright (c) 2025, Sergey Bronnikov. + +Tarantool's platform profiler, +https://www.tarantool.io/en/doc/latest/tooling/luajit_sysprof/ +]] + +local luzer = require("luzer") +local test_lib = require("lib") + +local has_sysprof, sysprof = pcall(require, "misc.sysprof") +if not has_sysprof then + print("Unsupported version.") + os.exit(0) +end + +local SYSPROF_DEFAULT_INTERVAL = 1 -- ms + +local function TestOneInput(buf) + local fdp = luzer.FuzzedDataProvider(buf) + local chunk = fdp:consume_string(test_lib.MAX_STR_LEN) + -- LuaJIT ASSERT lj_bcread.c:123: bcread_byte: buffer read + -- overflow. + local func = load(chunk, "luzer", "t") + local sysprof_mode = fdp:oneof({"D", "L", "C"}) + + assert(sysprof.start({ + interval = SYSPROF_DEFAULT_INTERVAL, + mode = sysprof_mode, + path = "/dev/null", + })) + pcall(func) + sysprof.report() + sysprof.stop() +end + +local args = { + artifact_prefix = "misc_sysprof_", +} +luzer.Fuzz(TestOneInput, nil, args)