[BACK]Return to shell_test.go CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / pkgsrc / pkgtools / pkglint / files

Annotation of pkgsrc/pkgtools/pkglint/files/shell_test.go, Revision 1.15

1.1       rillig      1: package main
                      2:
                      3: import (
                      4:        check "gopkg.in/check.v1"
1.15    ! rillig      5:        "netbsd.org/pkglint/textproc"
1.1       rillig      6: )
                      7:
1.11      rillig      8: func (s *Suite) Test_splitIntoShellTokens__line_continuation(c *check.C) {
1.9       rillig      9:        words, rest := splitIntoShellTokens(dummyLine, "if true; then \\")
1.1       rillig     10:
                     11:        c.Check(words, check.DeepEquals, []string{"if", "true", ";", "then"})
                     12:        c.Check(rest, equals, "\\")
                     13:
1.9       rillig     14:        c.Check(s.Output(), equals, "WARN: Pkglint parse error in ShTokenizer.ShAtom at \"\\\\\" (quoting=plain)\n")
                     15: }
                     16:
1.11      rillig     17: func (s *Suite) Test_splitIntoShellTokens__dollar_slash(c *check.C) {
1.9       rillig     18:        words, rest := splitIntoShellTokens(dummyLine, "pax -s /.*~$$//g")
1.1       rillig     19:
                     20:        c.Check(words, check.DeepEquals, []string{"pax", "-s", "/.*~$$//g"})
                     21:        c.Check(rest, equals, "")
                     22: }
                     23:
1.11      rillig     24: func (s *Suite) Test_splitIntoShellTokens__dollar_subshell(c *check.C) {
1.9       rillig     25:        words, rest := splitIntoShellTokens(dummyLine, "id=$$(${AWK} '{print}' < ${WRKSRC}/idfile) && echo \"$$id\"")
                     26:
                     27:        c.Check(words, deepEquals, []string{"id=", "$$(", "${AWK}", "'{print}'", "<", "${WRKSRC}/idfile", ")", "&&", "echo", "\"$$id\""})
                     28:        c.Check(rest, equals, "")
                     29: }
                     30:
1.11      rillig     31: func (s *Suite) Test_splitIntoShellTokens__semicolons(c *check.C) {
1.9       rillig     32:        words, rest := splitIntoShellTokens(dummyLine, "word1 word2;;;")
                     33:
                     34:        c.Check(words, deepEquals, []string{"word1", "word2", ";;", ";"})
                     35:        c.Check(rest, equals, "")
                     36: }
                     37:
1.11      rillig     38: func (s *Suite) Test_splitIntoShellTokens__whitespace(c *check.C) {
1.9       rillig     39:        text := "\t${RUN} cd ${WRKSRC}&&(${ECHO} ${PERL5:Q};${ECHO})|${BASH} ./install"
                     40:        words, rest := splitIntoShellTokens(dummyLine, text)
                     41:
                     42:        c.Check(words, deepEquals, []string{
                     43:                "${RUN}",
                     44:                "cd", "${WRKSRC}",
                     45:                "&&", "(", "${ECHO}", "${PERL5:Q}", ";", "${ECHO}", ")",
                     46:                "|", "${BASH}", "./install"})
                     47:        c.Check(rest, equals, "")
                     48: }
                     49:
1.11      rillig     50: func (s *Suite) Test_splitIntoShellTokens__varuse_with_embedded_space_and_other_vars(c *check.C) {
1.9       rillig     51:        varuseWord := "${GCONF_SCHEMAS:@.s.@${INSTALL_DATA} ${WRKSRC}/src/common/dbus/${.s.} ${DESTDIR}${GCONF_SCHEMAS_DIR}/@}"
                     52:        words, rest := splitIntoShellTokens(dummyLine, varuseWord)
                     53:
                     54:        c.Check(words, deepEquals, []string{varuseWord})
                     55:        c.Check(rest, equals, "")
                     56: }
                     57:
1.11      rillig     58: func (s *Suite) Test_splitIntoMkWords__semicolons(c *check.C) {
1.9       rillig     59:        words, rest := splitIntoMkWords(dummyLine, "word1 word2;;;")
                     60:
                     61:        c.Check(words, deepEquals, []string{"word1", "word2;;;"})
                     62:        c.Check(rest, equals, "")
                     63: }
                     64:
