/usr/share/lua/5.1/shake.lua is in shake 1.0.2-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 | -------------------------------------------------------------------------------
-- Shake, a simple test engine for Lua
--
-- Authors: Andre Carregal, Humberto dos Anjos
-- Copyright (c) 2007 Kepler Project
--
-- $Id: shake.lua,v 1.14 2008/03/17 17:20:43 carregal Exp $
-------------------------------------------------------------------------------
local io = require "io"
local lfs = require "lfs"
local table = require "table"
local string = require "string"
local _G, error, unpack, loadstring, pcall, xpcall, ipairs, setmetatable, setfenv, loadfile, dofile =
_G, error, unpack, loadstring, pcall, xpcall, ipairs, setmetatable, setfenv, loadfile, dofile
require "shake.stir"
-- tries to get the debug table
local debug = debug
if not next(debug) then
-- uses a stub when debug information is not available
debug = {
getinfo = function() return {linenumber = "???"} end,
traceback = function() return "No traceback information: debug is not available" end,
}
end
local getinfo = debug.getinfo
local traceback = debug.traceback
module(...)
_COPYRIGHT = "Copyright (C) 2007 Kepler Project"
_DESCRIPTION = "Shake is a simple and transparent test engine for Lua that assumes that tests only use standard assert and print calls."
_VERSION = "Shake 1.0.2"
----------- local functions ------------
-- Version of loadstring that stirs the file before compiling it
local function _loadstring(s, filename)
s = string.gsub(s, "^#![^\n]*\n", "-- keeps one line in place of an eventual one with a #! at the start\n")
s = stir(s)
return loadstring(s, filename)
end
-- Version of loadfile that stirs the file before compiling it
local function _loadfile(filename)
local f
local file = io.open(filename)
if not file then
return
else
local s = file:read'*a'
f, errmsg = _loadstring(s, filename)
end
return f, errmsg
end
-- Version of dostring that stirs the string before executing it
local function _dostring(s, filename)
local results = {pcall(_loadstring(s, filename))}
if results[1] then
table.remove(results, 1)
end
return unpack(results)
end
-- Version of dofile that stirs the file before executing it
local function _dofile(filename)
local results = {pcall(_loadfile(filename))}
if results[1] then
table.remove(results, 1)
end
return unpack(results)
end
-- Returns a new suite
local function _newsuite(filename, title, errmsg)
local source = {}
if not errmsg then
for line in io.lines(filename) do
source[#source + 1] = line
end
end
return {title = title, filename = filename, passed = 0, failed = 0, error = errmsg, source = source, contexts = {} }
end
-- Returns a new context
local function _newcontext(...)
return {output = {...}, passed = 0, failed = 0, tests = {} }
end
-- Returns a contextualized assert()
function _newassert(suite, context)
return function(val1, op, val2, msg, exp1, exp2, comments)
if comments then
context = _newcontext(comments)
suite.contexts[#suite.contexts + 1] = context
end
local test = { message = msg or "" }
context.tests[#context.tests + 1] = test
local PASSED = false
if not op then
PASSED = val1
elseif op == '==' then
PASSED = val1 == val2
elseif op == '~=' then
PASSED = val1 ~= val2
end
if PASSED then
context.passed = context.passed + 1
suite.passed = suite.passed + 1
else
context.failed = context.failed + 1
suite.failed = suite.failed + 1
end
test.val1 = val1
test.op = op
test.val2 = val2
test.exp1 = exp1
test.exp2 = exp2
test.msg = msg
test.passed = PASSED
test.linenumber = getinfo(2, "l").currentline
test.traceback = traceback("", 2)
return PASSED, msg
end
end
-------------------------------------------------------------------------------
-- Runs a suite of tests from filename using a title
-- Test results are added to the results table
-------------------------------------------------------------------------------
local function _test(self, filename, title)
f, errmsg = _loadfile(filename)
local results = self.results
title = title or ""
if not f then
-- error loading the file
errmsg = string.gsub(errmsg, '%[string "'..filename..'"%]', filename)
results.suites[#results.suites + 1] = _newsuite(filename, title, errmsg)
results.errors = results.errors + 1
else
-- runs the test suite
local _print = _G.print
local _write = _G.io.write
local ___STIR_assert = _G.___STIR_assert
local lf = _G.loadfile
local df = _G.dofile
local ls = _G.loadstring
local ds = _G.dostring
_G.loadfile = _loadfile
_G.dofile = _dofile
_G.loadstring = _loadstring
_G.dostring = _dostring
local suite = _newsuite(filename, title)
local context = _newcontext("")
_G.___STIR_assert = _newassert(suite, context) -- so assertions works even without a previous context
suite.contexts[#suite.contexts + 1] = context
-- separate contexts at every print or io.write
-- keeping the output stored in the context table
_G.print = function(...)
local context = suite.contexts[#suite.contexts]
if context.passed + context.failed > 0 then
-- create a new context if there was an assert before the previous context
context = _newcontext(...)
suite.contexts[#suite.contexts + 1] = context
else
-- converts all parameters to strings
local temp = {}
for i = 1, _G.select('#',...) do
table.insert(temp, _G.tostring(_G.select(i,...)))
end
-- and concatenates them
context.output[#context.output + 1] = table.concat(temp, "\t")
end
_G.___STIR_assert = _newassert(suite, context)
end
_G.io.write = _G.print
-- executes the suite
local res, errmsg = xpcall(f, function(err) return err end)
if not res then
-- error executing the suite
errmsg = errmsg or ""
suite.error = string.gsub(errmsg, '%[string "'..filename..'"%]', filename)
results.errors = results.errors + 1
end
results.passed = results.passed + suite.passed
results.failed = results.failed + suite.failed
results.suites[#results.suites + 1] = suite
-- restores the environment
_G.loadfile = lf
_G.dofile = df
_G.loadstring = ls
_G.dostring = ds
_G.print = _print
_G.io.write = _write
_G.___STIR_assert = ___STIR_assert
end
end
-------------------------------------------------------------------------------
-- Returns a summary of the test results using an optional line separator
-------------------------------------------------------------------------------
local function _summary(self, sep)
local out = {}
local results = self.results
sep = sep or "\n"
for cs, suite in ipairs(results.suites) do
if suite.error then
out[#out + 1] = ">>>>>>>>>>>>>>>> "..suite.title.." "..suite.filename.." has an error!!!".." <<<<<<<<<<<<<<<<"
out[#out + 1] = ""
out[#out + 1] = suite.error
out[#out + 1] = ""
elseif suite.failed > 0 then
out[#out + 1] = "---------------- "..suite.title.." "..suite.filename.." failed!".." ----------------"
for cg, context in ipairs(suite.contexts) do
if context.failed > 0 then
out[#out + 1] = ""
for _, output in ipairs(context.output) do
out[#out + 1] = _G.tostring(output)
end
if context.comments then
out[#out + 1] = context.comments
end
for ct, test in ipairs (context.tests) do
if not test.passed then
if suite.source[test.linenumber] then
out[#out + 1] = " #"..test.linenumber.." "..suite.source[test.linenumber]
end
if not isTerminal(test.exp1, test.val1) then
out[#out + 1] = " "..test.exp1.." -> ".._G.tostring(test.val1)
end
if not isTerminal(test.exp2, test.val2) then
out[#out + 1] = " "..test.exp2.." -> ".._G.tostring(test.val2)
end
end
end
end
end
else
out[#out + 1] = "-> "..suite.title.." "..suite.filename.." OK!"
end
end
out[#out + 1] = "_________________"
out[#out + 1] = ""
out[#out + 1] = "Tests: "..results.failed + results.passed
out[#out + 1] = "Failures: "..results.failed
out[#out + 1] = "Errors: "..results.errors
out[#out + 1] = ""
return table.concat(out, sep)
end
---------- Public functions --------------
-------------------------------------------------------------------------------
-- Returns a new runner with the functions
-- test(filename)
-- summary()
-------------------------------------------------------------------------------
function runner()
local runner = {results = {passed = 0, failed = 0, errors = 0, suites = {} } }
setmetatable(runner, {__index = {test = _test, summary = _summary} })
return runner
end
-------------------------------------------------------------------------------
-- Checks if an expression string represents a terminal value
-------------------------------------------------------------------------------
function isTerminal(exp, val)
if not exp then return true end
local chunk = loadstring('return '..exp)
local env = {}
setmetatable(env, {__index = function() return "___nil___" end})
setfenv(chunk, env)
local status, ret = pcall(chunk)
if status then
return ret == val
end
end
|