From a4115910336a2bc1f102a6942ce90304d92452ab Mon Sep 17 00:00:00 2001 From: Mikhail Galanin Date: Thu, 20 Sep 2018 16:36:35 +0100 Subject: [PATCH] [Test] Nicely print table difference when they do not match --- test/lua/rspamd_assertions.lua | 107 ++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/test/lua/rspamd_assertions.lua b/test/lua/rspamd_assertions.lua index 0f2eb3626..cebd13c54 100644 --- a/test/lua/rspamd_assertions.lua +++ b/test/lua/rspamd_assertions.lua @@ -17,5 +17,110 @@ local function rspamd_assert_table_equals(tbl) return util.table_cmp(tbl.expect, tbl.actual) end +local function table_keys_sorted(t) + local keys = {} + + for k,_ in pairs(t) do + table.insert(keys, k) + end + table.sort(keys) + return keys; +end + +local function format_line(level, key, v_expect, v_actual) + local prefix + if v_expect == v_actual then + prefix = string.rep(' ', level * 2 + 1) + return string.format("%s[%s] = %s", prefix, tostring(key), tostring(v_expect)) + else + prefix = string.rep(' ', level * 2) + local ret = {} + if v_expect then + ret[#ret + 1] = string.format("-%s[%s] = %s: %s", prefix, tostring(key), type(v_expect), tostring(v_expect)) + end + if v_actual then + ret[#ret + 1] = string.format("+%s[%s] = %s: %s", prefix, tostring(key), type(v_actual), tostring(v_actual)) + end + return table.concat(ret, "\n") + end +end + +local function format_table_begin(level, key) + local prefix = string.rep(' ', level * 2 + 1) + return string.format("%s[%s] = {", prefix, tostring(key)) +end + +local function format_table_end(level) + local prefix = string.rep(' ', level * 2 + 1) + return string.format("%s}", prefix) +end + +local function rspamd_assert_table_diff_msg(_, tbl) + local avoid_loops = {} + local msg = rspamd_assert_equals_msg(_, tbl) + + local diff = {} + local function recurse(expect, actual, level) + if avoid_loops[actual] then + return + end + avoid_loops[actual] = true + + local keys_expect = table_keys_sorted(expect) + local keys_actual = table_keys_sorted(actual) + + local i_k_expect, i_v_expect = next(keys_expect) + local i_k_actual, i_v_actual = next(keys_actual) + + while i_k_expect and i_k_actual do + local v_expect = expect[i_v_expect] + local v_actual = actual[i_v_actual] + + if i_v_expect == i_v_actual then + if type(v_expect) == 'table' and type(v_actual) == 'table' then + if util.table_cmp(v_expect, v_actual) then + -- we use the same value for 'actual' and 'expect' as soon as they're equal and don't bother us + diff[#diff + 1] = format_line(level, i_v_expect, v_expect, v_expect) + else + diff[#diff + 1] = format_table_begin(level, i_v_expect) + recurse(v_expect, v_actual, level + 1) + diff[#diff + 1] = format_table_end(level) + end + elseif v_expect ~= v_actual then + diff[#diff + 1] = format_line(level, i_v_expect, v_expect, v_actual) + else + diff[#diff + 1] = format_line(level, i_v_expect, v_expect, v_actual) + end + + i_k_expect, i_v_expect = next(keys_expect, i_k_expect) + i_k_actual, i_v_actual = next(keys_actual, i_k_actual) + elseif tostring(v_actual) > tostring(i_v_actual) then + diff[#diff + 1] = format_line(level, i_v_expect, v_expect, nil) + i_k_expect, i_v_expect = next(keys_expect, i_k_expect) + else + diff[#diff + 1] = format_line(level, i_v_actual, nil, v_actual) + i_k_actual, i_v_actual = next(keys_actual, i_k_actual) + end + + end + + while i_k_expect do + local v_expect = expect[i_v_expect] + diff[#diff + 1] = format_line(level, i_v_expect, v_expect, nil) + i_k_expect, i_v_expect = next(keys_expect, i_k_expect) + end + + while i_k_actual do + local v_actual = actual[i_v_actual] + diff[#diff + 1] = format_line(level, i_v_actual, nil, v_actual) + i_k_actual, i_v_actual = next(keys_actual, i_k_actual) + end + end + recurse(tbl.expect, tbl.actual, 0) + + return string.format("%s\n===== diff (-expect, +actual) ======\n%s", msg, table.concat(diff, "\n")) +end + telescope.make_assertion("rspamd_eq", rspamd_assert_equals_msg, rspamd_assert_equals) -telescope.make_assertion("rspamd_table_eq", rspamd_assert_equals_msg, rspamd_assert_table_equals) +-- telescope.make_assertion("rspamd_table_eq", rspamd_assert_equals_msg, rspamd_assert_table_equals) +telescope.make_assertion("rspamd_table_eq", rspamd_assert_table_diff_msg, rspamd_assert_table_equals) -- 2.39.5