1--
2-- tests/testfx.lua
3-- Automated test framework for Premake.
4-- Copyright (c) 2008-2009 Jason Perkins and the Premake project
5--
6
7
8--
9-- Define a namespace for the testing functions
10--
11
12	test = { }
13
14
15--
16-- Assertion functions
17--
18	function test.string_contains(buffer, expected)
19		if not string.find(buffer,expected) then
20			test.fail("\n==Fail==: Expected to find :\n%s\nyet it was not found in buffer:\n%s\n", expected,buffer)
21		end
22	end
23
24	function test.string_does_not_contain(buffer, expected)
25		if string.find(buffer,expected) then
26			test.fail("\n==Fail==: Did not expected to find :\n%s\nyet it was found in buffer:\n%s\n", expected,buffer)
27		end
28	end
29
30	function test.capture(expected)
31		local actual = io.endcapture()
32
33		local ait = actual:gfind("(.-)" .. io.eol)
34		local eit = expected:gfind("(.-)\n")
35
36		local linenum = 1
37		local atxt = ait()
38		local etxt = eit()
39		while etxt do
40			if (etxt ~= atxt) then
41				test.fail("(%d) expected:\n%s\n...but was:\n%s", linenum, etxt, atxt)
42			end
43
44			linenum = linenum + 1
45			atxt = ait()
46			etxt = eit()
47		end
48	end
49
50
51	function test.closedfile(expected)
52		if expected and not test.value_closedfile then
53			test.fail("expected file to be closed")
54		elseif not expected and test.value_closedfile then
55			test.fail("expected file to remain open")
56		end
57	end
58
59
60	function test.contains(value, expected)
61		if not table.contains(value, expected) then
62			test.fail("expected value %s not found", expected)
63		end
64	end
65
66
67	function test.fail(format, ...)
68		-- convert nils into something more usefuls
69		for i = 1, arg.n do
70			if (arg[i] == nil) then
71				arg[i] = "(nil)"
72			elseif (type(arg[i]) == "table") then
73				arg[i] = "{" .. table.concat(arg[i], ", ") .. "}"
74			end
75		end
76		error(string.format(format, unpack(arg)), 3)
77	end
78
79
80	function test.filecontains(expected, fn)
81		local f = io.open(fn)
82		local actual = f:read("*a")
83		f:close()
84		if (expected ~= actual) then
85			test.fail("expected %s but was %s", expected, actual)
86		end
87	end
88
89
90	function test.isequal(expected, actual)
91		if (type(expected) == "table") then
92			for k,v in pairs(expected) do
93				if not (test.isequal(expected[k], actual[k])) then
94					test.fail("expected %s but was %s", expected, actual)
95				end
96			end
97		else
98			if (expected ~= actual) then
99				test.fail("expected %s but was %s", expected, actual)
100			end
101		end
102		return true
103	end
104
105
106	function test.isfalse(value)
107		if (value) then
108			test.fail("expected false but was true")
109		end
110	end
111
112
113	function test.isnil(value)
114		if (value ~= nil) then
115			test.fail("expected nil but was " .. tostring(value))
116		end
117	end
118
119
120	function test.isnotnil(value)
121		if (value == nil) then
122			test.fail("expected not nil")
123		end
124	end
125
126
127	function test.istrue(value)
128		if (not value) then
129			test.fail("expected true but was false")
130		end
131	end
132
133
134	function test.openedfile(fname)
135		if fname ~= test.value_openedfilename then
136			local msg = "expected to open file '" .. fname .. "'"
137			if test.value_openedfilename then
138				msg = msg .. ", got '" .. test.value_openedfilename .. "'"
139			end
140			test.fail(msg)
141		end
142	end
143
144
145	function test.success(fn, ...)
146		local ok, err = pcall(fn, unpack(arg))
147		if not ok then
148			test.fail("call failed: " .. err)
149		end
150	end
151
152
153
154--
155-- Test stubs
156--
157
158	local function stub_io_open(fname, mode)
159		test.value_openedfilename = fname
160		test.value_openedfilemode = mode
161		return {
162			close = function()
163				test.value_closedfile = true
164			end
165		}
166	end
167
168	local function stub_io_output(f)
169	end
170
171	local function stub_print(s)
172	end
173
174
175--
176-- Define a collection for the test suites
177--
178
179	T = { }
180
181
182
183--
184-- Test execution function
185--
186
187	local function test_setup(suite, fn)
188		-- clear out some important globals
189		_ACTION = "test"
190		_ARGS = { }
191		_OPTIONS = { }
192		premake.solution.list = { }
193
194		-- reset captured I/O values
195		test.value_openedfilename = nil
196		test.value_openedfilemode = nil
197		test.value_closedfile     = false
198
199		if suite.setup then
200			return pcall(suite.setup)
201		else
202			return true
203		end
204	end
205
206
207	local function test_run(suite, fn)
208		return pcall(fn)
209	end
210
211
212	local function test_teardown(suite, fn)
213		if suite.teardown then
214			return pcall(suite.teardown)
215		else
216			return true
217		end
218	end
219
220
221	function test.runall()
222		test.print = print
223
224		print      = stub_print
225		io.open    = stub_io_open
226		io.output  = stub_io_output
227
228		local numpassed = 0
229		local numfailed = 0
230
231		for suitename, suitetests in pairs(T) do
232			for testname, testfunc in pairs(suitetests) do
233
234				local ok, err = test_setup(suitetests, testfunc)
235
236				if ok then
237					ok, err = test_run(suitetests, testfunc)
238				end
239
240				local tok, terr = test_teardown(suitetests, testfunc)
241				ok = ok and tok
242				err = err or tok
243
244				if (not ok) then
245					test.print(string.format("%s.%s: %s", suitename, testname, err))
246					numfailed = numfailed + 1
247				else
248					numpassed = numpassed + 1
249				end
250
251			end
252		end
253
254		print = test.print
255		return numpassed, numfailed
256	end
257
258