1.11      rillig     65: func (s *Suite) Test_splitIntoShellTokens__varuse_with_embedded_space(c *check.C) {
1.9       rillig     66:        words, rest := splitIntoShellTokens(dummyLine, "${VAR:S/ /_/g}")
                     67:
                     68:        c.Check(words, deepEquals, []string{"${VAR:S/ /_/g}"})
                     69:        c.Check(rest, equals, "")
                     70: }
                     71:
1.11      rillig     72: func (s *Suite) Test_splitIntoMkWords__varuse_with_embedded_space(c *check.C) {
1.9       rillig     73:        words, rest := splitIntoMkWords(dummyLine, "${VAR:S/ /_/g}")
                     74:
                     75:        c.Check(words, deepEquals, []string{"${VAR:S/ /_/g}"})
                     76:        c.Check(rest, equals, "")
                     77: }
                     78:
1.11      rillig     79: func (s *Suite) Test_splitIntoShellTokens__redirect(c *check.C) {
1.10      rillig     80:        words, rest := splitIntoShellTokens(dummyLine, "echo 1>output 2>>append 3>|clobber 4>&5 6<input >>append")
                     81:
                     82:        c.Check(words, deepEquals, []string{
                     83:                "echo",
                     84:                "1>", "output",
                     85:                "2>>", "append",
                     86:                "3>|", "clobber",
                     87:                "4>&", "5",
                     88:                "6<", "input",
                     89:                ">>", "append"})
                     90:        c.Check(rest, equals, "")
                     91:
                     92:        words, rest = splitIntoShellTokens(dummyLine, "echo 1> output 2>> append 3>| clobber 4>& 5 6< input >> append")
                     93:
                     94:        c.Check(words, deepEquals, []string{
                     95:                "echo",
                     96:                "1>", "output",
                     97:                "2>>", "append",
                     98:                "3>|", "clobber",
                     99:                "4>&", "5",
                    100:                "6<", "input",
                    101:                ">>", "append"})
                    102:        c.Check(rest, equals, "")
                    103: }
                    104:
