Files
2026-07-13 12:32:21 +08:00

197 lines
6.3 KiB
Perl

package t::Util;
use strict;
use warnings;
use Cwd qw(cwd);
our $cwd = cwd();
our $LuaPackagePath = "lua_package_path \'$cwd/?.lua;$cwd/?/init.lua;;\';";
our $JitLogConfig = <<_EOC_;
local verbose = false
-- local verbose = true
local outfile = "$Test::Nginx::Util::ErrLogFile"
if verbose then
local dump = require "jit.dump"
dump.on(nil, outfile)
else
local v = require "jit.v"
v.on(outfile)
end
_EOC_
our $InitByLuaBlockConfig = <<_EOC_;
local log = ngx.log
local ERR = ngx.ERR
if os.getenv("PDK_PHASE_CHECKS_LUACOV") == "1" then
require("luacov.runner")("t/phase_checks.luacov")
jit.off()
elseif os.getenv("PDK_LUACOV") == "1" then
require("luacov.runner")("t/pdk.luacov")
jit.off()
end
local private_phases = require("kong.pdk.private.phases")
local phases = private_phases.phases
-- This function executes 1 or more pdk methods twice: the first time with phase
-- checking deactivated, and the second time with phase checking activated.
-- Params:
-- * phase: the phase we want to test, i.e. "access"
-- * skip_fnlist controls a check: by default, this method
-- will check that the provided list of methods is "complete" - that
-- all the methods inside the `mod` (see below) are covered. Setting
-- `skip_fnlist` to `true` will skip that test (so the `mod` can have
-- methods that go untested)
--
-- This method also reads from 2 globals:
-- * phase_check_module is just a string used to determine the "module"
-- For example, if `phase_check_module` is "kong.response", then `mod` is "response"
-- * phase_check_data is an array of tables with this format:
-- {
-- method = "exit", -- the method inside mod, `kong.response.exit` for example
-- args = { 200 }, -- passed to the method
-- init_worker = false, -- expected to always throw an error on init_worker phase
-- certificate = "pending", -- ignored phase
-- rewrite = true, -- expected to work with and without the phase checker
-- access = true,
-- header_filter = "forced false", -- exit will only error with the phase_checks active
-- body_filter = false,
-- log = false,
-- admin_api = true,
-- }
--
function phase_check_functions(phase, skip_fnlist)
-- mock balancer structure
ngx.ctx.balancer_data = {}
local mod
do
local PDK = require "kong.pdk"
local pdk = PDK.new({ enabled_headers = { ["Server"] = true } })
mod = pdk
for part in phase_check_module:gmatch("[^.]+") do
mod = mod[part]
end
end
local entries = {}
for _, entry in ipairs(phase_check_data) do
entries[entry.method] = true
end
if not skip_fnlist then
for fname, fn in pairs(mod) do
if type(fn) == "function" and not entries[fname] then
log(ERR, "function " .. fname .. " has no phase checking data")
end
end
end
for _, fdata in ipairs(phase_check_data) do
local fname = fdata.method
local fn = mod[fname]
if type(fn) ~= "function" then
log(ERR, "function " .. fname .. " does not exist in module")
goto continue
end
local msg = "in " .. phases[phase] .. ", " ..
fname .. " expected "
-- Run function with phase checked disabled
if kong then
kong.ctx = nil
end
-- kong = nil
ngx.ctx.KONG_PHASE = nil
local expected = fdata[phases[phase]]
if expected == "pending" then
goto continue
end
local forced_false = expected == "forced false"
if forced_false then
expected = true
end
local ok1, err1 = pcall(fn, unpack(fdata.args or {}))
if ok1 ~= expected then
local errmsg = ""
if type(err1) == "string" then
errmsg = "; error: " .. err1:gsub(",", ";")
end
log(ERR, msg, tostring(expected),
" when phase check is disabled", errmsg)
ok1 = not ok1
end
if not forced_false
and ok1 == false
and err1
and not err1:match("attempt to index field ")
and not err1:match("API disabled in the ")
and not err1:match("headers have already been sent") then
log(ERR, msg, "an OpenResty error but got ", (err1:gsub(",", ";")))
end
-- Re-enable phase checking and compare results
if not kong then
kong = {}
end
kong.ctx = { core = { } }
ngx.ctx.KONG_PHASE = phase
if forced_false then
ok1, err1 = false, ""
expected = false
end
---[[
local ok2, err2 = pcall(fn, unpack(fdata.args or {}))
if ok1 then
-- succeeded without phase checking,
-- phase checking should not block it.
if not ok2 then
log(ERR, msg, "true when phase check is enabled; got: ", (err2:gsub(",", ";")))
end
else
if ok2 then
log(ERR, msg, "false when phase check is enabled")
end
-- if failed with OpenResty phase error
if err1 and err1:match("API disabled in the ") then
-- should replace with a Kong error
if not err2:match("function cannot be called") then
log(ERR, msg, "a Kong-generated error; got: ", (err2:gsub(",", ";")))
end
end
end
--]]
::continue::
end
end
_EOC_
our $HttpConfig = <<_EOC_;
$LuaPackagePath
init_by_lua_block {
$InitByLuaBlockConfig
}
_EOC_
1;