197 lines
6.3 KiB
Perl
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;
|