1.11      rillig    105: func (s *Suite) Test_ShellLine_CheckShellCommandLine(c *check.C) {
1.13      rillig    106:        s.Init(c)
                    107:        s.UseCommandLine("-Wall")
1.7       rillig    108:        G.Mk = s.NewMkLines("fname",
                    109:                "# dummy")
                    110:        shline := NewShellLine(G.Mk.mklines[0])
1.3       rillig    111:
1.7       rillig    112:        shline.CheckShellCommandLine("@# Comment")
1.3       rillig    113:
                    114:        c.Check(s.Output(), equals, "")
                    115:
1.7       rillig    116:        shline.CheckShellCommandLine("uname=`uname`; echo $$uname; echo")
1.3       rillig    117:
                    118:        c.Check(s.Output(), equals, ""+
                    119:                "WARN: fname:1: Unknown shell command \"uname\".\n"+
                    120:                "WARN: fname:1: Unknown shell command \"echo\".\n"+
1.7       rillig    121:                "WARN: fname:1: Unknown shell command \"echo\".\n")
1.3       rillig    122:
1.9       rillig    123:        s.RegisterTool(&Tool{Name: "echo", Predefined: true})
1.7       rillig    124:        G.Mk = s.NewMkLines("fname",
                    125:                "# dummy")
1.3       rillig    126:        G.globalData.InitVartypes()
                    127:
1.7       rillig    128:        shline.CheckShellCommandLine("echo ${PKGNAME:Q}") // vucQuotPlain
1.3       rillig    129:
                    130:        c.Check(s.Output(), equals, ""+
1.9       rillig    131:                "WARN: fname:1: PKGNAME may not be used in this file; it would be ok in Makefile, Makefile.*, *.mk.\n"+
1.3       rillig    132:                "NOTE: fname:1: The :Q operator isn't necessary for ${PKGNAME} here.\n")
                    133:
1.7       rillig    134:        shline.CheckShellCommandLine("echo \"${CFLAGS:Q}\"") // vucQuotDquot
1.1       rillig    135:
1.3       rillig    136:        c.Check(s.Output(), equals, ""+
                    137:                "WARN: fname:1: Please don't use the :Q operator in double quotes.\n"+
1.9       rillig    138:                "WARN: fname:1: CFLAGS may not be used in this file; it would be ok in Makefile, Makefile.common, options.mk, *.mk.\n"+
1.3       rillig    139:                "WARN: fname:1: Please use ${CFLAGS:M*:Q} instead of ${CFLAGS:Q} and make sure the variable appears outside of any quoting characters.\n")
                    140:
1.7       rillig    141:        shline.CheckShellCommandLine("echo '${COMMENT:Q}'") // vucQuotSquot
1.3       rillig    142:
1.9       rillig    143:        c.Check(s.Output(), equals, ""+
                    144:                "WARN: fname:1: COMMENT may not be used in any file; it is a write-only variable.\n"+
                    145:                "WARN: fname:1: Please move ${COMMENT:Q} outside of any quoting characters.\n")
1.4       rillig    146:
1.10      rillig    147:        shline.CheckShellCommandLine("echo target=$@ exitcode=$$? '$$' \"\\$$\"")
                    148:
                    149:        c.Check(s.Output(), equals, ""+
                    150:                "WARN: fname:1: Please use \"${.TARGET}\" instead of \"$@\".\n"+
                    151:                "WARN: fname:1: The $? shell variable is often not available in \"set -e\" mode.\n")
                    152:
1.7       rillig    153:        shline.CheckShellCommandLine("echo $$@")
1.3       rillig    154:
                    155:        c.Check(s.Output(), equals, "WARN: fname:1: The $@ shell variable should only be used in double quotes.\n")
1.4       rillig    156:
1.9       rillig    157:        shline.CheckShellCommandLine("echo \"$$\"") // As seen by make(1); the shell sees: echo "$"
1.7       rillig    158:
1.9       rillig    159:        c.Check(s.Output(), equals, ""+
                    160:                "WARN: fname:1: Pkglint parse error in ShTokenizer.ShAtom at \"$$\\\"\" (quoting=d)\n"+
1.10      rillig    161:                "WARN: fname:1: Pkglint ShellLine.CheckShellCommand: parse error at [\"]\n")
1.7       rillig    162:
1.10      rillig    163:        shline.CheckShellCommandLine("echo \"\\n\"")
1.7       rillig    164:
                    165:        c.Check(s.Output(), equals, "")
                    166:
                    167:        shline.CheckShellCommandLine("${RUN} for f in *.c; do echo $${f%.c}; done")
                    168:
                    169:        c.Check(s.Output(), equals, "")
                    170:
1.9       rillig    171:        shline.CheckShellCommandLine("${RUN} echo $${variable+set}")
                    172:
                    173:        c.Check(s.Output(), equals, "")
                    174:
1.7       rillig    175:        // Based on mail/thunderbird/Makefile, rev. 1.159
                    176:        shline.CheckShellCommandLine("${RUN} subdir=\"`unzip -c \"$$e\" install.rdf | awk '/re/ { print \"hello\" }'`\"")
1.4       rillig    177:
1.7       rillig    178:        c.Check(s.Output(), equals, ""+
1.10      rillig    179:                "WARN: fname:1: The exitcode of the left-hand-side command of the pipe operator is ignored.\n"+
1.7       rillig    180:                "WARN: fname:1: Unknown shell command \"unzip\".\n"+
                    181:                "WARN: fname:1: Unknown shell command \"awk\".\n")
                    182:
                    183:        // From mail/thunderbird/Makefile, rev. 1.159
                    184:        shline.CheckShellCommandLine("" +
                    185:                "${RUN} for e in ${XPI_FILES}; do " +
                    186:                "  subdir=\"`${UNZIP_CMD} -c \"$$e\" install.rdf | awk '/^    <em:id>/ {sub(\".*<em:id>\",\"\");sub(\"</em:id>.*\",\"\");print;exit;}'`\" && " +
                    187:                "  ${MKDIR} \"${WRKDIR}/extensions/$$subdir\" && " +
                    188:                "  cd \"${WRKDIR}/extensions/$$subdir\" && " +
                    189:                "  ${UNZIP_CMD} -aqo $$e; " +
                    190:                "done")
1.4       rillig    191:
1.7       rillig    192:        c.Check(s.Output(), equals, ""+
                    193:                "WARN: fname:1: XPI_FILES is used but not defined. Spelling mistake?\n"+
1.10      rillig    194:                "WARN: fname:1: The exitcode of the left-hand-side command of the pipe operator is ignored.\n"+
1.7       rillig    195:                "WARN: fname:1: UNZIP_CMD is used but not defined. Spelling mistake?\n"+
                    196:                "WARN: fname:1: Unknown shell command \"awk\".\n"+
1.10      rillig    197:                "WARN: fname:1: Unknown shell command \"${MKDIR}\".\n"+
1.7       rillig    198:                "WARN: fname:1: MKDIR is used but not defined. Spelling mistake?\n"+
1.10      rillig    199:                "WARN: fname:1: UNZIP_CMD is used but not defined. Spelling mistake?\n")
1.7       rillig    200:
                    201:        // From x11/wxGTK28/Makefile
                    202:        shline.CheckShellCommandLine("" +
                    203:                "set -e; cd ${WRKSRC}/locale; " +
                    204:                "for lang in *.po; do " +
                    205:                "  [ \"$${lang}\" = \"wxstd.po\" ] && continue; " +
                    206:                "  ${TOOLS_PATH.msgfmt} -c -o \"$${lang%.po}.mo\" \"$${lang}\"; " +
                    207:                "done")
1.4       rillig    208:
1.7       rillig    209:        c.Check(s.Output(), equals, ""+
1.9       rillig    210:                "WARN: fname:1: WRKSRC may not be used in this file; it would be ok in Makefile, Makefile.*, *.mk.\n"+
1.7       rillig    211:                "WARN: fname:1: Unknown shell command \"[\".\n"+
                    212:                "WARN: fname:1: Unknown shell command \"${TOOLS_PATH.msgfmt}\".\n")
                    213:
                    214:        shline.CheckShellCommandLine("@cp from to")
                    215:
                    216:        c.Check(s.Output(), equals, ""+
                    217:                "WARN: fname:1: The shell command \"cp\" should not be hidden.\n"+
                    218:                "WARN: fname:1: Unknown shell command \"cp\".\n")
                    219:
                    220:        shline.CheckShellCommandLine("${RUN} ${INSTALL_DATA_DIR} share/pkgbase ${PREFIX}/share/pkgbase")
                    221:
1.10      rillig    222:        c.Check(s.Output(), equals, ""+
                    223:                "NOTE: fname:1: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= share/pkgbase\" instead of \"${INSTALL_DATA_DIR}\".\n"+
                    224:                "WARN: fname:1: The INSTALL_*_DIR commands can only handle one directory at a time.\n")
                    225:
                    226:        // See PR 46570, item "1. It does not"
                    227:        shline.CheckShellCommandLine("for x in 1 2 3; do echo \"$$x\" || exit 1; done")
                    228:
                    229:        c.Check(s.Output(), equals, "") // No warning about missing error checking.
1.1       rillig    230: }
                    231:
