1---
2-- test_assertions.lua
3--
4-- Assertion functions for unit tests.
5--
6-- Author Jason Perkins
7-- Copyright (c) 2008-2016 Jason Perkins and the Premake project.
8---
9
10	local p = premake
11
12	local m = p.modules.self_test
13
14	local _ = {}
15
16
17
18	function m.capture(expected)
19		local actual = p.captured() .. p.eol()
20
21		-- create line-by-line iterators for both values
22		local ait = actual:gmatch("(.-)" .. p.eol())
23		local eit = expected:gmatch("(.-)\n")
24
25		-- compare each value line by line
26		local linenum = 1
27		local atxt = ait()
28		local etxt = eit()
29		while etxt do
30			if (etxt ~= atxt) then
31				m.fail("(%d) expected:\n%s\n...but was:\n%s\nfulltext:\n%s", linenum, etxt, atxt, actual)
32			end
33
34			linenum = linenum + 1
35			atxt = ait()
36			etxt = eit()
37		end
38	end
39
40
41
42	function m.closedfile(expected)
43		if expected and not m.value_closedfile then
44			m.fail("expected file to be closed")
45		elseif not expected and m.value_closedfile then
46			m.fail("expected file to remain open")
47		end
48	end
49
50
51
52	function m.contains(expected, actual)
53		if type(expected) == "table" then
54			for i, v in ipairs(expected) do
55				m.contains(v, actual)
56			end
57		elseif not table.contains(actual, expected) then
58			m.fail("expected value %s not found", expected)
59		end
60	end
61
62
63
64	function m.excludes(expected, actual)
65		if type(expected) == "table" then
66			for i, v in ipairs(expected) do
67				m.excludes(v, actual)
68			end
69		elseif table.contains(actual, expected) then
70			m.fail("excluded value %s found", expected)
71		end
72	end
73
74
75
76	function m.fail(format, ...)
77		-- if format is a number then it is the stack depth
78		local depth = 3
79		local arg = {...}
80		if type(format) == "number" then
81			depth = depth + format
82			format = table.remove(arg, 1)
83		end
84
85		-- convert nils into something more usefuls
86		for i = 1, #arg do
87			if (arg[i] == nil) then
88				arg[i] = "(nil)"
89			elseif (type(arg[i]) == "table") then
90				arg[i] = "{" .. table.concat(arg[i], ", ") .. "}"
91			end
92		end
93
94		local msg = string.format(format, table.unpack(arg))
95		error(debug.traceback(msg, depth), depth)
96	end
97
98
99
100	function m.filecontains(expected, fn)
101		local f = io.open(fn)
102		local actual = f:read("*a")
103		f:close()
104		if (expected ~= actual) then
105			m.fail("expected %s but was %s", expected, actual)
106		end
107	end
108
109
110
111	function m.hasoutput()
112		local actual = p.captured()
113		if actual == "" then
114			m.fail("expected output, received none");
115		end
116	end
117
118
119
120	function m.isemptycapture()
121		local actual = p.captured()
122		if actual ~= "" then
123			m.fail("expected empty capture, but was %s", actual);
124		end
125	end
126
127
128
129	function m.isequal(expected, actual, depth)
130		depth = depth or 0
131		if type(expected) == "table" then
132			if expected and not actual then
133				m.fail(depth, "expected table, got nil")
134			end
135			if #expected < #actual then
136				m.fail(depth, "expected %d items, got %d", #expected, #actual)
137			end
138			for k,v in pairs(expected) do
139				m.isequal(expected[k], actual[k], depth + 1)
140			end
141		else
142			if (expected ~= actual) then
143				m.fail(depth, "expected %s but was %s", expected, actual or "nil")
144			end
145		end
146		return true
147	end
148
149
150
151	function m.isfalse(value)
152		if (value) then
153			m.fail("expected false but was true")
154		end
155	end
156
157
158
159	function m.isnil(value)
160		if (value ~= nil) then
161			m.fail("expected nil but was " .. tostring(value))
162		end
163	end
164
165
166
167	function m.isnotnil(value)
168		if (value == nil) then
169			m.fail("expected not nil")
170		end
171	end
172
173
174
175	function m.issame(expected, action)
176		if expected ~= action then
177			m.fail("expected same value")
178		end
179	end
180
181
182
183	function m.istrue(value)
184		if (not value) then
185			m.fail("expected true but was false")
186		end
187	end
188
189
190
191	function m.missing(value, actual)
192		if table.contains(actual, value) then
193			m.fail("unexpected value %s found", value)
194		end
195	end
196
197
198
199	function m.openedfile(fname)
200		if fname ~= m.value_openedfilename then
201			local msg = "expected to open file '" .. fname .. "'"
202			if m.value_openedfilename then
203				msg = msg .. ", got '" .. m.value_openedfilename .. "'"
204			end
205			m.fail(msg)
206		end
207	end
208
209
210
211	function m.success(fn, ...)
212		local ok, err = pcall(fn, ...)
213		if not ok then
214			m.fail("call failed: " .. err)
215		end
216	end
217
218
219
220	function m.stderr(expected)
221		if not expected and m.stderr_capture then
222			m.fail("Unexpected: " .. m.stderr_capture)
223		elseif expected then
224			if not m.stderr_capture or not m.stderr_capture:find(expected) then
225				m.fail(string.format("expected '%s'; got %s", expected, m.stderr_capture or "(nil)"))
226			end
227		end
228	end
229
230
231
232	function m.notstderr(expected)
233		if not expected and not m.stderr_capture then
234			m.fail("Expected output on stderr; none received")
235		elseif expected then
236			if m.stderr_capture and m.stderr_capture:find(expected) then
237				m.fail(string.format("stderr contains '%s'; was %s", expected, m.stderr_capture))
238			end
239		end
240	end
241