diff --git a/spec/formatters_spec.lua b/spec/formatters_spec.lua index d91b2c4..3ac5962 100644 --- a/spec/formatters_spec.lua +++ b/spec/formatters_spec.lua @@ -17,7 +17,7 @@ describe("Test Formatters", function() after_each(function() snapshot:revert() end) - + it("Checks to see if types are returned as strings", function() assert.is.same(assert:format({ "a string", ["n"] = 1 })[1], "(string) 'a string'") assert.is.same(assert:format({ true, ["n"] = 1 })[1], "(boolean) true") @@ -37,38 +37,47 @@ describe("Test Formatters", function() end) it("Checks to see if tables are recursively serialized", function() - assert.is.same(assert:format({ {}, ["n"] = 1 })[1], "(table) { }") - assert.is.same(assert:format({ { 2, 3, 4, [-5] = 7}, ["n"] = 1 })[1], [[(table) { + local t = {} + assert.is.same(assert:format({ t, ["n"] = 1 })[1], "("..tostring(t)..") { }") + t = { 2, 3, 4, [-5] = 7} + assert.is.same(assert:format({ t, ["n"] = 1 })[1], [[(]]..tostring(t)..[[) { [1] = 2 [2] = 3 [3] = 4 [-5] = 7 }]]) - assert.is.same(assert:format({ { 1, ["k1"] = "v1", ["k2"] = "v2"}, ["n"] = 1 })[1], [[(table) { + t = { 1, ["k1"] = "v1", ["k2"] = "v2"} + assert.is.same(assert:format({ t, ["n"] = 1 })[1], [[(]]..tostring(t)..[[) { [1] = 1 [k1] = 'v1' [k2] = 'v2' }]]) - assert.is.same(assert:format({ { "{\n }\n" }, ["n"] = 1 })[1], [[(table) { + t = { "{\n }\n" } + assert.is.same(assert:format({ t, ["n"] = 1 })[1], [[(]]..tostring(t)..[[) { [1] = '{ } ' }]]) end) it("Checks to see if TableFormatLevel parameter limits table formatting depth", function() - assert.is.same(assert:format({ { { { { 1 } } } }, ["n"] = 1 })[1], [[(table) { + local t = { { { { 1 } } } } + assert.is.same(assert:format({ t, ["n"] = 1 })[1], [[(]]..tostring(t)..[[) { [1] = { [1] = { [1] = { ... more } } } }]]) - assert.is.same(assert:format({ { { { } } }, ["n"] = 1 })[1], [[(table) { + t = { { { } } } + assert.is.same(assert:format({ t, ["n"] = 1 })[1], [[(]]..tostring(t)..[[) { [1] = { [1] = { } } }]]) assert:set_parameter("TableFormatLevel", 0) - assert.is.same(assert:format({ { }, ["n"] = 1 })[1], "(table) { }") - assert.is.same(assert:format({ { 1 }, ["n"] = 1 })[1], "(table) { ... more }") + t = { } + assert.is.same(assert:format({ t, ["n"] = 1 })[1], "("..tostring(t)..") { }") + t = { 1 } + assert.is.same(assert:format({ t, ["n"] = 1 })[1], "("..tostring(t)..") { ... more }") end) it("Checks to see if TableFormatLevel parameter can display all levels", function() assert:set_parameter("TableFormatLevel", -1) - assert.is.same(assert:format({ { { { { 1 } } } }, ["n"] = 1 })[1], [[(table) { + local t = { { { { 1 } } } } + assert.is.same(assert:format({ t, ["n"] = 1 })[1], [[(]]..tostring(t)..[[) { [1] = { [1] = { [1] = { @@ -80,7 +89,7 @@ describe("Test Formatters", function() local t = {{1,2},{3,4}} local fmtargs = { {crumbs = {1,2}} } local formatted = assert:format({t, n = 1, fmtargs = fmtargs})[1] - local expected = "(table) {\n [1] = {\n [1] = 1\n [2] = 2 }\n *[2] = {\n *[1] = 3\n [2] = 4 } }" + local expected = "("..tostring(t)..") {\n [1] = {\n [1] = 1\n [2] = 2 }\n *[2] = {\n *[1] = 3\n [2] = 4 } }" assert.is.equal(expected, formatted) end) @@ -89,7 +98,7 @@ describe("Test Formatters", function() local t = {1,2,3} local fmtargs = { {crumbs = {2}} } local formatted = assert:format({t, n = 1, fmtargs = fmtargs})[1] - local expected = "(table) {\n [1] = 1\n**[2] = 2\n [3] = 3 }" + local expected = "("..tostring(t)..") {\n [1] = 1\n**[2] = 2\n [3] = 3 }" assert.is.equal(expected, formatted) end) @@ -101,7 +110,7 @@ describe("Test Formatters", function() local t = {1,2,3} local fmtargs = { {crumbs = {2}} } local formatted = assert:format({t, n = 1, fmtargs = fmtargs})[1] - local expected = string.format("(table) {\n [1] = 1\n %s[2] = 2\n [3] = 3 }", colors.red("*")) + local expected = string.format("("..tostring(t)..") {\n [1] = 1\n %s[2] = 2\n [3] = 3 }", colors.red("*")) assert.is.equal(expected, formatted) end) @@ -110,7 +119,7 @@ describe("Test Formatters", function() t[3] = t assert:set_parameter("TableFormatShowRecursion", true) local formatted = assert:format({t, n = 1})[1] - local expected = "(table) {\n [1] = 1\n [2] = 2\n [3] = { ... recursive } }" + local expected = "("..tostring(t)..") {\n [1] = 1\n [2] = 2\n [3] = { ... recursive } }" assert.is.equal(expected, formatted) end) @@ -137,7 +146,7 @@ describe("Test Formatters", function() assert.is.same(type(formatted[3]), "string") assert.is.same(type(formatted[4]), "nil") end) - + it("checks arguments not being formatted if set to do so", function() local arg1 = "argument1" local arg2 = "argument2" @@ -146,7 +155,7 @@ describe("Test Formatters", function() arguments = assert:format(arguments) assert.is.same(arg1, arguments[1]) end) - + it("checks extra formatters inserted to be called first", function() local expected = "formatted result" local f = function(value) @@ -155,11 +164,11 @@ describe("Test Formatters", function() end end local s = spy.new(f) - + assert:add_formatter(s) assert.are_equal(expected, assert:format({"some string"})[1]) assert.spy(s).was.called(1) assert:remove_formatter(s) end) - + end) diff --git a/spec/output_spec.lua b/spec/output_spec.lua index 7313176..57a72a5 100644 --- a/spec/output_spec.lua +++ b/spec/output_spec.lua @@ -72,8 +72,9 @@ describe("Output testing using string comparison with the has_error assertion", it("Should compare error strings correctly; table-string", function() --assert.has_error(function() error({}) end, "string") - local output = getoutput(function() error({}) end, "string") - local ok = output:find("Caught:\n%(table%) { }") + local t = {} + local output = getoutput(function() error(t) end, "string") + local ok = output:find("Caught:\n%("..tostring(t).."%) { }") assert(ok, "Output check 1 failed, comparing table-string;\n " .. output:gsub("\n","\n ")) local ok = output:find("Expected:\n%(string%) 'string'") assert(ok, "Output check 2 failed, comparing table-string;\n " .. output:gsub("\n","\n ")) @@ -81,19 +82,22 @@ describe("Output testing using string comparison with the has_error assertion", it("Should compare error strings correctly; string-table", function() --assert.has_error(function() error("string") end, {}) - local output = getoutput(function() error("string") end, {}) + local t = {} + local output = getoutput(function() error("string") end, t) local ok = output:find("Caught:\n%(string%) 'string'") assert(ok, "Output check 1 failed, comparing string-table;\n " .. output:gsub("\n","\n ")) - local ok = output:find("Expected:\n%(table%) { }") + local ok = output:find("Expected:\n%("..tostring(t).."%) { }") assert(ok, "Output check 2 failed, comparing string-table;\n " .. output:gsub("\n","\n ")) end) it("Should compare error objects correctly; table-table", function() --assert.has_error(function() error({}) end, { "table" }) - local output = getoutput(function() error({}) end, { "table" }) - local ok = output:find("Caught:\n%(table%) { }") + local t = {} + local t2 = { "table" } + local output = getoutput(function() error(t) end, t2) + local ok = output:find("Caught:\n%("..tostring(t).."%) { }") assert(ok, "Output check 1 failed, comparing table-table;\n " .. output:gsub("\n","\n ")) - local ok = output:find("Expected:\n%(table%) {\n %[1] = 'table' }") + local ok = output:find("Expected:\n%("..tostring(t2).."%) {\n %[1] = 'table' }") assert(ok, "Output check 2 failed, comparing table-table;\n " .. output:gsub("\n","\n ")) end) @@ -108,10 +112,11 @@ describe("Output testing using string comparison with the same assertion", funct it("Should compare tables correctly", function() -- assert.are.same({1}, {2}) - local output = getoutput({1}, {2}) - local ok = output:find("Passed in:\n(table) {\n *[1] = 2 }", nil, true) + local t1, t2 = {1}, {2} + local output = getoutput(t1, t2) + local ok = output:find("Passed in:\n("..tostring(t2)..") {\n *[1] = 2 }", nil, true) assert(ok, "Output check 1 failed, comparing table-table;\n " .. output:gsub("\n","\n ")) - local ok = output:find("Expected:\n(table) {\n *[1] = 1 }", nil, true) + local ok = output:find("Expected:\n("..tostring(t1)..") {\n *[1] = 1 }", nil, true) assert(ok, "Output check 2 failed, comparing table-table;\n " .. output:gsub("\n","\n ")) end) @@ -301,18 +306,19 @@ describe("Output testing using custom failure message", function() end) it("Should convert objects to string", function() - local t = setmetatable({},{__tostring=function(t) return "empty table" end}) - assert.is_equal("(table) { }", geterror("is_true", false, {})) + local t = {} + local t_tostring = setmetatable({},{__tostring=function(t) return "empty table" end}) + assert.is_equal("("..tostring(t)..") { }", geterror("is_true", false, t)) assert.is_equal("(number) 999", geterror("is_true", false, 999)) assert.is_equal("(boolean) true", geterror("is_true", false, true)) assert.is_equal("(boolean) false", geterror("is_true", false, false)) - assert.is_equal("empty table", geterror("is_true", false, t)) + assert.is_equal("empty table", geterror("is_true", false, t_tostring)) - assert.is_equal("(table) { }", geterror2("is_true", false, {})) + assert.is_equal("("..tostring(t)..") { }", geterror2("is_true", false, t)) assert.is_equal("(number) 999", geterror2("is_true", false, 999)) assert.is_equal("(boolean) true", geterror2("is_true", false, true)) assert.is_equal("(boolean) false", geterror2("is_true", false, false)) - assert.is_equal("empty table", geterror2("is_true", false, t)) + assert.is_equal("empty table", geterror2("is_true", false, t_tostring)) end) end) @@ -422,18 +428,19 @@ for _,ss in ipairs({"spy", "stub"}) do end) it("Should convert objects to string", function() - local t = setmetatable({},{__tostring=function(t) return "empty table" end}) - assert.is_equal("(table) { }", geterror("was_called", {}, {})) + local t = {} + local t_tostring = setmetatable({},{__tostring=function(t) return "empty table" end}) + assert.is_equal("("..tostring(t)..") { }", geterror("was_called", {}, t)) assert.is_equal("(number) 999", geterror("was_called", {}, 999)) assert.is_equal("(boolean) true", geterror("was_called", {}, true)) assert.is_equal("(boolean) false", geterror("was_called", {}, false)) - assert.is_equal("empty table", geterror("was_called", {}, t)) + assert.is_equal("empty table", geterror("was_called", {}, t_tostring)) - assert.is_equal("(table) { }", geterror2("was_called", {}, {})) + assert.is_equal("("..tostring(t)..") { }", geterror2("was_called", {}, t)) assert.is_equal("(number) 999", geterror2("was_called", {}, 999)) assert.is_equal("(boolean) true", geterror2("was_called", {}, true)) assert.is_equal("(boolean) false", geterror2("was_called", {}, false)) - assert.is_equal("empty table", geterror2("was_called", {}, t)) + assert.is_equal("empty table", geterror2("was_called", {}, t_tostring)) end) end) diff --git a/src/formatters/init.lua b/src/formatters/init.lua index ff69354..a92ad29 100644 --- a/src/formatters/init.lua +++ b/src/formatters/init.lua @@ -123,6 +123,20 @@ local function fmt_table(arg, fmtargs) local errcolor = assert:get_parameter("TableErrorHighlightColor") or "none" local crumbs = fmtargs and fmtargs.crumbs or {} local cache = {} + local type_desc + + if getmetatable(arg) == nil then + type_desc = "(" .. tostring(arg) .. ") " + elseif not pcall(setmetatable, arg, getmetatable(arg)) then + -- cannot set same metatable, so it is protected, skip id + type_desc = "(table) " + else + -- unprotected metatable, temporary remove the mt + local mt = getmetatable(arg) + setmetatable(arg, nil) + type_desc = "(" .. tostring(arg) .. ") " + setmetatable(arg, mt) + end local function ft(t, l, with_crumbs) if showrec and cache[t] and cache[t] > 0 then @@ -165,7 +179,7 @@ local function fmt_table(arg, fmtargs) return result .. " }" end - return "(table) " .. ft(arg, 1, true) + return type_desc .. ft(arg, 1, true) end local function fmt_function(arg)