1.11      rillig    232: func (s *Suite) Test_ShellLine_CheckShellCommandLine__nofix(c *check.C) {
1.13      rillig    233:        s.Init(c)
                    234:        s.UseCommandLine("-Wall")
1.6       rillig    235:        G.globalData.InitVartypes()
1.9       rillig    236:        s.RegisterTool(&Tool{Name: "echo", Predefined: true})
1.7       rillig    237:        G.Mk = s.NewMkLines("Makefile",
                    238:                "\techo ${PKGNAME:Q}")
                    239:        shline := NewShellLine(G.Mk.mklines[0])
                    240:
                    241:        shline.CheckShellCommandLine("echo ${PKGNAME:Q}")
                    242:
                    243:        c.Check(s.Output(), equals, ""+
                    244:                "NOTE: Makefile:1: The :Q operator isn't necessary for ${PKGNAME} here.\n")
                    245: }
                    246:
1.11      rillig    247: func (s *Suite) Test_ShellLine_CheckShellCommandLine__show_autofix(c *check.C) {
1.13      rillig    248:        s.Init(c)
                    249:        s.UseCommandLine("-Wall", "--show-autofix")
1.7       rillig    250:        G.globalData.InitVartypes()
1.9       rillig    251:        s.RegisterTool(&Tool{Name: "echo", Predefined: true})
1.7       rillig    252:        G.Mk = s.NewMkLines("Makefile",
                    253:                "\techo ${PKGNAME:Q}")
                    254:        shline := NewShellLine(G.Mk.mklines[0])
                    255:
                    256:        shline.CheckShellCommandLine("echo ${PKGNAME:Q}")
                    257:
                    258:        c.Check(s.Output(), equals, ""+
                    259:                "NOTE: Makefile:1: The :Q operator isn't necessary for ${PKGNAME} here.\n"+
                    260:                "AUTOFIX: Makefile:1: Replacing \"${PKGNAME:Q}\" with \"${PKGNAME}\".\n")
                    261: }
                    262:
