From a243a59e4e6f9fa22e8bc96654818659ca664a2b Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Tue, 23 Sep 2025 10:02:55 +0200 Subject: [PATCH] patch-git: Add assert_eq function for internal testing RPM-Changelog: - RPM-Skip-Release: yes Related: RHEL-111490 --- patch-git.lua | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/patch-git.lua b/patch-git.lua index 6223f6d..f5f7637 100644 --- a/patch-git.lua +++ b/patch-git.lua @@ -283,6 +283,137 @@ do end end +-- Testing helper: assert_eq(a, b) asserts if not a == b. +-- A third argument can be provided with a context string. +local assert_eq +do + -- quote(v) returns a string that evaluates to v, mostly in Lua syntax. + local quote + do + local quote_table = { + ['\n'] = '\\n', + ['\r'] = '\\r', + ['\t'] = '\\t', + ['\0'] = '\000', + ['"'] = '\\"', + ['\\'] = '\\\\', + } + local function quote_table_update(i) + local ch = string.char(i) + if quote_table[ch] == nil then + quote_table[ch] = string.format('\\x%02x', i) + end + end + for i=0,31 do + quote_table_update(i) + end + for i=127,255 do + quote_table_update(i) + end + local function quote1(v, seen) + if v == nil then + return 'nil' + elseif v == true then + return 'true' + elseif v == false then + return 'false' + elseif type(v) == 'number' then + return string.format('%q', v) + elseif type(v) == 'string' then + return '"' .. string.gsub(v, '.', quote_table) .. '"' + elseif type(v) == 'table' then + -- Prevent infinite recursion. + local idx = seen[v] + if idx then + return '&' .. idx + end + local seen_count = seen[1] + 1 + seen[1] = seen_count + seen[v] = seen_count + + local count = 0 + for _, _ in pairs(v) do + count = count + 1 + end + local result = {} + if count == #v then + -- Regular table. + for i=1,count do + result[i] = quote1(v[i], seen) + end + else + -- Not a regular table. + for key, value in pairs(v) do + result[#result + 1] = + '[' .. quote1(key, seen) .. ']=' + .. quote1(value, seen) + end + end + return '{' .. table.concat(result, ', ') .. '}' + else + return '#<' .. type(v) .. ':' .. quote(tostring(v)) .. '>' + end + end + function quote(v) + return quote1(v, {0}) + end + end + assert(quote('') == '""') + assert(quote('\n') == '"\\n"') + assert(quote('{}') == '"{}"') + assert(quote({}) == '{}') + assert(quote({1, 2, 3}) == '{1, 2, 3}') + assert(quote({a=1}) == '{["a"]=1}') + + local deep_eq + do + local function deep_eq1(a, b, seen) + if a == b then + return true + elseif type(a) == 'table' and type(b) == 'table' then + assert(not seen[a]) + assert(not seen[b]) + seen[a] = true + seen[b] = true + local acount = 0 + for ak, av in pairs(a) do + if not deep_eq1(av, b[ak], seen) then + return false + end + acount = acount + 1 + end + local bcount = 0 + for bk, bv in pairs(b) do + bcount = bcount + 1 + end + return acount == bcount + else + return false + end + end + function deep_eq(a, b) + if a == b then + return true + elseif type(a) == 'table' and type(b) == 'table' then + return deep_eq1(a, b, {}) + end + end + end + + function assert_eq(a, b, ctx) + if deep_eq(a, b) then + return + end + local prefix + if ctx then + prefix = ctx .. ': ' + else + prefix = '' + end + assert(a == b, prefix .. quote(a) .. ' ~= ' .. quote(b)) + end +end + -- Sort the list lexicographically, in place, treating sequences of -- digits as a single positive decimal number. local function version_sort(list)