-
Notifications
You must be signed in to change notification settings - Fork 77
/
array.lua
70 lines (62 loc) · 2.45 KB
/
array.lua
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
local assert = require('luassert.assert')
local say = require('say')
-- Example usage:
-- local arr = { "one", "two", "three" }
--
-- assert.array(arr).has.no.holes() -- checks the array to not contain holes --> passes
-- assert.array(arr).has.no.holes(4) -- sets explicit length to 4 --> fails
--
-- local first_hole = assert.array(arr).has.holes(4) -- check array of size 4 to contain holes --> passes
-- assert.equal(4, first_hole) -- passes, as the index of the first hole is returned
-- Unique key to store the object we operate on in the state object
-- key must be unique, to make sure we do not have name collissions in the shared state object
local ARRAY_STATE_KEY = "__array_state"
-- The modifier, to store the object in our state
local function array(state, args, level)
assert(args.n > 0, "No array provided to the array-modifier")
assert(rawget(state, ARRAY_STATE_KEY) == nil, "Array already set")
rawset(state, ARRAY_STATE_KEY, args[1])
return state
end
-- The actual assertion that operates on our object, stored via the modifier
local function holes(state, args, level)
local length = args[1]
local arr = rawget(state, ARRAY_STATE_KEY) -- retrieve previously set object
-- only check against nil, metatable types are allowed
assert(arr ~= nil, "No array set, please use the array modifier to set the array to validate")
if length == nil then
length = 0
for i in pairs(arr) do
if type(i) == "number" and
i > length and
math.floor(i) == i then
length = i
end
end
end
assert(type(length) == "number", "expected array length to be of type 'number', got: "..tostring(length))
-- let's do the actual assertion
local missing
for i = 1, length do
if arr[i] == nil then
missing = i
break
end
end
-- format arguments for output strings;
args[1] = missing
args.n = missing and 1 or 0
return missing ~= nil, { missing } -- assert result + first missing index as return value
end
-- Register the proper assertion messages
say:set("assertion.array_holes.positive", [[
Expected array to have holes, but none were found.
]])
say:set("assertion.array_holes.negative", [[
Expected array to not have holes, but found a hole at index: %s
]])
-- Register the assertion, and the modifier
assert:register("assertion", "holes", holes,
"assertion.array_holes.positive",
"assertion.array_holes.negative")
assert:register("modifier", "array", array)