From Wikipedia, the free encyclopedia

--[[

--  MIT LICENSE

--

--  Copyright (c) 2015 Serge Zaitsev

--

--  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.

--]]



local function TERMINAL_HANDLER(e, test, msg)

	if e == 'pass' then

		mw.log("�[32m✔�[0m "..test..': '..msg)

	elseif e == 'fail' then

		mw.log("�[31m✘�[0m "..test..': '..msg)

	elseif e == 'except' then

		mw.log("�[31m✘�[0m "..test..': '..msg)

	end

end



local function deepeq(a, b)

	-- Different types: false

	if type(a) ~= type(b) then return false end

	-- Functions

	if type(a) == 'function' then

		return string.dump(a) == string.dump(b)

	end

	-- Primitives and equal pointers

	if a == b then return true end

	-- Only equal tables could have passed previous tests

	if type(a) ~= 'table' then return false end

	-- Compare tables field by field

	for k,v in pairs(a) do

		if bk == nil or not deepeq(v, bk]) then return false end

	end

	for k,v in pairs(b) do

		if ak == nil or not deepeq(v, ak]) then return false end

	end

	return true

end



-- Compatibility for Lua 5.1 and Lua 5.2

local function args(...)

	return {n=select('#', ...), ...}

end



local function spy(f)

	local s = {}

	setmetatable(s, {__call = function(s, ...)

		s.called = s.called or {}

		local a = args(...)

		table.insert(s.called, {...})

		if f then

			local r

			r = args(pcall(f, (unpack or table.unpack)(a, 1, a.n)))

			if not r1 then

				s.errors = s.errors or {}

				s.errors#s.called = r2

			else

				return (unpack or table.unpack)(r, 2, r.n)

			end

		end

	end})

	return s

end





return function(handler, env)



	local pendingtests = {}



	local function runpending()

		if pendingtests1 ~= nil then pendingtests1](runpending) end

	end



	local function test(name, f, async)

		local testfn = function(next)



			local prev = {

				ok = env.ok,

				spy = env.spy,

				eq = env.eq

			}



			local restore = function()

				env.ok = prev.ok

				env.spy = prev.spy

				env.eq = prev.eq

				env.gambiarrahandler('end', name)

				table.remove(pendingtests, 1)

				if next then next() end

			end



			local handler = env.gambiarrahandler



			env.eq = deepeq

			env.spy = spy

			env.ok = function(cond, msg)

				if cond then

					handler('pass', name, msg)

				else

					handler('fail', name, msg)

				end

			end



			handler('begin', name);

			local ok, err = pcall(f, restore)

			if not ok then

				handler('except', name, err)

			end



			if not async then

				handler('end', name);

				env.ok = prev.ok;

				env.spy = prev.spy;

				env.eq = prev.eq;

			end

		end



		if not async then

			testfn()

		else

			table.insert(pendingtests, testfn)

			if #pendingtests == 1 then

				runpending()

			end

		end

	end



	env = env or _G

	env.gambiarrahandler = handler or TERMINAL_HANDLER



	env.test = test

end