1.11      rillig    263: func (s *Suite) Test_ShellLine_CheckShellCommandLine__autofix(c *check.C) {
1.13      rillig    264:        s.Init(c)
                    265:        s.UseCommandLine("-Wall", "--autofix")
1.7       rillig    266:        G.globalData.InitVartypes()
1.9       rillig    267:        s.RegisterTool(&Tool{Name: "echo", Predefined: true})
1.7       rillig    268:        G.Mk = s.NewMkLines("Makefile",
                    269:                "\techo ${PKGNAME:Q}")
                    270:        shline := NewShellLine(G.Mk.mklines[0])
                    271:
                    272:        shline.CheckShellCommandLine("echo ${PKGNAME:Q}")
                    273:
                    274:        c.Check(s.Output(), equals, ""+
                    275:                "AUTOFIX: Makefile:1: Replacing \"${PKGNAME:Q}\" with \"${PKGNAME}\".\n")
                    276: }
                    277:
1.11      rillig    278: func (s *Suite) Test_ShellLine_CheckShellCommandLine__implementation(c *check.C) {
1.13      rillig    279:        s.Init(c)
                    280:        s.UseCommandLine("-Wall")
1.7       rillig    281:        G.globalData.InitVartypes()
                    282:        G.Mk = s.NewMkLines("fname",
                    283:                "# dummy")
                    284:        shline := NewShellLine(G.Mk.mklines[0])
1.6       rillig    285:
                    286:        // foobar="`echo \"foo   bar\"`"
1.9       rillig    287:        text := "foobar=\"`echo \\\"foo   bar\\\"`\""
                    288:
                    289:        tokens, rest := splitIntoShellTokens(dummyLine, text)
                    290:
                    291:        c.Check(tokens, deepEquals, []string{text})
                    292:        c.Check(rest, equals, "")
1.6       rillig    293:
1.10      rillig    294:        shline.CheckWord(text, false)
                    295:
                    296:        c.Check(s.Output(), equals, "WARN: fname:1: Unknown shell command \"echo\".\n")
                    297:
1.9       rillig    298:        shline.CheckShellCommandLine(text)
                    299:
                    300:        c.Check(s.Output(), equals, ""+ // No parse errors
                    301:                "WARN: fname:1: Unknown shell command \"echo\".\n")
1.6       rillig    302: }
                    303:
1.11      rillig    304: func (s *Suite) Test_ShellLine_CheckShelltext__dollar_without_variable(c *check.C) {
1.6       rillig    305:        G.globalData.InitVartypes()
1.7       rillig    306:        G.Mk = s.NewMkLines("fname",
                    307:                "# dummy")
                    308:        shline := NewShellLine(G.Mk.mklines[0])
1.9       rillig    309:        s.RegisterTool(&Tool{Name: "pax", Varname: "PAX"})
1.7       rillig    310:        G.Mk.tools["pax"] = true
1.6       rillig    311:
1.7       rillig    312:        shline.CheckShellCommandLine("pax -rwpp -s /.*~$$//g . ${DESTDIR}${PREFIX}")
1.6       rillig    313:
1.7       rillig    314:        c.Check(s.Output(), equals, "")
1.6       rillig    315: }
                    316:
