Home | History | Annotate | Line # | Download | only in unit-tests
check-expect.lua revision 1.1
      1  1.1  rillig #!  /usr/bin/lua
      2  1.1  rillig -- $NetBSD: check-expect.lua,v 1.1 2022/01/15 12:35:18 rillig Exp $
      3  1.1  rillig 
      4  1.1  rillig --[[
      5  1.1  rillig 
      6  1.1  rillig usage: lua ./check-expect.lua *.mk
      7  1.1  rillig 
      8  1.1  rillig Check that each text from an '# expect: ...' comment in the .mk source files
      9  1.1  rillig occurs in the corresponding .exp file, in the same order as in the .mk file.
     10  1.1  rillig 
     11  1.1  rillig Check that each text from an '# expect[+-]offset: ...' comment in the .mk
     12  1.1  rillig source files occurs in the corresponding .exp file and refers back to the
     13  1.1  rillig correct line in the .mk file.
     14  1.1  rillig 
     15  1.1  rillig ]]
     16  1.1  rillig 
     17  1.1  rillig 
     18  1.1  rillig local had_errors = false
     19  1.1  rillig ---@param fmt string
     20  1.1  rillig function print_error(fmt, ...)
     21  1.1  rillig   print(fmt:format(...))
     22  1.1  rillig   had_errors = true
     23  1.1  rillig end
     24  1.1  rillig 
     25  1.1  rillig 
     26  1.1  rillig ---@return nil | string[]
     27  1.1  rillig local function load_lines(fname)
     28  1.1  rillig   local lines = {}
     29  1.1  rillig 
     30  1.1  rillig   local f = io.open(fname, "r")
     31  1.1  rillig   if f == nil then return nil end
     32  1.1  rillig 
     33  1.1  rillig   for line in f:lines() do
     34  1.1  rillig     table.insert(lines, line)
     35  1.1  rillig   end
     36  1.1  rillig   f:close()
     37  1.1  rillig 
     38  1.1  rillig   return lines
     39  1.1  rillig end
     40  1.1  rillig 
     41  1.1  rillig 
     42  1.1  rillig ---@param exp_lines string[]
     43  1.1  rillig local function collect_lineno_diagnostics(exp_lines)
     44  1.1  rillig   ---@type table<string, string[]>
     45  1.1  rillig   local by_location = {}
     46  1.1  rillig 
     47  1.1  rillig   for _, line in ipairs(exp_lines) do
     48  1.1  rillig     ---@type string | nil, string, string
     49  1.1  rillig     local l_fname, l_lineno, l_msg =
     50  1.1  rillig       line:match("^make: \"([^\"]+)\" line (%d+): (.*)")
     51  1.1  rillig     if l_fname ~= nil then
     52  1.1  rillig       local location = ("%s:%d"):format(l_fname, l_lineno)
     53  1.1  rillig       if by_location[location] == nil then
     54  1.1  rillig         by_location[location] = {}
     55  1.1  rillig       end
     56  1.1  rillig       table.insert(by_location[location], l_msg)
     57  1.1  rillig     end
     58  1.1  rillig   end
     59  1.1  rillig 
     60  1.1  rillig   return by_location
     61  1.1  rillig end
     62  1.1  rillig 
     63  1.1  rillig 
     64  1.1  rillig local function check_mk(mk_fname)
     65  1.1  rillig   local exp_fname = mk_fname:gsub("%.mk$", ".exp")
     66  1.1  rillig   local mk_lines = load_lines(mk_fname)
     67  1.1  rillig   local exp_lines = load_lines(exp_fname)
     68  1.1  rillig   if exp_lines == nil then return end
     69  1.1  rillig   local by_location = collect_lineno_diagnostics(exp_lines)
     70  1.1  rillig   local prev_expect_line = 0
     71  1.1  rillig 
     72  1.1  rillig   for mk_lineno, mk_line in ipairs(mk_lines) do
     73  1.1  rillig     for text in mk_line:gmatch("#%s*expect:%s*(.*)") do
     74  1.1  rillig       local i = prev_expect_line
     75  1.1  rillig       while i < #exp_lines and text ~= exp_lines[i + 1] do
     76  1.1  rillig         i = i + 1
     77  1.1  rillig       end
     78  1.1  rillig       if i < #exp_lines then
     79  1.1  rillig         prev_expect_line = i + 1
     80  1.1  rillig       else
     81  1.1  rillig         print_error("error: %s:%d: '%s:%d+' must contain '%s'",
     82  1.1  rillig           mk_fname, mk_lineno, exp_fname, prev_expect_line + 1, text)
     83  1.1  rillig       end
     84  1.1  rillig     end
     85  1.1  rillig 
     86  1.1  rillig     ---@param text string
     87  1.1  rillig     for offset, text in mk_line:gmatch("#%s*expect([+%-]%d+):%s*(.*)") do
     88  1.1  rillig       local location = ("%s:%d"):format(mk_fname, mk_lineno + tonumber(offset))
     89  1.1  rillig 
     90  1.1  rillig       local found = false
     91  1.1  rillig       if by_location[location] ~= nil then
     92  1.1  rillig         for i, message in ipairs(by_location[location]) do
     93  1.1  rillig           if message ~= "" and message:find(text, 1, true) then
     94  1.1  rillig             by_location[location][i] = ""
     95  1.1  rillig             found = true
     96  1.1  rillig             break
     97  1.1  rillig           end
     98  1.1  rillig         end
     99  1.1  rillig       end
    100  1.1  rillig 
    101  1.1  rillig       if not found then
    102  1.1  rillig         print_error("error: %s:%d: %s must contain '%s'",
    103  1.1  rillig           mk_fname, mk_lineno, exp_fname, text)
    104  1.1  rillig       end
    105  1.1  rillig     end
    106  1.1  rillig   end
    107  1.1  rillig end
    108  1.1  rillig 
    109  1.1  rillig for _, fname in ipairs(arg) do
    110  1.1  rillig   check_mk(fname)
    111  1.1  rillig end
    112  1.1  rillig os.exit(not had_errors)
    113