Module Name:    src
Committed By:   rillig
Date:           Sat Jan 15 12:35:18 UTC 2022

Modified Files:
        src/usr.bin/make/unit-tests: directive-for.mk directive-include.mk
            varmod-indirect.mk varmod-order.mk varname-dot-suffixes.mk
Added Files:
        src/usr.bin/make/unit-tests: check-expect.lua

Log Message:
tests/make: ensure that the 'expect' comments in tests are correct

Based on tests/usr.bin/xlint/check-expect.lua.

For now, this extra check needs to be run manually.


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/usr.bin/make/unit-tests/check-expect.lua
cvs rdiff -u -r1.12 -r1.13 src/usr.bin/make/unit-tests/directive-for.mk
cvs rdiff -u -r1.10 -r1.11 src/usr.bin/make/unit-tests/directive-include.mk \
    src/usr.bin/make/unit-tests/varmod-indirect.mk
cvs rdiff -u -r1.7 -r1.8 src/usr.bin/make/unit-tests/varmod-order.mk
cvs rdiff -u -r1.1 -r1.2 src/usr.bin/make/unit-tests/varname-dot-suffixes.mk

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/unit-tests/directive-for.mk
diff -u src/usr.bin/make/unit-tests/directive-for.mk:1.12 src/usr.bin/make/unit-tests/directive-for.mk:1.13
--- src/usr.bin/make/unit-tests/directive-for.mk:1.12	Sat Jan  8 10:22:03 2022
+++ src/usr.bin/make/unit-tests/directive-for.mk	Sat Jan 15 12:35:18 2022
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for.mk,v 1.12 2022/01/08 10:22:03 rillig Exp $
+# $NetBSD: directive-for.mk,v 1.13 2022/01/15 12:35:18 rillig Exp $
 #
 # Tests for the .for directive.
 #
@@ -157,10 +157,10 @@ var=	outer
 
 
 # An empty list of variables to the left of the 'in' is a parse error.
-.for in value			# expect: no iteration variables in for
+.for in value			# expect+0: no iteration variables in for
 # XXX: The loop body is evaluated once, even with the parse error above.
-.  error			# expect: Missing argument for ".error"
-.endfor				# expect: for-less endfor
+.  error			# expect+0: Missing argument for ".error"
+.endfor				# expect+0: for-less endfor
 
 # An empty list of iteration values to the right of the 'in' is accepted.
 # Unlike in the shell, it is not a parse error.
@@ -184,7 +184,7 @@ var=	outer
 # is processed.
 .for var in value
 .  if 0
-.endfor				# expect: 1 open conditional
+.endfor				# expect+0: 1 open conditional
 
 # If there are no iteration values, the loop body is not processed, and the
 # check for mismatched conditionals is not performed.
@@ -200,8 +200,8 @@ var=	outer
 .if 0
 .  for var in value		# does not need a corresponding .endfor
 .endif
-.endfor				# expect: for-less endfor
-.endif				# expect: if-less endif
+.endfor				# expect+0: for-less endfor
+.endif				# expect+0: if-less endif
 
 
 # When a .for without the corresponding .endfor occurs in an active branch of
@@ -209,7 +209,7 @@ var=	outer
 # without looking at any other directives.
 .if 1
 .  for var in value
-.    endif			# expect: if-less endif
+.    endif			# expect+0: if-less endif
 .  endfor			# no 'for-less endfor'
 .endif				# no 'if-less endif'
 

Index: src/usr.bin/make/unit-tests/directive-include.mk
diff -u src/usr.bin/make/unit-tests/directive-include.mk:1.10 src/usr.bin/make/unit-tests/directive-include.mk:1.11
--- src/usr.bin/make/unit-tests/directive-include.mk:1.10	Fri Jan  7 08:20:00 2022
+++ src/usr.bin/make/unit-tests/directive-include.mk	Sat Jan 15 12:35:18 2022
@@ -1,4 +1,4 @@
-# $NetBSD: directive-include.mk,v 1.10 2022/01/07 08:20:00 rillig Exp $
+# $NetBSD: directive-include.mk,v 1.11 2022/01/15 12:35:18 rillig Exp $
 #
 # Tests for the .include directive, which includes another file.
 
