diff options
| author | rillig <rillig@NetBSD.org> | 2020-12-31 03:05:12 +0000 |
|---|---|---|
| committer | rillig <rillig@NetBSD.org> | 2020-12-31 03:05:12 +0000 |
| commit | 9554f7288ea5fa7ff5d435a0806773c9970c5bce (patch) | |
| tree | 865e6824ad387041333c55f47257b378a0e8a1d6 /usr.bin/make/unit-tests | |
| parent | e2f6c5aab1697c0a074afe42c12c1ccdf79428cf (diff) | |
make(1): add test for error handling and expansion in .for loops
Diffstat (limited to 'usr.bin/make/unit-tests')
| -rw-r--r-- | usr.bin/make/unit-tests/Makefile | 4 | ||||
| -rw-r--r-- | usr.bin/make/unit-tests/directive-for-errors.exp | 22 | ||||
| -rw-r--r-- | usr.bin/make/unit-tests/directive-for-errors.mk | 75 | ||||
| -rw-r--r-- | usr.bin/make/unit-tests/directive-for-escape.exp | 44 | ||||
| -rw-r--r-- | usr.bin/make/unit-tests/directive-for-escape.mk | 61 |
5 files changed, 205 insertions, 1 deletions
diff --git a/usr.bin/make/unit-tests/Makefile b/usr.bin/make/unit-tests/Makefile index 0dc0f051ced..6d1ed0faab4 100644 --- a/usr.bin/make/unit-tests/Makefile +++ b/usr.bin/make/unit-tests/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.259 2020/12/30 14:50:08 rillig Exp $ +# $NetBSD: Makefile,v 1.260 2020/12/31 03:05:12 rillig Exp $ # # Unit tests for make(1) # @@ -162,6 +162,8 @@ TESTS+= directive-export-impl TESTS+= directive-export-gmake TESTS+= directive-export-literal TESTS+= directive-for +TESTS+= directive-for-errors +TESTS+= directive-for-escape TESTS+= directive-for-generating-endif TESTS+= directive-for-lines TESTS+= directive-for-null diff --git a/usr.bin/make/unit-tests/directive-for-errors.exp b/usr.bin/make/unit-tests/directive-for-errors.exp new file mode 100644 index 00000000000..6088a93c9a4 --- /dev/null +++ b/usr.bin/make/unit-tests/directive-for-errors.exp @@ -0,0 +1,22 @@ +make: "directive-for-errors.mk" line 7: Unknown directive "fori" +make: "directive-for-errors.mk" line 8: warning: +make: "directive-for-errors.mk" line 9: for-less endfor +make: "directive-for-errors.mk" line 19: Unknown directive "for" +make: "directive-for-errors.mk" line 20: warning: +make: "directive-for-errors.mk" line 21: for-less endfor +make: "directive-for-errors.mk" line 37: Dollar $ 1 1 and backslash 2 2 2. +make: "directive-for-errors.mk" line 37: Dollar $ 3 3 and backslash 4 4 4. +make: "directive-for-errors.mk" line 43: no iteration variables in for +make: "directive-for-errors.mk" line 47: warning: Should not be reached. +make: "directive-for-errors.mk" line 48: for-less endfor +make: "directive-for-errors.mk" line 53: Wrong number of words (5) in .for substitution list with 3 variables +make: "directive-for-errors.mk" line 64: missing `in' in for +make: "directive-for-errors.mk" line 66: warning: Should not be reached. +make: "directive-for-errors.mk" line 67: for-less endfor +make: "directive-for-errors.mk" line 73: Unknown modifier 'Z' +make: "directive-for-errors.mk" line 74: warning: Should not be reached. +make: "directive-for-errors.mk" line 74: warning: Should not be reached. +make: "directive-for-errors.mk" line 74: warning: Should not be reached. +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/usr.bin/make/unit-tests/directive-for-errors.mk b/usr.bin/make/unit-tests/directive-for-errors.mk new file mode 100644 index 00000000000..7890e2375af --- /dev/null +++ b/usr.bin/make/unit-tests/directive-for-errors.mk @@ -0,0 +1,75 @@ +# $NetBSD: directive-for-errors.mk,v 1.1 2020/12/31 03:05:12 rillig Exp $ +# +# Tests for error handling in .for loops. + +# A .for directive must be followed by whitespace, everything else results +# in a parse error. +.fori in 1 2 3 +. warning ${i} +.endfor + +# A slash is not whitespace, therefore this is not parsed as a .for loop. +# +# XXX: The error message is misleading though. As of 2020-12-31, it says +# "Unknown directive "for"", but that directive is actually known. This is +# because ForEval does not detect the .for loop as such, so parsing +# continues in ParseLine > ParseDependency > ParseDoDependency > +# ParseDoDependencyTargets > ParseErrorNoDependency, and there the directive +# name is parsed a bit differently. +.for/i in 1 2 3 +. warning ${i} +.endfor + +# As of 2020-12-31, the variable name can be an arbitrary word, it just needs +# to be separated by whitespace. Even '$' and '\' are valid variable names, +# which is not useful in practice. +# +# The '$$' is not replaced with the values '1' or '3' from the .for loop, +# instead it is kept as-is, and when the .info directive expands its argument, +# each '$$' gets replaced with a single '$'. The "long variable expression" +# ${$} gets replaced though, even though this would be a parse error everywhere +# outside a .for loop. +# +# The '\' on the other hand is treated as a normal variable name. +${:U\$}= dollar # see whether the "variable" '$' is local +${:U\\}= backslash # see whether the "variable" '\' is local +.for $ \ in 1 2 3 4 +. info Dollar $$ ${$} $($) and backslash $\ ${\} $(\). +.endfor + +# If there are no variables, there is no point in expanding the .for loop +# since this would end up in an endless loop, each time consuming 0 of the +# 3 values. +.for in 1 2 3 +# XXX: This should not be reached. It should be skipped, as already done +# when the number of values is not a multiple of the number of variables, +# see below. +. warning Should not be reached. +.endfor + +# There are 3 variables and 5 values. These 5 values cannot be split evenly +# among the variables, therefore the loop is not expanded at all, it is +# rather skipped. +.for a b c in 1 2 3 4 5 +. warning Should not be reached. +.endfor + +# The list of values after the 'in' may be empty, no matter if this emptiness +# comes from an empty expansion or even from a syntactically empty line. +.for i in +. info Would be reached if there were items to loop over. +.endfor + +# A missing 'in' should parse the .for loop but skip the body. +.for i : k +# XXX: As of 2020-12-31, this line is reached once. +. warning Should not be reached. +.endfor + +# A malformed modifier should be detected and skip the body of the loop. +# +# XXX: As of 2020-12-31, Var_Subst doesn't report any errors, therefore +# the loop body is expanded as if no error had happened. +.for i in 1 2 ${:U3:Z} 4 +. warning Should not be reached. +.endfor diff --git a/usr.bin/make/unit-tests/directive-for-escape.exp b/usr.bin/make/unit-tests/directive-for-escape.exp new file mode 100644 index 00000000000..8fa2a4be4d3 --- /dev/null +++ b/usr.bin/make/unit-tests/directive-for-escape.exp @@ -0,0 +1,44 @@ +For: end for 1 +For: loop body: +. info ${:U!"#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~} +make: Unclosed variable specification (expecting '}') for "" (value "!"") modifier U +make: "directive-for-escape.mk" line 19: !" +For: end for 1 +For: loop body: +. info ${:U!"\\\\#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~} +make: Unclosed variable specification (expecting '}') for "" (value "!"\\") modifier U +make: "directive-for-escape.mk" line 29: !"\\ +For: end for 1 +For: loop body: +. info ${:U\$} +make: "directive-for-escape.mk" line 41: $ +For: loop body: +. info ${:U${V}} +make: "directive-for-escape.mk" line 41: value +For: loop body: +. info ${:U${V:=-with-modifier}} +make: "directive-for-escape.mk" line 41: value-with-modifier +For: loop body: +. info ${:U$(V)} +make: "directive-for-escape.mk" line 41: value +For: loop body: +. info ${:U$(V:=-with-modifier)} +make: "directive-for-escape.mk" line 41: value-with-modifier +For: end for 1 +For: loop body: +. info ${:U\${UNDEF\:U\\$\\$} +make: "directive-for-escape.mk" line 52: ${UNDEF:U\$ +For: loop body: +. info ${:U{{\}\}} +make: "directive-for-escape.mk" line 52: {{}} +For: loop body: +. info ${:Uend\}} +make: "directive-for-escape.mk" line 52: end} +For: end for 1 +For: loop body: +. info ${:U\$} +make: "directive-for-escape.mk" line 60: $ +make: no target to make. + +make: stopped in unit-tests +exit status 2 diff --git a/usr.bin/make/unit-tests/directive-for-escape.mk b/usr.bin/make/unit-tests/directive-for-escape.mk new file mode 100644 index 00000000000..6af049d595c --- /dev/null +++ b/usr.bin/make/unit-tests/directive-for-escape.mk @@ -0,0 +1,61 @@ +# $NetBSD: directive-for-escape.mk,v 1.1 2020/12/31 03:05:12 rillig Exp $ +# +# Test escaping of special characters in the iteration values of a .for loop. +# These values get expanded later using the :U variable modifier, and this +# escaping and unescaping must pass all characters and strings effectively +# unmodified. + +.MAKEFLAGS: -df + +# Even though the .for loops takes quotes into account when splitting the +# string into words, the quotes don't need to be balances, as of 2020-12-31. +# This could be considered a bug. +ASCII= !"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~ + +# XXX: As of 2020-12-31, the '#' is not preserved in the expanded body of +# the loop since it would not need only the escaping for the :U variable +# modifier but also the escaping for the line-end comment. +.for chars in ${ASCII} +. info ${chars} +.endfor + +# As of 2020-12-31, using 2 backslashes before be '#' would treat the '#' +# as comment character. Using 3 backslashes doesn't help either since +# then the situation is essentially the same as with 1 backslash. +# This means that a '#' sign cannot be passed in the value of a .for loop +# at all. +ASCII.2020-12-31= !"\\\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~ +.for chars in ${ASCII.2020-12-31} +. info ${chars} +.endfor + +# Cover the code in for_var_len. +# +# XXX: It is unexpected that the variable V gets expanded in the loop body. +# The double '$$' should prevent exactly this. Probably nobody was +# adventurous enough to use literal dollar signs in the values for a .for +# loop. +V= value +VALUES= $$ $${V} $${V:=-with-modifier} $$(V) $$(V:=-with-modifier) +.for i in ${VALUES} +. info $i +.endfor + +# Cover the code for nested '{}' in for_var_len. +# +# The value of VALUES is not a variable expression. Instead, it is meant to +# represent dollar, lbrace, "UNDEF:U", backslash, dollar, backslash, dollar, +# space, nested braces, space, "end}". +VALUES= $${UNDEF:U\$$\$$ {{}} end} +# XXX: Where does the '\$$\$$' get converted into a single '\$'? +.for i in ${VALUES} +. info $i +.endfor + +# A single trailing dollar doesn't happen in practice. +# The dollar sign is correctly passed through to the body of the .for loop. +# There, it is expanded by the .info directive, but even there a trailing +# dollar sign is kept as-is. +.for i in ${:U\$} +. info ${i} +.endfor |
