@@ -1,22 +0,0 @@ | |||
MIT License Terms | |||
================= | |||
Copyright (c) 2012 Olivine Labs, LLC. | |||
Permission is hereby granted, free of charge, to any person obtaining a copy of | |||
this software and associated documentation files (the "Software"), to deal in | |||
the Software without restriction, including without limitation the rights to | |||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||
of the Software, and to permit persons to whom the Software is furnished to do | |||
so, subject to the following conditions: | |||
The above copyright notice and this permission notice shall be included in all | |||
copies or substantial portions of the Software. | |||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
SOFTWARE. |
@@ -1,3 +0,0 @@ | |||
return require 'busted.init' |
@@ -1,60 +0,0 @@ | |||
return { | |||
getfenv = getfenv or function(f) | |||
f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func) | |||
local name, value | |||
local up = 0 | |||
repeat | |||
up = up + 1 | |||
name, value = debug.getupvalue(f, up) | |||
until name == '_ENV' or name == nil | |||
return value | |||
end, | |||
setfenv = setfenv or function(f, t) | |||
f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func) | |||
local name | |||
local up = 0 | |||
repeat | |||
up = up + 1 | |||
name = debug.getupvalue(f, up) | |||
until name == '_ENV' or name == nil | |||
if name then | |||
debug.upvaluejoin(f, up, function() return name end, 1) | |||
debug.setupvalue(f, up, t) | |||
end | |||
if f ~= 0 then return f end | |||
end, | |||
unpack = table.unpack or unpack, | |||
osexit = function(code, close) | |||
if close and _VERSION == 'Lua 5.1' then | |||
-- From Lua 5.1 manual: | |||
-- > The userdata itself is freed only in the next | |||
-- > garbage-collection cycle. | |||
-- Call collectgarbage() while collectgarbage('count') | |||
-- changes + 3 times, at least 3 times, | |||
-- at max 100 times (to prevent infinite loop). | |||
local times_const = 0 | |||
for i = 1, 100 do | |||
local count_before = collectgarbage("count") | |||
collectgarbage() | |||
local count_after = collectgarbage("count") | |||
if count_after == count_before then | |||
times_const = times_const + 1 | |||
if times_const > 3 then | |||
break | |||
end | |||
else | |||
times_const = 0 | |||
end | |||
end | |||
end | |||
os.exit(code, close) | |||
end, | |||
} |
@@ -1,91 +0,0 @@ | |||
local tablex = require 'pl.tablex' | |||
local function save() | |||
local g = {} | |||
for k,_ in next, _G, nil do | |||
g[k] = rawget(_G, k) | |||
end | |||
return { | |||
gmt = getmetatable(_G), | |||
g = g, | |||
loaded = tablex.copy(package.loaded) | |||
} | |||
end | |||
local function restore(state) | |||
setmetatable(_G, state.gmt) | |||
for k,_ in next, _G, nil do | |||
rawset(_G, k, state.g[k]) | |||
end | |||
for k,_ in pairs(package.loaded) do | |||
package.loaded[k] = state.loaded[k] | |||
end | |||
end | |||
return function() | |||
local context = {} | |||
local data = {} | |||
local parents = {} | |||
local children = {} | |||
local stack = {} | |||
function context.ref() | |||
local ref = {} | |||
local ctx = data | |||
function ref.get(key) | |||
if not key then return ctx end | |||
return ctx[key] | |||
end | |||
function ref.set(key, value) | |||
ctx[key] = value | |||
end | |||
function ref.clear() | |||
data = {} | |||
parents = {} | |||
children = {} | |||
stack = {} | |||
ctx = data | |||
end | |||
function ref.attach(child) | |||
if not children[ctx] then children[ctx] = {} end | |||
parents[child] = ctx | |||
table.insert(children[ctx], child) | |||
end | |||
function ref.children(parent) | |||
return children[parent] or {} | |||
end | |||
function ref.parent(child) | |||
return parents[child] | |||
end | |||
function ref.push(current) | |||
if not parents[current] then error('Detached child. Cannot push.') end | |||
if ctx ~= current and current.descriptor == 'file' then | |||
current.state = save() | |||
end | |||
table.insert(stack, ctx) | |||
ctx = current | |||
end | |||
function ref.pop() | |||
local current = ctx | |||
ctx = table.remove(stack) | |||
if ctx ~= current and current.state then | |||
restore(current.state) | |||
current.state = nil | |||
end | |||
if not ctx then error('Context stack empty. Cannot pop.') end | |||
end | |||
return ref | |||
end | |||
return context | |||
end |
@@ -1,237 +0,0 @@ | |||
local getfenv = require 'busted.compatibility'.getfenv | |||
local setfenv = require 'busted.compatibility'.setfenv | |||
local unpack = require 'busted.compatibility'.unpack | |||
local path = require 'pl.path' | |||
local pretty = require 'pl.pretty' | |||
local throw = error | |||
local failureMt = { | |||
__index = {}, | |||
__tostring = function(e) return tostring(e.message) end, | |||
__type = 'failure' | |||
} | |||
local failureMtNoString = { | |||
__index = {}, | |||
__type = 'failure' | |||
} | |||
local pendingMt = { | |||
__index = {}, | |||
__tostring = function(p) return p.message end, | |||
__type = 'pending' | |||
} | |||
local function metatype(obj) | |||
local otype = type(obj) | |||
return otype == 'table' and (getmetatable(obj) or {}).__type or otype | |||
end | |||
local function hasToString(obj) | |||
return type(obj) == 'string' or (getmetatable(obj) or {}).__tostring | |||
end | |||
return function() | |||
local mediator = require 'mediator'() | |||
local busted = {} | |||
busted.version = '2.0.rc6-0' | |||
local root = require 'busted.context'() | |||
busted.context = root.ref() | |||
local environment = require 'busted.environment'(busted.context) | |||
busted.environment = { | |||
set = environment.set, | |||
wrap = function(callable) | |||
if (type(callable) == 'function' or getmetatable(callable).__call) then | |||
-- prioritize __call if it exists, like in files | |||
environment.wrap((getmetatable(callable) or {}).__call or callable) | |||
end | |||
end | |||
} | |||
busted.executors = {} | |||
local executors = {} | |||
busted.status = require 'busted.status' | |||
function busted.getTrace(element, level, msg) | |||
level = level or 3 | |||
local thisdir = path.dirname(debug.getinfo(1, 'Sl').source) | |||
local info = debug.getinfo(level, 'Sl') | |||
while info.what == 'C' or info.short_src:match('luassert[/\\].*%.lua$') or | |||
(info.source:sub(1,1) == '@' and thisdir == path.dirname(info.source)) do | |||
level = level + 1 | |||
info = debug.getinfo(level, 'Sl') | |||
end | |||
info.traceback = debug.traceback('', level) | |||
info.message = msg | |||
local file = busted.getFile(element) | |||
return file.getTrace(file.name, info) | |||
end | |||
function busted.rewriteMessage(element, message, trace) | |||
local file = busted.getFile(element) | |||
local msg = hasToString(message) and tostring(message) | |||
msg = msg or (message ~= nil and pretty.write(message) or 'Nil error') | |||
msg = (file.rewriteMessage and file.rewriteMessage(file.name, msg) or msg) | |||
local hasFileLine = msg:match('^[^\n]-:%d+: .*') | |||
if not hasFileLine then | |||
local trace = trace or busted.getTrace(element, 3, message) | |||
local fileline = trace.short_src .. ':' .. trace.currentline .. ': ' | |||
msg = fileline .. msg | |||
end | |||
return msg | |||
end | |||
function busted.publish(...) | |||
return mediator:publish(...) | |||
end | |||
function busted.subscribe(...) | |||
return mediator:subscribe(...) | |||
end | |||
function busted.getFile(element) | |||
local parent = busted.context.parent(element) | |||
while parent do | |||
if parent.file then | |||
local file = parent.file[1] | |||
return { | |||
name = file.name, | |||
getTrace = file.run.getTrace, | |||
rewriteMessage = file.run.rewriteMessage | |||
} | |||
end | |||
if parent.descriptor == 'file' then | |||
return { | |||
name = parent.name, | |||
getTrace = parent.run.getTrace, | |||
rewriteMessage = parent.run.rewriteMessage | |||
} | |||
end | |||
parent = busted.context.parent(parent) | |||
end | |||
return parent | |||
end | |||
function busted.fail(msg, level) | |||
local rawlevel = (type(level) ~= 'number' or level <= 0) and level | |||
local level = level or 1 | |||
local _, emsg = pcall(throw, msg, rawlevel or level+2) | |||
local e = { message = emsg } | |||
setmetatable(e, hasToString(msg) and failureMt or failureMtNoString) | |||
throw(e, rawlevel or level+1) | |||
end | |||
function busted.pending(msg) | |||
local p = { message = msg } | |||
setmetatable(p, pendingMt) | |||
throw(p) | |||
end | |||
function busted.replaceErrorWithFail(callable) | |||
local env = {} | |||
local f = (getmetatable(callable) or {}).__call or callable | |||
setmetatable(env, { __index = getfenv(f) }) | |||
env.error = busted.fail | |||
setfenv(f, env) | |||
end | |||
function busted.safe(descriptor, run, element) | |||
busted.context.push(element) | |||
local trace, message | |||
local status = 'success' | |||
local ret = { xpcall(run, function(msg) | |||
local errType = metatype(msg) | |||
status = ((errType == 'pending' or errType == 'failure') and errType or 'error') | |||
trace = busted.getTrace(element, 3, msg) | |||
message = busted.rewriteMessage(element, msg, trace) | |||
end) } | |||
if not ret[1] then | |||
busted.publish({ status, descriptor }, element, busted.context.parent(element), message, trace) | |||
end | |||
ret[1] = busted.status(status) | |||
busted.context.pop() | |||
return unpack(ret) | |||
end | |||
function busted.register(descriptor, executor) | |||
executors[descriptor] = executor | |||
local publisher = function(name, fn) | |||
if not fn and type(name) == 'function' then | |||
fn = name | |||
name = nil | |||
end | |||
local trace | |||
local ctx = busted.context.get() | |||
if busted.context.parent(ctx) then | |||
trace = busted.getTrace(ctx, 3, name) | |||
end | |||
local publish = function(f) | |||
busted.publish({ 'register', descriptor }, name, f, trace) | |||
end | |||
if fn then publish(fn) else return publish end | |||
end | |||
busted.executors[descriptor] = publisher | |||
if descriptor ~= 'file' then | |||
environment.set(descriptor, publisher) | |||
end | |||
busted.subscribe({ 'register', descriptor }, function(name, fn, trace) | |||
local ctx = busted.context.get() | |||
local plugin = { | |||
descriptor = descriptor, | |||
name = name, | |||
run = fn, | |||
trace = trace | |||
} | |||
busted.context.attach(plugin) | |||
if not ctx[descriptor] then | |||
ctx[descriptor] = { plugin } | |||
else | |||
ctx[descriptor][#ctx[descriptor]+1] = plugin | |||
end | |||
end) | |||
end | |||
function busted.alias(alias, descriptor) | |||
local publisher = busted.executors[descriptor] | |||
busted.executors[alias] = publisher | |||
environment.set(alias, publisher) | |||
end | |||
function busted.execute(current) | |||
if not current then current = busted.context.get() end | |||
for _, v in pairs(busted.context.children(current)) do | |||
local executor = executors[v.descriptor] | |||
if executor and not busted.skipAll then | |||
busted.safe(v.descriptor, function() executor(v) end, v) | |||
end | |||
end | |||
end | |||
return busted | |||
end |
@@ -1,121 +0,0 @@ | |||
local M = {} | |||
M.wait = function(self, ...) | |||
local tlist = { ... } | |||
for _, token in ipairs(tlist) do | |||
if type(token) ~= 'string' then | |||
error('Wait tokens must be strings. Got '..type(token), 2) | |||
end | |||
table.insert(self.tokens, token) | |||
end | |||
end | |||
M.wait_unordered = function(self, ...) | |||
self.ordered = false | |||
self:wait(...) | |||
end | |||
M.wait_ordered = function(self, ...) | |||
self.ordered = true | |||
self:wait(...) | |||
end | |||
M.tokenlist = function(self) | |||
local list | |||
if #self.tokens_done == 0 then | |||
list = 'No tokens received.' | |||
else | |||
list = 'Tokens received ('..tostring(#self.tokens_done)..')' | |||
local s = ': ' | |||
for _,t in ipairs(self.tokens_done) do | |||
list = list .. s .. '\''..t..'\'' | |||
s = ', ' | |||
end | |||
list = list .. '.' | |||
end | |||
if #self.tokens == 0 then | |||
list = list .. ' No more tokens expected.' | |||
else | |||
list = list .. ' Tokens not received ('..tostring(#self.tokens)..')' | |||
local s = ': ' | |||
for _, t in ipairs(self.tokens) do | |||
list = list .. s .. '\''..t..'\'' | |||
s = ', ' | |||
end | |||
list = list .. '.' | |||
end | |||
return list | |||
end | |||
M.done = function(self, ...) self:_done(...) end -- extra wrapper for same error level constant as __call method | |||
M._done = function(self, token) | |||
if token then | |||
if type(token) ~= 'string' then | |||
error('Wait tokens must be strings. Got '..type(token), 3) | |||
end | |||
if self.ordered then | |||
if self.tokens[1] == token then | |||
table.remove(self.tokens, 1) | |||
table.insert(self.tokens_done, token) | |||
else | |||
if self.tokens[1] then | |||
error(('Bad token, expected \'%s\' got \'%s\'. %s'):format(self.tokens[1], token, self:tokenlist()), 3) | |||
else | |||
error(('Bad token (no more tokens expected) got \'%s\'. %s'):format(token, self:tokenlist()), 3) | |||
end | |||
end | |||
else | |||
-- unordered | |||
for i, t in ipairs(self.tokens) do | |||
if t == token then | |||
table.remove(self.tokens, i) | |||
table.insert(self.tokens_done, token) | |||
token = nil | |||
break | |||
end | |||
end | |||
if token then | |||
error(('Unknown token \'%s\'. %s'):format(token, self:tokenlist()), 3) | |||
end | |||
end | |||
end | |||
if not next(self.tokens) then | |||
-- no more tokens, so we're really done... | |||
self.done_cb() | |||
end | |||
end | |||
M.new = function(done_callback) | |||
local obj = { | |||
tokens = {}, | |||
tokens_done = {}, | |||
done_cb = done_callback, | |||
ordered = true, -- default for sign off of tokens | |||
} | |||
return setmetatable( obj, { | |||
__call = function(self, ...) | |||
self:_done(...) | |||
end, | |||
__index = M, | |||
}) | |||
end | |||
return M |
@@ -1,45 +0,0 @@ | |||
local setfenv = require 'busted.compatibility'.setfenv | |||
return function(context) | |||
local environment = {} | |||
local function getEnv(self, key) | |||
if not self then return nil end | |||
return | |||
self.env and self.env[key] or | |||
getEnv(context.parent(self), key) or | |||
_G[key] | |||
end | |||
local function setEnv(self, key, value) | |||
if not self.env then self.env = {} end | |||
self.env[key] = value | |||
end | |||
local function __index(self, key) | |||
return getEnv(context.get(), key) | |||
end | |||
local function __newindex(self, key, value) | |||
setEnv(context.get(), key, value) | |||
end | |||
local env = setmetatable({}, { __index=__index, __newindex=__newindex }) | |||
function environment.wrap(fn) | |||
return setfenv(fn, env) | |||
end | |||
function environment.set(key, value) | |||
local env = context.get('env') | |||
if not env then | |||
env = {} | |||
context.set('env', env) | |||
end | |||
env[key] = value | |||
end | |||
return environment | |||
end |
@@ -1,227 +0,0 @@ | |||
local unpack = require 'busted.compatibility'.unpack | |||
local shuffle = require 'busted.utils'.shuffle | |||
local function sort(elements) | |||
table.sort(elements, function(t1, t2) | |||
if t1.name and t2.name then | |||
return t1.name < t2.name | |||
end | |||
return t2.name ~= nil | |||
end) | |||
return elements | |||
end | |||
local function remove(descriptors, element) | |||
for _, descriptor in ipairs(descriptors) do | |||
element.env[descriptor] = function(...) | |||
error("'" .. descriptor .. "' not supported inside current context block", 2) | |||
end | |||
end | |||
end | |||
local function init(busted) | |||
local function exec(descriptor, element) | |||
if not element.env then element.env = {} end | |||
remove({ 'randomize' }, element) | |||
remove({ 'pending' }, element) | |||
remove({ 'describe', 'context', 'it', 'spec', 'test' }, element) | |||
remove({ 'setup', 'teardown', 'before_each', 'after_each' }, element) | |||
local parent = busted.context.parent(element) | |||
setmetatable(element.env, { | |||
__newindex = function(self, key, value) | |||
if not parent.env then parent.env = {} end | |||
parent.env[key] = value | |||
end | |||
}) | |||
local ret = { busted.safe(descriptor, element.run, element) } | |||
return unpack(ret) | |||
end | |||
local function execAll(descriptor, current, propagate) | |||
local parent = busted.context.parent(current) | |||
if propagate and parent then | |||
local success, ancestor = execAll(descriptor, parent, propagate) | |||
if not success then | |||
return success, ancestor | |||
end | |||
end | |||
local list = current[descriptor] or {} | |||
local success = true | |||
for _, v in pairs(list) do | |||
if not exec(descriptor, v):success() then | |||
success = nil | |||
end | |||
end | |||
return success, current | |||
end | |||
local function dexecAll(descriptor, current, propagate) | |||
local parent = busted.context.parent(current) | |||
local list = current[descriptor] or {} | |||
local success = true | |||
for _, v in pairs(list) do | |||
if not exec(descriptor, v):success() then | |||
success = nil | |||
end | |||
end | |||
if propagate and parent then | |||
if not dexecAll(descriptor, parent, propagate) then | |||
success = nil | |||
end | |||
end | |||
return success | |||
end | |||
local file = function(file) | |||
busted.publish({ 'file', 'start' }, file.name) | |||
busted.environment.wrap(file.run) | |||
if not file.env then file.env = {} end | |||
local randomize = busted.randomize | |||
file.env.randomize = function() randomize = true end | |||
if busted.safe('file', file.run, file):success() then | |||
if randomize then | |||
file.randomseed = busted.randomseed | |||
shuffle(busted.context.children(file), busted.randomseed) | |||
elseif busted.sort then | |||
sort(busted.context.children(file)) | |||
end | |||
if execAll('setup', file) then | |||
busted.execute(file) | |||
end | |||
dexecAll('teardown', file) | |||
end | |||
busted.publish({ 'file', 'end' }, file.name) | |||
end | |||
local describe = function(describe) | |||
local parent = busted.context.parent(describe) | |||
busted.publish({ 'describe', 'start' }, describe, parent) | |||
if not describe.env then describe.env = {} end | |||
local randomize = busted.randomize | |||
describe.env.randomize = function() randomize = true end | |||
if busted.safe('describe', describe.run, describe):success() then | |||
if randomize then | |||
describe.randomseed = busted.randomseed | |||
shuffle(busted.context.children(describe), busted.randomseed) | |||
elseif busted.sort then | |||
sort(busted.context.children(describe)) | |||
end | |||
if execAll('setup', describe) then | |||
busted.execute(describe) | |||
end | |||
dexecAll('teardown', describe) | |||
end | |||
busted.publish({ 'describe', 'end' }, describe, parent) | |||
end | |||
local it = function(element) | |||
local parent = busted.context.parent(element) | |||
local finally | |||
busted.publish({ 'test', 'start' }, element, parent) | |||
if not element.env then element.env = {} end | |||
remove({ 'randomize' }, element) | |||
remove({ 'describe', 'context', 'it', 'spec', 'test' }, element) | |||
remove({ 'setup', 'teardown', 'before_each', 'after_each' }, element) | |||
element.env.finally = function(fn) finally = fn end | |||
element.env.pending = function(msg) busted.pending(msg) end | |||
local status = busted.status('success') | |||
local updateErrorStatus = function(descriptor) | |||
if element.message then element.message = element.message .. '\n' end | |||
element.message = (element.message or '') .. 'Error in ' .. descriptor | |||
status:update('error') | |||
end | |||
local pass, ancestor = execAll('before_each', parent, true) | |||
if pass then | |||
status:update(busted.safe('it', element.run, element)) | |||
else | |||
updateErrorStatus('before_each') | |||
end | |||
if not element.env.done then | |||
remove({ 'pending' }, element) | |||
if finally then status:update(busted.safe('finally', finally, element)) end | |||
if not dexecAll('after_each', ancestor, true) then | |||
updateErrorStatus('after_each') | |||
end | |||
busted.publish({ 'test', 'end' }, element, parent, tostring(status)) | |||
end | |||
end | |||
local pending = function(element) | |||
local parent = busted.context.parent(element) | |||
busted.publish({ 'test', 'start' }, element, parent) | |||
busted.publish({ 'test', 'end' }, element, parent, 'pending') | |||
end | |||
busted.register('file', file) | |||
busted.register('describe', describe) | |||
busted.register('it', it) | |||
busted.register('pending', pending) | |||
busted.register('setup') | |||
busted.register('teardown') | |||
busted.register('before_each') | |||
busted.register('after_each') | |||
busted.alias('context', 'describe') | |||
busted.alias('spec', 'it') | |||
busted.alias('test', 'it') | |||
local assert = require 'luassert' | |||
local spy = require 'luassert.spy' | |||
local mock = require 'luassert.mock' | |||
local stub = require 'luassert.stub' | |||
busted.environment.set('assert', assert) | |||
busted.environment.set('spy', spy) | |||
busted.environment.set('mock', mock) | |||
busted.environment.set('stub', stub) | |||
busted.replaceErrorWithFail(assert) | |||
busted.replaceErrorWithFail(assert.True) | |||
return busted | |||
end | |||
return setmetatable({}, { | |||
__call = function(self, busted) | |||
local root = busted.context.get() | |||
init(busted) | |||
return setmetatable(self, { | |||
__index = function(self, key) | |||
return rawget(root.env, key) or busted.executors[key] | |||
end, | |||
__newindex = function(self, key, value) | |||
error('Attempt to modify busted') | |||
end | |||
}) | |||
end | |||
}) |
@@ -1,42 +0,0 @@ | |||
local s = require('say') | |||
s:set_namespace('ar') | |||
s:set('output.pending', 'عالِق') | |||
s:set('output.failure', 'فَشَل') | |||
s:set('output.failure', 'نَجاح') | |||
s:set('output.pending_plural', 'عالِق') | |||
s:set('output.failure_plural', 'إخْفاقات') | |||
s:set('output.success_plural', 'نَجاحات') | |||
s:set('output.pending_zero', 'عالِق') | |||
s:set('output.failure_zero', 'إخْفاقات') | |||
s:set('output.success_zero', 'نَجاحات') | |||
s:set('output.pending_single', 'عالِق') | |||
s:set('output.failure_single', 'فَشَل') | |||
s:set('output.success_single', 'نَجاح') | |||
s:set('output.seconds', 'ثَوانٍ') | |||
return { | |||
failure_messages = { | |||
'فَشِلَت %d مِنْ الإِختِبارات', | |||
'فَشِلَت إخْتِباراتُك', | |||
'برمجيَّتُكَ ضَعيْفة، أنْصَحُكَ بالتَّقاعُد', | |||
'تقع برمجيَّتُكَ في مَنطِقَةِ الخَطَر', | |||
'أقترِحُ ألّا تَتَقَدَّم بالإختِبار، علَّ يبْقى الطابِقُ مَستوراَ', | |||
'جَدَّتي، فِي أَثْناءِ نَومِها، تَكتبُ بَرمَجياتٍ أفْضلُ مِن هذه', | |||
'يَوَدُّ ليْ مُساعَدَتُكْ، لَكِنّْ...' | |||
}, | |||
success_messages = { | |||
'رائِع! تَمَّ إجْتِيازُ جَميعُ الإختِباراتِ بِنَجاحٍ', | |||
'قُل ما شِئت، لا أكتَرِث: busted شَهِدَ لي!', | |||
'حَقَّ عَليْكَ الإفتِخار', | |||
'نَجاحٌ مُبْهِر!', | |||
'عَليكَ بالإحتِفال؛ نَجَحَت جَميعُ التَجارُب' | |||
} | |||
} |
@@ -1,42 +0,0 @@ | |||
local s = require('say') | |||
s:set_namespace('de') | |||
s:set('output.pending', 'Noch nicht erledigt') | |||
s:set('output.failure', 'Fehlgeschlagen') | |||
s:set('output.success', 'Erfolgreich') | |||
s:set('output.pending_plural', 'übersprungen') | |||
s:set('output.failure_plural', 'fehlgeschlagen') | |||
s:set('output.success_plural', 'erfolgreich') | |||
s:set('output.pending_zero', 'übersprungen') | |||
s:set('output.failure_zero', 'fehlgeschlagen') | |||
s:set('output.success_zero', 'erfolgreich') | |||
s:set('output.pending_single', 'übersprungen') | |||
s:set('output.failure_single', 'fehlgeschlagen') | |||
s:set('output.success_single', 'erfolgreich') | |||
s:set('output.seconds', 'Sekunden') | |||
return { | |||
failure_messages = { | |||
'Du hast %d kaputte Tests.', | |||
'Deine Tests sind kaputt.', | |||
'Dein Code ist schlecht; du solltest dich schlecht fühlen.', | |||
'Dein Code befindet sich in der Gefahrenzone.', | |||
'Ein seltsames Spiel. Der einzig gewinnbringende Zug ist nicht zu testen.', | |||
'Meine Großmutter hat auf einem 386er bessere Tests geschrieben.', | |||
'Immer wenn ein Test fehlschlägt, stirbt ein kleines Kätzchen.', | |||
'Das fühlt sich schlecht an, oder?' | |||
}, | |||
success_messages = { | |||
'Yeah, die Tests laufen durch.', | |||
'Fühlt sich gut an, oder?', | |||
'Großartig!', | |||
'Tests sind durchgelaufen, Zeit für ein Bier.', | |||
} | |||
} |
@@ -1,49 +0,0 @@ | |||
local s = require('say') | |||
s:set_namespace('en') | |||
s:set('output.pending', 'Pending') | |||
s:set('output.failure', 'Failure') | |||
s:set('output.error', 'Error') | |||
s:set('output.success', 'Success') | |||
s:set('output.pending_plural', 'pending') | |||
s:set('output.failure_plural', 'failures') | |||
s:set('output.error_plural', 'errors') | |||
s:set('output.success_plural', 'successes') | |||
s:set('output.pending_zero', 'pending') | |||
s:set('output.failure_zero', 'failures') | |||
s:set('output.error_zero', 'errors') | |||
s:set('output.success_zero', 'successes') | |||
s:set('output.pending_single', 'pending') | |||
s:set('output.failure_single', 'failure') | |||
s:set('output.error_single', 'error') | |||
s:set('output.success_single', 'success') | |||
s:set('output.seconds', 'seconds') | |||
s:set('output.no_test_files_match', 'No test files found matching Lua pattern: %s') | |||
return { | |||
failure_messages = { | |||
'You have %d busted specs', | |||
'Your specs are busted', | |||
'Your code is bad and you should feel bad', | |||
'Your code is in the Danger Zone', | |||
'Strange game. The only way to win is not to test', | |||
'My grandmother wrote better specs on a 3 86', | |||
'Every time there\'s a failure, drink another beer', | |||
'Feels bad man' | |||
}, | |||
success_messages = { | |||
'Aww yeah, passing specs', | |||
'Doesn\'t matter, had specs', | |||
'Feels good, man', | |||
'Great success', | |||
'Tests pass, drink another beer', | |||
} | |||
} |
@@ -1,45 +0,0 @@ | |||
local s = require('say') | |||
s:set_namespace('fr') | |||
s:set('output.pending', 'En attente') | |||
s:set('output.failure', 'Echec') | |||
s:set('output.success', 'Reussite') | |||
s:set('output.pending_plural', 'en attente') | |||
s:set('output.failure_plural', 'echecs') | |||
s:set('output.success_plural', 'reussites') | |||
s:set('output.pending_zero', 'en attente') | |||
s:set('output.failure_zero', 'echec') | |||
s:set('output.success_zero', 'reussite') | |||
s:set('output.pending_single', 'en attente') | |||
s:set('output.failure_single', 'echec') | |||
s:set('output.success_single', 'reussite') | |||
s:set('output.seconds', 'secondes') | |||
s:set('output.no_test_files_match', 'Aucun test n\'est pourrait trouvé qui corresponde au motif de Lua: %s') | |||
return { | |||
failure_messages = { | |||
'Vous avez %d test(s) qui a/ont echoue(s)', | |||
'Vos tests ont echoue.', | |||
'Votre code source est mauvais et vous devrez vous sentir mal', | |||
'Vous avez un code source de Destruction Massive', | |||
'Jeu plutot etrange game. Le seul moyen de gagner est de ne pas l\'essayer', | |||
'Meme ma grand-mere ecrivait de meilleurs tests sur un PIII x86', | |||
'A chaque erreur, prenez une biere', | |||
'Ca craint, mon pote' | |||
}, | |||
success_messages = { | |||
'Oh yeah, tests reussis', | |||
'Pas grave, y\'a eu du succes', | |||
'C\'est du bon, mon pote. Que du bon!', | |||
'Reussi, haut la main!', | |||
'Test reussi. Un de plus. Offre toi une biere, sur mon compte!', | |||
} | |||
} |
@@ -1,43 +0,0 @@ | |||
local s = require('say') | |||
s:set_namespace('ja') | |||
s:set('output.pending', '保留') | |||
s:set('output.failure', '失敗') | |||
s:set('output.success', '成功') | |||
s:set('output.pending_plural', '保留') | |||
s:set('output.failure_plural', '失敗') | |||
s:set('output.success_plural', '成功') | |||
s:set('output.pending_zero', '保留') | |||
s:set('output.failure_zero', '失敗') | |||
s:set('output.success_zero', '成功') | |||
s:set('output.pending_single', '保留') | |||
s:set('output.failure_single', '失敗') | |||
s:set('output.success_single', '成功') | |||
s:set('output.seconds', '秒') | |||
return { | |||
failure_messages = { | |||
'%d個の仕様が破綻しています', | |||
'仕様が破綻しています', | |||
'あなたの書くコードは良くないので反省するべきです', | |||
'あなたの書くコードは危険地帯にあります', | |||
'おかしなゲームです。勝利する唯一の方法はテストをしないことです', | |||
'私の祖母でもPentium Pentium III x86の上でもっといいコードを書いていましたよ', | |||
'いつも失敗しているのでビールでも飲みましょう', | |||
'罪悪感を持ちましょう', | |||
}, | |||
success_messages = { | |||
'オォーイェー、テストが通った', | |||
'問題ない、テストがある', | |||
'順調ですね', | |||
'大成功', | |||
'テストが通ったし、ビールでも飲もう', | |||
} | |||
} |
@@ -1,43 +0,0 @@ | |||
local s = require('say') | |||
s:set_namespace('nl') | |||
s:set('output.pending', 'Hangend') | |||
s:set('output.failure', 'Mislukt') | |||
s:set('output.success', 'Succes') | |||
s:set('output.pending_plural', 'hangenden') | |||
s:set('output.failure_plural', 'mislukkingen') | |||
s:set('output.success_plural', 'successen') | |||
s:set('output.pending_zero', 'hangend') | |||
s:set('output.failure_zero', 'mislukt') | |||
s:set('output.success_zero', 'successen') | |||
s:set('output.pending_single', 'hangt') | |||
s:set('output.failure_single', 'mislukt') | |||
s:set('output.success_single', 'succes') | |||
s:set('output.seconds', 'seconden') | |||
return { | |||
failure_messages = { | |||
'Je hebt %d busted specs', | |||
'Je specs zijn busted', | |||
'Je code is slecht en zo zou jij je ook moeten voelen', | |||
'Je code zit in de Gevaren Zone', | |||
'Vreemd spelletje. The enige manier om te winnen is door niet te testen', | |||
'Mijn oma schreef betere specs op een 3 86', | |||
'Elke keer dat iets mislukt, nog een biertje drinken', | |||
'Voelt klote man' | |||
}, | |||
success_messages = { | |||
'Joeperdepoep, de specs zijn er door', | |||
'Doet er niet toe, had specs', | |||
'Voelt goed, man', | |||
'Fantastisch success', | |||
'Testen geslaagd, neem nog een biertje', | |||
} | |||
} |
@@ -1,37 +0,0 @@ | |||
local s = require('say') | |||
s:set_namespace('ru') | |||
s:set('output.pending', 'Ожидает') | |||
s:set('output.failure', 'Поломалcя') | |||
s:set('output.success', 'Прошeл') | |||
s:set('output.pending_plural', 'ожидают') | |||
s:set('output.failure_plural', 'поломалиcь') | |||
s:set('output.success_plural', 'прошли') | |||
s:set('output.pending_zero', 'ожидающих') | |||
s:set('output.failure_zero', 'поломанных') | |||
s:set('output.success_zero', 'прошедших') | |||
s:set('output.pending_single', 'ожидает') | |||
s:set('output.failure_single', 'поломался') | |||
s:set('output.success_single', 'прошел') | |||
s:set('output.seconds', 'секунд') | |||
---- definitions following are not used within the 'say' namespace | |||
return { | |||
failure_messages = { | |||
'У тебя %d просратых тестов', | |||
'Твои тесты поломаны', | |||
'Твой код говеный - пойди напейся!' | |||
}, | |||
success_messages = { | |||
'Поехали!', | |||
'Жизнь - хороша!', | |||
'Ффух в этот раз пронесло!', | |||
'Ура!' | |||
} | |||
} |
@@ -1,43 +0,0 @@ | |||
local s = require('say') | |||
s:set_namespace('th') | |||
s:set('output.pending', 'อยู่ระหว่างดำเนินการ') | |||
s:set('output.failure', 'ล้มเหลว') | |||
s:set('output.success', 'สำเร็จ') | |||
s:set('output.pending_plural', 'อยู่ระหว่างดำเนินการ') | |||
s:set('output.failure_plural', 'ล้มเหลว') | |||
s:set('output.success_plural', 'สำเร็จ') | |||
s:set('output.pending_zero', 'อยู่ระหว่างดำเนินการ') | |||
s:set('output.failure_zero', 'ล้มเหลว') | |||
s:set('output.success_zero', 'สำเร็จ') | |||
s:set('output.pending_single', 'อยู่ระหว่างดำเนินการ') | |||
s:set('output.failure_single', 'ล้มเหลว') | |||
s:set('output.success_single', 'สำเร็จ') | |||
s:set('output.seconds', 'วินาที') | |||
return { | |||
failure_messages = { | |||
'คุณมี %d บัสเต็ดสเปค', | |||
'สเปคของคุณคือ บัสเต็ด', | |||
'โค้ดของคุณไม่ดีเลย คุณควรรู้สึกแย่น่ะ', | |||
'โค้ดของคุณอยู่ในเขตอันตราย!', | |||
'มันแปลกๆน่ะ วิธีที่จะชนะไม่ได้มีแค่เทสอย่างเดียว', | |||
'ยายผมเขียนสเปคดีกว่านี้อีก บนเครื่อง 386', | |||
'ทุกๆครั้งที่ล้มเหลว, ดื่มเบียร์แก้วใหม่', | |||
'แย่จัง นายท่าน' | |||
}, | |||
success_messages = { | |||
'อุ๊ตะ!!!, สเปคผ่าน!', | |||
'ไม่สำคัญ, มีสเปค', | |||
'ฟินเลยดิ นายท่าน', | |||
'สำเร็จ ยอดเยี่ยม', | |||
'เทสผ่าน, ดื่มเบียร์ๆๆๆ', | |||
} | |||
} |
@@ -1,37 +0,0 @@ | |||
local s = require('say') | |||
s:set_namespace('ua') | |||
s:set('output.pending', 'Очікує') | |||
s:set('output.failure', 'Зламався') | |||
s:set('output.success', 'Пройшов') | |||
s:set('output.pending_plural', 'очікують') | |||
s:set('output.failure_plural', 'зламались') | |||
s:set('output.success_plural', 'пройшли') | |||
s:set('output.pending_zero', 'очікуючих') | |||
s:set('output.failure_zero', 'зламаних') | |||
s:set('output.success_zero', 'пройдених') | |||
s:set('output.pending_single', 'очікує') | |||
s:set('output.failure_single', 'зламався') | |||
s:set('output.success_single', 'пройшов') | |||
s:set('output.seconds', 'секунд') | |||
---- definitions following are not used within the 'say' namespace | |||
return { | |||
failure_messages = { | |||
'Ти зрадив %d тестів!', | |||
'Ой йо..', | |||
'Вороги поламали наші тести!' | |||
}, | |||
success_messages = { | |||
'Слава Україні! Героям Слава!', | |||
'Тестування успішно пройдено!', | |||
'Всі баги знищено!' | |||
} | |||
} |
@@ -1,43 +0,0 @@ | |||
local s = require('say') | |||
s:set_namespace('zh') | |||
s:set('output.pending', '开发中') | |||
s:set('output.failure', '失败') | |||
s:set('output.success', '成功') | |||
s:set('output.pending_plural', '开发中') | |||
s:set('output.failure_plural', '失败') | |||
s:set('output.success_plural', '成功') | |||
s:set('output.pending_zero', '开发中') | |||
s:set('output.failure_zero', '失败') | |||
s:set('output.success_zero', '成功') | |||
s:set('output.pending_single', '开发中') | |||
s:set('output.failure_single', '失败') | |||
s:set('output.success_single', '成功') | |||
s:set('output.seconds', '秒') | |||
return { | |||
failure_messages = { | |||
'你一共提交了[%d]个测试用例', | |||
'又出错了!', | |||
'到底哪里不对呢?', | |||
'出错了,又要加班了!', | |||
'囧,出Bug了!', | |||
'据说比尔盖兹也写了一堆Bug,别灰心!', | |||
'又出错了,休息一下吧', | |||
'Bug好多,心情好坏!' | |||
}, | |||
success_messages = { | |||
'牛X,测试通过了!', | |||
'测试通过了,感觉不错吧,兄弟!', | |||
'哥们,干得漂亮!', | |||
'终于通过了!干一杯先!', | |||
'阿弥陀佛~,菩萨显灵了!', | |||
} | |||
} |
@@ -1,34 +0,0 @@ | |||
return function() | |||
local tablex = require 'pl.tablex' | |||
-- Function to load the .busted configuration file if available | |||
local loadBustedConfigurationFile = function(configFile, config, defaults) | |||
if type(configFile) ~= 'table' then | |||
return config, '.busted file does not return a table.' | |||
end | |||
local defaults = defaults or {} | |||
local run = config.run or defaults.run | |||
if run and run ~= '' then | |||
local runConfig = configFile[run] | |||
if type(runConfig) == 'table' then | |||
config = tablex.merge(runConfig, config, true) | |||
else | |||
return config, 'Task `' .. run .. '` not found, or not a table.' | |||
end | |||
end | |||
if type(configFile.default) == 'table' then | |||
config = tablex.merge(configFile.default, config, true) | |||
end | |||
config = tablex.merge(defaults, config, true) | |||
return config | |||
end | |||
return loadBustedConfigurationFile | |||
end | |||
@@ -1,24 +0,0 @@ | |||
local path = require 'pl.path' | |||
local ret = {} | |||
local getTrace = function(filename, info) | |||
local index = info.traceback:find('\n%s*%[C]') | |||
info.traceback = info.traceback:sub(1, index) | |||
return info, false | |||
end | |||
ret.match = function(busted, filename) | |||
return path.extension(filename) == '.lua' | |||
end | |||
ret.load = function(busted, filename) | |||
local file, err = loadfile(filename) | |||
if not file then | |||
busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) | |||
end | |||
return file, getTrace | |||
end | |||
return ret |
@@ -1,108 +0,0 @@ | |||
local path = require 'pl.path' | |||
local ok, moonscript, line_tables, util = pcall(function() | |||
return require 'moonscript', require 'moonscript.line_tables', require 'moonscript.util' | |||
end) | |||
local _cache = {} | |||
local lookup_line = function(fname, pos) | |||
if not _cache[fname] then | |||
local f = io.open(fname) | |||
_cache[fname] = f:read('*a') | |||
f:close() | |||
end | |||
return util.pos_to_line(_cache[fname], pos) | |||
end | |||
local rewrite_linenumber = function(fname, lineno) | |||
local tbl = line_tables['@' .. fname] | |||
if fname and tbl then | |||
for i = lineno, 0 ,-1 do | |||
if tbl[i] then | |||
return lookup_line(fname, tbl[i]) | |||
end | |||
end | |||
end | |||
return lineno | |||
end | |||
local rewrite_filename = function(filename) | |||
-- sometimes moonscript gives files like [string "./filename.moon"], so | |||
-- we'll chop it up to only get the filename. | |||
return filename:match('string "(.+)"') or filename | |||
end | |||
local rewrite_traceback = function(fname, trace) | |||
local rewrite_one = function(line, pattern, sub) | |||
if line == nil then return '' end | |||
local fname, lineno = line:match(pattern) | |||
if fname and lineno then | |||
fname = rewrite_filename(fname) | |||
local new_lineno = rewrite_linenumber(fname, tonumber(lineno)) | |||
if new_lineno then | |||
line = line:gsub(sub:format(tonumber(lineno)), sub:format(tonumber(new_lineno))) | |||
end | |||
end | |||
return line | |||
end | |||
local lines = {} | |||
local j = 0 | |||
for line in trace:gmatch('[^\r\n]+') do | |||
j = j + 1 | |||
line = rewrite_one(line, '%s*(.-):(%d+): ', ':%d:') | |||
line = rewrite_one(line, '<(.*):(%d+)>', ':%d>') | |||
lines[j] = line | |||
end | |||
return '\n' .. table.concat(lines, trace:match('[\r\n]+')) .. '\n' | |||
end | |||
local ret = {} | |||
local getTrace = function(filename, info) | |||
local index = info.traceback:find('\n%s*%[C]') | |||
info.traceback = info.traceback:sub(1, index) | |||
info.short_src = rewrite_filename(info.short_src) | |||
info.traceback = rewrite_traceback(filename, info.traceback) | |||
info.linedefined = rewrite_linenumber(filename, info.linedefined) | |||
info.currentline = rewrite_linenumber(filename, info.currentline) | |||
return info | |||
end | |||
local rewriteMessage = function(filename, message) | |||
local fname, line, msg = message:match('^([^\n]-):(%d+): (.*)') | |||
if not fname then | |||
return message | |||
end | |||
fname = rewrite_filename(fname) | |||
line = rewrite_linenumber(fname, tonumber(line)) | |||
return fname .. ':' .. tostring(line) .. ': ' .. msg | |||
end | |||
ret.match = function(busted, filename) | |||
return ok and path.extension(filename) == '.moon' | |||
end | |||
ret.load = function(busted, filename) | |||
local file, err = moonscript.loadfile(filename) | |||
if not file then | |||
busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) | |||
end | |||
return file, getTrace, rewriteMessage | |||
end | |||
return ret |
@@ -1,24 +0,0 @@ | |||
local path = require 'pl.path' | |||
local ret = {} | |||
local ok, terralib = pcall(function() return require 'terralib' end) | |||
local getTrace = function(filename, info) | |||
local index = info.traceback:find('\n%s*%[C]') | |||
info.traceback = info.traceback:sub(1, index) | |||
return info | |||
end | |||
ret.match = function(busted, filename) | |||
return ok and path.extension(filename) == '.t' | |||
end | |||
ret.load = function(busted, filename) | |||
local file, err = terralib.loadfile(filename) | |||
if not file then | |||
busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) | |||
end | |||
return file, getTrace | |||
end | |||
return ret |
@@ -1,23 +0,0 @@ | |||
local utils = require 'busted.utils' | |||
local hasMoon, moonscript = pcall(require, 'moonscript') | |||
return function() | |||
local loadHelper = function(helper, hpath, options, busted) | |||
local success, err = pcall(function() | |||
arg = options.arguments | |||
if helper:match('%.lua$') then | |||
dofile(utils.normpath(hpath)) | |||
elseif hasMoon and helper:match('%.moon$') then | |||
moonscript.dofile(utils.normpath(hpath)) | |||
else | |||
require(helper) | |||
end | |||
end) | |||
if not success then | |||
busted.publish({ 'error', 'helper' }, { descriptor = 'helper', name = helper }, nil, err, {}) | |||
end | |||
end | |||
return loadHelper | |||
end |
@@ -1,22 +0,0 @@ | |||
return function() | |||
-- Function to initialize luacov if available | |||
local loadLuaCov = function() | |||
local result, luacov = pcall(require, 'luacov.runner') | |||
if not result then | |||
return print('LuaCov not found on the system, try running without --coverage option, or install LuaCov first') | |||
end | |||
-- call it to start | |||
luacov() | |||
-- exclude busted files | |||
table.insert(luacov.configuration.exclude, 'busted_bootstrap$') | |||
table.insert(luacov.configuration.exclude, 'busted%.') | |||
table.insert(luacov.configuration.exclude, 'luassert%.') | |||
table.insert(luacov.configuration.exclude, 'say%.') | |||
table.insert(luacov.configuration.exclude, 'pl%.') | |||
end | |||
return loadLuaCov | |||
end |
@@ -1,31 +0,0 @@ | |||
local utils = require 'busted.utils' | |||
local hasMoon, moonscript = pcall(require, 'moonscript') | |||
return function() | |||
local loadOutputHandler = function(output, opath, options, busted, defaultOutput) | |||
local handler | |||
local success, err = pcall(function() | |||
if output:match('%.lua$') then | |||
handler = dofile(utils.normpath(opath)) | |||
elseif hasMoon and output:match('%.moon$') then | |||
handler = moonscript.dofile(utils.normpath(opath)) | |||
else | |||
handler = require('busted.outputHandlers.' .. output) | |||
end | |||
end) | |||
if not success and err:match("module '.-' not found:") then | |||
success, err = pcall(function() handler = require(output) end) | |||
end | |||
if not success then | |||
busted.publish({ 'error', 'output' }, { descriptor = 'output', name = output }, nil, err, {}) | |||
handler = require('busted.outputHandlers.' .. defaultOutput) | |||
end | |||
return handler(options, busted) | |||
end | |||
return loadOutputHandler | |||
end |
@@ -1,84 +0,0 @@ | |||
local s = require 'say' | |||
return function(busted, loaders, options) | |||
local path = require 'pl.path' | |||
local dir = require 'pl.dir' | |||
local tablex = require 'pl.tablex' | |||
local shuffle = require 'busted.utils'.shuffle | |||
local fileLoaders = {} | |||
for _, v in pairs(loaders) do | |||
local loader = require('busted.modules.files.'..v) | |||
fileLoaders[#fileLoaders+1] = loader | |||
end | |||
local getTestFiles = function(rootFile, pattern) | |||
local fileList | |||
if path.isfile(rootFile) then | |||
fileList = { rootFile } | |||
elseif path.isdir(rootFile) then | |||
local getfiles = options.recursive and dir.getallfiles or dir.getfiles | |||
fileList = getfiles(rootFile) | |||
fileList = tablex.filter(fileList, function(filename) | |||
return path.basename(filename):find(pattern) | |||
end) | |||
fileList = tablex.filter(fileList, function(filename) | |||
if path.is_windows then | |||
return not filename:find('%\\%.%w+.%w+') | |||
else | |||
return not filename:find('/%.%w+.%w+') | |||
end | |||
end) | |||
else | |||
fileList = {} | |||
end | |||
return fileList | |||
end | |||
-- runs a testfile, loading its tests | |||
local loadTestFile = function(busted, filename) | |||
for _, v in pairs(fileLoaders) do | |||
if v.match(busted, filename) then | |||
return v.load(busted, filename) | |||
end | |||
end | |||
end | |||
local loadTestFiles = function(rootFile, pattern, loaders) | |||
local fileList = getTestFiles(rootFile, pattern) | |||
if options.shuffle then | |||
shuffle(fileList, options.seed) | |||
elseif options.sort then | |||
table.sort(fileList) | |||
end | |||
for i, fileName in ipairs(fileList) do | |||
local testFile, getTrace, rewriteMessage = loadTestFile(busted, fileName, loaders) | |||
if testFile then | |||
local file = setmetatable({ | |||
getTrace = getTrace, | |||
rewriteMessage = rewriteMessage | |||
}, { | |||
__call = testFile | |||
}) | |||
busted.executors.file(fileName, file) | |||
end | |||
end | |||
if #fileList == 0 then | |||
busted.publish({ 'error' }, {}, nil, s('output.no_test_files_match'):format(pattern), {}) | |||
end | |||
return fileList | |||
end | |||
return loadTestFiles, loadTestFile, getTestFiles | |||
end | |||
@@ -1,51 +0,0 @@ | |||
local pretty = require 'pl.pretty' | |||
return function(options, busted) | |||
local handler = require 'busted.outputHandlers.base'(busted) | |||
handler.suiteEnd = function() | |||
local total = handler.successesCount + handler.errorsCount + handler.failuresCount | |||
print('1..' .. total) | |||
local success = 'ok %u - %s' | |||
local failure = 'not ' .. success | |||
local counter = 0 | |||
for i,t in pairs(handler.successes) do | |||
counter = counter + 1 | |||
print(success:format(counter, t.name)) | |||
end | |||
local showFailure = function(t) | |||
counter = counter + 1 | |||
local message = t.message | |||
local trace = t.trace or {} | |||
if message == nil then | |||
message = 'Nil error' | |||
elseif type(message) ~= 'string' then | |||
message = pretty.write(message) | |||
end | |||
print(failure:format(counter, t.name)) | |||
print('# ' .. t.element.trace.short_src .. ' @ ' .. t.element.trace.currentline) | |||
print('# Failure message: ' .. message:gsub('\n', '\n# ')) | |||
if options.verbose and trace.traceback then | |||
print('# ' .. trace.traceback:gsub('^\n', '', 1):gsub('\n', '\n# ')) | |||
end | |||
end | |||
for i,t in pairs(handler.errors) do | |||
showFailure(t) | |||
end | |||
for i,t in pairs(handler.failures) do | |||
showFailure(t) | |||
end | |||
return nil, true | |||
end | |||
busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) | |||
return handler | |||
end |
@@ -1,177 +0,0 @@ | |||
return function(busted) | |||
local handler = { | |||
successes = {}, | |||
successesCount = 0, | |||
pendings = {}, | |||
pendingsCount = 0, | |||
failures = {}, | |||
failuresCount = 0, | |||
errors = {}, | |||
errorsCount = 0, | |||
inProgress = {} | |||
} | |||
handler.cancelOnPending = function(element, parent, status) | |||
return not ((element.descriptor == 'pending' or status == 'pending') and handler.options.suppressPending) | |||
end | |||
handler.subscribe = function(handler, options) | |||
require('busted.languages.en') | |||
handler.options = options | |||
if options.language ~= 'en' then | |||
require('busted.languages.' .. options.language) | |||
end | |||
busted.subscribe({ 'suite', 'reinitialize' }, handler.baseSuiteRepeat, { priority = 1 }) | |||
busted.subscribe({ 'suite', 'start' }, handler.baseSuiteStart, { priority = 1 }) | |||
busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd, { priority = 1 }) | |||
busted.subscribe({ 'test', 'start' }, handler.baseTestStart, { priority = 1, predicate = handler.cancelOnPending }) | |||
busted.subscribe({ 'test', 'end' }, handler.baseTestEnd, { priority = 1, predicate = handler.cancelOnPending }) | |||
busted.subscribe({ 'pending' }, handler.basePending, { priority = 1, predicate = handler.cancelOnPending }) | |||
busted.subscribe({ 'failure', 'it' }, handler.baseTestFailure, { priority = 1 }) | |||
busted.subscribe({ 'error', 'it' }, handler.baseTestError, { priority = 1 }) | |||
busted.subscribe({ 'failure' }, handler.baseError, { priority = 1 }) | |||
busted.subscribe({ 'error' }, handler.baseError, { priority = 1 }) | |||
end | |||
handler.getFullName = function(context) | |||
local parent = busted.context.parent(context) | |||
local names = { (context.name or context.descriptor) } | |||
while parent and (parent.name or parent.descriptor) and | |||
parent.descriptor ~= 'file' do | |||
table.insert(names, 1, parent.name or parent.descriptor) | |||
parent = busted.context.parent(parent) | |||
end | |||
return table.concat(names, ' ') | |||
end | |||
handler.format = function(element, parent, message, debug, isError) | |||
local formatted = { | |||
trace = debug or element.trace, | |||
element = element, | |||
name = handler.getFullName(element), | |||
message = message, | |||
isError = isError | |||
} | |||
formatted.element.trace = element.trace or debug | |||
return formatted | |||
end | |||
handler.getDuration = function() | |||
if not handler.endTime or not handler.startTime then | |||
return 0 | |||
end | |||
return handler.endTime - handler.startTime | |||
end | |||
handler.baseSuiteStart = function() | |||
handler.startTime = os.clock() | |||
return nil, true | |||
end | |||
handler.baseSuiteRepeat = function() | |||
handler.successes = {} | |||
handler.successesCount = 0 | |||
handler.pendings = {} | |||
handler.pendingsCount = 0 | |||
handler.failures = {} | |||
handler.failuresCount = 0 | |||
handler.errors = {} | |||
handler.errorsCount = 0 | |||
handler.inProgress = {} | |||
return nil, true | |||
end | |||
handler.baseSuiteEnd = function() | |||
handler.endTime = os.clock() | |||
return nil, true | |||
end | |||
handler.baseTestStart = function(element, parent) | |||
handler.inProgress[tostring(element)] = {} | |||
return nil, true | |||
end | |||
handler.baseTestEnd = function(element, parent, status, debug) | |||
local isError | |||
local insertTable | |||
if status == 'success' then | |||
insertTable = handler.successes | |||
handler.successesCount = handler.successesCount + 1 | |||
elseif status == 'pending' then | |||
insertTable = handler.pendings | |||
handler.pendingsCount = handler.pendingsCount + 1 | |||
elseif status == 'failure' then | |||
insertTable = handler.failures | |||
-- failure count already incremented in error handler | |||
elseif status == 'error' then | |||
-- error count already incremented in error handler | |||
insertTable = handler.errors | |||
isError = true | |||
end | |||
local formatted = handler.format(element, parent, element.message, debug, isError) | |||
local id = tostring(element) | |||
if handler.inProgress[id] then | |||
for k, v in pairs(handler.inProgress[id]) do | |||
formatted[k] = v | |||
end | |||
handler.inProgress[id] = nil | |||
end | |||
table.insert(insertTable, formatted) | |||
return nil, true | |||
end | |||
local function saveInProgress(element, message, debug) | |||
local id = tostring(element) | |||
handler.inProgress[id].message = message | |||
handler.inProgress[id].trace = debug | |||
end | |||
local function saveError(element, parent, message, debug) | |||
if parent.randomseed then | |||
message = 'Random Seed: ' .. parent.randomseed .. '\n' .. message | |||
end | |||
saveInProgress(element, message, debug) | |||
end | |||
handler.basePending = function(element, parent, message, debug) | |||
saveInProgress(element, message, debug) | |||
return nil, true | |||
end | |||
handler.baseTestFailure = function(element, parent, message, debug) | |||
handler.failuresCount = handler.failuresCount + 1 | |||
saveError(element, parent, message, debug) | |||
return nil, true | |||
end | |||
handler.baseTestError = function(element, parent, message, debug) | |||
handler.errorsCount = handler.errorsCount + 1 | |||
saveError(element, parent, message, debug) | |||
return nil, true | |||
end | |||
handler.baseError = function(element, parent, message, debug) | |||
if element.descriptor ~= 'it' then | |||
handler.errorsCount = handler.errorsCount + 1 | |||
table.insert(handler.errors, handler.format(element, parent, message, debug, true)) | |||
end | |||
return nil, true | |||
end | |||
return handler | |||
end |
@@ -1,21 +0,0 @@ | |||
local json = require 'dkjson' | |||
return function(options, busted) | |||
local handler = require 'busted.outputHandlers.base'(busted) | |||
handler.suiteEnd = function() | |||
print(json.encode({ | |||
pendings = handler.pendings, | |||
successes = handler.successes, | |||
failures = handler.failures, | |||
errors = handler.errors, | |||
duration = handler.getDuration() | |||
})) | |||
return nil, true | |||
end | |||
busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) | |||
return handler | |||
end |
@@ -1,136 +0,0 @@ | |||
local xml = require 'pl.xml' | |||
local socket = require("socket") | |||
local string = require("string") | |||
return function(options, busted) | |||
local handler = require 'busted.outputHandlers.base'(busted) | |||
local top = { | |||
start_time = socket.gettime(), | |||
xml_doc = xml.new('testsuites', { | |||
tests = 0, | |||
errors = 0, | |||
failures = 0, | |||
skip = 0, | |||
}) | |||
} | |||
local stack = {} | |||
local testStartTime | |||
handler.suiteStart = function(count, total) | |||
local suite = { | |||
start_time = socket.gettime(), | |||
xml_doc = xml.new('testsuite', { | |||
name = 'Run ' .. count .. ' of ' .. total, | |||
tests = 0, | |||
errors = 0, | |||
failures = 0, | |||
skip = 0, | |||
timestamp = os.date('!%Y-%m-%dT%T'), | |||
}) | |||
} | |||
top.xml_doc:add_direct_child(suite.xml_doc) | |||
table.insert(stack, top) | |||
top = suite | |||
return nil, true | |||
end | |||
local function elapsed(start_time) | |||
return string.format("%.2f", (socket.gettime() - start_time)) | |||
end | |||
handler.suiteEnd = function(count, total) | |||
local suite = top | |||
suite.xml_doc.attr.time = elapsed(suite.start_time) | |||
top = table.remove(stack) | |||
top.xml_doc.attr.tests = top.xml_doc.attr.tests + suite.xml_doc.attr.tests | |||
top.xml_doc.attr.errors = top.xml_doc.attr.errors + suite.xml_doc.attr.errors | |||
top.xml_doc.attr.failures = top.xml_doc.attr.failures + suite.xml_doc.attr.failures | |||
top.xml_doc.attr.skip = top.xml_doc.attr.skip + suite.xml_doc.attr.skip | |||
return nil, true | |||
end | |||
handler.exit = function() | |||
top.xml_doc.attr.time = elapsed(top.start_time) | |||
print(xml.tostring(top.xml_doc, '', '\t', nil, false)) | |||
return nil, true | |||
end | |||
local function testStatus(element, parent, message, status, trace) | |||
local testcase_node = xml.new('testcase', { | |||
classname = element.trace.short_src .. ':' .. element.trace.currentline, | |||
name = handler.getFullName(element), | |||
time = elapsed(testStartTime) | |||
}) | |||
top.xml_doc:add_direct_child(testcase_node) | |||
if status ~= 'success' then | |||
testcase_node:addtag(status) | |||
if message then testcase_node:text(message) end | |||
if trace and trace.traceback then testcase_node:text(trace.traceback) end | |||
testcase_node:up() | |||
end | |||
end | |||
handler.testStart = function(element, parent) | |||
testStartTime = socket.gettime() | |||
return nil, true | |||
end | |||
handler.testEnd = function(element, parent, status) | |||
top.xml_doc.attr.tests = top.xml_doc.attr.tests + 1 | |||
if status == 'success' then | |||
testStatus(element, parent, nil, 'success') | |||
elseif status == 'pending' then | |||
top.xml_doc.attr.skip = top.xml_doc.attr.skip + 1 | |||
local formatted = handler.pendings[#handler.pendings] | |||
local trace = element.trace ~= formatted.trace and formatted.trace | |||
testStatus(element, parent, formatted.message, 'skipped', trace) | |||
end | |||
return nil, true | |||
end | |||
handler.failureTest = function(element, parent, message, trace) | |||
top.xml_doc.attr.failures = top.xml_doc.attr.failures + 1 | |||
testStatus(element, parent, message, 'failure', trace) | |||
return nil, true | |||
end | |||
handler.errorTest = function(element, parent, message, trace) | |||
top.xml_doc.attr.errors = top.xml_doc.attr.errors + 1 | |||
testStatus(element, parent, message, 'error', trace) | |||
return nil, true | |||
end | |||
handler.error = function(element, parent, message, trace) | |||
if element.descriptor ~= 'it' then | |||
top.xml_doc.attr.errors = top.xml_doc.attr.errors + 1 | |||
top.xml_doc:addtag('error') | |||
top.xml_doc:text(message) | |||
if trace and trace.traceback then | |||
top.xml_doc:text(trace.traceback) | |||
end | |||
top.xml_doc:up() | |||
end | |||
return nil, true | |||
end | |||
busted.subscribe({ 'exit' }, handler.exit) | |||
busted.subscribe({ 'suite', 'start' }, handler.suiteStart) | |||
busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) | |||
busted.subscribe({ 'test', 'start' }, handler.testStart, { predicate = handler.cancelOnPending }) | |||
busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) | |||
busted.subscribe({ 'error', 'it' }, handler.errorTest) | |||
busted.subscribe({ 'failure', 'it' }, handler.failureTest) | |||
busted.subscribe({ 'error' }, handler.error) | |||
busted.subscribe({ 'failure' }, handler.error) | |||
return handler | |||
end |
@@ -1,175 +0,0 @@ | |||
local s = require 'say' | |||
local pretty = require 'pl.pretty' | |||
return function(options, busted) | |||
local handler = require 'busted.outputHandlers.base'(busted) | |||
local successDot = '+' | |||
local failureDot = '-' | |||
local errorDot = '*' | |||
local pendingDot = '.' | |||
local pendingDescription = function(pending) | |||
local name = pending.name | |||
local string = s('output.pending') .. ' → ' .. | |||
pending.trace.short_src .. ' @ ' .. | |||
pending.trace.currentline .. | |||
'\n' .. name | |||
if type(pending.message) == 'string' then | |||
string = string .. '\n' .. pending.message | |||
elseif pending.message ~= nil then | |||
string = string .. '\n' .. pretty.write(pending.message) | |||
end | |||
return string | |||
end | |||
local failureMessage = function(failure) | |||
local string | |||
if type(failure.message) == 'string' then | |||
string = failure.message | |||
elseif failure.message == nil then | |||
string = 'Nil error' | |||
else | |||
string = pretty.write(failure.message) | |||
end | |||
return string | |||
end | |||
local failureDescription = function(failure, isError) | |||
local string = s('output.failure') .. ' → ' | |||
if isError then | |||
string = s('output.error') .. ' → ' | |||
end | |||
if not failure.element.trace or not failure.element.trace.short_src then | |||
string = string .. | |||
failureMessage(failure) .. '\n' .. | |||
failure.name | |||
else | |||
string = string .. | |||
failure.element.trace.short_src .. ' @ ' .. | |||
failure.element.trace.currentline .. '\n' .. | |||
failure.name .. '\n' .. | |||
failureMessage(failure) | |||
end | |||
if options.verbose and failure.trace and failure.trace.traceback then | |||
string = string .. '\n' .. failure.trace.traceback | |||
end | |||
return string | |||
end | |||
local statusString = function() | |||
local successString = s('output.success_plural') | |||
local failureString = s('output.failure_plural') | |||
local pendingString = s('output.pending_plural') | |||
local errorString = s('output.error_plural') | |||
local ms = handler.getDuration() | |||
local successes = handler.successesCount | |||
local pendings = handler.pendingsCount | |||
local failures = handler.failuresCount | |||
local errors = handler.errorsCount | |||
if successes == 0 then | |||
successString = s('output.success_zero') | |||
elseif successes == 1 then | |||
successString = s('output.success_single') | |||
end | |||
if failures == 0 then | |||
failureString = s('output.failure_zero') | |||
elseif failures == 1 then | |||
failureString = s('output.failure_single') | |||
end | |||
if pendings == 0 then | |||
pendingString = s('output.pending_zero') | |||
elseif pendings == 1 then | |||
pendingString = s('output.pending_single') | |||
end | |||
if errors == 0 then | |||
errorString = s('output.error_zero') | |||
elseif errors == 1 then | |||
errorString = s('output.error_single') | |||
end | |||
local formattedTime = ('%.6f'):format(ms):gsub('([0-9])0+$', '%1') | |||
return successes .. ' ' .. successString .. ' / ' .. | |||
failures .. ' ' .. failureString .. ' / ' .. | |||
errors .. ' ' .. errorString .. ' / ' .. | |||
pendings .. ' ' .. pendingString .. ' : ' .. | |||
formattedTime .. ' ' .. s('output.seconds') | |||
end | |||
handler.testEnd = function(element, parent, status, debug) | |||
if not options.deferPrint then | |||
local string = successDot | |||
if status == 'pending' then | |||
string = pendingDot | |||
elseif status == 'failure' then | |||
string = failureDot | |||
elseif status == 'error' then | |||
string = errorDot | |||
end | |||
io.write(string) | |||
io.flush() | |||
end | |||
return nil, true | |||
end | |||
handler.suiteStart = function(count, total) | |||
local runString = (total > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') | |||
io.write(runString:format(count, total)) | |||
io.flush() | |||
end | |||
handler.suiteEnd = function() | |||
print('') | |||
print(statusString()) | |||
for i, pending in pairs(handler.pendings) do | |||
print('') | |||
print(pendingDescription(pending)) | |||
end | |||
for i, err in pairs(handler.failures) do | |||
print('') | |||
print(failureDescription(err)) | |||
end | |||
for i, err in pairs(handler.errors) do | |||
print('') | |||
print(failureDescription(err, true)) | |||
end | |||
return nil, true | |||
end | |||
handler.error = function(element, parent, message, debug) | |||
io.write(errorDot) | |||
io.flush() | |||
return nil, true | |||
end | |||
busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) | |||
busted.subscribe({ 'suite', 'start' }, handler.suiteStart) | |||
busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) | |||
busted.subscribe({ 'error', 'file' }, handler.error) | |||
busted.subscribe({ 'failure', 'file' }, handler.error) | |||
busted.subscribe({ 'error', 'describe' }, handler.error) | |||
busted.subscribe({ 'failure', 'describe' }, handler.error) | |||
return handler | |||
end |
@@ -1,36 +0,0 @@ | |||
local app = require 'pl.app' | |||
return function(options, busted) | |||
local handler = require 'busted.outputHandlers.base'(busted) | |||
local language = require('busted.languages.' .. options.language) | |||
handler.suiteEnd = function() | |||
local system = app.platform() | |||
local sayer_pre, sayer_post | |||
local messages | |||
if system == 'Linux' then | |||
sayer_pre = 'espeak -s 160 ' | |||
sayer_post = ' > /dev/null 2>&1' | |||
elseif system and system:match('^Windows') then | |||
sayer_pre = 'echo ' | |||
sayer_post = ' | ptts' | |||
else | |||
sayer_pre = 'say ' | |||
sayer_post = '' | |||
end | |||
if handler.failuresCount > 0 then | |||
messages = language.failure_messages | |||
else | |||
messages = language.success_messages | |||
end | |||
io.popen(sayer_pre .. '"' .. messages[math.random(1, #messages)] .. '"' .. sayer_post) | |||
return nil, true | |||
end | |||
busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) | |||
return handler | |||
end |
@@ -1,176 +0,0 @@ | |||
local ansicolors = require 'ansicolors' | |||
local s = require 'say' | |||
local pretty = require 'pl.pretty' | |||
return function(options, busted) | |||
local handler = require 'busted.outputHandlers.base'(busted) | |||
local successDot = ansicolors('%{green}●') | |||
local failureDot = ansicolors('%{red}◼') | |||
local errorDot = ansicolors('%{magenta}✱') | |||
local pendingDot = ansicolors('%{yellow}◌') | |||
local pendingDescription = function(pending) | |||
local name = pending.name | |||
local string = ansicolors('%{yellow}' .. s('output.pending')) .. ' → ' .. | |||
ansicolors('%{cyan}' .. pending.trace.short_src) .. ' @ ' .. | |||
ansicolors('%{cyan}' .. pending.trace.currentline) .. | |||
'\n' .. ansicolors('%{bright}' .. name) | |||
if type(pending.message) == 'string' then | |||
string = string .. '\n' .. pending.message | |||
elseif pending.message ~= nil then | |||
string = string .. '\n' .. pretty.write(pending.message) | |||
end | |||
return string | |||
end | |||
local failureMessage = function(failure) | |||
local string | |||
if type(failure.message) == 'string' then | |||
string = failure.message | |||
elseif failure.message == nil then | |||
string = 'Nil error' | |||
else | |||
string = pretty.write(failure.message) | |||
end | |||
return string | |||
end | |||
local failureDescription = function(failure, isError) | |||
local string = ansicolors('%{red}' .. s('output.failure')) .. ' → ' | |||
if isError then | |||
string = ansicolors('%{magenta}' .. s('output.error')) .. ' → ' | |||
end | |||
if not failure.element.trace or not failure.element.trace.short_src then | |||
string = string .. | |||
ansicolors('%{cyan}' .. failureMessage(failure)) .. '\n' .. | |||
ansicolors('%{bright}' .. failure.name) | |||
else | |||
string = string .. | |||
ansicolors('%{cyan}' .. failure.element.trace.short_src) .. ' @ ' .. | |||
ansicolors('%{cyan}' .. failure.element.trace.currentline) .. '\n' .. | |||
ansicolors('%{bright}' .. failure.name) .. '\n' .. | |||
failureMessage(failure) | |||
end | |||
if options.verbose and failure.trace and failure.trace.traceback then | |||
string = string .. '\n' .. failure.trace.traceback | |||
end | |||
return string | |||
end | |||
local statusString = function() | |||
local successString = s('output.success_plural') | |||
local failureString = s('output.failure_plural') | |||
local pendingString = s('output.pending_plural') | |||
local errorString = s('output.error_plural') | |||
local ms = handler.getDuration() | |||
local successes = handler.successesCount | |||
local pendings = handler.pendingsCount | |||
local failures = handler.failuresCount | |||
local errors = handler.errorsCount | |||
if successes == 0 then | |||
successString = s('output.success_zero') | |||
elseif successes == 1 then | |||
successString = s('output.success_single') | |||
end | |||
if failures == 0 then | |||
failureString = s('output.failure_zero') | |||
elseif failures == 1 then | |||
failureString = s('output.failure_single') | |||
end | |||
if pendings == 0 then | |||
pendingString = s('output.pending_zero') | |||
elseif pendings == 1 then | |||
pendingString = s('output.pending_single') | |||
end | |||
if errors == 0 then | |||
errorString = s('output.error_zero') | |||
elseif errors == 1 then | |||
errorString = s('output.error_single') | |||
end | |||
local formattedTime = ('%.6f'):format(ms):gsub('([0-9])0+$', '%1') | |||
return ansicolors('%{green}' .. successes) .. ' ' .. successString .. ' / ' .. | |||
ansicolors('%{red}' .. failures) .. ' ' .. failureString .. ' / ' .. | |||
ansicolors('%{magenta}' .. errors) .. ' ' .. errorString .. ' / ' .. | |||
ansicolors('%{yellow}' .. pendings) .. ' ' .. pendingString .. ' : ' .. | |||
ansicolors('%{bright}' .. formattedTime) .. ' ' .. s('output.seconds') | |||
end | |||
handler.testEnd = function(element, parent, status, debug) | |||
if not options.deferPrint then | |||
local string = successDot | |||
if status == 'pending' then | |||
string = pendingDot | |||
elseif status == 'failure' then | |||
string = failureDot | |||
elseif status == 'error' then | |||
string = errorDot | |||
end | |||
io.write(string) | |||
io.flush() | |||
end | |||
return nil, true | |||
end | |||
handler.suiteStart = function(count, total) | |||
local runString = (total > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') | |||
io.write(runString:format(count, total)) | |||
io.flush() | |||
end | |||
handler.suiteEnd = function(count, total) | |||
print('') | |||
print(statusString()) | |||
for i, pending in pairs(handler.pendings) do | |||
print('') | |||
print(pendingDescription(pending)) | |||
end | |||
for i, err in pairs(handler.failures) do | |||
print('') | |||
print(failureDescription(err)) | |||
end | |||
for i, err in pairs(handler.errors) do | |||
print('') | |||
print(failureDescription(err, true)) | |||
end | |||
return nil, true | |||
end | |||
handler.error = function(element, parent, message, debug) | |||
io.write(errorDot) | |||
io.flush() | |||
return nil, true | |||
end | |||
busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) | |||
busted.subscribe({ 'suite', 'start' }, handler.suiteStart) | |||
busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) | |||
busted.subscribe({ 'error', 'file' }, handler.error) | |||
busted.subscribe({ 'failure', 'file' }, handler.error) | |||
busted.subscribe({ 'error', 'describe' }, handler.error) | |||
busted.subscribe({ 'failure', 'describe' }, handler.error) | |||
return handler | |||
end |
@@ -1,400 +0,0 @@ | |||
local path = require 'pl.path' | |||
local term = require 'term' | |||
local utils = require 'busted.utils' | |||
local loaded = false | |||
return function(options) | |||
if loaded then return else loaded = true end | |||
local opt = options or {} | |||
local isBatch = opt.batch | |||
local cli = require 'cliargs' | |||
local busted = require 'busted.core'() | |||
local configLoader = require 'busted.modules.configuration_loader'() | |||
local helperLoader = require 'busted.modules.helper_loader'() | |||
local outputHandlerLoader = require 'busted.modules.output_handler_loader'() | |||
local luacov = require 'busted.modules.luacov'() | |||
local osexit = require 'busted.compatibility'.osexit | |||
require 'busted'(busted) | |||
-- Default cli arg values | |||
local defaultOutput = term.isatty(io.stdout) and 'utfTerminal' or 'plainTerminal' | |||
local defaultLoaders = 'lua,moonscript' | |||
local defaultPattern = '_spec' | |||
local defaultSeed = 'os.time()' | |||
local lpathprefix = './src/?.lua;./src/?/?.lua;./src/?/init.lua' | |||
local cpathprefix = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' | |||
local level = 2 | |||
local info = debug.getinfo(level, 'Sf') | |||
local source = info.source | |||
local fileName = source:sub(1,1) == '@' and source:sub(2) or source | |||
local cliArgsParsed = {} | |||
local function processOption(key, value, altkey, opt) | |||
if altkey then cliArgsParsed[altkey] = value end | |||
cliArgsParsed[key] = value | |||
return true | |||
end | |||
local function processNumber(key, value, altkey, opt) | |||
local number = tonumber(value) | |||
if not number then | |||
return nil, 'argument to ' .. opt:gsub('=.*', '') .. ' must be a number' | |||
end | |||
if altkey then cliArgsParsed[altkey] = number end | |||
cliArgsParsed[key] = number | |||
return true | |||
end | |||
local function processVersion() | |||
-- Return early if asked for the version | |||
print(busted.version) | |||
osexit(0, true) | |||
end | |||
-- Load up the command-line interface options | |||
cli:set_name(path.basename(fileName)) | |||
cli:add_flag('--version', 'prints the program version and exits', processVersion) | |||
if isBatch then | |||
cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 1) | |||
cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processOption) | |||
end | |||
cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput, processOption) | |||
cli:add_option('-d, --cwd=cwd', 'path to current working directory', './', processOption) | |||
cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags', nil, processOption) | |||
cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', nil, processOption) | |||
cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern', nil, processOption) | |||
cli:add_option('--filter-out=PATTERN', 'do not run test names matching the Lua pattern, takes precedence over --filter', nil, processOption) | |||
cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix, processOption) | |||
cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix, processOption) | |||
cli:add_option('-r, --run=RUN', 'config to run from .busted file', nil, processOption) | |||
cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1', processNumber) | |||
cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed, processNumber) | |||
cli:add_option('--lang=LANG', 'language for error messages', 'en', processOption) | |||
cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders, processOption) | |||
cli:add_option('--helper=PATH', 'A helper script that is run before tests', nil, processOption) | |||
cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.', nil, processOption) | |||
cli:add_option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.', nil, processOption) | |||
cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)', processOption) | |||
cli:add_flag('-v, --verbose', 'verbose output of errors', processOption) | |||
cli:add_flag('-s, --enable-sound', 'executes `say` command if available', processOption) | |||
cli:add_flag('-l, --list', 'list the names of all tests instead of running them', processOption) | |||
cli:add_flag('--no-keep-going', 'quit after first error or failure', processOption) | |||
cli:add_flag('--no-recursive', 'do not recurse into subdirectories', processOption) | |||
cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processOption) | |||
cli:add_flag('--shuffle-files', 'randomize file execution order, takes precedence over --sort-files', processOption) | |||
cli:add_flag('--shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests', processOption) | |||
cli:add_flag('--sort', 'sort file and test order (--sort-tests and --sort-files)', processOption) | |||
cli:add_flag('--sort-files', 'sort file execution order', processOption) | |||
cli:add_flag('--sort-tests', 'sort test order within a file', processOption) | |||
cli:add_flag('--suppress-pending', 'suppress `pending` test output', processOption) | |||
cli:add_flag('--defer-print', 'defer print to when test suite is complete', processOption) | |||
-- Parse the cli arguments | |||
local cliArgs = cli:parse(arg) | |||
if not cliArgs then | |||
osexit(1, true) | |||
end | |||
-- Load current working directory | |||
local fpath = utils.normpath(cliArgs.cwd) | |||
-- Load busted config file if available | |||
local configFile = { } | |||
local bustedConfigFilePath = utils.normpath(path.join(fpath, '.busted')) | |||
local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) | |||
if bustedConfigFile then | |||
local config, err = configLoader(configFile, cliArgsParsed, cliArgs) | |||
if err then | |||
print('Error: ' .. err) | |||
osexit(1, true) | |||
else | |||
cliArgs = config | |||
end | |||
end | |||
local tags = {} | |||
local excludeTags = {} | |||
if cliArgs.tags and cliArgs.tags ~= '' then | |||
tags = utils.split(cliArgs.tags, ',') | |||
end | |||
if cliArgs['exclude-tags'] and cliArgs['exclude-tags'] ~= '' then | |||
excludeTags = utils.split(cliArgs['exclude-tags'], ',') | |||
end | |||
-- If coverage arg is passed in, load LuaCovsupport | |||
if cliArgs.coverage then | |||
luacov() | |||
end | |||
-- Add additional package paths based on lpath and cpath cliArgs | |||
if #cliArgs.lpath > 0 then | |||
lpathprefix = cliArgs.lpath | |||
lpathprefix = lpathprefix:gsub('^%.([/%\\])', fpath .. '%1') | |||
lpathprefix = lpathprefix:gsub(';%.([/%\\])', ';' .. fpath .. '%1') | |||
package.path = (lpathprefix .. ';' .. package.path):gsub(';;',';') | |||
end | |||
if #cliArgs.cpath > 0 then | |||
cpathprefix = cliArgs.cpath | |||
cpathprefix = cpathprefix:gsub('^%.([/%\\])', fpath .. '%1') | |||
cpathprefix = cpathprefix:gsub(';%.([/%\\])', ';' .. fpath .. '%1') | |||
package.cpath = (cpathprefix .. ';' .. package.cpath):gsub(';;',';') | |||
end | |||
local loaders = {} | |||
if #cliArgs.loaders > 0 then | |||
string.gsub(cliArgs.loaders, '([^,]+)', function(c) loaders[#loaders+1] = c end) | |||
end | |||
-- We report an error if the same tag appears in both `options.tags` | |||
-- and `options.excluded_tags` because it does not make sense for the | |||
-- user to tell Busted to include and exclude the same tests at the | |||
-- same time. | |||
for _, excluded in pairs(excludeTags) do | |||
for _, included in pairs(tags) do | |||
if excluded == included then | |||
print('Error: Cannot use --tags and --exclude-tags for the same tags') | |||
osexit(1, true) | |||
end | |||
end | |||
end | |||
-- watch for test errors | |||
local failures = 0 | |||
local errors = 0 | |||
local quitOnError = cliArgs['no-keep-going'] | |||
busted.subscribe({ 'error', 'output' }, function(element, parent, message) | |||
print('Error: Cannot load output library: ' .. element.name .. '\n' .. message) | |||
return nil, true | |||
end) | |||
busted.subscribe({ 'error', 'helper' }, function(element, parent, message) | |||
print('Error: Cannot load helper script: ' .. element.name .. '\n' .. message) | |||
return nil, true | |||
end) | |||
busted.subscribe({ 'error' }, function(element, parent, message) | |||
errors = errors + 1 | |||
busted.skipAll = quitOnError | |||
return nil, true | |||
end) | |||
busted.subscribe({ 'failure' }, function(element, parent, message) | |||
if element.descriptor == 'it' then | |||
failures = failures + 1 | |||
else | |||
errors = errors + 1 | |||
end | |||
busted.skipAll = quitOnError | |||
return nil, true | |||
end) | |||
-- Set up output handler to listen to events | |||
local outputHandlerOptions = { | |||
verbose = cliArgs.verbose, | |||
suppressPending = cliArgs['suppress-pending'], | |||
language = cliArgs.lang, | |||
deferPrint = cliArgs['defer-print'], | |||
arguments = utils.split(cliArgs.Xoutput or '', ',') or {} | |||
} | |||
local opath = utils.normpath(path.join(fpath, cliArgs.output)) | |||
local outputHandler = outputHandlerLoader(cliArgs.output, opath, outputHandlerOptions, busted, defaultOutput) | |||
outputHandler:subscribe(outputHandlerOptions) | |||
if cliArgs['enable-sound'] then | |||
require 'busted.outputHandlers.sound'(outputHandlerOptions, busted) | |||
end | |||
-- Set up randomization options | |||
busted.sort = cliArgs['sort-tests'] or cliArgs.sort | |||
busted.randomize = cliArgs['shuffle-tests'] or cliArgs.shuffle | |||
busted.randomseed = tonumber(cliArgs.seed) or os.time() | |||
local getFullName = function(name) | |||
local parent = busted.context.get() | |||
local names = { name } | |||
while parent and (parent.name or parent.descriptor) and | |||
parent.descriptor ~= 'file' do | |||
table.insert(names, 1, parent.name or parent.descriptor) | |||
parent = busted.context.parent(parent) | |||
end | |||
return table.concat(names, ' ') | |||
end | |||
local hasTag = function(name, tag) | |||
local found = name:find('#' .. tag) | |||
return (found ~= nil) | |||
end | |||
local filterExcludeTags = function(name) | |||
for i, tag in pairs(excludeTags) do | |||
if hasTag(name, tag) then | |||
return nil, false | |||
end | |||
end | |||
return nil, true | |||
end | |||
local filterTags = function(name) | |||
local fullname = getFullName(name) | |||
for i, tag in pairs(tags) do | |||
if hasTag(fullname, tag) then | |||
return nil, true | |||
end | |||
end | |||
return nil, (#tags == 0) | |||
end | |||
local filterOutNames = function(name) | |||
local found = (getFullName(name):find(cliArgs['filter-out']) ~= nil) | |||
return nil, not found | |||
end | |||
local filterNames = function(name) | |||
local found = (getFullName(name):find(cliArgs.filter) ~= nil) | |||
return nil, found | |||
end | |||
local printNameOnly = function(name, fn, trace) | |||
local fullname = getFullName(name) | |||
if trace and trace.what == 'Lua' then | |||
print(trace.short_src .. ':' .. trace.currentline .. ': ' .. fullname) | |||
else | |||
print(fullname) | |||
end | |||
return nil, false | |||
end | |||
local ignoreAll = function() | |||
return nil, false | |||
end | |||
local skipOnError = function() | |||
return nil, (failures == 0 and errors == 0) | |||
end | |||
local applyFilter = function(descriptors, name, fn) | |||
if cliArgs[name] and cliArgs[name] ~= '' then | |||
for _, descriptor in ipairs(descriptors) do | |||
busted.subscribe({ 'register', descriptor }, fn, { priority = 1 }) | |||
end | |||
end | |||
end | |||
if cliArgs.list then | |||
busted.subscribe({ 'suite', 'start' }, ignoreAll, { priority = 1 }) | |||
busted.subscribe({ 'suite', 'end' }, ignoreAll, { priority = 1 }) | |||
applyFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'list', ignoreAll) | |||
applyFilter({ 'it', 'pending' }, 'list', printNameOnly) | |||
end | |||
applyFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'no-keep-going', skipOnError) | |||
applyFilter({ 'file', 'describe', 'it', 'pending' }, 'no-keep-going', skipOnError) | |||
-- The following filters are applied in reverse order | |||
applyFilter({ 'it', 'pending' } , 'filter' , filterNames ) | |||
applyFilter({ 'describe', 'it', 'pending' }, 'filter-out' , filterOutNames ) | |||
applyFilter({ 'it', 'pending' } , 'tags' , filterTags ) | |||
applyFilter({ 'describe', 'it', 'pending' }, 'exclude-tags', filterExcludeTags) | |||
-- Set up helper script | |||
if cliArgs.helper and cliArgs.helper ~= '' then | |||
local helperOptions = { | |||
verbose = cliArgs.verbose, | |||
language = cliArgs.lang, | |||
arguments = utils.split(cliArgs.Xhelper or '', ',') or {} | |||
} | |||
local hpath = utils.normpath(path.join(fpath, cliArgs.helper)) | |||
helperLoader(cliArgs.helper, hpath, helperOptions, busted) | |||
end | |||
-- Set up test loader options | |||
local testFileLoaderOptions = { | |||
verbose = cliArgs.verbose, | |||
sort = cliArgs['sort-files'] or cliArgs.sort, | |||
shuffle = cliArgs['shuffle-files'] or cliArgs.shuffle, | |||
recursive = not cliArgs['no-recursive'], | |||
seed = busted.randomseed | |||
} | |||
-- Load test directory | |||
local rootFile = cliArgs.ROOT and utils.normpath(path.join(fpath, cliArgs.ROOT)) or fileName | |||
local pattern = cliArgs.pattern | |||
local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders, testFileLoaderOptions) | |||
local fileList = testFileLoader(rootFile, pattern) | |||
if not cliArgs.ROOT then | |||
local ctx = busted.context.get() | |||
local file = busted.context.children(ctx)[1] | |||
getmetatable(file.run).__call = info.func | |||
end | |||
busted.subscribe({'suite', 'reinitialize'}, function() | |||
local oldctx = busted.context.get() | |||
local children = busted.context.children(oldctx) | |||
busted.context.clear() | |||
local ctx = busted.context.get() | |||
for k, v in pairs(oldctx) do | |||
ctx[k] = v | |||
end | |||
for _, child in pairs(children) do | |||
for descriptor, _ in pairs(busted.executors) do | |||
child[descriptor] = nil | |||
end | |||
busted.context.attach(child) | |||
end | |||
busted.randomseed = tonumber(cliArgs.seed) or os.time() | |||
return nil, true | |||
end) | |||
local runs = tonumber(cliArgs['repeat']) or 1 | |||
for i = 1, runs do | |||
if i > 1 then | |||
busted.publish({ 'suite', 'reinitialize' }) | |||
end | |||
busted.publish({ 'suite', 'start' }, i, runs) | |||
busted.execute() | |||
busted.publish({ 'suite', 'end' }, i, runs) | |||
if quitOnError and (failures > 0 or errors > 0) then | |||
break | |||
end | |||
end | |||
busted.publish({ 'exit' }) | |||
local exit = 0 | |||
if failures > 0 or errors > 0 then | |||
exit = failures + errors | |||
if exit > 255 then | |||
exit = 255 | |||
end | |||
end | |||
osexit(exit, true) | |||
end |
@@ -1,43 +0,0 @@ | |||
local function get_status(status) | |||
local smap = { | |||
['success'] = 'success', | |||
['pending'] = 'pending', | |||
['failure'] = 'failure', | |||
['error'] = 'error', | |||
['true'] = 'success', | |||
['false'] = 'failure', | |||
['nil'] = 'error', | |||
} | |||
return smap[tostring(status)] or 'error' | |||
end | |||
return function(inital_status) | |||
local objstat = get_status(inital_status) | |||
local obj = { | |||
success = function(self) return (objstat == 'success') end, | |||
pending = function(self) return (objstat == 'pending') end, | |||
failure = function(self) return (objstat == 'failure') end, | |||
error = function(self) return (objstat == 'error') end, | |||
get = function(self) | |||
return objstat | |||
end, | |||
set = function(self, status) | |||
objstat = get_status(status) | |||
end, | |||
update = function(self, status) | |||
-- prefer current failure/error status over new status | |||
status = get_status(status) | |||
if objstat == 'success' or (objstat == 'pending' and status ~= 'success') then | |||
objstat = status | |||
end | |||
end | |||
} | |||
return setmetatable(obj, { | |||
__index = {}, | |||
__tostring = function(self) return objstat end | |||
}) | |||
end |
@@ -1,53 +0,0 @@ | |||
local path = require 'pl.path' | |||
math.randomseed(os.time()) | |||
local function normpath(fpath) | |||
if type(fpath) ~= 'string' then | |||
error(fpath .. ' is not a string') | |||
end | |||
local sep = '/' | |||
if path.is_windows then | |||
sep = '\\' | |||
if fpath:match '^\\\\' then -- UNC | |||
return '\\\\' .. normpath(fpath:sub(3)) | |||
end | |||
fpath = fpath:gsub('/','\\') | |||
end | |||
local np_gen1, np_gen2 = '([^SEP]+)SEP(%.%.SEP?)', 'SEP+%.?SEP' | |||
local np_pat1 = np_gen1:gsub('SEP', sep) | |||
local np_pat2 = np_gen2:gsub('SEP', sep) | |||
local k | |||
repeat -- /./ -> / | |||
fpath, k = fpath:gsub(np_pat2, sep) | |||
until k == 0 | |||
repeat -- A/../ -> (empty) | |||
local oldpath = fpath | |||
fpath, k = fpath:gsub(np_pat1, function(d, up) | |||
if d == '..' then return nil end | |||
if d == '.' then return up end | |||
return '' | |||
end) | |||
until k == 0 or oldpath == fpath | |||
if fpath == '' then fpath = '.' end | |||
return fpath | |||
end | |||
return { | |||
split = require 'pl.utils'.split, | |||
normpath = normpath, | |||
shuffle = function(t, seed) | |||
if seed then math.randomseed(seed) end | |||
local n = #t | |||
while n >= 2 do | |||
local k = math.random(n) | |||
t[n], t[k] = t[k], t[n] | |||
n = n - 1 | |||
end | |||
return t | |||
end | |||
} |
@@ -1,7 +1,5 @@ | |||
-- Test rsa signing | |||
require "busted" () | |||
describe("rsa signarture test", function() | |||
local rsa_privkey = require "rspamd_rsa_privkey" | |||
local rsa_pubkey = require "rspamd_rsa_pubkey" |
@@ -29,15 +29,12 @@ | |||
static const char *lua_src = "./lua"; | |||
void | |||
rspamd_lua_test_func (void) | |||
rspamd_lua_test_func (int argc, char **argv) | |||
{ | |||
lua_State *L = rspamd_lua_init (NULL); | |||
gchar *lua_file; | |||
gchar rp[PATH_MAX]; | |||
glob_t globbuf; | |||
gchar *pattern; | |||
guint i, len; | |||
struct stat st; | |||
gchar rp[PATH_MAX], path_buf[PATH_MAX]; | |||
const gchar *old_path; | |||
guint i; | |||
msg_info ("Starting lua tests"); | |||
@@ -46,40 +43,39 @@ rspamd_lua_test_func (void) | |||
g_assert (0); | |||
} | |||
globbuf.gl_offs = 0; | |||
len = strlen (rp) + sizeof ("*.lua") + 1; | |||
pattern = g_malloc (len); | |||
rspamd_snprintf (pattern, len, "%s/%s", rp, "*.lua"); | |||
/* Set lua path */ | |||
lua_getglobal (L, "package"); | |||
lua_getfield (L, -1, "path"); | |||
old_path = luaL_checkstring (L, -1); | |||
if (glob (pattern, GLOB_DOOFFS, NULL, &globbuf) == 0) { | |||
for (i = 0; i < globbuf.gl_pathc; i++) { | |||
lua_file = globbuf.gl_pathv[i]; | |||
rspamd_snprintf (path_buf, sizeof (path_buf), "%s;%s/?.lua;%s/busted/?.lua", | |||
old_path, rp, rp); | |||
lua_pop (L, 1); | |||
lua_pushstring (L, path_buf); | |||
lua_setfield (L, -2, "path"); | |||
lua_pop (L, 1); | |||
if (stat (lua_file, &st) == -1 || !S_ISREG (st.st_mode)) { | |||
continue; | |||
} | |||
lua_getglobal (L, "arg"); | |||
if (strstr (lua_file, "busted") != NULL) { | |||
/* Skip busted code itself */ | |||
continue; | |||
} | |||
if (lua_type (L, -1) != LUA_TTABLE) { | |||
lua_newtable (L); | |||
} | |||
if (luaL_loadfile (L, lua_file) != 0) { | |||
msg_err ("load test from %s failed", lua_file); | |||
g_assert (0); | |||
} | |||
/* Now do it */ | |||
if (lua_pcall (L, 0, LUA_MULTRET, 0) != 0) { | |||
msg_err ("run test from %s failed: %s", lua_file, | |||
lua_tostring (L, -1)); | |||
g_assert (0); | |||
} | |||
} | |||
globfree (&globbuf); | |||
g_free (pattern); | |||
for (i = 0; i < argc - 1; i ++) { | |||
lua_pushinteger (L, i + 1); | |||
lua_pushstring (L, argv[i]); | |||
lua_settable (L, -3); | |||
} | |||
else { | |||
msg_err ("glob for %s failed: %s", pattern, strerror (errno)); | |||
lua_setglobal (L, "arg"); | |||
lua_pop (L, 1); | |||
rspamd_snprintf (path_buf, sizeof (path_buf), | |||
"require 'busted.runner'({ batch = true })"); | |||
if (luaL_dostring (L, path_buf) != 0) { | |||
rspamd_fprintf (stderr, "run test failed: %s", lua_tostring (L, -1)); | |||
g_assert (0); | |||
} | |||
exit (EXIT_SUCCESS); | |||
} |
@@ -13,6 +13,11 @@ main (int argc, char **argv) | |||
{ | |||
struct rspamd_config *cfg; | |||
if (argc > 0 && strcmp (argv[1], "lua") == 0) { | |||
/* Special lua testing mode */ | |||
rspamd_lua_test_func (argc - 1, &argv[2]); | |||
} | |||
g_test_init (&argc, &argv, NULL); | |||
rspamd_main = (struct rspamd_main *)g_malloc (sizeof (struct rspamd_main)); | |||
@@ -56,7 +61,6 @@ main (int argc, char **argv) | |||
g_test_add_func ("/rspamd/upstream", rspamd_upstream_test_func); | |||
g_test_add_func ("/rspamd/shingles", rspamd_shingles_test_func); | |||
g_test_add_func ("/rspamd/http", rspamd_http_test_func); | |||
g_test_add_func ("/rspamd/lua", rspamd_lua_test_func); | |||
g_test_run (); | |||
@@ -41,6 +41,6 @@ void rspamd_shingles_test_func (void); | |||
void rspamd_http_test_func (void); | |||
void rspamd_lua_test_func (void); | |||
void rspamd_lua_test_func (int argc, char **argv); | |||
#endif |