@@ -62,7 +62,7 @@ include /dev/null /dev/null
 include
 
 # XXX: trailing whitespace in diagnostic, missing quotes around filename
-### expect+1: Could not find
+### TODO: expect+1: Could not find
 # The following include directive behaves differently, depending on whether
 # the current file has a slash or is a relative filename.  In the first case,
 # make opens the directory of the current file and tries to read from it,
Index: src/usr.bin/make/unit-tests/varmod-indirect.mk
diff -u src/usr.bin/make/unit-tests/varmod-indirect.mk:1.10 src/usr.bin/make/unit-tests/varmod-indirect.mk:1.11
--- src/usr.bin/make/unit-tests/varmod-indirect.mk:1.10	Sat Jan  8 20:21:34 2022
+++ src/usr.bin/make/unit-tests/varmod-indirect.mk	Sat Jan 15 12:35:18 2022
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-indirect.mk,v 1.10 2022/01/08 20:21:34 rillig Exp $
+# $NetBSD: varmod-indirect.mk,v 1.11 2022/01/15 12:35:18 rillig Exp $
 #
 # Tests for indirect variable modifiers, such as in ${VAR:${M_modifiers}}.
 # These can be used for very basic purposes like converting a string to either
@@ -15,7 +15,7 @@
 # The following expression generates a parse error since its indirect
 # modifier contains more than a sole variable expression.
 #
-# expect+1: Unknown modifier '$'
+# expect+1: Unknown modifier "${"
 .if ${value:L:${:US}${:U,value,replacement,}} != "S,value,replacement,}"
 .  warning unexpected
 .endif
@@ -47,7 +47,7 @@
 # error.  Because of this parse error, this feature cannot be used reasonably
 # in practice.
 #
-# expect+2: Unknown modifier '$'
+# expect+2: Unknown modifier "${"
 #.MAKEFLAGS: -dvc
 .if ${value:L:${:UM*}S,value,replaced,} == "M*S,value,replaced,}"
 .  warning	FIXME: this expression should have resulted in a parse $\

Index: src/usr.bin/make/unit-tests/varmod-order.mk
diff -u src/usr.bin/make/unit-tests/varmod-order.mk:1.7 src/usr.bin/make/unit-tests/varmod-order.mk:1.8
--- src/usr.bin/make/unit-tests/varmod-order.mk:1.7	Tue Aug  3 04:46:49 2021
+++ src/usr.bin/make/unit-tests/varmod-order.mk	Sat Jan 15 12:35:18 2022
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-order.mk,v 1.7 2021/08/03 04:46:49 rillig Exp $
+# $NetBSD: varmod-order.mk,v 1.8 2022/01/15 12:35:18 rillig Exp $
 #
 # Tests for the :O variable modifier and its variants, which either sort the
 # words of the value or shuffle them.
