-- test/test-supple.capi.lua -- -- Supple - Tests for the capi module -- -- Copyright 2012 Daniel Silverstone -- -- For Licence terms, see COPYING -- -- Step one, start coverage local luacov = require 'luacov' local capi = require 'supple.capi' local testnames = {} local real_assert = assert local total_asserts = 0 local function assert(...) local retval = real_assert(...) total_asserts = total_asserts + 1 return retval end local function add_test(suite, name, value) rawset(suite, name, value) testnames[#testnames+1] = name end local suite = setmetatable({}, {__newindex = add_test}) function suite.capi_has_api() assert(capi._API, "No _API found in the CAPI") end function suite.capi_has_abi() assert(capi._ABI, "No _ABI found in the CAPI") end function suite.capi_explain_non_table_etc() local ok = pcall(capi.explain, nil, ""); assert(ok == false, "Explained nil unexpectedly") ok = pcall(capi.explain, true, ""); assert(ok == false, "Explained true unexpectedly") ok = pcall(capi.explain, false, ""); assert(ok == false, "Explained false unexpectedly") ok = pcall(capi.explain, 123, ""); assert(ok == false, "Explained number unexpectedly") ok = pcall(capi.explain, "", ""); assert(ok == false, "Explained string unexpectedly") ok = pcall(capi.explain, coroutine.create(function()end), ""); assert(ok == false, "Explained coroutine unexpectedly") end function suite.capi_explain_bad_tag() local ok = pcall(capi.explain, {}, nil) assert(ok == false, "Explained with nil tag unexpectedly") ok = pcall(capi.explain, {}, 1233) assert(ok == false, "Explained with number tag unexpectedly") ok = pcall(capi.explain, {}, true) assert(ok == false, "Explained with true tag unexpectedly") ok = pcall(capi.explain, {}, false) assert(ok == false, "Explained with false tag unexpectedly") ok = pcall(capi.explain, {}, {}) assert(ok == false, "Explained with table tag unexpectedly") ok = pcall(capi.explain, {}, function()end) assert(ok == false, "Explained with function tag unexpectedly") ok = pcall(capi.explain, {}, coroutine.create(function()end)) assert(ok == false, "Explained with coroutine tag unexpectedly") end function suite.capi_explain_simple_table() local expn = capi.explain({}, "fish") assert(type(expn) == "table", "Explanation wasn't a table") assert(type(expn.tag) == "string", "Tag not a string") assert(expn.tag == "fish", "Tag wasn't as passed in") assert(type(expn.type) == "string", "Type wasn't a string") assert(expn.type == "table", "Type didn't declare it is a table") assert(expn.methods == nil, "Methods table was present in some form") end function suite.capi_explain_table_with_mode() local tab = setmetatable({}, { __mode="k"}) local expn = capi.explain(tab, "fish") assert(type(expn) == "table", "Explanation wasn't a table") assert(type(expn.tag) == "string", "Tag not a string") assert(expn.tag == "fish", "Tag wasn't as passed in") assert(type(expn.type) == "string", "Type wasn't a string") assert(expn.type == "table", "Type didn't declare it is a table") assert(type(expn.methods) == "table", "Methods were not present") assert(next(expn.methods) == nil, "Methods had something in") end function suite.capi_explain_table_with_index() local tab = setmetatable({}, { __index = {} }) local expn = capi.explain(tab, "fish") assert(type(expn) == "table", "Explanation wasn't a table") assert(type(expn.tag) == "string", "Tag not a string") assert(expn.tag == "fish", "Tag wasn't as passed in") assert(type(expn.type) == "string", "Type wasn't a string") assert(expn.type == "table", "Type didn't declare it is a table") assert(type(expn.methods) == "table", "Methods were not present") assert(expn.methods[1] == "__index", "Missing __index") assert(expn.methods[2] == nil, "Something other than __index") end function suite.capi_explain_function() local expn = capi.explain(function()end, "fish") assert(type(expn) == "table", "Explanation wasn't a table") assert(type(expn.tag) == "string", "Tag not a string") assert(expn.tag == "fish", "Tag wasn't as passed in") assert(type(expn.type) == "string", "Type wasn't a string") assert(expn.type == "function", "Type didn't declare it is a table") assert(expn.methods == nil, "Methods table was present in some form") end function suite.capi_type_chains() assert(capi.type({}) == "table", "Plain table wasn't a table") local t = setmetatable({}, { __type = function() return "jeff" end }) assert(capi.type(t) == "jeff", "Chained table wasn't jeff") end function suite.capi_rawtype() assert(capi.rawtype() == "nil", "nil was't nil") assert(capi.rawtype({}) == "table", "table wasn't") assert(capi.rawtype("") == "string", "string wasn't") assert(capi.rawtype(false) == "boolean", "boolean wasn't") assert(capi.rawtype(function()end) == "function", "function wasn't") assert(capi.rawtype(coroutine.create(function()end)) == "thread", "coroutine wasn't") assert(capi.rawtype(capi.new_proxy("table")) == "userdata", "userdata wasn't") end function suite.capi_new_proxy_fails() local ok = pcall(capi.new_proxy) assert(ok == false, "Made a new proxy with a nil type string") ok = pcall(capi.new_proxy, {}) assert(ok == false, "Made a new proxy with a table type string") end function suite.capi_new_proxy_function() local proxy, mt = capi.new_proxy("function") local sparetype = mt.__type mt.__type = nil assert(capi.type(proxy) == "userdata", "Proxy wasn't userdata") mt.__type = sparetype assert(capi.type(proxy) == "function", "Proxy did not override type") assert(tostring(proxy):match("^function: "), "Proxy didn't tostring nicely") end function suite.capi_new_proxy_table() local proxy, mt = capi.new_proxy("table") local sparetype = mt.__type mt.__type = nil assert(type(proxy) == "userdata", "Proxy wasn't userdata") mt.__type = sparetype assert(capi.type(proxy) == "table", "Proxy did not override type") assert(tostring(proxy):match("^table: "), "Proxy didn't tostring nicely") end function suite.capi_new_proxy_table() local proxy, mt = capi.new_proxy("userdata") local sparetype = mt.__type mt.__type = nil assert(type(proxy) == "userdata", "Proxy wasn't userdata") mt.__type = sparetype assert(capi.type(proxy) == "userdata", "Proxy did not override type") assert(tostring(proxy):match("^userdata: "), "Proxy didn't tostring nicely") end function suite.capi_test_next_on_table() local t = { foo = "bar" } local k, v = capi.next(t) assert(k == "foo", "Key was not 'foo'") assert(v == "bar", "Value was not 'bar'") assert(capi.next(t, "foo") == nil, "Next after 'foo' was not nil") end function suite.capi_test_next_on_proxied_table() local proxied = { foo = "bar" } local proxy, mt = capi.new_proxy("table") mt.__next = function(self, key) return next(proxied, key) end local k, v = capi.next(proxy) assert(k == "foo", "Key was not 'foo'") assert(v == "bar", "Value was not 'bar'") assert(capi.next(proxy, "foo") == nil, "Next after 'foo' was not nil") end function suite.capi_test_ipairs_on_table() local tab = { "a", "b" } for i, v in capi.ipairs(tab) do assert(i > 0 and i < 3, "Index out of range") assert((i == 1 and v == "a") or (i == 2 and v == "b"), "Key/value pair wrong") end end function suite.capi_test_ipairs_on_proxied_table() local proxied = { "a", "b" } local tab, mt = capi.new_proxy("table") mt.__index = function(self, idx) return proxied[idx] end for i, v in capi.ipairs(tab) do assert(i > 0 and i < 3, "Index out of range") assert((i == 1 and v == "a") or (i == 2 and v == "b"), "Key/value pair wrong") end end function suite.capi_test_pairs_on_table() local tab = { foo = "bar", baz = "meta" } for k, v in capi.pairs(tab) do assert(k == "foo" or k == "baz", "Key not right") assert((k == "foo" and v == "bar") or (k == "baz" and v == "meta"), "key/value pair wrong") end end function suite.capi_test_pairs_on_proxied_table() local proxied = { foo = "bar", baz = "meta" } local tab, mt = capi.new_proxy("table") mt.__next = function(self, idx) return next(proxied, idx) end for k, v in capi.pairs(tab) do assert(k == "foo" or k == "baz", "Key not right") assert((k == "foo" and v == "bar") or (k == "baz" and v == "meta"), "key/value pair wrong") end end local count_ok = 0 for _, testname in ipairs(testnames) do -- print("Run: " .. testname) local ok, err = xpcall(suite[testname], debug.traceback) if not ok then print(err) print() else count_ok = count_ok + 1 end end print(tostring(count_ok) .. "/" .. tostring(#testnames) .. " [" .. tostring(total_asserts) .. "] OK") os.exit(count_ok == #testnames and 0 or 1)