Mercurial > luatestmorecoronaexamples
changeset 0:eacdc5a12922
Initial commit
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BasicTest/Builder.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,310 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local debug = require 'debug' +local io = require 'io' +local os = require 'os' +local table = require 'table' +local error = error +local pairs = pairs +local print = print +local setmetatable = setmetatable +local tonumber = tonumber +local tostring = tostring +local type = type + +_ENV = nil +local m = {} + +local testout = io and io.stdout +local testerr = io and (io.stderr or io.stdout) + +function m.puts (f, str) + f:write(str) +end + +local function _print (self, ...) + local f = self:output() + if f then + local msg = table.concat({..., "\n"}) + m.puts(f, msg) + else + print(...) + end +end + +local function print_comment (f, ...) + if f then + local arg = {...} + for k, v in pairs(arg) do + arg[k] = tostring(v) + end + local msg = table.concat(arg) + msg = msg:gsub("\n", "\n# ") + msg = msg:gsub("\n# \n", "\n#\n") + msg = msg:gsub("\n# $", '') + m.puts(f, "# " .. msg .. "\n") + else + print("# ", ...) + end +end + +function m:create () + local o = {} + setmetatable(o, self) + self.__index = self + o:reset() + o:reset_outputs() + return o +end + +local test +function m:new () + test = test or self:create() + return test +end + +function m:reset () + self.curr_test = 0 + self._done_testing = false + self.expected_tests = 0 + self.is_passing = true + self.todo_upto = -1 + self.todo_reason = nil + self.have_plan = false + self.no_plan = false + self.have_output_plan = false +end + +local function _output_plan (self, max, directive, reason) + local out = "1.." .. max + if directive then + out = out .. " # " .. directive + end + if reason then + out = out .. " " .. reason + end + _print(self, out) + self.have_output_plan = true +end + +function m:plan (arg) + if self.have_plan then + error("You tried to plan twice") + end + if type(arg) == 'string' and arg == 'no_plan' then + self.have_plan = true + self.no_plan = true + return true + elseif type(arg) ~= 'number' then + error("Need a number of tests") + elseif arg < 0 then + error("Number of tests must be a positive integer. You gave it '" .. arg .."'.") + else + self.expected_tests = arg + self.have_plan = true + _output_plan(self, arg) + return arg + end +end + +function m:done_testing (num_tests) + num_tests = num_tests or self.curr_test + if self._done_testing then + tb:ok(false, "done_testing() was already called") + return + end + self._done_testing = true + if self.expected_tests > 0 and num_tests ~= self.expected_tests then + self:ok(false, "planned to run " .. self.expected_tests + .. " but done_testing() expects " .. num_tests) + else + self.expected_tests = num_tests + end + if not self.have_output_plan then + _output_plan(self, num_tests) + end + self.have_plan = true + -- The wrong number of tests were run + if self.expected_tests ~= self.curr_test then + self.is_passing = false + end + -- No tests were run + if self.curr_test == 0 then + self.is_passing = false + end +end + +function m:has_plan () + if self.expected_tests > 0 then + return self.expected_tests + end + if self.no_plan then + return 'no_plan' + end + return nil +end + +function m:skip_all (reason) + if self.have_plan then + error("You tried to plan twice") + end + _output_plan(self, 0, 'SKIP', reason) + os.exit(0) +end + +local function in_todo (self) + return self.todo_upto >= self.curr_test +end + +local function _check_is_passing_plan (self) + local plan = self:has_plan() + if not plan or not tonumber(plan) then + return + end + if plan < self.curr_test then + self.is_passing = false + end +end + +function m:ok (test, name, level) + name = name or '' + level = level or 0 + if not self.have_plan then + error("You tried to run a test without a plan") + end + self.curr_test = self.curr_test + 1 + name = tostring(name) + if name:match('^[%d%s]+$') then + self:diag(" You named your test '" .. name .."'. You shouldn't use numbers for your test names." + .. "\n Very confusing.") + end + local out = '' + if not test then + out = "not " + end + out = out .. "ok " .. self.curr_test + if name ~= '' then + out = out .. " - " .. name + end + if self.todo_reason and in_todo(self) then + out = out .. " # TODO # " .. self.todo_reason + end + _print(self, out) + if not test then + local msg = "Failed" + if in_todo(self) then + msg = msg .. " (TODO)" + end + if debug then + local info = debug.getinfo(3 + level) + local file = info.short_src + local line = info.currentline + self:diag(" " .. msg .. " test (" .. file .. " at line " .. line .. ")") + else + self:diag(" " .. msg .. " test") + end + end + if not test and not in_todo(self) then + self.is_passing = false + end + _check_is_passing_plan(self) +end + +function m:BAIL_OUT (reason) + local out = "Bail out!" + if reason then + out = out .. " " .. reason + end + _print(self, out) + os.exit(255) +end + +function m:current_test (num) + if num then + self.curr_test = num + end + return self.curr_test +end + +function m:todo (reason, count) + count = count or 1 + self.todo_upto = self.curr_test + count + self.todo_reason = reason +end + +function m:skip (reason, count) + count = count or 1 + local name = "# skip" + if reason then + name = name .. " " .. reason + end + for i = 1, count do + self:ok(true, name) + end +end + +function m:todo_skip (reason) + local name = "# TODO & SKIP" + if reason then + name = name .. " " .. reason + end + self:ok(false, name, 1) +end + +function m:skip_rest (reason) + self:skip(reason, self.expected_tests - self.curr_test) +end + +local function diag_file (self) + if in_todo(self) then + return self:todo_output() + else + return self:failure_output() + end +end + +function m:diag (...) + print_comment(diag_file(self), ...) +end + +function m:note (...) + print_comment(self:output(), ...) +end + +function m:output (f) + if f then + self.out_file = f + end + return self.out_file +end + +function m:failure_output (f) + if f then + self.fail_file = f + end + return self.fail_file +end + +function m:todo_output (f) + if f then + self.todo_file = f + end + return self.todo_file +end + +function m:reset_outputs () + self:output(testout) + self:failure_output(testerr) + self:todo_output(testout) +end + +return m +-- +-- Copyright (c) 2009-2011 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BasicTest/CoronaTest.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,166 @@ +-- This is a customization script for Lua Test More that configures the test environment to work with our custom needs. +-- This file transparently configures things in Test More such as socket connections and timeouts. +-- This file must be included before calling "require('More') + +require 'socket' + +local s_tbOriginalDoneTesting = nil +local s_CoronaTimeOutValue = nil + +module("CoronaTest", package.seeall) + + +local function CoronaTestTimerAppKiller( event ) + print("Corona Test timeout expired (application side)...calling os.exit()") + note("CoronaTest timeout triggered") + os.exit() +end + + +local function GetHostAndPort() + local host = nil + local port = nil + --[[ + local host = "127.0.0.1" + local port = 12345 + --]] + + +-- print("GetHostAndPort", GetHostAndPort) +-- print("os.getenv", os.getenv("HOME")) +-- print("os.getenv", os.getenv("HOST")) + if arg then + host = arg[1] + port = arg[2] + elseif os.getenv("TESTMORE_HOST") and os.getenv("TESTMORE_PORT") then + print("Detected environmental variables TESTMORE_HOST & TESTMORE_PORT") + host = os.getenv("TESTMORE_HOST") + port = os.getenv("TESTMORE_PORT") + print("Detected environmental variables TESTMORE_HOST & TESTMORE_PORT", host, port) + else + local ok = pcall(require, 'TestMoreOutputServerInfo') + if ok then + --print("got data from pcall") + host = TestMoreOutputServerInfo.Host + port = TestMoreOutputServerInfo.Port + s_CoronaTimeOutValue = TestMoreOutputServerInfo.TimeOut + end + + end + + return host, port +end + +local function GetOutputFileName() + local filename = nil + if arg then + filename = arg[1] + elseif os.getenv("TESTMORE_OUTPUT_FILENAME") then + filename = os.getenv("TESTMORE_OUTPUT_FILENAME") + print("Detected environmental variable TESTMORE_OUTPUT_FILENAME", filename) + else + local ok = pcall(require, 'TestMoreOutputFileInfo') + if ok then + --print("got data from pcall") + filename = TestMoreOutputFileInfo.FileName + s_CoronaTimeOutValue = TestMoreOutputFileInfo.TimeOut + end + + end + + return filename + +end + + +local function SetupFileOrStdout() + + local filename = GetOutputFileName() + if filename then + require 'FileOutput'.init(filename) + require 'More' + note("App is reporting to file: " .. tostring(filename)) + + else + require 'More' + note("App is reporting to stdout/stderr") + + end +end + +-- CoronaTest.Init +local function Init() +-- local tb = test_builder() + + --[[ + local host = "127.0.0.1" + local port = 12345 + --]] + -- + + -- Override assert to kill the test program + -- This is not really necessary if we trap lua errors to call exit() for us. + do + local old_assert = assert + assert = function(condition) + if not condition then + print("Dectected assertion failure: aborting Corona program") + return old_assert(condition) + --os.exit() + end + return old_assert(condition) + end + end + + local host, port = GetHostAndPort() + if host and port then + print("Application connecting to host and port", host, port) + local server = socket.connect(host, port) + if not server then + -- Might not want to abort in case we are running the simulator and have a stray host/port file + note("Failure of app connect to specified host and port: " .. tostring(host) ..":" .. tostring(port) .. ". Maybe you have a stale TestMoreOutputServerInfo.lua file?") + + SetupFileOrStdout() + else + require 'SocketOutput'.init(server) + require 'More' + note("App successfully connected to server on host and port: " .. tostring(host) ..":" .. tostring(port)) + end + else + SetupFileOrStdout() + note("App is reporting results to local machine") + end + + -- Override done_testing() + do + s_tbOriginalDoneTesting = done_testing + _G["done_testing"] = function(num_tests) + note("CoronaTest completed all tests") + return s_tbOriginalDoneTesting(num_tests) + end + end + + -- Capture Test More plan() so our plan function can invoke it + s_tbPlan = plan + + -- The timeout was loaded in the TestMoreOutput*Info if set + if s_CoronaTimeOutValue and type(s_CoronaTimeOutValue) == "number" then + timer.performWithDelay(s_CoronaTimeOutValue, CoronaTestTimerAppKiller) + end +end + +-- Override the global plan function defined by More. +-- This is the magic that hides all the setup from users. +-- But you must require this file before More. +_G["plan"] = function(plan_args) + Init() + -- s_tbPlan was setup in Init(). It is the regular test more plan function. + s_tbPlan(plan_args) +end + +-- Placeholder for done_testing. +-- Should be rewritten during Init() +_G["done_testing"] = function(num_tests) + print("Assertion error: called done_testing before our custom init (via plan) was invoked") + assert(false) +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BasicTest/More.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,374 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local loadstring = loadstring +local pairs = pairs +local pcall = pcall +local require = require +local tostring = tostring +local type = type +local unpack = require 'table'.unpack or unpack +local _G = _G + +-- We need to modify this because Corona doesn't handle subdirectories. +--local tb = require 'Test.Builder':new() +local tb = require 'Builder':new() + +_ENV = nil +local m = {} + +function m.plan (arg) + tb:plan(arg) +end + +function m.done_testing (num_tests) + tb:done_testing(num_tests) +end + +function m.skip_all (reason) + tb:skip_all(reason) +end + +function m.BAIL_OUT (reason) + tb:BAIL_OUT(reason) +end + +function m.ok (test, name) + tb:ok(test, name) +end + +function m.nok (test, name) + tb:ok(not test, name) +end + +function m.is (got, expected, name) + local pass = got == expected + tb:ok(pass, name) + if not pass then + tb:diag(" got: " .. tostring(got) + .. "\n expected: " .. tostring(expected)) + end +end + +function m.isnt (got, expected, name) + local pass = got ~= expected + tb:ok(pass, name) + if not pass then + tb:diag(" got: " .. tostring(got) + .. "\n expected: anything else") + end +end + +function m.like (got, pattern, name) + if type(pattern) ~= 'string' then + tb:ok(false, name) + tb:diag("pattern isn't a string : " .. tostring(pattern)) + return + end + got = tostring(got) + local pass = got:match(pattern) + tb:ok(pass, name) + if not pass then + tb:diag(" '" .. got .. "'" + .. "\n doesn't match '" .. pattern .. "'") + end +end + +function m.unlike (got, pattern, name) + if type(pattern) ~= 'string' then + tb:ok(false, name) + tb:diag("pattern isn't a string : " .. tostring(pattern)) + return + end + got = tostring(got) + local pass = not got:match(pattern) + tb:ok(pass, name) + if not pass then + tb:diag(" '" .. got .. "'" + .. "\n matches '" .. pattern .. "'") + end +end + +local cmp = { + ['<'] = function (a, b) return a < b end, + ['<='] = function (a, b) return a <= b end, + ['>'] = function (a, b) return a > b end, + ['>='] = function (a, b) return a >= b end, + ['=='] = function (a, b) return a == b end, + ['~='] = function (a, b) return a ~= b end, +} + +function m.cmp_ok (this, op, that, name) + local f = cmp[op] + if not f then + tb:ok(false, name) + tb:diag("unknown operator : " .. tostring(op)) + return + end + local pass = f(this, that) + tb:ok(pass, name) + if not pass then + tb:diag(" " .. tostring(this) + .. "\n " .. op + .. "\n " .. tostring(that)) + end +end + +function m.type_ok (val, t, name) + if type(t) ~= 'string' then + tb:ok(false, name) + tb:diag("type isn't a string : " .. tostring(t)) + return + end + if type(val) == t then + tb:ok(true, name) + else + tb:ok(false, name) + tb:diag(" " .. tostring(val) .. " isn't a '" .. t .."' it's a '" .. type(val) .. "'") + end +end + +function m.pass (name) + tb:ok(true, name) +end + +function m.fail (name) + tb:ok(false, name) +end + +function m.require_ok (mod) + local r, msg = pcall(require, mod) + tb:ok(r, "require '" .. tostring(mod) .. "'") + if not r then + tb:diag(" " .. msg) + end + return r +end + +function m.eq_array (got, expected, name) + if type(got) ~= 'table' then + tb:ok(false, name) + tb:diag("got value isn't a table : " .. tostring(got)) + return + elseif type(expected) ~= 'table' then + tb:ok(false, name) + tb:diag("expected value isn't a table : " .. tostring(expected)) + return + end + for i = 1, #expected do + local v = expected[i] + local val = got[i] + if val ~= v then + tb:ok(false, name) + tb:diag(" at index: " .. tostring(i) + .. "\n got: " .. tostring(val) + .. "\n expected: " .. tostring(v)) + return + end + end + local extra = #got - #expected + if extra ~= 0 then + tb:ok(false, name) + tb:diag(" " .. tostring(extra) .. " unexpected item(s)") + else + tb:ok(true, name) + end +end + +function m.is_deeply (got, expected, name) + if type(got) ~= 'table' then + tb:ok(false, name) + tb:diag("got value isn't a table : " .. tostring(got)) + return + elseif type(expected) ~= 'table' then + tb:ok(false, name) + tb:diag("expected value isn't a table : " .. tostring(expected)) + return + end + local msg1 + local msg2 + + local function deep_eq (t1, t2, key_path) + if t1 == t2 then + return true + end + for k, v2 in pairs(t2) do + local v1 = t1[k] + if type(v1) == 'table' and type(v2) == 'table' then + local r = deep_eq(v1, v2, key_path .. "." .. tostring(k)) + if not r then + return false + end + else + if v1 ~= v2 then + key_path = key_path .. "." .. tostring(k) + msg1 = " got" .. key_path .. ": " .. tostring(v1) + msg2 = "expected" .. key_path .. ": " .. tostring(v2) + return false + end + end + end + for k in pairs(t1) do + local v2 = t2[k] + if v2 == nil then + key_path = key_path .. "." .. tostring(k) + msg1 = " got" .. key_path .. ": " .. tostring(t1[k]) + msg2 = "expected" .. key_path .. ": " .. tostring(v2) + return false + end + end + return true + end -- deep_eq + + local pass = deep_eq(got, expected, '') + tb:ok(pass, name) + if not pass then + tb:diag(" Tables begin differing at:") + tb:diag(" " .. msg1) + tb:diag(" " .. msg2) + end +end + +function m.error_is (code, arg2, arg3, arg4) + local params, expected, name + if type(arg2) == 'table' then + params = arg2 + expected = arg3 + name = arg4 + else + params = {} + expected = arg2 + name = arg3 + end + if type(code) == 'string' then + local msg + code, msg = loadstring(code) + if not code then + tb:ok(false, name) + tb:diag(" can't compile code :" + .. "\n " .. msg) + return + end + end + local r, msg = pcall(code, unpack(params)) + if r then + tb:ok(false, name) + tb:diag(" unexpected success" + .. "\n expected: " .. tostring(expected)) + else + local pass = msg == expected + tb:ok(pass, name) + if not pass then + tb:diag(" got: " .. msg + .. "\n expected: " .. tostring(expected)) + end + end +end + +function m.error_like (code, arg2, arg3, arg4) + local params, pattern, name + if type(arg2) == 'table' then + params = arg2 + pattern = arg3 + name = arg4 + else + params = {} + pattern = arg2 + name = arg3 + end + if type(code) == 'string' then + local msg + code, msg = loadstring(code) + if not code then + tb:ok(false, name) + tb:diag(" can't compile code :" + .. "\n " .. msg) + return + end + end + local r, msg = pcall(code, unpack(params)) + if r then + tb:ok(false, name) + tb:diag(" unexpected success" + .. "\n expected: " .. tostring(pattern)) + else + if type(pattern) ~= 'string' then + tb:ok(false, name) + tb:diag("pattern isn't a string : " .. tostring(pattern)) + return + end + local pass = msg:match(pattern) + tb:ok(pass, name) + if not pass then + tb:diag(" '" .. msg .. "'" + .. "\n doesn't match '" .. pattern .. "'") + end + end +end + +function m.lives_ok (code, arg2, arg3) + local params, name + if type(arg2) == 'table' then + params = arg2 + name = arg3 + else + params = {} + name = arg2 + end + if type(code) == 'string' then + local msg + code, msg = loadstring(code) + if not code then + tb:ok(false, name) + tb:diag(" can't compile code :" + .. "\n " .. msg) + return + end + end + local r, msg = pcall(code, unpack(params)) + tb:ok(r, name) + if not r then + tb:diag(" " .. msg) + end +end + +function m.diag (msg) + tb:diag(msg) +end + +function m.note (msg) + tb:note(msg) +end + +function m.skip (reason, count) + tb:skip(reason, count) +end + +function m.todo_skip (reason) + tb:todo_skip(reason) +end + +function m.skip_rest (reason) + tb:skip_rest(reason) +end + +function m.todo (reason, count) + tb:todo(reason, count) +end + +for k, v in pairs(m) do -- injection + _G[k] = v +end +_G.Test = _G.Test or {} +_G.Test.More = m + +m._VERSION = "0.2.3" +m._DESCRIPTION = "lua-TestMore : an Unit Testing Framework" +m._COPYRIGHT = "Copyright (c) 2009-2010 Francois Perrad" +return m +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BasicTest/NoOutput.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,60 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local io = require 'io' +local pairs = pairs +local require = require + +_ENV = nil +local m = {} + +function m:create () + local tb = require 'Test.Builder':create() + tb:output(io.tmpfile()) + tb:failure_output(io.tmpfile()) + tb:todo_output(io.tmpfile()) + + function tb:read (stream) + if stream == 'out' then + local f = self:output() + f:seek 'set' + local out = f:read '*a' + f:close() + self:output(io.tmpfile()) + return out + elseif stream == 'err' then + local f = self:failure_output() + f:seek 'set' + local out = f:read '*a' + f:close() + self:failure_output(io.tmpfile()) + return out + elseif stream == 'todo' then + local f = self:todo_output() + f:seek 'set' + local out = f:read '*a' + f:close() + self:todo_output(io.tmpfile()) + return out + else + self:output():close() + self:output(io.tmpfile()) + self:failure_output():close() + self:failure_output(io.tmpfile()) + self:todo_output():close() + self:todo_output(io.tmpfile()) + end + end + + return tb +end + +return m +-- +-- Copyright (c) 2009-2010 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BasicTest/SocketOutput.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,40 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +--[[ + require 'socket' + local conn = socket.connect(host, port) + require 'Test.Builder.Socket'.init(conn) + require 'Test.More' -- now, as usual + + plan(...) + ... +--]] + +local assert = assert + +-- We need to modify this because Corona doesn't handle subdirectories. +--local tb = require 'Test.Builder':new() +local tb = require 'Builder':new() +local m = getmetatable(tb) +_ENV = nil + +function m.init (sock) + tb:output(sock) + tb:failure_output(sock) + tb:todo_output(sock) +end + +function m.puts (sock, str) + assert(sock:send(str)) +end + +return m +-- +-- Copyright (c) 2011 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BasicTest/Tester.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,141 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local error = error +local pairs = pairs +local setmetatable = setmetatable +local type = type +local _G = _G +local debug = require 'debug' + +local tb = require 'Test.Builder':new() +local out = require 'Test.Builder.Tester.File':new 'out' +local err = require 'Test.Builder.Tester.File':new 'err' + +_ENV = nil +local m = {} + +-- for remembering that we're testing and where we're testing at +local testing = false +local testing_num + +-- remembering where the file handles were originally connected +local original_output_handle +local original_failure_handle +local original_todo_handle + +local function _start_testing () + -- remember what the handles were set to + original_output_handle = tb:output() + original_failure_handle = tb:failure_output() + original_todo_handle = tb:todo_output() + + -- switch out to our own handles + tb:output(out) + tb:failure_output(err) + tb:todo_output(err) + + -- clear the expected list + out:reset() + err:reset() + + -- remeber that we're testing + testing = true + testing_num = tb:current_test() + tb:current_test(0) + + -- look, we shouldn't do the ending stuff + tb.no_ending = true +end + +function m.test_out (...) + if not testing then + _start_testing() + end + out:expect(...) +end + +function m.test_err (...) + if not testing then + _start_testing() + end + err:expect(...) +end + +function m.test_fail (offset) + offset = offset or 0 + if not testing then + _start_testing() + end + local info = debug.getinfo(2) + local prog = info.short_src + local line = info.currentline + offset + err:expect("# Failed test (" .. prog .. " at line " .. line .. ")") +end + +function m.test_diag (...) + local arg = {...} + if not testing then + _start_testing() + end + for i = 1, #arg do + err:expect("# " .. arg[i]) + end +end + +function m.test_test (args) + local mess + if type(args) == 'table' then + mess = args[1] + else + mess = args + args = {} + end + + if not testing then + error "Not testing. You must declare output with a test function first." + end + + -- okay, reconnect the test suite back to the saved handles + tb:output(original_output_handle) + tb:failure_output(original_failure_handle) + tb:todo_output(original_todo_handle) + + -- restore the test no, etc, back to the original point + tb:current_test(testing_num) + testing = false + + -- check the output we've stashed + local pass = (args.skip_out or out:check()) + and (args.skip_err or err:check()) + tb:ok(pass, mess) + if not pass then + -- print out the diagnostic information about why this + -- test failed + if not out:check() then + tb:diag(out:complaint()) + end + if not err:check() then + tb:diag(err:complaint()) + end + end +end + +function m.line_num () + return debug.getinfo(2).currentline +end + +for k, v in pairs(m) do -- injection + _G[k] = v +end + +return m + +-- +-- Copyright (c) 2009 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BasicTest/main.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,11 @@ +require('More') +plan(2) -- Specify the number of tests you plan to run. +local nothing = nil +local test_count = 0 +is(someValue, 1, "someValue should be equal to 1") -- This function verifies parameter 1 is equal to parameter 2 +test_count = test_count + 1 +isnt(someValue, nil) -- This function verifies parameter 1 is not equal to parameter 2 +test_count = test_count + 1 +done_testing(test_count) -- declare you are done testing and the number of tests you have run +--os.exit() -- convenient to have to make sure the process completely ends. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.txt Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,3 @@ +These are the lua-TestMore scripts and examples described here: +http://playcontrol.net/ewing/jibberjabber/automated-mobile-test-part3.html +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ServerMisc/FindFreeSocketPort.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,7 @@ +require('socket') + +local my_socket = socket.bind(arg[1] or "*", 0) +local ipaddress, port = my_socket:getsockname() +my_socket:close() +print(port) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ServerMisc/TapSocketListener.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,72 @@ +----------------------------------------------------------------------------- +-- TCP sample: Little program to dump lines received at a given port +-- LuaSocket sample files +-- Author: Diego Nehab +-- RCS ID: $Id: listener.lua,v 1.11 2005/01/02 22:44:00 diego Exp $ +----------------------------------------------------------------------------- +-- Example Usage: lua TapSocketLisener.lua "*" 12345 ../test-output/mytest.tap true +-- param IPaddress +-- param port +-- param testoutputfile +-- param echoOn +local socket = require("socket") +require('os') +host = host or "*" +port = port or 12345 +destinationFile = "/tmp/LuaTestMore_results.log" +echoOn = true +if arg then + host = arg[1] or host + port = arg[2] or port + destinationFile = arg[3] or destinationFile + + if arg[4] == "false" then + echoOn = false + else + echoOn = true + end +end +print("opening file", destinationFile) +print("Tap Listener echo is", echoOn) + +file = assert(io.open(destinationFile, "w+")) +print("Binding to host '" ..host.. "' and port " ..port.. "...") +file:write("# TapSocketListener started on host " .. tostring(host) .. ":" .. tostring(port) .. " to file: " .. tostring(destinationFile) .. ", echo is: " .. tostring(echoOn) .. "\n") +s = assert(socket.bind(host, port)) +i, p = s:getsockname() +assert(i, p) +print("Waiting connection from talker on " .. i .. ":" .. p .. "...") +c = assert(s:accept()) +file:write("# TapSocketListener received connection.\n") +print("Connected. Here is the stuff:") +l, e = c:receive() +while not e do + if true == echoOn then + print(l) + end + + file:write(l) + file:write("\n") + + if "# CoronaTest timeout triggered" == l then + print("Timeout notification received...terminating") + print(e) + c:close() + file:close() + os.exit(1) + + elseif "# CoronaTest completed all tests" == l then + print("Completed notification received...terminating") + print(e) + c:close() + file:close() + os.exit(0) + + end + l, e = c:receive() +end +print(e) +file:write("# TapSocketListener was disconnected unexpectedly\n") +file:close() +os.exit(2) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ServerMisc/TestMoreOutputServerInfo.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,4 @@ +module('TestMoreOutputServerInfo', package.seeall) +Host = '192.168.192.129' +Port = '58833' +TimeOut = '300000'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaAudio/Builder.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,310 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local debug = require 'debug' +local io = require 'io' +local os = require 'os' +local table = require 'table' +local error = error +local pairs = pairs +local print = print +local setmetatable = setmetatable +local tonumber = tonumber +local tostring = tostring +local type = type + +_ENV = nil +local m = {} + +local testout = io and io.stdout +local testerr = io and (io.stderr or io.stdout) + +function m.puts (f, str) + f:write(str) +end + +local function _print (self, ...) + local f = self:output() + if f then + local msg = table.concat({..., "\n"}) + m.puts(f, msg) + else + print(...) + end +end + +local function print_comment (f, ...) + if f then + local arg = {...} + for k, v in pairs(arg) do + arg[k] = tostring(v) + end + local msg = table.concat(arg) + msg = msg:gsub("\n", "\n# ") + msg = msg:gsub("\n# \n", "\n#\n") + msg = msg:gsub("\n# $", '') + m.puts(f, "# " .. msg .. "\n") + else + print("# ", ...) + end +end + +function m:create () + local o = {} + setmetatable(o, self) + self.__index = self + o:reset() + o:reset_outputs() + return o +end + +local test +function m:new () + test = test or self:create() + return test +end + +function m:reset () + self.curr_test = 0 + self._done_testing = false + self.expected_tests = 0 + self.is_passing = true + self.todo_upto = -1 + self.todo_reason = nil + self.have_plan = false + self.no_plan = false + self.have_output_plan = false +end + +local function _output_plan (self, max, directive, reason) + local out = "1.." .. max + if directive then + out = out .. " # " .. directive + end + if reason then + out = out .. " " .. reason + end + _print(self, out) + self.have_output_plan = true +end + +function m:plan (arg) + if self.have_plan then + error("You tried to plan twice") + end + if type(arg) == 'string' and arg == 'no_plan' then + self.have_plan = true + self.no_plan = true + return true + elseif type(arg) ~= 'number' then + error("Need a number of tests") + elseif arg < 0 then + error("Number of tests must be a positive integer. You gave it '" .. arg .."'.") + else + self.expected_tests = arg + self.have_plan = true + _output_plan(self, arg) + return arg + end +end + +function m:done_testing (num_tests) + num_tests = num_tests or self.curr_test + if self._done_testing then + tb:ok(false, "done_testing() was already called") + return + end + self._done_testing = true + if self.expected_tests > 0 and num_tests ~= self.expected_tests then + self:ok(false, "planned to run " .. self.expected_tests + .. " but done_testing() expects " .. num_tests) + else + self.expected_tests = num_tests + end + if not self.have_output_plan then + _output_plan(self, num_tests) + end + self.have_plan = true + -- The wrong number of tests were run + if self.expected_tests ~= self.curr_test then + self.is_passing = false + end + -- No tests were run + if self.curr_test == 0 then + self.is_passing = false + end +end + +function m:has_plan () + if self.expected_tests > 0 then + return self.expected_tests + end + if self.no_plan then + return 'no_plan' + end + return nil +end + +function m:skip_all (reason) + if self.have_plan then + error("You tried to plan twice") + end + _output_plan(self, 0, 'SKIP', reason) + os.exit(0) +end + +local function in_todo (self) + return self.todo_upto >= self.curr_test +end + +local function _check_is_passing_plan (self) + local plan = self:has_plan() + if not plan or not tonumber(plan) then + return + end + if plan < self.curr_test then + self.is_passing = false + end +end + +function m:ok (test, name, level) + name = name or '' + level = level or 0 + if not self.have_plan then + error("You tried to run a test without a plan") + end + self.curr_test = self.curr_test + 1 + name = tostring(name) + if name:match('^[%d%s]+$') then + self:diag(" You named your test '" .. name .."'. You shouldn't use numbers for your test names." + .. "\n Very confusing.") + end + local out = '' + if not test then + out = "not " + end + out = out .. "ok " .. self.curr_test + if name ~= '' then + out = out .. " - " .. name + end + if self.todo_reason and in_todo(self) then + out = out .. " # TODO # " .. self.todo_reason + end + _print(self, out) + if not test then + local msg = "Failed" + if in_todo(self) then + msg = msg .. " (TODO)" + end + if debug then + local info = debug.getinfo(3 + level) + local file = info.short_src + local line = info.currentline + self:diag(" " .. msg .. " test (" .. file .. " at line " .. line .. ")") + else + self:diag(" " .. msg .. " test") + end + end + if not test and not in_todo(self) then + self.is_passing = false + end + _check_is_passing_plan(self) +end + +function m:BAIL_OUT (reason) + local out = "Bail out!" + if reason then + out = out .. " " .. reason + end + _print(self, out) + os.exit(255) +end + +function m:current_test (num) + if num then + self.curr_test = num + end + return self.curr_test +end + +function m:todo (reason, count) + count = count or 1 + self.todo_upto = self.curr_test + count + self.todo_reason = reason +end + +function m:skip (reason, count) + count = count or 1 + local name = "# skip" + if reason then + name = name .. " " .. reason + end + for i = 1, count do + self:ok(true, name) + end +end + +function m:todo_skip (reason) + local name = "# TODO & SKIP" + if reason then + name = name .. " " .. reason + end + self:ok(false, name, 1) +end + +function m:skip_rest (reason) + self:skip(reason, self.expected_tests - self.curr_test) +end + +local function diag_file (self) + if in_todo(self) then + return self:todo_output() + else + return self:failure_output() + end +end + +function m:diag (...) + print_comment(diag_file(self), ...) +end + +function m:note (...) + print_comment(self:output(), ...) +end + +function m:output (f) + if f then + self.out_file = f + end + return self.out_file +end + +function m:failure_output (f) + if f then + self.fail_file = f + end + return self.fail_file +end + +function m:todo_output (f) + if f then + self.todo_file = f + end + return self.todo_file +end + +function m:reset_outputs () + self:output(testout) + self:failure_output(testerr) + self:todo_output(testout) +end + +return m +-- +-- Copyright (c) 2009-2011 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaAudio/CoronaTest.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,166 @@ +-- This is a customization script for Lua Test More that configures the test environment to work with our custom needs. +-- This file transparently configures things in Test More such as socket connections and timeouts. +-- This file must be included before calling "require('More') + +require 'socket' + +local s_tbOriginalDoneTesting = nil +local s_CoronaTimeOutValue = nil + +module("CoronaTest", package.seeall) + + +local function CoronaTestTimerAppKiller( event ) + print("Corona Test timeout expired (application side)...calling os.exit()") + note("CoronaTest timeout triggered") + os.exit() +end + + +local function GetHostAndPort() + local host = nil + local port = nil + --[[ + local host = "127.0.0.1" + local port = 12345 + --]] + + +-- print("GetHostAndPort", GetHostAndPort) +-- print("os.getenv", os.getenv("HOME")) +-- print("os.getenv", os.getenv("HOST")) + if arg then + host = arg[1] + port = arg[2] + elseif os.getenv("TESTMORE_HOST") and os.getenv("TESTMORE_PORT") then + print("Detected environmental variables TESTMORE_HOST & TESTMORE_PORT") + host = os.getenv("TESTMORE_HOST") + port = os.getenv("TESTMORE_PORT") + print("Detected environmental variables TESTMORE_HOST & TESTMORE_PORT", host, port) + else + local ok = pcall(require, 'TestMoreOutputServerInfo') + if ok then + --print("got data from pcall") + host = TestMoreOutputServerInfo.Host + port = TestMoreOutputServerInfo.Port + s_CoronaTimeOutValue = TestMoreOutputServerInfo.TimeOut + end + + end + + return host, port +end + +local function GetOutputFileName() + local filename = nil + if arg then + filename = arg[1] + elseif os.getenv("TESTMORE_OUTPUT_FILENAME") then + filename = os.getenv("TESTMORE_OUTPUT_FILENAME") + print("Detected environmental variable TESTMORE_OUTPUT_FILENAME", filename) + else + local ok = pcall(require, 'TestMoreOutputFileInfo') + if ok then + --print("got data from pcall") + filename = TestMoreOutputFileInfo.FileName + s_CoronaTimeOutValue = TestMoreOutputFileInfo.TimeOut + end + + end + + return filename + +end + + +local function SetupFileOrStdout() + + local filename = GetOutputFileName() + if filename then + require 'FileOutput'.init(filename) + require 'More' + note("App is reporting to file: " .. tostring(filename)) + + else + require 'More' + note("App is reporting to stdout/stderr") + + end +end + +-- CoronaTest.Init +local function Init() +-- local tb = test_builder() + + --[[ + local host = "127.0.0.1" + local port = 12345 + --]] + -- + + -- Override assert to kill the test program + -- This is not really necessary if we trap lua errors to call exit() for us. + do + local old_assert = assert + assert = function(condition) + if not condition then + print("Dectected assertion failure: aborting Corona program") + return old_assert(condition) + --os.exit() + end + return old_assert(condition) + end + end + + local host, port = GetHostAndPort() + if host and port then + print("Application connecting to host and port", host, port) + local server = socket.connect(host, port) + if not server then + -- Might not want to abort in case we are running the simulator and have a stray host/port file + note("Failure of app connect to specified host and port: " .. tostring(host) ..":" .. tostring(port) .. ". Maybe you have a stale TestMoreOutputServerInfo.lua file?") + + SetupFileOrStdout() + else + require 'SocketOutput'.init(server) + require 'More' + note("App successfully connected to server on host and port: " .. tostring(host) ..":" .. tostring(port)) + end + else + SetupFileOrStdout() + note("App is reporting results to local machine") + end + + -- Override done_testing() + do + s_tbOriginalDoneTesting = done_testing + _G["done_testing"] = function(num_tests) + note("CoronaTest completed all tests") + return s_tbOriginalDoneTesting(num_tests) + end + end + + -- Capture Test More plan() so our plan function can invoke it + s_tbPlan = plan + + -- The timeout was loaded in the TestMoreOutput*Info if set + if s_CoronaTimeOutValue and type(s_CoronaTimeOutValue) == "number" then + timer.performWithDelay(s_CoronaTimeOutValue, CoronaTestTimerAppKiller) + end +end + +-- Override the global plan function defined by More. +-- This is the magic that hides all the setup from users. +-- But you must require this file before More. +_G["plan"] = function(plan_args) + Init() + -- s_tbPlan was setup in Init(). It is the regular test more plan function. + s_tbPlan(plan_args) +end + +-- Placeholder for done_testing. +-- Should be rewritten during Init() +_G["done_testing"] = function(num_tests) + print("Assertion error: called done_testing before our custom init (via plan) was invoked") + assert(false) +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaAudio/FileOutput.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,29 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- +local io = require 'io' + +local assert = assert + +-- We need to modify this because Corona doesn't handle subdirectories. +--local tb = require 'Test.Builder':new() +local tb = require 'Builder':new() +local m = getmetatable(tb) +_ENV = nil + +function m.init (filename) + local filehandle = assert(io.open(filename, "w+")) + + tb:output(filehandle) + tb:failure_output(filehandle) + tb:todo_output(filehandle) +end + +return m +-- +-- Copyright (c) 2011 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaAudio/More.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,374 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local loadstring = loadstring +local pairs = pairs +local pcall = pcall +local require = require +local tostring = tostring +local type = type +local unpack = require 'table'.unpack or unpack +local _G = _G + +-- We need to modify this because Corona doesn't handle subdirectories. +--local tb = require 'Test.Builder':new() +local tb = require 'Builder':new() + +_ENV = nil +local m = {} + +function m.plan (arg) + tb:plan(arg) +end + +function m.done_testing (num_tests) + tb:done_testing(num_tests) +end + +function m.skip_all (reason) + tb:skip_all(reason) +end + +function m.BAIL_OUT (reason) + tb:BAIL_OUT(reason) +end + +function m.ok (test, name) + tb:ok(test, name) +end + +function m.nok (test, name) + tb:ok(not test, name) +end + +function m.is (got, expected, name) + local pass = got == expected + tb:ok(pass, name) + if not pass then + tb:diag(" got: " .. tostring(got) + .. "\n expected: " .. tostring(expected)) + end +end + +function m.isnt (got, expected, name) + local pass = got ~= expected + tb:ok(pass, name) + if not pass then + tb:diag(" got: " .. tostring(got) + .. "\n expected: anything else") + end +end + +function m.like (got, pattern, name) + if type(pattern) ~= 'string' then + tb:ok(false, name) + tb:diag("pattern isn't a string : " .. tostring(pattern)) + return + end + got = tostring(got) + local pass = got:match(pattern) + tb:ok(pass, name) + if not pass then + tb:diag(" '" .. got .. "'" + .. "\n doesn't match '" .. pattern .. "'") + end +end + +function m.unlike (got, pattern, name) + if type(pattern) ~= 'string' then + tb:ok(false, name) + tb:diag("pattern isn't a string : " .. tostring(pattern)) + return + end + got = tostring(got) + local pass = not got:match(pattern) + tb:ok(pass, name) + if not pass then + tb:diag(" '" .. got .. "'" + .. "\n matches '" .. pattern .. "'") + end +end + +local cmp = { + ['<'] = function (a, b) return a < b end, + ['<='] = function (a, b) return a <= b end, + ['>'] = function (a, b) return a > b end, + ['>='] = function (a, b) return a >= b end, + ['=='] = function (a, b) return a == b end, + ['~='] = function (a, b) return a ~= b end, +} + +function m.cmp_ok (this, op, that, name) + local f = cmp[op] + if not f then + tb:ok(false, name) + tb:diag("unknown operator : " .. tostring(op)) + return + end + local pass = f(this, that) + tb:ok(pass, name) + if not pass then + tb:diag(" " .. tostring(this) + .. "\n " .. op + .. "\n " .. tostring(that)) + end +end + +function m.type_ok (val, t, name) + if type(t) ~= 'string' then + tb:ok(false, name) + tb:diag("type isn't a string : " .. tostring(t)) + return + end + if type(val) == t then + tb:ok(true, name) + else + tb:ok(false, name) + tb:diag(" " .. tostring(val) .. " isn't a '" .. t .."' it's a '" .. type(val) .. "'") + end +end + +function m.pass (name) + tb:ok(true, name) +end + +function m.fail (name) + tb:ok(false, name) +end + +function m.require_ok (mod) + local r, msg = pcall(require, mod) + tb:ok(r, "require '" .. tostring(mod) .. "'") + if not r then + tb:diag(" " .. msg) + end + return r +end + +function m.eq_array (got, expected, name) + if type(got) ~= 'table' then + tb:ok(false, name) + tb:diag("got value isn't a table : " .. tostring(got)) + return + elseif type(expected) ~= 'table' then + tb:ok(false, name) + tb:diag("expected value isn't a table : " .. tostring(expected)) + return + end + for i = 1, #expected do + local v = expected[i] + local val = got[i] + if val ~= v then + tb:ok(false, name) + tb:diag(" at index: " .. tostring(i) + .. "\n got: " .. tostring(val) + .. "\n expected: " .. tostring(v)) + return + end + end + local extra = #got - #expected + if extra ~= 0 then + tb:ok(false, name) + tb:diag(" " .. tostring(extra) .. " unexpected item(s)") + else + tb:ok(true, name) + end +end + +function m.is_deeply (got, expected, name) + if type(got) ~= 'table' then + tb:ok(false, name) + tb:diag("got value isn't a table : " .. tostring(got)) + return + elseif type(expected) ~= 'table' then + tb:ok(false, name) + tb:diag("expected value isn't a table : " .. tostring(expected)) + return + end + local msg1 + local msg2 + + local function deep_eq (t1, t2, key_path) + if t1 == t2 then + return true + end + for k, v2 in pairs(t2) do + local v1 = t1[k] + if type(v1) == 'table' and type(v2) == 'table' then + local r = deep_eq(v1, v2, key_path .. "." .. tostring(k)) + if not r then + return false + end + else + if v1 ~= v2 then + key_path = key_path .. "." .. tostring(k) + msg1 = " got" .. key_path .. ": " .. tostring(v1) + msg2 = "expected" .. key_path .. ": " .. tostring(v2) + return false + end + end + end + for k in pairs(t1) do + local v2 = t2[k] + if v2 == nil then + key_path = key_path .. "." .. tostring(k) + msg1 = " got" .. key_path .. ": " .. tostring(t1[k]) + msg2 = "expected" .. key_path .. ": " .. tostring(v2) + return false + end + end + return true + end -- deep_eq + + local pass = deep_eq(got, expected, '') + tb:ok(pass, name) + if not pass then + tb:diag(" Tables begin differing at:") + tb:diag(" " .. msg1) + tb:diag(" " .. msg2) + end +end + +function m.error_is (code, arg2, arg3, arg4) + local params, expected, name + if type(arg2) == 'table' then + params = arg2 + expected = arg3 + name = arg4 + else + params = {} + expected = arg2 + name = arg3 + end + if type(code) == 'string' then + local msg + code, msg = loadstring(code) + if not code then + tb:ok(false, name) + tb:diag(" can't compile code :" + .. "\n " .. msg) + return + end + end + local r, msg = pcall(code, unpack(params)) + if r then + tb:ok(false, name) + tb:diag(" unexpected success" + .. "\n expected: " .. tostring(expected)) + else + local pass = msg == expected + tb:ok(pass, name) + if not pass then + tb:diag(" got: " .. msg + .. "\n expected: " .. tostring(expected)) + end + end +end + +function m.error_like (code, arg2, arg3, arg4) + local params, pattern, name + if type(arg2) == 'table' then + params = arg2 + pattern = arg3 + name = arg4 + else + params = {} + pattern = arg2 + name = arg3 + end + if type(code) == 'string' then + local msg + code, msg = loadstring(code) + if not code then + tb:ok(false, name) + tb:diag(" can't compile code :" + .. "\n " .. msg) + return + end + end + local r, msg = pcall(code, unpack(params)) + if r then + tb:ok(false, name) + tb:diag(" unexpected success" + .. "\n expected: " .. tostring(pattern)) + else + if type(pattern) ~= 'string' then + tb:ok(false, name) + tb:diag("pattern isn't a string : " .. tostring(pattern)) + return + end + local pass = msg:match(pattern) + tb:ok(pass, name) + if not pass then + tb:diag(" '" .. msg .. "'" + .. "\n doesn't match '" .. pattern .. "'") + end + end +end + +function m.lives_ok (code, arg2, arg3) + local params, name + if type(arg2) == 'table' then + params = arg2 + name = arg3 + else + params = {} + name = arg2 + end + if type(code) == 'string' then + local msg + code, msg = loadstring(code) + if not code then + tb:ok(false, name) + tb:diag(" can't compile code :" + .. "\n " .. msg) + return + end + end + local r, msg = pcall(code, unpack(params)) + tb:ok(r, name) + if not r then + tb:diag(" " .. msg) + end +end + +function m.diag (msg) + tb:diag(msg) +end + +function m.note (msg) + tb:note(msg) +end + +function m.skip (reason, count) + tb:skip(reason, count) +end + +function m.todo_skip (reason) + tb:todo_skip(reason) +end + +function m.skip_rest (reason) + tb:skip_rest(reason) +end + +function m.todo (reason, count) + tb:todo(reason, count) +end + +for k, v in pairs(m) do -- injection + _G[k] = v +end +_G.Test = _G.Test or {} +_G.Test.More = m + +m._VERSION = "0.2.3" +m._DESCRIPTION = "lua-TestMore : an Unit Testing Framework" +m._COPYRIGHT = "Copyright (c) 2009-2010 Francois Perrad" +return m +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaAudio/NoOutput.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,60 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local io = require 'io' +local pairs = pairs +local require = require + +_ENV = nil +local m = {} + +function m:create () + local tb = require 'Test.Builder':create() + tb:output(io.tmpfile()) + tb:failure_output(io.tmpfile()) + tb:todo_output(io.tmpfile()) + + function tb:read (stream) + if stream == 'out' then + local f = self:output() + f:seek 'set' + local out = f:read '*a' + f:close() + self:output(io.tmpfile()) + return out + elseif stream == 'err' then + local f = self:failure_output() + f:seek 'set' + local out = f:read '*a' + f:close() + self:failure_output(io.tmpfile()) + return out + elseif stream == 'todo' then + local f = self:todo_output() + f:seek 'set' + local out = f:read '*a' + f:close() + self:todo_output(io.tmpfile()) + return out + else + self:output():close() + self:output(io.tmpfile()) + self:failure_output():close() + self:failure_output(io.tmpfile()) + self:todo_output():close() + self:todo_output(io.tmpfile()) + end + end + + return tb +end + +return m +-- +-- Copyright (c) 2009-2010 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaAudio/SocketOutput.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,40 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +--[[ + require 'socket' + local conn = socket.connect(host, port) + require 'Test.Builder.Socket'.init(conn) + require 'Test.More' -- now, as usual + + plan(...) + ... +--]] + +local assert = assert + +-- We need to modify this because Corona doesn't handle subdirectories. +--local tb = require 'Test.Builder':new() +local tb = require 'Builder':new() +local m = getmetatable(tb) +_ENV = nil + +function m.init (sock) + tb:output(sock) + tb:failure_output(sock) + tb:todo_output(sock) +end + +function m.puts (sock, str) + assert(sock:send(str)) +end + +return m +-- +-- Copyright (c) 2011 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaAudio/Tester.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,141 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local error = error +local pairs = pairs +local setmetatable = setmetatable +local type = type +local _G = _G +local debug = require 'debug' + +local tb = require 'Test.Builder':new() +local out = require 'Test.Builder.Tester.File':new 'out' +local err = require 'Test.Builder.Tester.File':new 'err' + +_ENV = nil +local m = {} + +-- for remembering that we're testing and where we're testing at +local testing = false +local testing_num + +-- remembering where the file handles were originally connected +local original_output_handle +local original_failure_handle +local original_todo_handle + +local function _start_testing () + -- remember what the handles were set to + original_output_handle = tb:output() + original_failure_handle = tb:failure_output() + original_todo_handle = tb:todo_output() + + -- switch out to our own handles + tb:output(out) + tb:failure_output(err) + tb:todo_output(err) + + -- clear the expected list + out:reset() + err:reset() + + -- remeber that we're testing + testing = true + testing_num = tb:current_test() + tb:current_test(0) + + -- look, we shouldn't do the ending stuff + tb.no_ending = true +end + +function m.test_out (...) + if not testing then + _start_testing() + end + out:expect(...) +end + +function m.test_err (...) + if not testing then + _start_testing() + end + err:expect(...) +end + +function m.test_fail (offset) + offset = offset or 0 + if not testing then + _start_testing() + end + local info = debug.getinfo(2) + local prog = info.short_src + local line = info.currentline + offset + err:expect("# Failed test (" .. prog .. " at line " .. line .. ")") +end + +function m.test_diag (...) + local arg = {...} + if not testing then + _start_testing() + end + for i = 1, #arg do + err:expect("# " .. arg[i]) + end +end + +function m.test_test (args) + local mess + if type(args) == 'table' then + mess = args[1] + else + mess = args + args = {} + end + + if not testing then + error "Not testing. You must declare output with a test function first." + end + + -- okay, reconnect the test suite back to the saved handles + tb:output(original_output_handle) + tb:failure_output(original_failure_handle) + tb:todo_output(original_todo_handle) + + -- restore the test no, etc, back to the original point + tb:current_test(testing_num) + testing = false + + -- check the output we've stashed + local pass = (args.skip_out or out:check()) + and (args.skip_err or err:check()) + tb:ok(pass, mess) + if not pass then + -- print out the diagnostic information about why this + -- test failed + if not out:check() then + tb:diag(out:complaint()) + end + if not err:check() then + tb:diag(err:complaint()) + end + end +end + +function m.line_num () + return debug.getinfo(2).currentline +end + +for k, v in pairs(m) do -- injection + _G[k] = v +end + +return m + +-- +-- Copyright (c) 2009 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaAudio/main.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,422 @@ +--[[ +1. Does API internal state tests + a. channels + b. volume +2. Load tests +3. Seek tests +4. Plays Battle and Declaration at seeked positions (louder part of Battle, We hold these truths) +5. Plays note2 with callback +6. On callback, pauses Battle, fade-in Bouncing and play 2 times (loop=1), plays UFO infinite-looping +7. Bouncing callback: resume Battle, fade UFO to .5, play laser 3 times +8. Laser callback: fadeOut UFO in 2 secs +9. UFO callback: stop all and quit + +TODO: +a. Need to test free/in-use channels when actually playing. +b. Need to max out playing channels +c. Need to do seek channel instead of seek source +d. Need to test rewind +e. Need to test more file formats +--]] + +require('CoronaTest') + + +local EXPECTED_NUMBER_OF_CHANNELS = 32 +local NUMBER_OF_TOTAL_CHANNEL_LOOPS = 4 +local NUMBER_OF_SINGLE_TESTS = 66 +local NUMBER_OF_TESTS_IN_LOOP_INIT = 7 +local NUMBER_OF_TESTS_IN_LOOP_RESERVE = 2 +local NUMBER_OF_TESTS_IN_LOOP_AVERAGE_VOLUME = 2 +local number_of_tests = NUMBER_OF_SINGLE_TESTS + + EXPECTED_NUMBER_OF_CHANNELS * NUMBER_OF_TESTS_IN_LOOP_INIT + + EXPECTED_NUMBER_OF_CHANNELS * NUMBER_OF_TESTS_IN_LOOP_RESERVE + + EXPECTED_NUMBER_OF_CHANNELS * NUMBER_OF_TESTS_IN_LOOP_AVERAGE_VOLUME +g_numberOfTests = 0 + + + +function Quit() + print("disposing audio memory") + audio.dispose(declarationHandle) + audio.dispose(battleHymnHandle) + audio.dispose(note2Handle) + audio.dispose(bouncingHandle) + audio.dispose(ufoHandle) + audio.dispose(laserHandle) + audio.dispose(laserHandle2) + collectgarbage() + + print("Number of audio tests run", g_numberOfTests) + done_testing(g_numberOfTests) + os.exit() +end +print("Expected number of audio tests", number_of_tests) +plan(number_of_tests) + +local total_channels = audio.totalChannels +is(audio.totalChannels, EXPECTED_NUMBER_OF_CHANNELS, "totalChannels init") +g_numberOfTests = g_numberOfTests + 1 + +is(audio.reservedChannels, 0, "reservedChannels init") +g_numberOfTests = g_numberOfTests + 1 + +is(audio.freeChannels, EXPECTED_NUMBER_OF_CHANNELS, "freeChannels init") +g_numberOfTests = g_numberOfTests + 1 + +is(audio.unreservedFreeChannels, EXPECTED_NUMBER_OF_CHANNELS, "unreservedFreeChannels init") +g_numberOfTests = g_numberOfTests + 1 + +is(audio.usedChannels, 0, "usedChannels init") +g_numberOfTests = g_numberOfTests + 1 + +is(audio.unreservedUsedChannels, 0, "unreservedUsedChannels init") +g_numberOfTests = g_numberOfTests + 1 +-- g_numberOfTests = 6 + +-- LOOP INIT +for i=1, audio.totalChannels do + + is(audio.isChannelActive(i), false, "isChannelActive init channel=" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 + + is(audio.isSourceActive( audio.getSourceFromChannel(i) ), false, "isSourceActive & getSourceFromChannel init channel=" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 + + is(audio.isChannelPlaying(i), false, "isChannelPlaying init channel=" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 + + is(audio.isSourcePlaying( audio.getSourceFromChannel(i) ), false, "isSourcePlaying & getSourceFromChannel init channel=" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 + + is(audio.isChannelPaused(i), false, "isChannelPaused init channel=" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 + + is(audio.isSourcePaused( audio.getSourceFromChannel(i) ), false, "isChannelPaused & getSourceFromChannel init channel=" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 + + + + is(audio.getVolume({channel=i}), 1.0, "init getVolume{channel=}" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 + +end + +is(audio.getVolume(), 1.0, "getVolume (master) init") +g_numberOfTests = g_numberOfTests + 1 + + +-- Start mucking with state +is(audio.reserveChannels(2), 2, "reserveChannels( 2 )") +g_numberOfTests = g_numberOfTests + 1 + +is(audio.totalChannels, EXPECTED_NUMBER_OF_CHANNELS, "totalChannels reserved=2") +g_numberOfTests = g_numberOfTests + 1 + +is(audio.reservedChannels, 2, "reservedChannels reserved=2") +g_numberOfTests = g_numberOfTests + 1 + +is(audio.freeChannels, EXPECTED_NUMBER_OF_CHANNELS, "freeChannels reserved=2") +g_numberOfTests = g_numberOfTests + 1 + +is(audio.unreservedFreeChannels, EXPECTED_NUMBER_OF_CHANNELS-2, "unreservedFreeChannels reserved=2") +g_numberOfTests = g_numberOfTests + 1 + +is(audio.usedChannels, 0, "usedChannels reserved=2") +g_numberOfTests = g_numberOfTests + 1 + +is(audio.unreservedUsedChannels, 0, "unreservedUsedChannels reserved=2") +g_numberOfTests = g_numberOfTests + 1 + +-- LOOP RESERVE +for i=1, audio.totalChannels do + + is(audio.setVolume(0.5, {channel=i}), true, "RESERVE setVolume{channel=}" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 + + is(audio.getVolume({channel=i}), 0.5, "RESERVE getVolume{channel=}" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 +end + +-- test average volume +for i=1, audio.totalChannels/2 do + is(audio.setVolume(0.25, {channel=i}), true, " average setVolume(.25, {channel=}" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 + + is(audio.getVolume({channel=i}), 0.25, "average getVolume{channel=}" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 +end +for i=audio.totalChannels/2+1, audio.totalChannels do + is(audio.setVolume(0.75, {channel=i}), true, "average setVolume(.75, {channel=}" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 + + is(audio.getVolume({channel=i}), 0.75, "average getVolume{channel=}" .. tostring(i)) + g_numberOfTests = g_numberOfTests + 1 +end + +is(audio.getVolume({channel=0}), 0.50, "average getVolume{channel=0}") +g_numberOfTests = g_numberOfTests + 1 + + +is(audio.getVolume(), 1.0, "average getVolume (master)") +g_numberOfTests = g_numberOfTests + 1 + + +-- just reset volume +for i=1, audio.totalChannels do + audio.setVolume(1.0, {channel=i}) +end +audio.setVolume(1.0) + + + + +-- Loading tests +declarationHandle = audio.loadStream("TheDeclarationOfIndependencePreambleJFK.wav") +battleHymnHandle = audio.loadStream("battle_hymn_of_the_republic.mp3") +if system.getInfo("platformName") == "iPhone OS" or system.getInfo("platformName") == "Mac OS X" then + -- Right now only Apple supports M4A/AAC + note2Handle = audio.loadSound("note2_m4a.m4a") +else + -- Only Windows, Android, and Mac support Ogg Vorbis + note2Handle = audio.loadSound("note2_ogg.ogg") +end + +bouncingHandle = audio.loadSound("bouncing_mp3.mp3") +ufoHandle = audio.loadSound("UFO_engine.wav") +laserHandle = audio.loadSound("laser1.wav") +laserHandle2 = audio.loadSound("laser1.wav") +is(laserHandle == laserHandle2, true, "double loadSound on laser1 returned cached value") +g_numberOfTests = g_numberOfTests + 1 + +isnt(declarationHandle, nil, "loadStream declarationHandle") +g_numberOfTests = g_numberOfTests + 1 + +isnt(battleHymnHandle, nil, "loadStream battleHymnHandle") +g_numberOfTests = g_numberOfTests + 1 + +isnt(note2Handle, nil, "loadSound note2Handle") +g_numberOfTests = g_numberOfTests + 1 + +isnt(bouncingHandle, nil, "loadSound bouncingHandle") +g_numberOfTests = g_numberOfTests + 1 + +isnt(ufoHandle, nil, "loadSound ufoHandle") +g_numberOfTests = g_numberOfTests + 1 + +isnt(laserHandle, nil, "loadSound laserHandle") +g_numberOfTests = g_numberOfTests + 1 + + + +badHandle = audio.loadStream("fakefile.wav") +is(badHandle, nil, "loadStream fakefile") +g_numberOfTests = g_numberOfTests + 1 + +badHandle = audio.loadSound("fakefile.wav") +is(badHandle, nil, "loadSound fakefile") +g_numberOfTests = g_numberOfTests + 1 + + +badHandle = audio.loadSound("fakefile.wav") +is(badHandle, nil, "loadSound fakefile") +g_numberOfTests = g_numberOfTests + 1 + + + +-- Get times +local battle_hymm_duration = audio.getDuration(battleHymnHandle) +--print(battle_hymm_duration) +local declaration_duration = audio.getDuration(declarationHandle) +--print(declaration_duration) +local note2_duration = audio.getDuration(note2Handle) +--print(note2_duration) + +-- I don't know if my times are correct, but they seem to be in the ballpark. +-- Apple returns 314613. libmpg123 (Android) returns 314070 +if system.getInfo("platformName") == "iPhone OS" or system.getInfo("platformName") == "Mac OS X" then + is(battle_hymm_duration, 314613, "battle_hymm_duration") +else + is(battle_hymm_duration, 314070, "battle_hymm_duration") +end + +g_numberOfTests = g_numberOfTests + 1 + +-- This is probably fragile, but I expect WAV decoders to be pretty consistent regardless of implementation +is(declaration_duration, 124308, "declaration_duration") +g_numberOfTests = g_numberOfTests + 1 + +is(note2_duration, 1986, "note2_duration") +g_numberOfTests = g_numberOfTests + 1 + +-- Seek declaration to 'We hold these truths..." +is(audio.seek(29500, declarationHandle), true, "Seek Declaration to 'We hold these truths...'") +g_numberOfTests = g_numberOfTests + 1 + +-- Seek battle to less silent part" +is(audio.seek(148000, battleHymnHandle), true, "Seek battle to less silent part") +g_numberOfTests = g_numberOfTests + 1 + + + +-- start playing +battleHymmChannel, battleHymmSource = audio.play(battleHymnHandle, {channel=1}) +is(battleHymmChannel, 1, "play battleHymnHandle channel") +g_numberOfTests = g_numberOfTests + 1 +isnt(battleHymmSource, 0, "play battleHymnHandle source") +g_numberOfTests = g_numberOfTests + 1 + +-- should fail because channel is in use +declarationChannel, declarationSource = audio.play(declarationHandle, {channel=1}) +is(declarationChannel, 0, "play declarationHandle (should fail because channel is in use)") +g_numberOfTests = g_numberOfTests + 1 +is(declarationSource, 0, "play declarationSource") +g_numberOfTests = g_numberOfTests + 1 + +-- should work +declarationChannel, declarationSource = audio.play(declarationHandle, {channel=2, loops=-1}) +is(declarationChannel, 2, "play declarationHandle (should work)") +g_numberOfTests = g_numberOfTests + 1 +isnt(declarationSource, 0, "play declarationSource source") +g_numberOfTests = g_numberOfTests + 1 + +-- should fail because streamed source is already playing +battleHymmChannel2, battleHymmSource2 = audio.play(battleHymnHandle) +is(battleHymmChannel2, 0, "play battleHymnHandle (should fail because stream is already in use)") +g_numberOfTests = g_numberOfTests + 1 +is(battleHymmSource2, 0, "play battleHymmSource2 source (should fail because stream is already in use)") +g_numberOfTests = g_numberOfTests + 1 +-- NUMBER_OF_SINGLE_TESTS=25 + + +-- should fail because channel exceeds max +note2Channel, note2Source = audio.play(note2Handle, {channel=33}) +is(note2Channel, 0, "play note2Handle (should fail because channel exceeds max)") +g_numberOfTests = g_numberOfTests + 1 +is(note2Source, 0, "play note2Handle source (should fail because channel exceeds max)") +g_numberOfTests = g_numberOfTests + 1 + + +function laserCallback(event) + is(event.channel, laserChannel, "laserCallback channel assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.source, laserSource, "laserCallback source assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.handle, laserHandle, "laserCallback handle assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.completed, true, "laserCallback completed assert") + g_numberOfTests = g_numberOfTests + 1 + + isnt(audio.fadeOut({channel=ufoChannel, time=2000}), 0, "fadeOut UFO") + g_numberOfTests = g_numberOfTests + 1 +end + +function ufoCallback(event) + is(event.channel, ufoChannel, "ufoChannel channel assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.source, ufoSource, "ufoSource source assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.handle, ufoHandle, "ufoHandle handle assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.completed, false, "ufoCallback NOT completed assert") + g_numberOfTests = g_numberOfTests + 1 + + is(audio.fadeOut({channel=ufoChannel, time=2000}), 0, "fadeOut UFO (should fail because nothing is playing)") + g_numberOfTests = g_numberOfTests + 1 + + + is(audio.stop(), 2, "stop, expecting 2") + g_numberOfTests = g_numberOfTests + 1 + +-- done_testing(g_numberOfTests) + Quit() + +end + +function bouncingCallback(event) + is(event.channel, bouncingChannel, "bouncingCallback channel assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.source, bouncingSource, "bouncingCallback source assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.handle, bouncingHandle, "bouncingCallback handle assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.completed, true, "bouncingCallback completed assert") + g_numberOfTests = g_numberOfTests + 1 + + + isnt(audio.resume(battleHymmChannel), 0, "resuming Battle Hymn") + g_numberOfTests = g_numberOfTests + 1 + +-- print(ufoChannel) + isnt(audio.fade({channel=ufoChannel, time=4000, volume=0.5}), 0, "fading UFO") + g_numberOfTests = g_numberOfTests + 1 + + + local free_channel, free_source = audio.findFreeChannel() + isnt(free_channel, 0, "findFreeChannel") + g_numberOfTests = g_numberOfTests + 1 + + isnt(free_source, 0, "findFreeChannel source") + g_numberOfTests = g_numberOfTests + 1 + + +-- print(free_channel) + laserChannel, laserSource = audio.play(laserHandle, {channel=free_channel, onComplete=laserCallback, loops=2}) +-- print(laserChannel) + + +end + +function note2Callback(event) + is(event.channel, note2Channel, "note2Callback channel assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.source, note2Source, "note2Callback source assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.handle, note2Handle, "note2Callback handle assert") + g_numberOfTests = g_numberOfTests + 1 + + is(event.completed, true, "note2Callback completed assert") + g_numberOfTests = g_numberOfTests + 1 + + audio.dispose(note2Handle) + note2Handle = nil + + + isnt(audio.pause(battleHymmChannel), 0, "pausing Battle Hymn") + g_numberOfTests = g_numberOfTests + 1 + + bouncingChannel, bouncingSource = audio.play(bouncingHandle, {fadein=5000, onComplete=bouncingCallback, loops=1}) + + ufoChannel, ufoSource = audio.play(ufoHandle, {fadein=10000, loops=-1, onComplete=ufoCallback}) + +end + +-- should work +note2Channel, note2Source = audio.play(note2Handle, {onComplete=note2Callback}) +isnt(note2Channel, 0, "play note2Handle (should work)") +g_numberOfTests = g_numberOfTests + 1 + + +--[[ +audio.stop() +audio.dispose(declarationHandle) +audio.dispose(battleHymnHandle) +audio.dispose(note2Handle) +--]] + +--while true do +-- print("while") + +--end +--done_testing(g_numberOfTests)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaDisplayObjectsGroup/Builder.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,310 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local debug = require 'debug' +local io = require 'io' +local os = require 'os' +local table = require 'table' +local error = error +local pairs = pairs +local print = print +local setmetatable = setmetatable +local tonumber = tonumber +local tostring = tostring +local type = type + +_ENV = nil +local m = {} + +local testout = io and io.stdout +local testerr = io and (io.stderr or io.stdout) + +function m.puts (f, str) + f:write(str) +end + +local function _print (self, ...) + local f = self:output() + if f then + local msg = table.concat({..., "\n"}) + m.puts(f, msg) + else + print(...) + end +end + +local function print_comment (f, ...) + if f then + local arg = {...} + for k, v in pairs(arg) do + arg[k] = tostring(v) + end + local msg = table.concat(arg) + msg = msg:gsub("\n", "\n# ") + msg = msg:gsub("\n# \n", "\n#\n") + msg = msg:gsub("\n# $", '') + m.puts(f, "# " .. msg .. "\n") + else + print("# ", ...) + end +end + +function m:create () + local o = {} + setmetatable(o, self) + self.__index = self + o:reset() + o:reset_outputs() + return o +end + +local test +function m:new () + test = test or self:create() + return test +end + +function m:reset () + self.curr_test = 0 + self._done_testing = false + self.expected_tests = 0 + self.is_passing = true + self.todo_upto = -1 + self.todo_reason = nil + self.have_plan = false + self.no_plan = false + self.have_output_plan = false +end + +local function _output_plan (self, max, directive, reason) + local out = "1.." .. max + if directive then + out = out .. " # " .. directive + end + if reason then + out = out .. " " .. reason + end + _print(self, out) + self.have_output_plan = true +end + +function m:plan (arg) + if self.have_plan then + error("You tried to plan twice") + end + if type(arg) == 'string' and arg == 'no_plan' then + self.have_plan = true + self.no_plan = true + return true + elseif type(arg) ~= 'number' then + error("Need a number of tests") + elseif arg < 0 then + error("Number of tests must be a positive integer. You gave it '" .. arg .."'.") + else + self.expected_tests = arg + self.have_plan = true + _output_plan(self, arg) + return arg + end +end + +function m:done_testing (num_tests) + num_tests = num_tests or self.curr_test + if self._done_testing then + tb:ok(false, "done_testing() was already called") + return + end + self._done_testing = true + if self.expected_tests > 0 and num_tests ~= self.expected_tests then + self:ok(false, "planned to run " .. self.expected_tests + .. " but done_testing() expects " .. num_tests) + else + self.expected_tests = num_tests + end + if not self.have_output_plan then + _output_plan(self, num_tests) + end + self.have_plan = true + -- The wrong number of tests were run + if self.expected_tests ~= self.curr_test then + self.is_passing = false + end + -- No tests were run + if self.curr_test == 0 then + self.is_passing = false + end +end + +function m:has_plan () + if self.expected_tests > 0 then + return self.expected_tests + end + if self.no_plan then + return 'no_plan' + end + return nil +end + +function m:skip_all (reason) + if self.have_plan then + error("You tried to plan twice") + end + _output_plan(self, 0, 'SKIP', reason) + os.exit(0) +end + +local function in_todo (self) + return self.todo_upto >= self.curr_test +end + +local function _check_is_passing_plan (self) + local plan = self:has_plan() + if not plan or not tonumber(plan) then + return + end + if plan < self.curr_test then + self.is_passing = false + end +end + +function m:ok (test, name, level) + name = name or '' + level = level or 0 + if not self.have_plan then + error("You tried to run a test without a plan") + end + self.curr_test = self.curr_test + 1 + name = tostring(name) + if name:match('^[%d%s]+$') then + self:diag(" You named your test '" .. name .."'. You shouldn't use numbers for your test names." + .. "\n Very confusing.") + end + local out = '' + if not test then + out = "not " + end + out = out .. "ok " .. self.curr_test + if name ~= '' then + out = out .. " - " .. name + end + if self.todo_reason and in_todo(self) then + out = out .. " # TODO # " .. self.todo_reason + end + _print(self, out) + if not test then + local msg = "Failed" + if in_todo(self) then + msg = msg .. " (TODO)" + end + if debug then + local info = debug.getinfo(3 + level) + local file = info.short_src + local line = info.currentline + self:diag(" " .. msg .. " test (" .. file .. " at line " .. line .. ")") + else + self:diag(" " .. msg .. " test") + end + end + if not test and not in_todo(self) then + self.is_passing = false + end + _check_is_passing_plan(self) +end + +function m:BAIL_OUT (reason) + local out = "Bail out!" + if reason then + out = out .. " " .. reason + end + _print(self, out) + os.exit(255) +end + +function m:current_test (num) + if num then + self.curr_test = num + end + return self.curr_test +end + +function m:todo (reason, count) + count = count or 1 + self.todo_upto = self.curr_test + count + self.todo_reason = reason +end + +function m:skip (reason, count) + count = count or 1 + local name = "# skip" + if reason then + name = name .. " " .. reason + end + for i = 1, count do + self:ok(true, name) + end +end + +function m:todo_skip (reason) + local name = "# TODO & SKIP" + if reason then + name = name .. " " .. reason + end + self:ok(false, name, 1) +end + +function m:skip_rest (reason) + self:skip(reason, self.expected_tests - self.curr_test) +end + +local function diag_file (self) + if in_todo(self) then + return self:todo_output() + else + return self:failure_output() + end +end + +function m:diag (...) + print_comment(diag_file(self), ...) +end + +function m:note (...) + print_comment(self:output(), ...) +end + +function m:output (f) + if f then + self.out_file = f + end + return self.out_file +end + +function m:failure_output (f) + if f then + self.fail_file = f + end + return self.fail_file +end + +function m:todo_output (f) + if f then + self.todo_file = f + end + return self.todo_file +end + +function m:reset_outputs () + self:output(testout) + self:failure_output(testerr) + self:todo_output(testout) +end + +return m +-- +-- Copyright (c) 2009-2011 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaDisplayObjectsGroup/CoronaTest.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,166 @@ +-- This is a customization script for Lua Test More that configures the test environment to work with our custom needs. +-- This file transparently configures things in Test More such as socket connections and timeouts. +-- This file must be included before calling "require('More') + +require 'socket' + +local s_tbOriginalDoneTesting = nil +local s_CoronaTimeOutValue = nil + +module("CoronaTest", package.seeall) + + +local function CoronaTestTimerAppKiller( event ) + print("Corona Test timeout expired (application side)...calling os.exit()") + note("CoronaTest timeout triggered") + os.exit() +end + + +local function GetHostAndPort() + local host = nil + local port = nil + --[[ + local host = "127.0.0.1" + local port = 12345 + --]] + + +-- print("GetHostAndPort", GetHostAndPort) +-- print("os.getenv", os.getenv("HOME")) +-- print("os.getenv", os.getenv("HOST")) + if arg then + host = arg[1] + port = arg[2] + elseif os.getenv("TESTMORE_HOST") and os.getenv("TESTMORE_PORT") then + print("Detected environmental variables TESTMORE_HOST & TESTMORE_PORT") + host = os.getenv("TESTMORE_HOST") + port = os.getenv("TESTMORE_PORT") + print("Detected environmental variables TESTMORE_HOST & TESTMORE_PORT", host, port) + else + local ok = pcall(require, 'TestMoreOutputServerInfo') + if ok then + --print("got data from pcall") + host = TestMoreOutputServerInfo.Host + port = TestMoreOutputServerInfo.Port + s_CoronaTimeOutValue = TestMoreOutputServerInfo.TimeOut + end + + end + + return host, port +end + +local function GetOutputFileName() + local filename = nil + if arg then + filename = arg[1] + elseif os.getenv("TESTMORE_OUTPUT_FILENAME") then + filename = os.getenv("TESTMORE_OUTPUT_FILENAME") + print("Detected environmental variable TESTMORE_OUTPUT_FILENAME", filename) + else + local ok = pcall(require, 'TestMoreOutputFileInfo') + if ok then + --print("got data from pcall") + filename = TestMoreOutputFileInfo.FileName + s_CoronaTimeOutValue = TestMoreOutputFileInfo.TimeOut + end + + end + + return filename + +end + + +local function SetupFileOrStdout() + + local filename = GetOutputFileName() + if filename then + require 'FileOutput'.init(filename) + require 'More' + note("App is reporting to file: " .. tostring(filename)) + + else + require 'More' + note("App is reporting to stdout/stderr") + + end +end + +-- CoronaTest.Init +local function Init() +-- local tb = test_builder() + + --[[ + local host = "127.0.0.1" + local port = 12345 + --]] + -- + + -- Override assert to kill the test program + -- This is not really necessary if we trap lua errors to call exit() for us. + do + local old_assert = assert + assert = function(condition) + if not condition then + print("Dectected assertion failure: aborting Corona program") + return old_assert(condition) + --os.exit() + end + return old_assert(condition) + end + end + + local host, port = GetHostAndPort() + if host and port then + print("Application connecting to host and port", host, port) + local server = socket.connect(host, port) + if not server then + -- Might not want to abort in case we are running the simulator and have a stray host/port file + note("Failure of app connect to specified host and port: " .. tostring(host) ..":" .. tostring(port) .. ". Maybe you have a stale TestMoreOutputServerInfo.lua file?") + + SetupFileOrStdout() + else + require 'SocketOutput'.init(server) + require 'More' + note("App successfully connected to server on host and port: " .. tostring(host) ..":" .. tostring(port)) + end + else + SetupFileOrStdout() + note("App is reporting results to local machine") + end + + -- Override done_testing() + do + s_tbOriginalDoneTesting = done_testing + _G["done_testing"] = function(num_tests) + note("CoronaTest completed all tests") + return s_tbOriginalDoneTesting(num_tests) + end + end + + -- Capture Test More plan() so our plan function can invoke it + s_tbPlan = plan + + -- The timeout was loaded in the TestMoreOutput*Info if set + if s_CoronaTimeOutValue and type(s_CoronaTimeOutValue) == "number" then + timer.performWithDelay(s_CoronaTimeOutValue, CoronaTestTimerAppKiller) + end +end + +-- Override the global plan function defined by More. +-- This is the magic that hides all the setup from users. +-- But you must require this file before More. +_G["plan"] = function(plan_args) + Init() + -- s_tbPlan was setup in Init(). It is the regular test more plan function. + s_tbPlan(plan_args) +end + +-- Placeholder for done_testing. +-- Should be rewritten during Init() +_G["done_testing"] = function(num_tests) + print("Assertion error: called done_testing before our custom init (via plan) was invoked") + assert(false) +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaDisplayObjectsGroup/FileOutput.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,29 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- +local io = require 'io' + +local assert = assert + +-- We need to modify this because Corona doesn't handle subdirectories. +--local tb = require 'Test.Builder':new() +local tb = require 'Builder':new() +local m = getmetatable(tb) +_ENV = nil + +function m.init (filename) + local filehandle = assert(io.open(filename, "w+")) + + tb:output(filehandle) + tb:failure_output(filehandle) + tb:todo_output(filehandle) +end + +return m +-- +-- Copyright (c) 2011 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaDisplayObjectsGroup/More.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,374 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local loadstring = loadstring +local pairs = pairs +local pcall = pcall +local require = require +local tostring = tostring +local type = type +local unpack = require 'table'.unpack or unpack +local _G = _G + +-- We need to modify this because Corona doesn't handle subdirectories. +--local tb = require 'Test.Builder':new() +local tb = require 'Builder':new() + +_ENV = nil +local m = {} + +function m.plan (arg) + tb:plan(arg) +end + +function m.done_testing (num_tests) + tb:done_testing(num_tests) +end + +function m.skip_all (reason) + tb:skip_all(reason) +end + +function m.BAIL_OUT (reason) + tb:BAIL_OUT(reason) +end + +function m.ok (test, name) + tb:ok(test, name) +end + +function m.nok (test, name) + tb:ok(not test, name) +end + +function m.is (got, expected, name) + local pass = got == expected + tb:ok(pass, name) + if not pass then + tb:diag(" got: " .. tostring(got) + .. "\n expected: " .. tostring(expected)) + end +end + +function m.isnt (got, expected, name) + local pass = got ~= expected + tb:ok(pass, name) + if not pass then + tb:diag(" got: " .. tostring(got) + .. "\n expected: anything else") + end +end + +function m.like (got, pattern, name) + if type(pattern) ~= 'string' then + tb:ok(false, name) + tb:diag("pattern isn't a string : " .. tostring(pattern)) + return + end + got = tostring(got) + local pass = got:match(pattern) + tb:ok(pass, name) + if not pass then + tb:diag(" '" .. got .. "'" + .. "\n doesn't match '" .. pattern .. "'") + end +end + +function m.unlike (got, pattern, name) + if type(pattern) ~= 'string' then + tb:ok(false, name) + tb:diag("pattern isn't a string : " .. tostring(pattern)) + return + end + got = tostring(got) + local pass = not got:match(pattern) + tb:ok(pass, name) + if not pass then + tb:diag(" '" .. got .. "'" + .. "\n matches '" .. pattern .. "'") + end +end + +local cmp = { + ['<'] = function (a, b) return a < b end, + ['<='] = function (a, b) return a <= b end, + ['>'] = function (a, b) return a > b end, + ['>='] = function (a, b) return a >= b end, + ['=='] = function (a, b) return a == b end, + ['~='] = function (a, b) return a ~= b end, +} + +function m.cmp_ok (this, op, that, name) + local f = cmp[op] + if not f then + tb:ok(false, name) + tb:diag("unknown operator : " .. tostring(op)) + return + end + local pass = f(this, that) + tb:ok(pass, name) + if not pass then + tb:diag(" " .. tostring(this) + .. "\n " .. op + .. "\n " .. tostring(that)) + end +end + +function m.type_ok (val, t, name) + if type(t) ~= 'string' then + tb:ok(false, name) + tb:diag("type isn't a string : " .. tostring(t)) + return + end + if type(val) == t then + tb:ok(true, name) + else + tb:ok(false, name) + tb:diag(" " .. tostring(val) .. " isn't a '" .. t .."' it's a '" .. type(val) .. "'") + end +end + +function m.pass (name) + tb:ok(true, name) +end + +function m.fail (name) + tb:ok(false, name) +end + +function m.require_ok (mod) + local r, msg = pcall(require, mod) + tb:ok(r, "require '" .. tostring(mod) .. "'") + if not r then + tb:diag(" " .. msg) + end + return r +end + +function m.eq_array (got, expected, name) + if type(got) ~= 'table' then + tb:ok(false, name) + tb:diag("got value isn't a table : " .. tostring(got)) + return + elseif type(expected) ~= 'table' then + tb:ok(false, name) + tb:diag("expected value isn't a table : " .. tostring(expected)) + return + end + for i = 1, #expected do + local v = expected[i] + local val = got[i] + if val ~= v then + tb:ok(false, name) + tb:diag(" at index: " .. tostring(i) + .. "\n got: " .. tostring(val) + .. "\n expected: " .. tostring(v)) + return + end + end + local extra = #got - #expected + if extra ~= 0 then + tb:ok(false, name) + tb:diag(" " .. tostring(extra) .. " unexpected item(s)") + else + tb:ok(true, name) + end +end + +function m.is_deeply (got, expected, name) + if type(got) ~= 'table' then + tb:ok(false, name) + tb:diag("got value isn't a table : " .. tostring(got)) + return + elseif type(expected) ~= 'table' then + tb:ok(false, name) + tb:diag("expected value isn't a table : " .. tostring(expected)) + return + end + local msg1 + local msg2 + + local function deep_eq (t1, t2, key_path) + if t1 == t2 then + return true + end + for k, v2 in pairs(t2) do + local v1 = t1[k] + if type(v1) == 'table' and type(v2) == 'table' then + local r = deep_eq(v1, v2, key_path .. "." .. tostring(k)) + if not r then + return false + end + else + if v1 ~= v2 then + key_path = key_path .. "." .. tostring(k) + msg1 = " got" .. key_path .. ": " .. tostring(v1) + msg2 = "expected" .. key_path .. ": " .. tostring(v2) + return false + end + end + end + for k in pairs(t1) do + local v2 = t2[k] + if v2 == nil then + key_path = key_path .. "." .. tostring(k) + msg1 = " got" .. key_path .. ": " .. tostring(t1[k]) + msg2 = "expected" .. key_path .. ": " .. tostring(v2) + return false + end + end + return true + end -- deep_eq + + local pass = deep_eq(got, expected, '') + tb:ok(pass, name) + if not pass then + tb:diag(" Tables begin differing at:") + tb:diag(" " .. msg1) + tb:diag(" " .. msg2) + end +end + +function m.error_is (code, arg2, arg3, arg4) + local params, expected, name + if type(arg2) == 'table' then + params = arg2 + expected = arg3 + name = arg4 + else + params = {} + expected = arg2 + name = arg3 + end + if type(code) == 'string' then + local msg + code, msg = loadstring(code) + if not code then + tb:ok(false, name) + tb:diag(" can't compile code :" + .. "\n " .. msg) + return + end + end + local r, msg = pcall(code, unpack(params)) + if r then + tb:ok(false, name) + tb:diag(" unexpected success" + .. "\n expected: " .. tostring(expected)) + else + local pass = msg == expected + tb:ok(pass, name) + if not pass then + tb:diag(" got: " .. msg + .. "\n expected: " .. tostring(expected)) + end + end +end + +function m.error_like (code, arg2, arg3, arg4) + local params, pattern, name + if type(arg2) == 'table' then + params = arg2 + pattern = arg3 + name = arg4 + else + params = {} + pattern = arg2 + name = arg3 + end + if type(code) == 'string' then + local msg + code, msg = loadstring(code) + if not code then + tb:ok(false, name) + tb:diag(" can't compile code :" + .. "\n " .. msg) + return + end + end + local r, msg = pcall(code, unpack(params)) + if r then + tb:ok(false, name) + tb:diag(" unexpected success" + .. "\n expected: " .. tostring(pattern)) + else + if type(pattern) ~= 'string' then + tb:ok(false, name) + tb:diag("pattern isn't a string : " .. tostring(pattern)) + return + end + local pass = msg:match(pattern) + tb:ok(pass, name) + if not pass then + tb:diag(" '" .. msg .. "'" + .. "\n doesn't match '" .. pattern .. "'") + end + end +end + +function m.lives_ok (code, arg2, arg3) + local params, name + if type(arg2) == 'table' then + params = arg2 + name = arg3 + else + params = {} + name = arg2 + end + if type(code) == 'string' then + local msg + code, msg = loadstring(code) + if not code then + tb:ok(false, name) + tb:diag(" can't compile code :" + .. "\n " .. msg) + return + end + end + local r, msg = pcall(code, unpack(params)) + tb:ok(r, name) + if not r then + tb:diag(" " .. msg) + end +end + +function m.diag (msg) + tb:diag(msg) +end + +function m.note (msg) + tb:note(msg) +end + +function m.skip (reason, count) + tb:skip(reason, count) +end + +function m.todo_skip (reason) + tb:todo_skip(reason) +end + +function m.skip_rest (reason) + tb:skip_rest(reason) +end + +function m.todo (reason, count) + tb:todo(reason, count) +end + +for k, v in pairs(m) do -- injection + _G[k] = v +end +_G.Test = _G.Test or {} +_G.Test.More = m + +m._VERSION = "0.2.3" +m._DESCRIPTION = "lua-TestMore : an Unit Testing Framework" +m._COPYRIGHT = "Copyright (c) 2009-2010 Francois Perrad" +return m +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaDisplayObjectsGroup/NoOutput.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,60 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local io = require 'io' +local pairs = pairs +local require = require + +_ENV = nil +local m = {} + +function m:create () + local tb = require 'Test.Builder':create() + tb:output(io.tmpfile()) + tb:failure_output(io.tmpfile()) + tb:todo_output(io.tmpfile()) + + function tb:read (stream) + if stream == 'out' then + local f = self:output() + f:seek 'set' + local out = f:read '*a' + f:close() + self:output(io.tmpfile()) + return out + elseif stream == 'err' then + local f = self:failure_output() + f:seek 'set' + local out = f:read '*a' + f:close() + self:failure_output(io.tmpfile()) + return out + elseif stream == 'todo' then + local f = self:todo_output() + f:seek 'set' + local out = f:read '*a' + f:close() + self:todo_output(io.tmpfile()) + return out + else + self:output():close() + self:output(io.tmpfile()) + self:failure_output():close() + self:failure_output(io.tmpfile()) + self:todo_output():close() + self:todo_output(io.tmpfile()) + end + end + + return tb +end + +return m +-- +-- Copyright (c) 2009-2010 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaDisplayObjectsGroup/SocketOutput.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,40 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +--[[ + require 'socket' + local conn = socket.connect(host, port) + require 'Test.Builder.Socket'.init(conn) + require 'Test.More' -- now, as usual + + plan(...) + ... +--]] + +local assert = assert + +-- We need to modify this because Corona doesn't handle subdirectories. +--local tb = require 'Test.Builder':new() +local tb = require 'Builder':new() +local m = getmetatable(tb) +_ENV = nil + +function m.init (sock) + tb:output(sock) + tb:failure_output(sock) + tb:todo_output(sock) +end + +function m.puts (sock, str) + assert(sock:send(str)) +end + +return m +-- +-- Copyright (c) 2011 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaDisplayObjectsGroup/Tester.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,141 @@ + +-- +-- lua-TestMore : <http://fperrad.github.com/lua-TestMore/> +-- + +local error = error +local pairs = pairs +local setmetatable = setmetatable +local type = type +local _G = _G +local debug = require 'debug' + +local tb = require 'Test.Builder':new() +local out = require 'Test.Builder.Tester.File':new 'out' +local err = require 'Test.Builder.Tester.File':new 'err' + +_ENV = nil +local m = {} + +-- for remembering that we're testing and where we're testing at +local testing = false +local testing_num + +-- remembering where the file handles were originally connected +local original_output_handle +local original_failure_handle +local original_todo_handle + +local function _start_testing () + -- remember what the handles were set to + original_output_handle = tb:output() + original_failure_handle = tb:failure_output() + original_todo_handle = tb:todo_output() + + -- switch out to our own handles + tb:output(out) + tb:failure_output(err) + tb:todo_output(err) + + -- clear the expected list + out:reset() + err:reset() + + -- remeber that we're testing + testing = true + testing_num = tb:current_test() + tb:current_test(0) + + -- look, we shouldn't do the ending stuff + tb.no_ending = true +end + +function m.test_out (...) + if not testing then + _start_testing() + end + out:expect(...) +end + +function m.test_err (...) + if not testing then + _start_testing() + end + err:expect(...) +end + +function m.test_fail (offset) + offset = offset or 0 + if not testing then + _start_testing() + end + local info = debug.getinfo(2) + local prog = info.short_src + local line = info.currentline + offset + err:expect("# Failed test (" .. prog .. " at line " .. line .. ")") +end + +function m.test_diag (...) + local arg = {...} + if not testing then + _start_testing() + end + for i = 1, #arg do + err:expect("# " .. arg[i]) + end +end + +function m.test_test (args) + local mess + if type(args) == 'table' then + mess = args[1] + else + mess = args + args = {} + end + + if not testing then + error "Not testing. You must declare output with a test function first." + end + + -- okay, reconnect the test suite back to the saved handles + tb:output(original_output_handle) + tb:failure_output(original_failure_handle) + tb:todo_output(original_todo_handle) + + -- restore the test no, etc, back to the original point + tb:current_test(testing_num) + testing = false + + -- check the output we've stashed + local pass = (args.skip_out or out:check()) + and (args.skip_err or err:check()) + tb:ok(pass, mess) + if not pass then + -- print out the diagnostic information about why this + -- test failed + if not out:check() then + tb:diag(out:complaint()) + end + if not err:check() then + tb:diag(err:complaint()) + end + end +end + +function m.line_num () + return debug.getinfo(2).currentline +end + +for k, v in pairs(m) do -- injection + _G[k] = v +end + +return m + +-- +-- Copyright (c) 2009 Francois Perrad +-- +-- This library is licensed under the terms of the MIT/X11 license, +-- like Lua itself. +--
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaDisplayObjectsGroup/config.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,9 @@ +application = +{ + content = + { + width = 320, + height = 480, + scale = "zoomEven" + }, +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestCoronaDisplayObjectsGroup/main.lua Wed Aug 10 12:47:55 2011 -0700 @@ -0,0 +1,344 @@ +-- Test Code Project: display_objects-group +-- +-- Date: February 9, 2011 +-- +-- Version: 1.0 +-- +-- File name: main.lua +-- +-- Author: Tom Newman +-- +-- Tests: Display groups APIs and textMemory with images +-- +-- File dependencies: automated test files +-- +-- Target devices: Simulator (results in Console) +-- +-- Limitations: + +-- Update History: +-- ver 1.0 2/9/10 Initial test +-- +-- Tests Performed: +-- +-- 1. Start +-- 2. Create group +-- 3. Insert image 1 +-- 4. Insert Image 2 +-- 5. Insert Image 3 +-- 6. object:toBack +-- 7. object:toFront +-- 8. re-insert object (moving it front) +-- 9. remove image 1 +-- 10. remove testGroup (automatically removes image 2 and image 3) +-- 11. remove all text messages (textureMemory should be 0) +-- 12. done +-- +-- The state is incremented every 30 frames +-- The testing of memory and group is displayed every 30 frames +-- +-- +-- APIs Tested +-- display.newGroup +-- group:insert +-- object:toBack +-- object:toFront +-- object:removeSelf +-- system.getInfo("textureMemoryUsed") +-- +-- Comments: + +--------------------------------------------------------------------------------- + +require('CoronaTest') + +local number_of_tests = 31 + +function Quit() +-- print("Number of Display-1 tests run", numberOfTests) + done_testing(numberOfTests) + os.exit() +end + +print(); print( "Testing Display Objects - Groups" ) +print("Expected number of Display tests", number_of_tests) +plan(number_of_tests) + +-------------------------------------------------- +-- Test coding starts here -- +-------------------------------------------------- + +----------------------------------------------------------- +-- Add Commas to whole numbers +-- +-- Enter: number = number to format +-- maxPos = maximum common position: 3, 6, 9, 12 +-- +-- Returns: formatted number string +----------------------------------------------------------- +-- +local function AddCommas( number, maxPos ) + + local s = tostring( number ) + local len = string.len( s ) + + if len > maxPos then + -- Add comma to the string + local s2 = string.sub( s, -maxPos ) + local s1 = string.sub( s, 1, len - maxPos ) + s = (s1 .. "," .. s2) + end + + maxPos = maxPos - 3 -- next comma position + + if maxPos > 0 then + return AddCommas( s, maxPos ) + else + return s + end + +end + +----------------------------------------------------------- +-- Verify objects in Group +-- +-- Enter: group = pointer to group +-- items = lua table of objects expected in group +-- +-- Returns: true if items are in group and in correct order +-- false if any item missing or out of order +----------------------------------------------------------- +-- +local function verifyGroup( group, items ) +--t print( #items, group, tostring( items[1] ), tostring( items[2] ), group[1] ) -- debug + + for i = 1, #items do + if group[i] ~= items[i] then + return false + end + end + + return true -- all items found and match + +end + + +display.setStatusBar( display.HiddenStatusBar ) -- hide status bar + +print( "TextureMemory: " .. AddCommas( system.getInfo("textureMemoryUsed"), 9 ) .. " bytes" ) +print() + +-- Displays text message in center of screen +txtMsg1 = display.newText( "See Console for Test Results", 55, 200, "Verdana-Bold", 14 ) +txtMsg1:setTextColor( 255, 255, 0 ) + +-- Displays text message in center of screen +txtMsg2 = display.newText( "Touch screen for each state", 55, 400, "Verdana-Bold", 14 ) +txtMsg2:setTextColor( 255, 255, 255, 128 ) + +-------------------------------- +-- Code Execution Start Here +-------------------------------- + +-- Forward references +-- +local image1, image2, image3, testGrp + +local nextState = false + + +local frame = 0 +local state = 1 + +function render(event) + +-- Comment out the next line to run automated (no touch required) +-- if not nextState then return end + + frame=frame+1 + +-- Display information at frame 10 +-- Action performed at frame 1 +-- + if frame == 1 then + + -- Create / destroys objects based on current state + -- + if 1 == state then + print(">>> Starting" ) + + -- Create a test group + -- + elseif 2 == state then + print(">>> Creating testGroup" ) + testGroup = display.newGroup() + + elseif 3 == state then + print(">>> Creating & Inserting Image1" ) + image1 = display.newImage( "Image1.png" ) + image1.name = "image1" + testGroup:insert( image1 ) + + elseif 4 == state then + print(">>> Creating & Inserting Image2" ) + image2 = display.newImage( "Image2.jpg" ) + image2.name = "image2" + testGroup:insert( image2 ) + + elseif 5 == state then + print(">>> Creating & Inserting Image3" ) + image3 = display.newImage( "Image3.jpg" ) + image3.name = "image3" + testGroup:insert( image3 ) + + elseif 6 == state then + print(">>> toBack: Image3" ) + image3:toBack() + + elseif 7 == state then + print(">>> toFront: Image1" ) + image1:toFront() + + elseif 8 == state then + print(">>> re-insert: Image2" ) + testGroup:insert(image2) + + elseif 9 == state then + print(">>> Removing Image1" ) + image1:removeSelf() + + elseif 10 == state then + print(">>> Remove testGroup" ) + testGroup:removeSelf() + + elseif 11 == state then + print(">>> Deleting txtMsg1 & txtMsg2 (text messages)" ) + txtMsg1:removeSelf() + txtMsg2:removeSelf() + + elseif 12 == state then + -- End the looping + -- + -- Remove the listener and references to the objects + -- + image1 = nil + image2 = nil + image3 = nil + testGroup = nil + txtMsg1 = nil + txtMsg2 = nil + + Runtime:removeEventListener( "enterFrame", render) + Runtime:removeEventListener( "touch", screenTouch ) + + -------------------------------------------------- + -- Testing Done + -------------------------------------------------- + Quit() + + end + + + -- Display status information about the objects/group + -- + elseif frame == 5 then + + print( "State: " .. state ) + + if 1 == state then + -- Starting + is( system.getInfo("textureMemoryUsed"), 16384, "starting: textureMemoryUsed" ) + + elseif 2 == state then + -- Creating testGroup + isnt( testGroup, "testGroup created" ) + is( testGroup.numChildren, 0, "numChildren" ) + is( system.getInfo("textureMemoryUsed"), 16384, "textureMemoryUsed" ) + + elseif 3 == state then + -- Added Image1 + is( testGroup.numChildren, 1, "numChildren" ) + is( system.getInfo("textureMemoryUsed"), 1064960, "textureMemoryUsed" ) + ok( verifyGroup( testGroup, {image1} ), "Image1 in Group" ) + + elseif 4 == state then + -- Added Image2 + is( testGroup.numChildren, 2, "numChildren" ) + is( system.getInfo("textureMemoryUsed"), 2113536, "textureMemoryUsed" ) + ok( verifyGroup( testGroup, {image1, image2} ), "Image1, Image2 in Group" ) + + elseif 5 == state then + -- Added Image3 + is( testGroup.numChildren, 3, "numChildren" ) + is( system.getInfo("textureMemoryUsed"), 3162112, "textureMemoryUsed" ) + ok( verifyGroup( testGroup, {image1, image2, image3} ), "Image1, Image2, Image3 in Group" ) +-- print( "+++ testGroup: " .. testGroup[1].name .. ", " .. testGroup[2].name .. ", " .. testGroup[3].name ) -- debug + + elseif 6 == state then + -- toBack Image3 + is( testGroup.numChildren, 3, "numChildren" ) + is( system.getInfo("textureMemoryUsed"), 3162112, "textureMemoryUsed" ) + ok( verifyGroup( testGroup, {image3, image1, image2} ), "image3:toBack: Image3, Image1, Image2" ) +-- print( "+++ testGroup: " .. testGroup[1].name .. ", " .. testGroup[2].name .. ", " .. testGroup[3].name ) -- debug + + elseif 7 == state then + -- toBack Image1 + is( testGroup.numChildren, 3, "numChildren" ) + is( system.getInfo("textureMemoryUsed"), 3162112, "textureMemoryUsed" ) + ok( verifyGroup( testGroup, {image3, image2, image1} ), "image1:toFront: Image3, Image2, Image1" ) +-- print( "+++ testGroup: " .. testGroup[1].name .. ", " .. testGroup[2].name .. ", " .. testGroup[3].name ) -- debug + + elseif 8 == state then + -- re-insert Image2 + is( testGroup.numChildren, 3, "numChildren" ) + is( system.getInfo("textureMemoryUsed"), 3162112, "textureMemoryUsed" ) + ok( verifyGroup( testGroup, {image3, image1, image2} ), "re-insert image2: Image3, Image1, Image2" ) +-- print( "+++ testGroup: " .. testGroup[1].name .. ", " .. testGroup[2].name .. ", " .. testGroup[3].name ) -- debug + + elseif 9 == state then + -- remove Image1 + is( testGroup.numChildren, 2, "numChildren" ) + is( system.getInfo("textureMemoryUsed"), 2113536, "textureMemoryUsed" ) + ok( verifyGroup( testGroup, {image3, image2} ), "removeSelf image1: Image3, Image2" ) +-- print( "+++ testGroup: " .. testGroup[1].name .. ", " .. testGroup[2].name ) -- debug + + elseif 10 == state then + -- remove testGroup + is( system.getInfo("textureMemoryUsed"), 16384, "textureMemoryUsed" ) + + -- This verifies that the Display Object properties have been removed + nok( testGroup.numChildren, "remove testGroup: numChildren" ) + nok( image1.x, "remove testGroup: image1.x" ) + nok( image2.x, "remove testGroup: image2.x" ) + nok( image3.x, "remove testGroup: image3.x" ) + + elseif 11 == state then + -- remove all text messages + is( system.getInfo("textureMemoryUsed"), 0, "text msgs removed: textureMemoryUsed" ) + + end -- end of state + + state = state + 1 -- next state + + print() + + -- Reset frame count and pause until the next screen touch + -- + elseif frame == 6 then + frame = 0 + nextState = false -- reset our flag + + end + +end + +-- Set nextState flag when user touches the screen +-- +local function screenTouch( event ) + if "ended" == event.phase then + nextState = true + end +end + +Runtime:addEventListener( "touch", screenTouch ) +Runtime:addEventListener( "enterFrame", render )