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
|
-- vim: et:ts=2:sw=2
-- Helper variables and functions
local get_info = debug.getinfo
local pcall = pcall
local slice = string.sub
local sprintf = string.format
local str_find = string.find
local tonumber = tonumber
-- Lua 5.3 moved unpack to table.unpack
local unpack = unpack or table.unpack
local write = io.write
local rawget = rawget
local getmetatable = getmetatable
local exit = os.exit
local krprint = require("krprint")
---- Helper methods
--- C-like printf method
local printf = function(fmt, ...)
write(sprintf(fmt, ...))
end
local printdiff = function(func_name, actual, expected)
printf("Assertion %s() failed for test below (marked 'not ok'):\n", func_name)
printf("Expected: %s\n", krprint.pprint(expected))
printf("Got: %s\n", krprint.pprint(actual))
end
--- Compare potentially complex tables or objects
--
-- Ideas here are taken from [Penlight][p], [Underscore][u], [cwtest][cw], and
-- [luassert][l].
-- [p]: https://github.com/stevedonovan/Penlight
-- [u]: https://github.com/mirven/underscore.lua
-- [cw]: https://github.com/catwell/cwtest
-- [l]: https://github.com/Olivine-Labs/luassert
--
-- Predeclare both function names
local keyvaluesame
local deepsame
--
--- keyvaluesame(table, table) => true or false
-- Helper method to compare all the keys and values of a table
keyvaluesame = function (t1, t2)
for k1, v1 in pairs(t1) do
local v2 = t2[k1]
if v2 == nil or not deepsame(v1, v2) then return false end
end
-- Check for any keys present in t2 but not t1
for k2, _ in pairs(t2) do
if t1[k2] == nil then return false end
end
return true
end
--
--- deepsame(item, item) => true or false
-- Compare two items of any type for identity
deepsame = function (t1, t2)
local ty1, ty2 = type(t1), type(t2)
if ty1 ~= ty2 then return false end
if ty1 ~= 'table' then return t1 == t2 end
-- If ._eq is found, use == and end quickly.
-- As of Lua 5.3 == only cares if **one** of the two items has a __eq
-- metamethod. Penlight, underscore and cwtest take the same approach,
-- so I will as well.
local eq = rawget(getmetatable(t1) or {}, '__eq')
if (type(eq) == 'function') then
return not not eq(t1, t2)
else
return keyvaluesame(t1, t2)
end
end
---- tapered test suite
local exit_status = 0
local test_count = 0
local debug_level = 3
-- All other tests are defined in terms of this primitive, which is
-- kept private.
local _test = function (exp, msg)
test_count = test_count + 1
if msg then
msg = sprintf(" - %s", msg)
else
msg = ''
end
if exp then
printf("ok %s%s\n", test_count, msg)
else
exit_status = 1 + exit_status
printf("not ok %s%s\n", test_count, msg)
local info = get_info(debug_level)
printf("# Trouble in %s around line %s\n",
slice(info.source, 2), info.currentline)
end
end
local ok = function (expression, msg)
_test(expression, msg)
end
local nok = function (expression, msg)
_test(not expression, msg)
end
local is = function (actual, expected, msg)
local result = actual == expected;
if not result then
printdiff("is", actual, expected)
end
_test(result, msg)
end
local isnt = function (actual, expected, msg)
_test(actual ~= expected, msg)
end
local same = function (actual, expected, msg)
local result = deepsame(actual, expected)
if not result then
printdiff("same", actual, expected)
end
_test(result, msg)
end
local like = function (str, pattern, msg)
_test(str_find(str, pattern), msg)
end
local unlike = function (str, pattern, msg)
_test(not str_find(str, pattern), msg)
end
local pass = function (msg)
_test(true, msg)
end
local fail = function (msg)
_test(false, msg)
end
local boom = function (func, args, msg)
local err, errmsg
err, errmsg = pcall(func, unpack(args))
_test(not err, msg)
if not err and type(errmsg) == 'string' then
printf('# Got this error: "%s"\n', errmsg)
end
end
local done = function (n)
local expected = tonumber(n)
if not expected or test_count == expected then
printf('1..%d\n', test_count)
elseif expected ~= test_count then
exit_status = 1 + exit_status
local s
if expected == 1 then s = '' else s = 's' end
printf("# Bad plan. You planned %d test%s but ran %d\n",
expected, s, test_count)
end
exit(exit_status)
end
local version = function ()
return "2.3.0"
end
local author = function ()
return "Peter Aronoff"
end
local url = function ()
return "https://github.com/telemachus/tapered"
end
local license = function ()
return "BSD 3-Clause"
end
return {
ok = ok,
nok = nok,
is = is,
isnt = isnt,
same = same,
like = like,
unlike = unlike,
pass = pass,
fail = fail,
boom = boom,
done = done,
version = version,
author = author,
url = url,
license = license
}
|