1.9       rillig    317: func (s *Suite) Test_ShellLine_CheckWord(c *check.C) {
1.13      rillig    318:        s.Init(c)
                    319:        s.UseCommandLine("-Wall")
1.1       rillig    320:        G.globalData.InitVartypes()
1.7       rillig    321:        shline := NewShellLine(NewMkLine(NewLine("fname", 1, "# dummy", nil)))
1.1       rillig    322:
1.9       rillig    323:        shline.CheckWord("${${list}}", false)
1.1       rillig    324:
1.9       rillig    325:        c.Check(s.Output(), equals, "") // No warning for variables that are completely indirect.
1.1       rillig    326:
1.9       rillig    327:        shline.CheckWord("${SED_FILE.${id}}", false)
                    328:
1.10      rillig    329:        c.Check(s.Output(), equals, "") // No warning for variables that are partly indirect.
1.1       rillig    330:
1.9       rillig    331:        shline.CheckWord("\"$@\"", false)
1.1       rillig    332:
                    333:        c.Check(s.Output(), equals, "WARN: fname:1: Please use \"${.TARGET}\" instead of \"$@\".\n")
1.7       rillig    334:
1.9       rillig    335:        shline.CheckWord("${COMMENT:Q}", true)
1.7       rillig    336:
1.9       rillig    337:        c.Check(s.Output(), equals, "WARN: fname:1: COMMENT may not be used in any file; it is a write-only variable.\n")
1.7       rillig    338:
1.9       rillig    339:        shline.CheckWord("\"${DISTINFO_FILE:Q}\"", true)
1.7       rillig    340:
                    341:        c.Check(s.Output(), equals, ""+
1.9       rillig    342:                "WARN: fname:1: DISTINFO_FILE may not be used in this file; it would be ok in Makefile, Makefile.*, *.mk.\n"+
1.7       rillig    343:                "NOTE: fname:1: The :Q operator isn't necessary for ${DISTINFO_FILE} here.\n")
                    344:
1.9       rillig    345:        shline.CheckWord("embed${DISTINFO_FILE:Q}ded", true)
1.7       rillig    346:
                    347:        c.Check(s.Output(), equals, ""+
1.9       rillig    348:                "WARN: fname:1: DISTINFO_FILE may not be used in this file; it would be ok in Makefile, Makefile.*, *.mk.\n"+
1.7       rillig    349:                "NOTE: fname:1: The :Q operator isn't necessary for ${DISTINFO_FILE} here.\n")
                    350:
1.9       rillig    351:        shline.CheckWord("s,\\.,,", true)
1.7       rillig    352:
                    353:        c.Check(s.Output(), equals, "")
                    354:
1.9       rillig    355:        shline.CheckWord("\"s,\\.,,\"", true)
1.7       rillig    356:
                    357:        c.Check(s.Output(), equals, "")
1.1       rillig    358: }
                    359:
1.11      rillig    360: func (s *Suite) Test_ShellLine_CheckWord__dollar_without_variable(c *check.C) {
1.7       rillig    361:        shline := NewShellLine(NewMkLine(NewLine("fname", 1, "# dummy", nil)))
1.6       rillig    362:
1.9       rillig    363:        shline.CheckWord("/.*~$$//g", false) // Typical argument to pax(1).
1.6       rillig    364:
1.7       rillig    365:        c.Check(s.Output(), equals, "")
1.6       rillig    366: }
                    367:
1.11      rillig    368: func (s *Suite) Test_ShellLine_CheckShellCommandLine__echo(c *check.C) {
1.13      rillig    369:        s.Init(c)
                    370:        s.UseCommandLine("-Wall")
1.9       rillig    371:        s.RegisterTool(&Tool{Name: "echo", Varname: "ECHO", MustUseVarForm: true, Predefined: true})
1.7       rillig    372:        G.Mk = s.NewMkLines("fname",
                    373:                "# dummy")
                    374:        mkline := NewMkLine(NewLine("fname", 3, "# dummy", nil))
                    375:
1.15    ! rillig    376:        MkLineChecker{mkline}.checkText("echo \"hello, world\"")
1.1       rillig    377:
1.7       rillig    378:        c.Check(s.Output(), equals, "")
                    379:
                    380:        NewShellLine(mkline).CheckShellCommandLine("echo \"hello, world\"")
1.1       rillig    381:
                    382:        c.Check(s.Output(), equals, ""+
                    383:                "WARN: fname:3: Please use \"${ECHO}\" instead of \"echo\".\n")
                    384: }