@@ -24,7 +24,7 @@ _:=	${NUMBERS:Onr
 # Shuffling numerically doesn't make sense, so don't allow 'x' and 'n' to be
 # combined.
 #
-# expect-text: Bad modifier ":Oxn" for variable "NUMBERS"
+# expect: make: Bad modifier ":Oxn" for variable "NUMBERS"
 # expect+1: Malformed conditional (${NUMBERS:Oxn})
 .if ${NUMBERS:Oxn}
 .  error
@@ -35,7 +35,7 @@ _:=	${NUMBERS:Onr
 # Extra characters after ':On' are detected and diagnosed.
 # TODO: Add line number information to the "Bad modifier" diagnostic.
 #
-# expect-text: Bad modifier ":On_typo" for variable "NUMBERS"
+# expect: make: Bad modifier ":On_typo" for variable "NUMBERS"
 .if ${NUMBERS:On_typo}
 .  error
 .else
@@ -44,7 +44,7 @@ _:=	${NUMBERS:Onr
 
 # Extra characters after ':Onr' are detected and diagnosed.
 #
-# expect-text: Bad modifier ":Onr_typo" for variable "NUMBERS"
+# expect: make: Bad modifier ":Onr_typo" for variable "NUMBERS"
 .if ${NUMBERS:Onr_typo}
 .  error
 .else
@@ -53,7 +53,7 @@ _:=	${NUMBERS:Onr
 
 # Extra characters after ':Orn' are detected and diagnosed.
 #
-# expect+1: Bad modifier ":Orn_typo" for variable "NUMBERS"
+# expect: make: Bad modifier ":Orn_typo" for variable "NUMBERS"
 .if ${NUMBERS:Orn_typo}
 .  error
 .else
@@ -64,7 +64,7 @@ _:=	${NUMBERS:Onr
 # criteria are fixed, not computed, therefore allowing this redundancy does
 # not make sense.
 #
-# expect-text: Bad modifier ":Onn" for variable "NUMBERS"
+# expect: make: Bad modifier ":Onn" for variable "NUMBERS"
 .if ${NUMBERS:Onn}
 .  error
 .else
@@ -73,7 +73,7 @@ _:=	${NUMBERS:Onr
 
 # Repeating the 'r' is not supported as well, for the same reasons as above.
 #
-# expect-text: Bad modifier ":Onrr" for variable "NUMBERS"
+# expect: make: Bad modifier ":Onrr" for variable "NUMBERS"
 .if ${NUMBERS:Onrr}
 .  error
 .else
@@ -82,7 +82,7 @@ _:=	${NUMBERS:Onr
 
 # Repeating the 'r' is not supported as well, for the same reasons as above.
 #
-# expect-text: Bad modifier ":Orrn" for variable "NUMBERS"
+# expect: make: Bad modifier ":Orrn" for variable "NUMBERS"
 .if ${NUMBERS:Orrn}
 .  error
 .else

Index: src/usr.bin/make/unit-tests/varname-dot-suffixes.mk
diff -u src/usr.bin/make/unit-tests/varname-dot-suffixes.mk:1.1 src/usr.bin/make/unit-tests/varname-dot-suffixes.mk:1.2
--- src/usr.bin/make/unit-tests/varname-dot-suffixes.mk:1.1	Sun Dec 12 22:16:48 2021
+++ src/usr.bin/make/unit-tests/varname-dot-suffixes.mk	Sat Jan 15 12:35:18 2022
@@ -1,4 +1,4 @@
-# $NetBSD: varname-dot-suffixes.mk,v 1.1 2021/12/12 22:16:48 rillig Exp $
+# $NetBSD: varname-dot-suffixes.mk,v 1.2 2022/01/15 12:35:18 rillig Exp $
 #
 # Tests for the special "variable" .SUFFIXES, which lists the suffixes that
 # have been registered for use in suffix transformation rules.  Suffixes are
@@ -67,7 +67,7 @@
 .SUFFIXES+=	append
 # expect: Global: .SUFFIXES = assign ignored (read-only)
 _:=		${.SUFFIXES::=assign}
-# expect: Command: .SUFFIXES = preserve ignored (read-only)
+# expect: Global: .SUFFIXES = preserve ignored (read-only)
 _:=		${preserve:L:_=.SUFFIXES}
 .MAKEFLAGS: -d0
 
@@ -96,6 +96,8 @@ _:=		${preserve:L:_=.SUFFIXES}
 .MAKEFLAGS: -dv
 # expect: Command: .SUFFIXES = 1 ignored (read-only)
 # expect: Command: .SUFFIXES = 2 ignored (read-only)
+# XXX: Missing space after ':'
+# expect: Command:delete .SUFFIXES (not found)
 .if ${1 2:L:@.SUFFIXES@${.SUFFIXES}@} != ".c .o .1 .err .tar.gz .c .o .1 .err .tar.gz"
 .  error
 .endif

Added files:

Index: src/usr.bin/make/unit-tests/check-expect.lua
diff -u /dev/null src/usr.bin/make/unit-tests/check-expect.lua:1.1
--- /dev/null	Sat Jan 15 12:35:19 2022
+++ src/usr.bin/make/unit-tests/check-expect.lua	Sat Jan 15 12:35:18 2022
@@ -0,0 +1,112 @@
+#!  /usr/bin/lua
+-- $NetBSD: check-expect.lua,v 1.1 2022/01/15 12:35:18 rillig Exp $
+
+--[[
+
+usage: lua ./check-expect.lua *.mk
+
+Check that each text from an '# expect: ...' comment in the .mk source files
+occurs in the corresponding .exp file, in the same order as in the .mk file.
+
+Check that each text from an '# expect[+-]offset: ...' comment in the .mk
+source files occurs in the corresponding .exp file and refers back to the
+correct line in the .mk file.
+
+]]
+
+
+local had_errors = false
+---@param fmt string
+function print_error(fmt, ...)
+  print(fmt:format(...))
+  had_errors = true
+end
+
+
+---@return nil | string[]
+local function load_lines(fname)
+  local lines = {}
+
+  local f = io.open(fname, "r")
+  if f == nil then return nil end
+
+  for line in f:lines() do
+    table.insert(lines, line)
+  end
+  f:close()
+
+  return lines
+end
+
+
+---@param exp_lines string[]
+local function collect_lineno_diagnostics(exp_lines)
+  ---@type table<string, string[]>
+  local by_location = {}
+
+  for _, line in ipairs(exp_lines) do
+    ---@type string | nil, string, string
+    local l_fname, l_lineno, l_msg =
+      line:match("^make: \"([^\"]+)\" line (%d+): (.*)")
+    if l_fname ~= nil then
+      local location = ("%s:%d"):format(l_fname, l_lineno)
+      if by_location[location] == nil then
+        by_location[location] = {}
+      end
+      table.insert(by_location[location], l_msg)
+    end
+  end
+
+  return by_location
+end
+
+
+local function check_mk(mk_fname)
+  local exp_fname = mk_fname:gsub("%.mk$", ".exp")
+  local mk_lines = load_lines(mk_fname)
+  local exp_lines = load_lines(exp_fname)
+  if exp_lines == nil then return end
+  local by_location = collect_lineno_diagnostics(exp_lines)
+  local prev_expect_line = 0
+
+  for mk_lineno, mk_line in ipairs(mk_lines) do
+    for text in mk_line:gmatch("#%s*expect:%s*(.*)") do
+      local i = prev_expect_line
+      while i < #exp_lines and text ~= exp_lines[i + 1] do
+        i = i + 1
+      end
+      if i < #exp_lines then
+        prev_expect_line = i + 1
+      else
+        print_error("error: %s:%d: '%s:%d+' must contain '%s'",
+          mk_fname, mk_lineno, exp_fname, prev_expect_line + 1, text)
+      end
+    end
+
+    ---@param text string
+    for offset, text in mk_line:gmatch("#%s*expect([+%-]%d+):%s*(.*)") do
+      local location = ("%s:%d"):format(mk_fname, mk_lineno + tonumber(offset))
+
+      local found = false
+      if by_location[location] ~= nil then
+        for i, message in ipairs(by_location[location]) do
+          if message ~= "" and message:find(text, 1, true) then
+            by_location[location][i] = ""
+            found = true
+            break
+          end
+        end
+      end
+
+      if not found then
+        print_error("error: %s:%d: %s must contain '%s'",
+          mk_fname, mk_lineno, exp_fname, text)
+      end
+    end
+  end
+end
+
+for _, fname in ipairs(arg) do
+  check_mk(fname)
+end
+os.exit(not had_errors)

Reply via email to