/usr/share/lua/5.1/luassert/assertions.lua is in lua-luassert 1.7.10-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | -- module will not return anything, only register assertions with the main assert engine
-- assertions take 2 parameters;
-- 1) state
-- 2) arguments list. The list has a member 'n' with the argument count to check for trailing nils
-- 3) level The level of the error position relative to the called function
-- returns; boolean; whether assertion passed
local assert = require('luassert.assert')
local astate = require ('luassert.state')
local util = require ('luassert.util')
local s = require('say')
local function format(val)
return astate.format_argument(val) or tostring(val)
end
local function set_failure_message(state, message)
if message ~= nil then
state.failure_message = message
end
end
local function unique(state, arguments, level)
local list = arguments[1]
local deep
local argcnt = arguments.n
if type(arguments[2]) == "boolean" or (arguments[2] == nil and argcnt > 2) then
deep = arguments[2]
set_failure_message(state, arguments[3])
else
if type(arguments[3]) == "boolean" then
deep = arguments[3]
end
set_failure_message(state, arguments[2])
end
for k,v in pairs(list) do
for k2, v2 in pairs(list) do
if k ~= k2 then
if deep and util.deepcompare(v, v2, true) then
return false
else
if v == v2 then
return false
end
end
end
end
end
return true
end
local function near(state, arguments, level)
local level = (level or 1) + 1
local argcnt = arguments.n
assert(argcnt > 2, s("assertion.internal.argtolittle", { "near", 3, tostring(argcnt) }), level)
local expected = tonumber(arguments[1])
local actual = tonumber(arguments[2])
local tolerance = tonumber(arguments[3])
local numbertype = "number or object convertible to a number"
assert(expected, s("assertion.internal.badargtype", { 1, "near", numbertype, format(arguments[1]) }), level)
assert(actual, s("assertion.internal.badargtype", { 2, "near", numbertype, format(arguments[2]) }), level)
assert(tolerance, s("assertion.internal.badargtype", { 3, "near", numbertype, format(arguments[3]) }), level)
-- switch arguments for proper output message
util.tinsert(arguments, 1, util.tremove(arguments, 2))
arguments[3] = tolerance
arguments.nofmt = arguments.nofmt or {}
arguments.nofmt[3] = true
set_failure_message(state, arguments[4])
return (actual >= expected - tolerance and actual <= expected + tolerance)
end
local function matches(state, arguments, level)
local level = (level or 1) + 1
local argcnt = arguments.n
assert(argcnt > 1, s("assertion.internal.argtolittle", { "matches", 2, tostring(argcnt) }), level)
local pattern = arguments[1]
local actual = nil
if util.hastostring(arguments[2]) or type(arguments[2]) == "number" then
actual = tostring(arguments[2])
end
local err_message
local init_arg_num = 3
for i=3,argcnt,1 do
if arguments[i] and type(arguments[i]) ~= "boolean" and not tonumber(arguments[i]) then
if i == 3 then init_arg_num = init_arg_num + 1 end
err_message = util.tremove(arguments, i)
break
end
end
local init = arguments[3]
local plain = arguments[4]
local stringtype = "string or object convertible to a string"
assert(type(pattern) == "string", s("assertion.internal.badargtype", { 1, "matches", "string", type(arguments[1]) }), level)
assert(actual, s("assertion.internal.badargtype", { 2, "matches", stringtype, format(arguments[2]) }), level)
assert(init == nil or tonumber(init), s("assertion.internal.badargtype", { init_arg_num, "matches", "number", type(arguments[3]) }), level)
-- switch arguments for proper output message
util.tinsert(arguments, 1, util.tremove(arguments, 2))
set_failure_message(state, err_message)
local retargs
local ok
if plain then
ok = (actual:find(pattern, init, plain) ~= nil)
retargs = ok and { pattern } or {}
else
retargs = { actual:match(pattern, init) }
ok = (retargs[1] ~= nil)
end
return ok, retargs
end
local function equals(state, arguments, level)
local level = (level or 1) + 1
local argcnt = arguments.n
assert(argcnt > 1, s("assertion.internal.argtolittle", { "equals", 2, tostring(argcnt) }), level)
local result = arguments[1] == arguments[2]
-- switch arguments for proper output message
util.tinsert(arguments, 1, util.tremove(arguments, 2))
set_failure_message(state, arguments[3])
return result
end
local function same(state, arguments, level)
local level = (level or 1) + 1
local argcnt = arguments.n
assert(argcnt > 1, s("assertion.internal.argtolittle", { "same", 2, tostring(argcnt) }), level)
if type(arguments[1]) == 'table' and type(arguments[2]) == 'table' then
local result, crumbs = util.deepcompare(arguments[1], arguments[2], true)
-- switch arguments for proper output message
util.tinsert(arguments, 1, util.tremove(arguments, 2))
arguments.fmtargs = arguments.fmtargs or {}
arguments.fmtargs[1] = { crumbs = crumbs }
arguments.fmtargs[2] = { crumbs = crumbs }
set_failure_message(state, arguments[3])
return result
end
local result = arguments[1] == arguments[2]
-- switch arguments for proper output message
util.tinsert(arguments, 1, util.tremove(arguments, 2))
set_failure_message(state, arguments[3])
return result
end
local function truthy(state, arguments, level)
set_failure_message(state, arguments[2])
return arguments[1] ~= false and arguments[1] ~= nil
end
local function falsy(state, arguments, level)
return not truthy(state, arguments, level)
end
local function has_error(state, arguments, level)
local level = (level or 1) + 1
local retargs = util.shallowcopy(arguments)
local func = arguments[1]
local err_expected = arguments[2]
local failure_message = arguments[3]
assert(util.callable(func), s("assertion.internal.badargtype", { 1, "error", "function or callable object", type(func) }), level)
local ok, err_actual = pcall(func)
if type(err_actual) == 'string' then
-- remove 'path/to/file:line: ' from string
err_actual = err_actual:gsub('^.-:%d+: ', '', 1)
end
retargs[1] = err_actual
arguments.nofmt = {}
arguments.n = 2
arguments[1] = (ok and '(no error)' or err_actual)
arguments[2] = (err_expected == nil and '(error)' or err_expected)
arguments.nofmt[1] = ok
arguments.nofmt[2] = (err_expected == nil)
set_failure_message(state, failure_message)
if ok or err_expected == nil then
return not ok, retargs
end
if type(err_expected) == 'string' then
-- err_actual must be (convertible to) a string
if util.hastostring(err_actual) then
err_actual = tostring(err_actual)
retargs[1] = err_actual
end
if type(err_actual) == 'string' then
return err_expected == err_actual, retargs
end
elseif type(err_expected) == 'number' then
if type(err_actual) == 'string' then
return tostring(err_expected) == tostring(tonumber(err_actual)), retargs
end
end
return same(state, {err_expected, err_actual, ["n"] = 2}), retargs
end
local function error_matches(state, arguments, level)
local level = (level or 1) + 1
local retargs = util.shallowcopy(arguments)
local argcnt = arguments.n
local func = arguments[1]
local pattern = arguments[2]
assert(argcnt > 1, s("assertion.internal.argtolittle", { "error_matches", 2, tostring(argcnt) }), level)
assert(util.callable(func), s("assertion.internal.badargtype", { 1, "error_matches", "function or callable object", type(func) }), level)
assert(pattern == nil or type(pattern) == "string", s("assertion.internal.badargtype", { 2, "error", "string", type(pattern) }), level)
local failure_message
local init_arg_num = 3
for i=3,argcnt,1 do
if arguments[i] and type(arguments[i]) ~= "boolean" and not tonumber(arguments[i]) then
if i == 3 then init_arg_num = init_arg_num + 1 end
failure_message = util.tremove(arguments, i)
break
end
end
local init = arguments[3]
local plain = arguments[4]
assert(init == nil or tonumber(init), s("assertion.internal.badargtype", { init_arg_num, "matches", "number", type(arguments[3]) }), level)
local ok, err_actual = pcall(func)
if type(err_actual) == 'string' then
-- remove 'path/to/file:line: ' from string
err_actual = err_actual:gsub('^.-:%d+: ', '', 1)
end
retargs[1] = err_actual
arguments.nofmt = {}
arguments.n = 2
arguments[1] = (ok and '(no error)' or err_actual)
arguments[2] = pattern
arguments.nofmt[1] = ok
arguments.nofmt[2] = false
set_failure_message(state, failure_message)
if ok then return not ok, retargs end
if err_actual == nil and pattern == nil then
return true, {}
end
-- err_actual must be (convertible to) a string
if util.hastostring(err_actual) then
err_actual = tostring(err_actual)
retargs[1] = err_actual
end
if type(err_actual) == 'string' then
local ok
local retargs_ok
if plain then
retargs_ok = { pattern }
ok = (err_actual:find(pattern, init, plain) ~= nil)
else
retargs_ok = { err_actual:match(pattern, init) }
ok = (retargs_ok[1] ~= nil)
end
if ok then retargs = retargs_ok end
return ok, retargs
end
return false, retargs
end
local function is_true(state, arguments, level)
util.tinsert(arguments, 2, true)
set_failure_message(state, arguments[3])
return arguments[1] == arguments[2]
end
local function is_false(state, arguments, level)
util.tinsert(arguments, 2, false)
set_failure_message(state, arguments[3])
return arguments[1] == arguments[2]
end
local function is_type(state, arguments, level, etype)
util.tinsert(arguments, 2, "type " .. etype)
arguments.nofmt = arguments.nofmt or {}
arguments.nofmt[2] = true
set_failure_message(state, arguments[3])
return arguments.n > 1 and type(arguments[1]) == etype
end
local function returned_arguments(state, arguments, level)
arguments[1] = tostring(arguments[1])
arguments[2] = tostring(arguments.n - 1)
arguments.nofmt = arguments.nofmt or {}
arguments.nofmt[1] = true
arguments.nofmt[2] = true
if arguments.n < 2 then arguments.n = 2 end
return arguments[1] == arguments[2]
end
local function set_message(state, arguments, level)
state.failure_message = arguments[1]
end
local function is_boolean(state, arguments, level) return is_type(state, arguments, level, "boolean") end
local function is_number(state, arguments, level) return is_type(state, arguments, level, "number") end
local function is_string(state, arguments, level) return is_type(state, arguments, level, "string") end
local function is_table(state, arguments, level) return is_type(state, arguments, level, "table") end
local function is_nil(state, arguments, level) return is_type(state, arguments, level, "nil") end
local function is_userdata(state, arguments, level) return is_type(state, arguments, level, "userdata") end
local function is_function(state, arguments, level) return is_type(state, arguments, level, "function") end
local function is_thread(state, arguments, level) return is_type(state, arguments, level, "thread") end
assert:register("modifier", "message", set_message)
assert:register("assertion", "true", is_true, "assertion.same.positive", "assertion.same.negative")
assert:register("assertion", "false", is_false, "assertion.same.positive", "assertion.same.negative")
assert:register("assertion", "boolean", is_boolean, "assertion.same.positive", "assertion.same.negative")
assert:register("assertion", "number", is_number, "assertion.same.positive", "assertion.same.negative")
assert:register("assertion", "string", is_string, "assertion.same.positive", "assertion.same.negative")
assert:register("assertion", "table", is_table, "assertion.same.positive", "assertion.same.negative")
assert:register("assertion", "nil", is_nil, "assertion.same.positive", "assertion.same.negative")
assert:register("assertion", "userdata", is_userdata, "assertion.same.positive", "assertion.same.negative")
assert:register("assertion", "function", is_function, "assertion.same.positive", "assertion.same.negative")
assert:register("assertion", "thread", is_thread, "assertion.same.positive", "assertion.same.negative")
assert:register("assertion", "returned_arguments", returned_arguments, "assertion.returned_arguments.positive", "assertion.returned_arguments.negative")
assert:register("assertion", "same", same, "assertion.same.positive", "assertion.same.negative")
assert:register("assertion", "matches", matches, "assertion.matches.positive", "assertion.matches.negative")
assert:register("assertion", "match", matches, "assertion.matches.positive", "assertion.matches.negative")
assert:register("assertion", "near", near, "assertion.near.positive", "assertion.near.negative")
assert:register("assertion", "equals", equals, "assertion.equals.positive", "assertion.equals.negative")
assert:register("assertion", "equal", equals, "assertion.equals.positive", "assertion.equals.negative")
assert:register("assertion", "unique", unique, "assertion.unique.positive", "assertion.unique.negative")
assert:register("assertion", "error", has_error, "assertion.error.positive", "assertion.error.negative")
assert:register("assertion", "errors", has_error, "assertion.error.positive", "assertion.error.negative")
assert:register("assertion", "error_matches", error_matches, "assertion.error.positive", "assertion.error.negative")
assert:register("assertion", "error_match", error_matches, "assertion.error.positive", "assertion.error.negative")
assert:register("assertion", "matches_error", error_matches, "assertion.error.positive", "assertion.error.negative")
assert:register("assertion", "match_error", error_matches, "assertion.error.positive", "assertion.error.negative")
assert:register("assertion", "truthy", truthy, "assertion.truthy.positive", "assertion.truthy.negative")
assert:register("assertion", "falsy", falsy, "assertion.falsy.positive", "assertion.falsy.negative")
|