1.3       rillig    385:
1.11      rillig    386: func (s *Suite) Test_ShellLine_CheckShellCommandLine__shell_variables(c *check.C) {
1.9       rillig    387:        text := "\tfor f in *.pl; do ${SED} s,@PREFIX@,${PREFIX}, < $f > $f.tmp && ${MV} $f.tmp $f; done"
1.3       rillig    388:
1.9       rillig    389:        shline := NewShellLine(NewMkLine(NewLine("Makefile", 3, text, nil)))
                    390:        shline.CheckShellCommandLine(text)
1.3       rillig    391:
1.9       rillig    392:        c.Check(s.Output(), equals, ""+
                    393:                "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+
                    394:                "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+
                    395:                "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+
                    396:                "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+
                    397:                "NOTE: Makefile:3: Please use the SUBST framework instead of ${SED} and ${MV}.\n")
1.3       rillig    398:
1.7       rillig    399:        shline.CheckShellCommandLine("install -c manpage.1 ${PREFIX}/man/man1/manpage.1")
1.3       rillig    400:
1.5       rillig    401:        c.Check(s.Output(), equals, "WARN: Makefile:3: Please use ${PKGMANDIR} instead of \"man\".\n")
1.3       rillig    402:
1.7       rillig    403:        shline.CheckShellCommandLine("cp init-script ${PREFIX}/etc/rc.d/service")
1.3       rillig    404:
1.5       rillig    405:        c.Check(s.Output(), equals, "WARN: Makefile:3: Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to ${RCD_SCRIPTS_EXAMPLEDIR}.\n")
1.3       rillig    406: }
                    407:
1.11      rillig    408: func (s *Suite) Test_ShellLine_checkCommandUse(c *check.C) {
1.7       rillig    409:        G.Mk = s.NewMkLines("fname",
                    410:                "# dummy")
                    411:        G.Mk.target = "do-install"
1.3       rillig    412:
1.7       rillig    413:        shline := NewShellLine(NewMkLine(NewLine("fname", 1, "\tdummy", nil)))
1.3       rillig    414:
                    415:        shline.checkCommandUse("sed")
                    416:
                    417:        c.Check(s.Output(), equals, "WARN: fname:1: The shell command \"sed\" should not be used in the install phase.\n")
                    418:
                    419:        shline.checkCommandUse("cp")
                    420:
                    421:        c.Check(s.Output(), equals, "WARN: fname:1: ${CP} should not be used to install files.\n")
                    422: }
1.7       rillig    423:
1.11      rillig    424: func (s *Suite) Test_splitIntoMkWords(c *check.C) {
1.7       rillig    425:        url := "http://registry.gimp.org/file/fix-ca.c?action=download&id=9884&file="
                    426:
1.14      rillig    427:        words, rest := splitIntoShellTokens(dummyLine, url) // Doesn't really make sense
1.7       rillig    428:
                    429:        c.Check(words, check.DeepEquals, []string{"http://registry.gimp.org/file/fix-ca.c?action=download", "&", "id=9884", "&", "file="})
                    430:        c.Check(rest, equals, "")
                    431:
1.9       rillig    432:        words, rest = splitIntoMkWords(dummyLine, url)
1.7       rillig    433:
                    434:        c.Check(words, check.DeepEquals, []string{"http://registry.gimp.org/file/fix-ca.c?action=download&id=9884&file="})
                    435:        c.Check(rest, equals, "")
                    436:
1.9       rillig    437:        words, rest = splitIntoMkWords(dummyLine, "a b \"c  c  c\" d;;d;; \"e\"''`` 'rest")
1.7       rillig    438:
                    439:        c.Check(words, check.DeepEquals, []string{"a", "b", "\"c  c  c\"", "d;;d;;", "\"e\"''``"})
                    440:        c.Check(rest, equals, "'rest")
                    441: }
                    442:
1.11      rillig    443: func (s *Suite) Test_ShellLine_CheckShellCommandLine__sed_and_mv(c *check.C) {
1.7       rillig    444:        shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} ${SED} 's,#,// comment:,g' fname > fname.tmp; ${MV} fname.tmp fname", nil)))
                    445:
                    446:        shline.CheckShellCommandLine(shline.mkline.Shellcmd())
                    447:
                    448:        c.Check(s.Output(), equals, "NOTE: Makefile:85: Please use the SUBST framework instead of ${SED} and ${MV}.\n")
                    449: }
                    450:
1.11      rillig    451: func (s *Suite) Test_ShellLine_CheckShellCommandLine__subshell(c *check.C) {
1.7       rillig    452:        shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} uname=$$(uname)", nil)))
                    453:
                    454:        shline.CheckShellCommandLine(shline.mkline.Shellcmd())
                    455:
                    456:        c.Check(s.Output(), equals, "WARN: Makefile:85: Invoking subshells via $(...) is not portable enough.\n")
                    457: }
                    458:
1.11      rillig    459: func (s *Suite) Test_ShellLine_CheckShellCommandLine__install_dir(c *check.C) {
1.7       rillig    460:        shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} ${INSTALL_DATA_DIR} ${DESTDIR}${PREFIX}/dir1 ${DESTDIR}${PREFIX}/dir2", nil)))
                    461:
                    462:        shline.CheckShellCommandLine(shline.mkline.Shellcmd())
                    463:
                    464:        c.Check(s.Output(), equals, ""+
1.10      rillig    465:                "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir1\" instead of \"${INSTALL_DATA_DIR}\".\n"+
                    466:                "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir2\" instead of \"${INSTALL_DATA_DIR}\".\n"+
                    467:                "WARN: Makefile:85: The INSTALL_*_DIR commands can only handle one directory at a time.\n")
                    468:
                    469:        shline.CheckShellCommandLine("${INSTALL_DATA_DIR} -d -m 0755 ${DESTDIR}${PREFIX}/share/examples/gdchart")
                    470:
                    471:        // No warning about multiple directories, since 0755 is an option, not an argument.
                    472:        c.Check(s.Output(), equals, ""+
                    473:                "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= share/examples/gdchart\" instead of \"${INSTALL_DATA_DIR}\".\n")
                    474:
                    475:        shline.CheckShellCommandLine("${INSTALL_DATA_DIR} -d -m 0755 ${DESTDIR}${PREFIX}/dir1 ${PREFIX}/dir2")
                    476:
                    477:        c.Check(s.Output(), equals, ""+
                    478:                "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir1\" instead of \"${INSTALL_DATA_DIR}\".\n"+
                    479:                "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir2\" instead of \"${INSTALL_DATA_DIR}\".\n"+
1.7       rillig    480:                "WARN: Makefile:85: The INSTALL_*_DIR commands can only handle one directory at a time.\n")
                    481: }
                    482:
1.11      rillig    483: func (s *Suite) Test_ShellLine_CheckShellCommandLine__install_option_d(c *check.C) {
1.7       rillig    484:        shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} ${INSTALL} -d ${DESTDIR}${PREFIX}/dir1 ${DESTDIR}${PREFIX}/dir2", nil)))
                    485:
                    486:        shline.CheckShellCommandLine(shline.mkline.Shellcmd())
                    487:
                    488:        c.Check(s.Output(), equals, ""+
1.10      rillig    489:                "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir1\" instead of \"${INSTALL} -d\".\n"+
                    490:                "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir2\" instead of \"${INSTALL} -d\".\n")
1.7       rillig    491: }
                    492:
1.11      rillig    493: func (s *Suite) Test_ShellLine__shell_comment_with_line_continuation(c *check.C) {
1.13      rillig    494:        s.Init(c)
                    495:        tmpfile := s.CreateTmpFile("Makefile", ""+
1.7       rillig    496:                "# $"+"NetBSD$\n"+
                    497:                "pre-install:\n"+
                    498:                "\t"+"# comment\\\n"+
                    499:                "\t"+"echo \"hello\"\n")
                    500:        lines := LoadNonemptyLines(tmpfile, true)
                    501:
                    502:        NewMkLines(lines).Check()
                    503:
1.8       rillig    504:        c.Check(s.Output(), equals, "WARN: ~/Makefile:3--4: A shell comment does not stop at the end of line.\n")
1.7       rillig    505: }
1.9       rillig    506:
1.11      rillig    507: func (s *Suite) Test_ShellLine_unescapeBackticks(c *check.C) {
1.9       rillig    508:        shline := NewShellLine(NewMkLine(dummyLine))
                    509:        // foobar="`echo \"foo   bar\"`"
                    510:        text := "foobar=\"`echo \\\"foo   bar\\\"`\""
1.15    ! rillig    511:        repl := textproc.NewPrefixReplacer(text)
1.9       rillig    512:        repl.AdvanceStr("foobar=\"`")
                    513:
                    514:        backtCommand, newQuoting := shline.unescapeBackticks(text, repl, shqDquotBackt)
                    515:        c.Check(backtCommand, equals, "echo \"foo   bar\"")
                    516:        c.Check(newQuoting, equals, shqDquot)
1.15    ! rillig    517:        c.Check(repl.Rest(), equals, "\"")
1.9       rillig    518: }

CVSweb <webmaster@jp.NetBSD.org>