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

Annotation of pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go, Revision 1.47

1.38      rillig      1: package pkglint
1.1       rillig      2:
                      3: import (
1.20      rillig      4:        "gopkg.in/check.v1"
1.1       rillig      5: )
                      6:
1.12      rillig      7: func (s *Suite) Test_VartypeCheck_AwkCommand(c *check.C) {
1.40      rillig      8:        t := s.Init(c)
                      9:        vt := NewVartypeCheckTester(t, (*VartypeCheck).AwkCommand)
1.21      rillig     10:
1.31      rillig     11:        vt.Varname("PLIST_AWK")
                     12:        vt.Op(opAssignAppend)
                     13:        vt.Values(
1.5       rillig     14:                "{print $0}",
                     15:                "{print $$0}")
1.40      rillig     16:        t.DisableTracing()
                     17:        vt.Values(
                     18:                "{print $0}",
                     19:                "{print $$0}")
                     20:
                     21:        // TODO: In this particular context of AWK programs, $$0 is not a shell variable.
                     22:        //  The warning should be adjusted to reflect this.
1.5       rillig     23:
1.31      rillig     24:        vt.Output(
1.43      rillig     25:                "WARN: filename.mk:1: $0 is ambiguous. "+
1.40      rillig     26:                        "Use ${0} if you mean a Make variable or $$0 if you mean a shell variable.",
1.43      rillig     27:                "WARN: filename.mk:3: $0 is ambiguous. "+
1.40      rillig     28:                        "Use ${0} if you mean a Make variable or $$0 if you mean a shell variable.")
1.2       rillig     29: }
                     30:
1.12      rillig     31: func (s *Suite) Test_VartypeCheck_BasicRegularExpression(c *check.C) {
1.40      rillig     32:        t := s.Init(c)
                     33:        vt := NewVartypeCheckTester(t, (*VartypeCheck).BasicRegularExpression)
1.21      rillig     34:
1.31      rillig     35:        vt.Varname("REPLACE_FILES.pl")
                     36:        vt.Values(
1.5       rillig     37:                ".*\\.pl$",
                     38:                ".*\\.pl$$")
1.40      rillig     39:        t.DisableTracing()
                     40:        vt.Values(
                     41:                ".*\\.pl$",
                     42:                ".*\\.pl$$")
1.5       rillig     43:
1.31      rillig     44:        vt.Output(
1.43      rillig     45:                "WARN: filename.mk:1: Internal pkglint error in MkLine.Tokenize at \"$\".",
                     46:                "WARN: filename.mk:3: Internal pkglint error in MkLine.Tokenize at \"$\".")
1.40      rillig     47:
1.2       rillig     48: }
                     49:
1.12      rillig     50: func (s *Suite) Test_VartypeCheck_BuildlinkDepmethod(c *check.C) {
1.31      rillig     51:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).BuildlinkDepmethod)
1.21      rillig     52:
1.31      rillig     53:        vt.Varname("BUILDLINK_DEPMETHOD.libc")
                     54:        vt.Op(opAssignDefault)
                     55:        vt.Values(
1.5       rillig     56:                "full",
1.40      rillig     57:                "unknown",
                     58:                "${BUILDLINK_DEPMETHOD.kernel}")
1.2       rillig     59:
1.31      rillig     60:        vt.Output(
1.43      rillig     61:                "WARN: filename.mk:2: Invalid dependency method \"unknown\". Valid methods are \"build\" or \"full\".")
1.2       rillig     62: }
                     63:
1.12      rillig     64: func (s *Suite) Test_VartypeCheck_Category(c *check.C) {
1.21      rillig     65:        t := s.Init(c)
1.31      rillig     66:        vt := NewVartypeCheckTester(t, (*VartypeCheck).Category)
1.21      rillig     67:
1.32      rillig     68:        t.CreateFileLines("filesyscategory/Makefile",
1.21      rillig     69:                "# empty")
1.32      rillig     70:        t.CreateFileLines("wip/Makefile",
1.21      rillig     71:                "# empty")
1.5       rillig     72:
1.31      rillig     73:        vt.Varname("CATEGORIES")
                     74:        vt.Values(
1.5       rillig     75:                "chinese",
                     76:                "arabic",
1.9       rillig     77:                "filesyscategory",
                     78:                "wip")
1.1       rillig     79:
1.31      rillig     80:        vt.Output(
1.43      rillig     81:                "ERROR: filename.mk:2: Invalid category \"arabic\".",
                     82:                "ERROR: filename.mk:4: Invalid category \"wip\".")
1.1       rillig     83: }
                     84:
1.12      rillig     85: func (s *Suite) Test_VartypeCheck_CFlag(c *check.C) {
1.31      rillig     86:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).CFlag)
1.21      rillig     87:
1.40      rillig     88:        vt.tester.SetUpTool("pkg-config", "", AtRunTime)
1.39      rillig     89:
1.31      rillig     90:        vt.Varname("CFLAGS")
                     91:        vt.Op(opAssignAppend)
                     92:        vt.Values(
1.5       rillig     93:                "-Wall",
                     94:                "/W3",
                     95:                "target:sparc64",
                     96:                "-std=c99",
                     97:                "-XX:+PrintClassHistogramAfterFullGC",
1.40      rillig     98:                "`pkg-config pidgin --cflags`",
                     99:                "-c99",
                    100:                "-c",
                    101:                "-no-integrated-as",
                    102:                "-pthread",
                    103:                "`pkg-config`_plus")
1.2       rillig    104:
1.31      rillig    105:        vt.Output(
1.43      rillig    106:                "WARN: filename.mk:2: Compiler flag \"/W3\" should start with a hyphen.",
                    107:                "WARN: filename.mk:3: Compiler flag \"target:sparc64\" should start with a hyphen.",
                    108:                "WARN: filename.mk:5: Unknown compiler flag \"-XX:+PrintClassHistogramAfterFullGC\".",
                    109:                "WARN: filename.mk:11: Compiler flag \"`pkg-config`_plus\" should start with a hyphen.")
1.31      rillig    110:
                    111:        vt.Op(opUseMatch)
                    112:        vt.Values(
                    113:                "anything")
                    114:
                    115:        vt.OutputEmpty()
1.2       rillig    116: }
                    117:
1.12      rillig    118: func (s *Suite) Test_VartypeCheck_Comment(c *check.C) {
1.21      rillig    119:        t := s.Init(c)
1.31      rillig    120:        vt := NewVartypeCheckTester(t, (*VartypeCheck).Comment)
1.21      rillig    121:
1.30      rillig    122:        G.Pkg = NewPackage(t.File("category/converter"))
1.22      rillig    123:        G.Pkg.EffectivePkgbase = "converter"
                    124:
1.31      rillig    125:        vt.Varname("COMMENT")
                    126:        vt.Values(
1.5       rillig    127:                "Versatile Programming Language",
                    128:                "TODO: Short description of the package",
                    129:                "A great package.",
1.15      rillig    130:                "some packages need a very very long comment to explain their basic usefulness",
                    131:                "\"Quoting the comment is wrong\"",
1.22      rillig    132:                "'Quoting the comment is wrong'",
                    133:                "Package is a great package",
                    134:                "Package is an awesome package",
                    135:                "The Big New Package is a great package",
1.40      rillig    136:                "Converter converts between measurement units",
1.42      rillig    137:                "Converter is a unit converter",
1.40      rillig    138:                "\"Official\" office suite",
                    139:                "'SQL injection fuzzer")
1.2       rillig    140:
1.31      rillig    141:        vt.Output(
1.43      rillig    142:                "ERROR: filename.mk:2: COMMENT must be set.",
                    143:                "WARN: filename.mk:3: COMMENT should not begin with \"A\".",
                    144:                "WARN: filename.mk:3: COMMENT should not end with a period.",
                    145:                "WARN: filename.mk:4: COMMENT should start with a capital letter.",
                    146:                "WARN: filename.mk:4: COMMENT should not be longer than 70 characters.",
                    147:                "WARN: filename.mk:5: COMMENT should not be enclosed in quotes.",
                    148:                "WARN: filename.mk:6: COMMENT should not be enclosed in quotes.",
                    149:                "WARN: filename.mk:7: COMMENT should not contain \"is a\".",
                    150:                "WARN: filename.mk:8: COMMENT should not contain \"is an\".",
                    151:                "WARN: filename.mk:9: COMMENT should not contain \"is a\".",
                    152:                "WARN: filename.mk:10: COMMENT should not start with the package name.",
                    153:                "WARN: filename.mk:11: COMMENT should not start with the package name.",
                    154:                "WARN: filename.mk:11: COMMENT should not contain \"is a\".")
1.2       rillig    155: }
                    156:
1.16      rillig    157: func (s *Suite) Test_VartypeCheck_ConfFiles(c *check.C) {
1.31      rillig    158:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).ConfFiles)
1.21      rillig    159:
1.31      rillig    160:        vt.Varname("CONF_FILES")
                    161:        vt.Op(opAssignAppend)
                    162:        vt.Values(
1.16      rillig    163:                "single/file",
1.17      rillig    164:                "share/etc/config ${PKG_SYSCONFDIR}/etc/config",
                    165:                "share/etc/config ${PKG_SYSCONFBASE}/etc/config file",
                    166:                "share/etc/config ${PREFIX}/etc/config share/etc/config2 ${VARBASE}/config2",
                    167:                "share/etc/bootrc /etc/bootrc")
1.16      rillig    168:
1.31      rillig    169:        vt.Output(
1.43      rillig    170:                "WARN: filename.mk:1: Values for CONF_FILES should always be pairs of paths.",
                    171:                "WARN: filename.mk:3: Values for CONF_FILES should always be pairs of paths.",
                    172:                "WARN: filename.mk:5: The destination file \"/etc/bootrc\" should start with a variable reference.")
1.16      rillig    173: }
                    174:
1.45      rillig    175: // See Test_MkParser_Dependency.
1.12      rillig    176: func (s *Suite) Test_VartypeCheck_Dependency(c *check.C) {
1.31      rillig    177:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Dependency)
1.21      rillig    178:
1.31      rillig    179:        vt.Varname("CONFLICTS")
                    180:        vt.Op(opAssignAppend)
1.45      rillig    181:
                    182:        // comparison operators
1.31      rillig    183:        vt.Values(
1.5       rillig    184:                "perl5>=5.22",
1.45      rillig    185:                "libkipi>=0.1.5<4.0",
                    186:                "gtk2+>=2.16")
                    187:        vt.OutputEmpty()
                    188:
                    189:        // pattern matching
                    190:        vt.Values(
                    191:                "perl-5*",
1.5       rillig    192:                "perl5-*",
1.45      rillig    193:                "perl-5.22",
1.5       rillig    194:                "perl5-5.22.*",
1.45      rillig    195:                "gtksourceview-sharp-2.0-[0-9]*")
                    196:        vt.Output(
                    197:                "WARN: filename.mk:11: Please use \"5.*\" instead of \"5*\" as the version pattern.",
                    198:                "WARN: filename.mk:12: Please use \"perl5-[0-9]*\" instead of \"perl5-*\".",
                    199:                "WARN: filename.mk:13: Please use \"5.22{,nb*}\" instead of \"5.22\" as the version pattern.",
                    200:                "WARN: filename.mk:15: The version pattern \"2.0-[0-9]*\" should not contain a hyphen.")
                    201:
                    202:        // nb suffix
                    203:        vt.Values(
1.5       rillig    204:                "perl5-5.22.*{,nb*}",
                    205:                "perl-5.22{,nb*}",
                    206:                "perl-5.22{,nb[0-9]*}",
                    207:                "mbrola-301h{,nb[0-9]*}",
1.45      rillig    208:                "ncurses-${NC_VERS}{,nb*}",
                    209:                "gnome-control-center>=2.20.1{,nb*}",
                    210:                "gnome-control-center>=2.20.1{,nb[0-9]*}")
                    211:        vt.Output(
                    212:                "WARN: filename.mk:26: Dependency patterns of the form pkgbase>=1.0 don't need the \"{,nb*}\" extension.",
                    213:                "WARN: filename.mk:27: Dependency patterns of the form pkgbase>=1.0 don't need the \"{,nb*}\" extension.")
                    214:
                    215:        // alternative patterns, using braces or brackets
                    216:        vt.Values(
1.5       rillig    217:                "mpg123{,-esound,-nas}>=0.59.18",
                    218:                "mysql*-{client,server}-[0-9]*",
1.45      rillig    219:                "{ssh{,6}-[0-9]*,openssh-[0-9]*}",
                    220:                "libao-[a-z]*-[0-9]*")
                    221:        vt.OutputEmpty()
                    222:
                    223:        // variables
                    224:        vt.Values(
1.5       rillig    225:                "postgresql8[0-35-9]-${module}-[0-9]*",
1.40      rillig    226:                "${_EMACS_CONFLICTS.${_EMACS_FLAVOR}}",
1.45      rillig    227:                "${PYPKGPREFIX}-sqlite3",
                    228:                "${PYPKGPREFIX}-sqlite3-${VERSION}",
                    229:                "${PYPKGPREFIX}-sqlite3-${PYSQLITE_REQD}",
                    230:                "${PYPKGPREFIX}-sqlite3>=${PYSQLITE_REQD}",
                    231:                "${EMACS_PACKAGE}>=${EMACS_MAJOR}",
                    232:
                    233:                // The "*" is ambiguous. It could either continue the PKGBASE or
                    234:                // start the version number.
                    235:                "${PKGNAME_NOREV:S/jdk/jre/}*",
                    236:
                    237:                // The canonical form is "{,nb*}" instead of "{nb*,}".
                    238:                // Plus, mentioning nb* is not necessary when using >=.
                    239:                "dovecot>=${PKGVERSION_NOREV}{nb*,}",
                    240:
                    241:                "oxygen-icons>=${KF5VER}{,nb[0-9]*}",
                    242:
                    243:                // The following pattern should have "]*}" instead of "]}*".
                    244:                "ja-vflib-lib-${VFLIB_VERSION}{,nb[0-9]}*",
                    245:
                    246:                // The following pattern uses both ">=" and "*", which doesn't make sense.
                    247:                "${PYPKGPREFIX}-sphinx>=1.2.3nb1*",
                    248:
                    249:                "{${NETSCAPE_PREFERRED:C/:/,/g}}-[0-9]*")
1.1       rillig    250:
1.31      rillig    251:        vt.Output(
1.45      rillig    252:                "WARN: filename.mk:43: Invalid dependency pattern \"${PYPKGPREFIX}-sqlite3\".",
                    253:                // This pattern is invalid because the variable name doesn't contain "VER".
                    254:                "WARN: filename.mk:45: Invalid dependency pattern \"${PYPKGPREFIX}-sqlite3-${PYSQLITE_REQD}\".",
                    255:                "WARN: filename.mk:48: Invalid dependency pattern \"${PKGNAME_NOREV:S/jdk/jre/}*\".",
                    256:                "WARN: filename.mk:49: Invalid dependency pattern \"dovecot>=${PKGVERSION_NOREV}{nb*,}\".",
                    257:                "WARN: filename.mk:50: Dependency patterns of the form pkgbase>=1.0 don't need the \"{,nb*}\" extension.",
                    258:                "WARN: filename.mk:51: Invalid dependency pattern \"ja-vflib-lib-${VFLIB_VERSION}{,nb[0-9]}*\".",
                    259:                "WARN: filename.mk:52: Invalid dependency pattern \"${PYPKGPREFIX}-sphinx>=1.2.3nb1*\".")
                    260:
                    261:        // invalid dependency patterns
                    262:        vt.Values(
                    263:                "Perl",
                    264:                "py-docs",
                    265:                "perl5-[5.10-5.22]*",
                    266:                "package-1.0|garbage",
                    267:                "package>=1.0:../../category/package",
                    268:                "package-1.0>=1.0.3",
                    269:                // This should be regarded as invalid since the [a-z0-9] might either
                    270:                // continue the PKGBASE or start the version number.
                    271:                "${RUBY_PKGPREFIX}-theme-[a-z0-9]*")
                    272:        vt.Output(
                    273:                "WARN: filename.mk:61: Invalid dependency pattern \"Perl\".",
                    274:                "WARN: filename.mk:62: Invalid dependency pattern \"py-docs\".",
                    275:                "WARN: filename.mk:63: Only [0-9]* is allowed in the numeric part of a dependency.",
                    276:                "WARN: filename.mk:63: The version pattern \"[5.10-5.22]*\" should not contain a hyphen.",
                    277:                "WARN: filename.mk:64: Invalid dependency pattern \"package-1.0|garbage\".",
1.40      rillig    278:                // TODO: Mention that the path should be removed.
1.45      rillig    279:                "WARN: filename.mk:65: Invalid dependency pattern \"package>=1.0:../../category/package\".",
1.40      rillig    280:                // TODO: Mention that version numbers in a pkgbase must be appended directly, without hyphen.
1.45      rillig    281:                "WARN: filename.mk:66: Invalid dependency pattern \"package-1.0>=1.0.3\".",
                    282:                "WARN: filename.mk:67: Invalid dependency pattern \"${RUBY_PKGPREFIX}-theme-[a-z0-9]*\".")
1.5       rillig    283: }
                    284:
1.12      rillig    285: func (s *Suite) Test_VartypeCheck_DependencyWithPath(c *check.C) {
1.21      rillig    286:        t := s.Init(c)
1.31      rillig    287:        vt := NewVartypeCheckTester(t, (*VartypeCheck).DependencyWithPath)
1.21      rillig    288:
1.29      rillig    289:        t.CreateFileLines("category/package/Makefile")
1.45      rillig    290:        t.CreateFileLines("databases/py-sqlite3/Makefile")
1.31      rillig    291:        t.CreateFileLines("devel/gettext/Makefile")
                    292:        t.CreateFileLines("devel/gmake/Makefile")
1.40      rillig    293:        t.CreateFileLines("devel/py-module/Makefile")
                    294:        t.CreateFileLines("x11/alacarte/Makefile")
1.30      rillig    295:        G.Pkg = NewPackage(t.File("category/package"))
1.29      rillig    296:
1.31      rillig    297:        vt.Varname("DEPENDS")
                    298:        vt.Op(opAssignAppend)
1.36      rillig    299:        vt.File(G.Pkg.File("filename.mk"))
1.31      rillig    300:        vt.Values(
1.5       rillig    301:                "Perl",
                    302:                "perl5>=5.22:../perl5",
                    303:                "perl5>=5.24:../../lang/perl5",
1.31      rillig    304:                "gtk2+>=2.16:../../x11/alacarte",
                    305:                "gettext-[0-9]*:../../devel/gettext",
1.45      rillig    306:                "gmake-[0-9]*:../../devel/gmake")
1.1       rillig    307:
1.31      rillig    308:        vt.Output(
1.36      rillig    309:                "WARN: ~/category/package/filename.mk:1: Invalid dependency pattern with path \"Perl\".",
1.45      rillig    310:                "WARN: ~/category/package/filename.mk:2: Dependency paths should have the form \"../../category/package\".",
1.46      rillig    311:                "ERROR: ~/category/package/filename.mk:2: Relative path \"../perl5/Makefile\" does not exist.",
1.45      rillig    312:                "WARN: ~/category/package/filename.mk:2: \"../perl5\" is not a valid relative package directory.",
                    313:                "WARN: ~/category/package/filename.mk:2: Please use USE_TOOLS+=perl:run instead of this dependency.",
1.46      rillig    314:                "ERROR: ~/category/package/filename.mk:3: Relative path \"../../lang/perl5/Makefile\" does not exist.",
1.36      rillig    315:                "WARN: ~/category/package/filename.mk:3: Please use USE_TOOLS+=perl:run instead of this dependency.",
1.45      rillig    316:                "WARN: ~/category/package/filename.mk:5: Please use USE_TOOLS+=msgfmt instead of this dependency.",
                    317:                "WARN: ~/category/package/filename.mk:6: Please use USE_TOOLS+=gmake instead of this dependency.")
                    318:
                    319:        vt.Values(
                    320:                "broken0.12.1:../../x11/alacarte", // missing version
                    321:                "broken[0-9]*:../../x11/alacarte", // missing version
                    322:                "broken[0-9]*../../x11/alacarte",  // missing colon
                    323:                "broken>=:../../x11/alacarte",     // incomplete comparison
                    324:                "broken=0:../../x11/alacarte",     // invalid comparison operator
                    325:                "broken=:../../x11/alacarte",      // incomplete comparison
                    326:                "broken-:../../x11/alacarte",      // incomplete pattern
                    327:                "broken>:../../x11/alacarte")      // incomplete comparison
                    328:
                    329:        vt.Output(
                    330:                "WARN: ~/category/package/filename.mk:11: Invalid dependency pattern \"broken0.12.1\".",
                    331:                "WARN: ~/category/package/filename.mk:12: Invalid dependency pattern \"broken[0-9]*\".",
                    332:                "WARN: ~/category/package/filename.mk:13: Invalid dependency pattern with path \"broken[0-9]*../../x11/alacarte\".",
                    333:                "WARN: ~/category/package/filename.mk:14: Invalid dependency pattern \"broken>=\".",
                    334:                "WARN: ~/category/package/filename.mk:15: Invalid dependency pattern \"broken=0\".",
                    335:                "WARN: ~/category/package/filename.mk:16: Invalid dependency pattern \"broken=\".",
                    336:                "WARN: ~/category/package/filename.mk:17: Invalid dependency pattern \"broken-\".",
                    337:                "WARN: ~/category/package/filename.mk:18: Invalid dependency pattern \"broken>\".")
                    338:
                    339:        vt.Values(
                    340:                "${PYPKGPREFIX}-sqlite3:../../${MY_PKGPATH.py-sqlite3}",
                    341:                "${PYPKGPREFIX}-sqlite3:../../databases/py-sqlite3",
                    342:                "${DEPENDS.NetBSD}",
                    343:                "${DEPENDENCY_PATTERN.py-sqlite3}:${DEPENDENCY_PATH.py-sqlite}",
                    344:                "${PYPKGPREFIX}-module>=0:../../devel/py-module",
                    345:                "${EMACS_PACKAGE}>=${EMACS_MAJOR}:${EMACS_PKGDIR}",
                    346:                "{${NETSCAPE_PREFERRED:C/:/,/g}}-[0-9]*:../../www/${NETSCAPE_PREFERRED:C/:.*//}")
                    347:
                    348:        vt.Output(
                    349:                "WARN: ~/category/package/filename.mk:21: "+
                    350:                        "Invalid dependency pattern \"${PYPKGPREFIX}-sqlite3\".",
                    351:                "WARN: ~/category/package/filename.mk:22: "+
                    352:                        "Invalid dependency pattern \"${PYPKGPREFIX}-sqlite3\".")
1.1       rillig    353: }
                    354:
1.12      rillig    355: func (s *Suite) Test_VartypeCheck_DistSuffix(c *check.C) {
1.31      rillig    356:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).DistSuffix)
1.21      rillig    357:
1.31      rillig    358:        vt.Varname("EXTRACT_SUFX")
                    359:        vt.Values(
1.5       rillig    360:                ".tar.gz",
1.40      rillig    361:                ".tar.bz2",
                    362:                ".tar.gz # overrides a definition from a Makefile.common")
1.2       rillig    363:
1.31      rillig    364:        vt.Output(
1.43      rillig    365:                "NOTE: filename.mk:1: EXTRACT_SUFX is \".tar.gz\" by default, so this definition may be redundant.")
1.2       rillig    366: }
                    367:
1.12      rillig    368: func (s *Suite) Test_VartypeCheck_EmulPlatform(c *check.C) {
1.31      rillig    369:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).EmulPlatform)
1.21      rillig    370:
1.31      rillig    371:        vt.Varname("EMUL_PLATFORM")
                    372:        vt.Values(
1.5       rillig    373:                "linux-i386",
                    374:                "nextbsd-8087",
                    375:                "${LINUX}")
1.2       rillig    376:
1.31      rillig    377:        vt.Output(
1.43      rillig    378:                "WARN: filename.mk:2: \"nextbsd\" is not valid for the operating system part of EMUL_PLATFORM. "+
1.21      rillig    379:                        "Use one of "+
                    380:                        "{ bitrig bsdos cygwin darwin dragonfly freebsd haiku hpux "+
                    381:                        "interix irix linux mirbsd netbsd openbsd osf1 solaris sunos "+
                    382:                        "} instead.",
1.43      rillig    383:                "WARN: filename.mk:2: \"8087\" is not valid for the hardware architecture part of EMUL_PLATFORM. "+
1.40      rillig    384:                        "Use one of { "+
                    385:                        "aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 "+
                    386:                        "cobalt coldfire convex dreamcast "+
                    387:                        "earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb "+
                    388:                        "earmv6 earmv6eb earmv6hf earmv6hfeb "+
                    389:                        "earmv7 earmv7eb earmv7hf earmv7hfeb evbarm "+
                    390:                        "hpcmips hpcsh hppa hppa64 "+
                    391:                        "i386 i586 i686 ia64 m68000 m68k m88k "+
                    392:                        "mips mips64 mips64eb mips64el mipseb mipsel mipsn32 "+
                    393:                        "mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 "+
                    394:                        "s390 sh3eb sh3el sparc sparc64 vax x86_64 "+
1.21      rillig    395:                        "} instead.",
1.43      rillig    396:                "WARN: filename.mk:3: \"${LINUX}\" is not a valid emulation platform.")
1.2       rillig    397: }
                    398:
1.12      rillig    399: func (s *Suite) Test_VartypeCheck_Enum(c *check.C) {
1.31      rillig    400:        vt := NewVartypeCheckTester(s.Init(c), enum("jdk1 jdk2 jdk4").checker)
1.21      rillig    401:
1.31      rillig    402:        vt.Varname("JDK")
                    403:        vt.Op(opUseMatch)
                    404:        vt.Values(
1.7       rillig    405:                "*",
                    406:                "jdk*",
                    407:                "sun-jdk*",
1.31      rillig    408:                "${JDKNAME}",
                    409:                "[")
1.7       rillig    410:
1.31      rillig    411:        vt.Output(
1.43      rillig    412:                "WARN: filename.mk:3: The pattern \"sun-jdk*\" cannot match any of { jdk1 jdk2 jdk4 } for JDK.",
                    413:                "WARN: filename.mk:5: Invalid match pattern \"[\".")
1.7       rillig    414: }
                    415:
1.29      rillig    416: func (s *Suite) Test_VartypeCheck_Enum__use_match(c *check.C) {
                    417:        t := s.Init(c)
                    418:
1.40      rillig    419:        t.SetUpVartypes()
                    420:        t.SetUpCommandLine("-Wall", "--explain")
1.29      rillig    421:
                    422:        mklines := t.NewMkLines("module.mk",
                    423:                MkRcsID,
                    424:                "",
                    425:                ".if !empty(MACHINE_ARCH:Mi386) || ${MACHINE_ARCH} == i386",
                    426:                ".endif",
                    427:                ".if !empty(PKGSRC_COMPILER:Mclang) || ${PKGSRC_COMPILER} == clang",
1.30      rillig    428:                ".endif",
                    429:                ".if ${MACHINE_ARCH:Ni386:Nx86_64:Nsparc64}",
1.29      rillig    430:                ".endif")
                    431:
                    432:        mklines.Check()
                    433:
                    434:        t.CheckOutputLines(
1.37      rillig    435:                "NOTE: module.mk:3: MACHINE_ARCH should be compared using == instead of matching against \":Mi386\".",
1.40      rillig    436:                "",
                    437:                "\tThis variable has a single value, not a list of values. Therefore it",
                    438:                "\tfeels strange to apply list operators like :M and :N onto it. A more",
                    439:                "\tdirect approach is to use the == and != operators.",
                    440:                "",
                    441:                "\tAn entirely different case is when the pattern contains wildcards",
                    442:                "\tlike ^, *, $. In such a case, using the :M or :N modifiers is useful",
                    443:                "\tand preferred.",
                    444:                "",
                    445:                "WARN: module.mk:5: Use ${PKGSRC_COMPILER:Mclang} instead of the == operator.",
                    446:                "",
                    447:                "\tThe PKGSRC_COMPILER can be a list of chained compilers, e.g. \"ccache",
                    448:                "\tdistcc clang\". Therefore, comparing it using == or != leads to wrong",
                    449:                "\tresults in these cases.",
                    450:                "")
1.29      rillig    451: }
                    452:
1.12      rillig    453: func (s *Suite) Test_VartypeCheck_FetchURL(c *check.C) {
1.21      rillig    454:        t := s.Init(c)
1.31      rillig    455:        vt := NewVartypeCheckTester(t, (*VartypeCheck).FetchURL)
1.1       rillig    456:
1.40      rillig    457:        t.SetUpMasterSite("MASTER_SITE_GNU", "http://ftp.gnu.org/pub/gnu/")
                    458:        t.SetUpMasterSite("MASTER_SITE_GITHUB", "https://github.com/")
1.21      rillig    459:
1.31      rillig    460:        vt.Varname("MASTER_SITES")
                    461:        vt.Values(
1.5       rillig    462:                "https://github.com/example/project/",
                    463:                "http://ftp.gnu.org/pub/gnu/bison", // Missing a slash at the end
                    464:                "${MASTER_SITE_GNU:=bison}",
                    465:                "${MASTER_SITE_INVALID:=subdir/}")
1.1       rillig    466:
1.31      rillig    467:        vt.Output(
1.43      rillig    468:                "WARN: filename.mk:1: Please use ${MASTER_SITE_GITHUB:=example/} "+
1.21      rillig    469:                        "instead of \"https://github.com/example/project/\" "+
                    470:                        "and run \""+confMake+" help topic=github\" for further tips.",
1.43      rillig    471:                "WARN: filename.mk:2: Please use ${MASTER_SITE_GNU:=bison} "+
1.40      rillig    472:                        "instead of \"http://ftp.gnu.org/pub/gnu/bison\".",
1.43      rillig    473:                "ERROR: filename.mk:3: The subdirectory in MASTER_SITE_GNU must end with a slash.",
                    474:                "ERROR: filename.mk:4: The site MASTER_SITE_INVALID does not exist.")
1.5       rillig    475:
                    476:        // PR 46570, keyword gimp-fix-ca
1.31      rillig    477:        vt.Values(
1.36      rillig    478:                "https://example.org/download.cgi?filename=filename&sha1=12341234")
1.1       rillig    479:
1.45      rillig    480:        vt.OutputEmpty()
1.9       rillig    481:
1.31      rillig    482:        vt.Values(
1.9       rillig    483:                "http://example.org/distfiles/",
1.36      rillig    484:                "http://example.org/download?filename=distfile;version=1.0",
                    485:                "http://example.org/download?filename=<distfile>;version=<version>")
1.9       rillig    486:
1.31      rillig    487:        vt.Output(
1.45      rillig    488:                "WARN: filename.mk:23: \"http://example.org/download?filename=<distfile>;version=<version>\" is not a valid URL.")
1.1       rillig    489: }
                    490:
1.36      rillig    491: func (s *Suite) Test_VartypeCheck_Filename(c *check.C) {
                    492:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Filename)
1.21      rillig    493:
1.31      rillig    494:        vt.Varname("FNAME")
                    495:        vt.Values(
1.36      rillig    496:                "Filename with spaces.docx",
1.5       rillig    497:                "OS/2-manual.txt")
1.2       rillig    498:
1.31      rillig    499:        vt.Output(
1.43      rillig    500:                "WARN: filename.mk:1: \"Filename with spaces.docx\" is not a valid filename.",
                    501:                "WARN: filename.mk:2: A filename should not contain a slash.")
1.31      rillig    502:
                    503:        vt.Op(opUseMatch)
                    504:        vt.Values(
1.36      rillig    505:                "Filename with spaces.docx")
1.31      rillig    506:
1.36      rillig    507:        // There's no guarantee that a filename only contains [A-Za-z0-9.].
1.31      rillig    508:        // Therefore there are no useful checks in this situation.
                    509:        vt.OutputEmpty()
                    510: }
                    511:
1.35      rillig    512: func (s *Suite) Test_VartypeCheck_FileMask(c *check.C) {
                    513:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).FileMask)
1.31      rillig    514:
                    515:        vt.Varname("FNAME")
                    516:        vt.Values(
1.35      rillig    517:                "FileMask with spaces.docx",
1.31      rillig    518:                "OS/2-manual.txt")
                    519:
                    520:        vt.Output(
1.43      rillig    521:                "WARN: filename.mk:1: \"FileMask with spaces.docx\" is not a valid filename mask.",
                    522:                "WARN: filename.mk:2: A filename mask should not contain a slash.")
1.31      rillig    523:
                    524:        vt.Op(opUseMatch)
                    525:        vt.Values(
1.35      rillig    526:                "FileMask with spaces.docx")
1.31      rillig    527:
1.36      rillig    528:        // There's no guarantee that a filename only contains [A-Za-z0-9.].
1.31      rillig    529:        // Therefore there are no useful checks in this situation.
                    530:        vt.OutputEmpty()
                    531: }
                    532:
                    533: func (s *Suite) Test_VartypeCheck_FileMode(c *check.C) {
                    534:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).FileMode)
                    535:
                    536:        vt.Varname("HIGHSCORE_PERMS")
                    537:        vt.Values(
                    538:                "u+rwx",
                    539:                "0600",
                    540:                "1234",
                    541:                "12345",
1.36      rillig    542:                "${OTHER_PERMS}",
                    543:                "")
1.31      rillig    544:
                    545:        vt.Output(
1.43      rillig    546:                "WARN: filename.mk:1: Invalid file mode \"u+rwx\".",
                    547:                "WARN: filename.mk:4: Invalid file mode \"12345\".",
                    548:                "WARN: filename.mk:6: Invalid file mode \"\".")
1.31      rillig    549:
                    550:        vt.Op(opUseMatch)
                    551:        vt.Values(
                    552:                "u+rwx")
                    553:
1.36      rillig    554:        // There's no guarantee that a filename only contains [A-Za-z0-9.].
1.31      rillig    555:        // Therefore there are no useful checks in this situation.
                    556:        vt.Output(
1.43      rillig    557:                "WARN: filename.mk:11: Invalid file mode \"u+rwx\".")
1.31      rillig    558: }
                    559:
1.34      rillig    560: func (s *Suite) Test_VartypeCheck_GccReqd(c *check.C) {
                    561:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).GccReqd)
                    562:
                    563:        vt.Varname("GCC_REQD")
                    564:        vt.Op(opAssignAppend)
                    565:        vt.Values(
                    566:                "2.95",
                    567:                "3.1.5",
                    568:                "4.7",
                    569:                "4.8",
                    570:                "5.1",
                    571:                "6",
                    572:                "7.3")
                    573:        vt.Output(
1.43      rillig    574:                "WARN: filename.mk:5: GCC version numbers should only contain the major version (5).",
                    575:                "WARN: filename.mk:7: GCC version numbers should only contain the major version (7).")
1.34      rillig    576: }
                    577:
1.31      rillig    578: func (s *Suite) Test_VartypeCheck_Homepage(c *check.C) {
                    579:        t := s.Init(c)
                    580:        vt := NewVartypeCheckTester(t, (*VartypeCheck).Homepage)
                    581:
                    582:        vt.Varname("HOMEPAGE")
                    583:        vt.Values(
1.40      rillig    584:                "http://www.pkgsrc.org/",
                    585:                "https://www.pkgsrc.org/",
1.31      rillig    586:                "${MASTER_SITES}")
                    587:
                    588:        vt.Output(
1.43      rillig    589:                "WARN: filename.mk:3: HOMEPAGE should not be defined in terms of MASTER_SITEs.")
1.31      rillig    590:
                    591:        G.Pkg = NewPackage(t.File("category/package"))
                    592:
                    593:        vt.Values(
                    594:                "${MASTER_SITES}")
                    595:
1.40      rillig    596:        // When this assignment occurs while checking a package, but the package
                    597:        // doesn't define MASTER_SITES, that variable cannot be expanded, which means
                    598:        // the warning cannot refer to its value.
                    599:        vt.Output(
1.45      rillig    600:                "WARN: filename.mk:11: HOMEPAGE should not be defined in terms of MASTER_SITEs.")
1.40      rillig    601:
1.42      rillig    602:        delete(G.Pkg.vars.firstDef, "MASTER_SITES")
                    603:        delete(G.Pkg.vars.lastDef, "MASTER_SITES")
1.40      rillig    604:        G.Pkg.vars.Define("MASTER_SITES", t.NewMkLine(G.Pkg.File("Makefile"), 5,
                    605:                "MASTER_SITES=\thttps://cdn.NetBSD.org/pub/pkgsrc/distfiles/"))
                    606:
                    607:        vt.Values(
                    608:                "${MASTER_SITES}")
                    609:
                    610:        vt.Output(
1.45      rillig    611:                "WARN: filename.mk:21: HOMEPAGE should not be defined in terms of MASTER_SITEs. " +
1.40      rillig    612:                        "Use https://cdn.NetBSD.org/pub/pkgsrc/distfiles/ directly.")
                    613:
1.42      rillig    614:        delete(G.Pkg.vars.firstDef, "MASTER_SITES")
                    615:        delete(G.Pkg.vars.lastDef, "MASTER_SITES")
1.40      rillig    616:        G.Pkg.vars.Define("MASTER_SITES", t.NewMkLine(G.Pkg.File("Makefile"), 5,
                    617:                "MASTER_SITES=\t${MASTER_SITE_GITHUB}"))
                    618:
                    619:        vt.Values(
                    620:                "${MASTER_SITES}")
                    621:
                    622:        // When MASTER_SITES itself makes use of another variable, pkglint doesn't
                    623:        // resolve that variable and just outputs the simple variant of this warning.
1.31      rillig    624:        vt.Output(
1.45      rillig    625:                "WARN: filename.mk:31: HOMEPAGE should not be defined in terms of MASTER_SITEs.")
1.40      rillig    626:
1.31      rillig    627: }
                    628:
                    629: func (s *Suite) Test_VartypeCheck_Identifier(c *check.C) {
                    630:        t := s.Init(c)
                    631:        vt := NewVartypeCheckTester(t, (*VartypeCheck).Identifier)
                    632:
1.40      rillig    633:        vt.Varname("MYSQL_CHARSET")
1.31      rillig    634:        vt.Values(
                    635:                "${OTHER_VAR}",
                    636:                "identifiers cannot contain spaces",
1.40      rillig    637:                "id/cannot/contain/slashes",
                    638:                "id-${OTHER_VAR}",
                    639:                "")
                    640:
                    641:        vt.Output(
1.43      rillig    642:                "WARN: filename.mk:2: Invalid identifier \"identifiers cannot contain spaces\".",
                    643:                "WARN: filename.mk:3: Invalid identifier \"id/cannot/contain/slashes\".",
                    644:                "WARN: filename.mk:5: Invalid identifier \"\".")
1.40      rillig    645:
1.31      rillig    646:        vt.Op(opUseMatch)
                    647:        vt.Values(
                    648:                "[A-Z]",
1.40      rillig    649:                "[A-Z.]",
                    650:                "${PKG_OPTIONS:Moption}",
1.31      rillig    651:                "A*B")
                    652:
                    653:        vt.Output(
1.43      rillig    654:                "WARN: filename.mk:12: Invalid identifier pattern \"[A-Z.]\" for MYSQL_CHARSET.")
1.31      rillig    655: }
                    656:
                    657: func (s *Suite) Test_VartypeCheck_Integer(c *check.C) {
                    658:        t := s.Init(c)
                    659:        vt := NewVartypeCheckTester(t, (*VartypeCheck).Integer)
                    660:
                    661:        vt.Varname("NUMBER")
                    662:        vt.Values(
                    663:                "${OTHER_VAR}",
                    664:                "123",
                    665:                "-13",
                    666:                "11111111111111111111111111111111111111111111111")
                    667:
                    668:        vt.Output(
1.43      rillig    669:                "WARN: filename.mk:1: Invalid integer \"${OTHER_VAR}\".",
                    670:                "WARN: filename.mk:3: Invalid integer \"-13\".")
1.5       rillig    671: }
1.2       rillig    672:
1.12      rillig    673: func (s *Suite) Test_VartypeCheck_LdFlag(c *check.C) {
1.31      rillig    674:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).LdFlag)
1.21      rillig    675:
1.40      rillig    676:        vt.tester.SetUpTool("pkg-config", "", AtRunTime)
1.39      rillig    677:
1.31      rillig    678:        vt.Varname("LDFLAGS")
                    679:        vt.Op(opAssignAppend)
                    680:        vt.Values(
1.5       rillig    681:                "-lc",
                    682:                "-L/usr/lib64",
                    683:                "`pkg-config pidgin --ldflags`",
1.31      rillig    684:                "-unknown",
                    685:                "no-hyphen",
1.36      rillig    686:                "-Wl,--rpath,/usr/lib64",
                    687:                "-pthread",
                    688:                "-static",
                    689:                "-static-something",
                    690:                "${LDFLAGS.NetBSD}",
1.40      rillig    691:                "-l${LIBNCURSES}",
                    692:                "`pkg-config`_plus")
1.31      rillig    693:        vt.Op(opUseMatch)
                    694:        vt.Values(
                    695:                "anything")
                    696:
                    697:        vt.Output(
1.43      rillig    698:                "WARN: filename.mk:4: Unknown linker flag \"-unknown\".",
                    699:                "WARN: filename.mk:5: Linker flag \"no-hyphen\" should start with a hyphen.",
                    700:                "WARN: filename.mk:6: Please use \"${COMPILER_RPATH_FLAG}\" instead of \"-Wl,--rpath\".",
                    701:                "WARN: filename.mk:12: Linker flag \"`pkg-config`_plus\" should start with a hyphen.")
1.2       rillig    702: }
                    703:
1.14      rillig    704: func (s *Suite) Test_VartypeCheck_License(c *check.C) {
1.36      rillig    705:        t := s.Init(c)
1.46      rillig    706:
1.40      rillig    707:        t.SetUpPkgsrc() // Adds the gnu-gpl-v2 and 2-clause-bsd licenses
1.46      rillig    708:        t.SetUpPackage("category/package")
                    709:        t.FinishSetUp()
1.36      rillig    710:
1.44      rillig    711:        G.Pkg = NewPackage(t.File("category/package"))
                    712:
                    713:        mklines := t.NewMkLines("perl5.mk",
1.36      rillig    714:                MkRcsID,
                    715:                "PERL5_LICENSE= gnu-gpl-v2 OR artistic")
1.44      rillig    716:        // Also registers the PERL5_LICENSE variable in the package.
                    717:        mklines.collectDefinedVariables()
1.36      rillig    718:
                    719:        vt := NewVartypeCheckTester(t, (*VartypeCheck).License)
1.21      rillig    720:
1.31      rillig    721:        vt.Varname("LICENSE")
                    722:        vt.Values(
1.14      rillig    723:                "gnu-gpl-v2",
1.36      rillig    724:                "AND mit",
                    725:                "${PERL5_LICENSE}", // Is properly resolved, see perl5.mk above.
                    726:                "${UNKNOWN_LICENSE}")
1.14      rillig    727:
1.31      rillig    728:        vt.Output(
1.43      rillig    729:                "ERROR: filename.mk:2: Parse error for license condition \"AND mit\".",
                    730:                "WARN: filename.mk:3: License file ~/licenses/artistic does not exist.",
                    731:                "ERROR: filename.mk:4: Parse error for license condition \"${UNKNOWN_LICENSE}\".")
1.14      rillig    732:
1.31      rillig    733:        vt.Op(opAssignAppend)
                    734:        vt.Values(
1.14      rillig    735:                "gnu-gpl-v2",
                    736:                "AND mit")
                    737:
1.31      rillig    738:        vt.Output(
1.43      rillig    739:                "ERROR: filename.mk:11: Parse error for appended license condition \"gnu-gpl-v2\".",
                    740:                "WARN: filename.mk:12: License file ~/licenses/mit does not exist.")
1.14      rillig    741: }
                    742:
1.12      rillig    743: func (s *Suite) Test_VartypeCheck_MachineGnuPlatform(c *check.C) {
1.31      rillig    744:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).MachineGnuPlatform)
1.21      rillig    745:
1.31      rillig    746:        vt.Varname("MACHINE_GNU_PLATFORM")
                    747:        vt.Op(opUseMatch)
                    748:        vt.Values(
1.9       rillig    749:                "x86_64-pc-cygwin",
1.31      rillig    750:                "Cygwin-*-amd64",
                    751:                "x86_64-*",
                    752:                "*-*-*-*",
1.40      rillig    753:                "${OTHER_VAR}",
                    754:                "x86_64-pc") // Just for code coverage.
1.9       rillig    755:
1.31      rillig    756:        vt.Output(
1.43      rillig    757:                "WARN: filename.mk:2: The pattern \"Cygwin\" cannot match any of "+
1.21      rillig    758:                        "{ aarch64 aarch64_be alpha amd64 arc arm armeb armv4 armv4eb armv6 armv6eb armv7 armv7eb "+
                    759:                        "cobalt convex dreamcast hpcmips hpcsh hppa hppa64 i386 i486 ia64 m5407 m68010 m68k m88k "+
                    760:                        "mips mips64 mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 "+
                    761:                        "rs6000 s390 sh shle sparc sparc64 vax x86_64 "+
                    762:                        "} for the hardware architecture part of MACHINE_GNU_PLATFORM.",
1.43      rillig    763:                "WARN: filename.mk:2: The pattern \"amd64\" cannot match any of "+
1.21      rillig    764:                        "{ bitrig bsdos cygwin darwin dragonfly freebsd haiku hpux interix irix linux mirbsd "+
                    765:                        "netbsd openbsd osf1 solaris sunos } "+
1.31      rillig    766:                        "for the operating system part of MACHINE_GNU_PLATFORM.",
1.43      rillig    767:                "WARN: filename.mk:4: \"*-*-*-*\" is not a valid platform pattern.",
                    768:                "WARN: filename.mk:6: \"x86_64-pc\" is not a valid platform pattern.")
1.40      rillig    769: }
                    770:
                    771: func (s *Suite) Test_VartypeCheck_MachinePlatformPattern(c *check.C) {
                    772:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).MachinePlatformPattern)
                    773:
                    774:        vt.Varname("ONLY_FOR_PLATFORM")
                    775:        vt.Op(opUseMatch)
                    776:        vt.Values(
                    777:                "linux-i386",
                    778:                "nextbsd-5.0-8087",
                    779:                "netbsd-7.0-l*",
                    780:                "NetBSD-1.6.2-i386",
                    781:                "FreeBSD*",
                    782:                "FreeBSD-*",
                    783:                "${LINUX}",
                    784:                "NetBSD-[0-1]*-*")
                    785:
                    786:        vt.Output(
1.43      rillig    787:                "WARN: filename.mk:1: \"linux-i386\" is not a valid platform pattern.",
                    788:                "WARN: filename.mk:2: The pattern \"nextbsd\" cannot match any of "+
1.40      rillig    789:                        "{ AIX BSDOS Bitrig Cygwin Darwin DragonFly FreeBSD FreeMiNT GNUkFreeBSD HPUX Haiku "+
                    790:                        "IRIX Interix Linux Minix MirBSD NetBSD OSF1 OpenBSD QNX SCO_SV SunOS UnixWare "+
                    791:                        "} for the operating system part of ONLY_FOR_PLATFORM.",
1.43      rillig    792:                "WARN: filename.mk:2: The pattern \"8087\" cannot match any of "+
1.40      rillig    793:                        "{ aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 "+
                    794:                        "cobalt coldfire convex dreamcast "+
                    795:                        "earm earmeb earmhf earmhfeb earmv4 earmv4eb "+
                    796:                        "earmv5 earmv5eb earmv6 earmv6eb earmv6hf "+
                    797:                        "earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 "+
                    798:                        "i386 i586 i686 ia64 m68000 m68k m88k "+
                    799:                        "mips mips64 mips64eb mips64el mipseb mipsel mipsn32 "+
                    800:                        "mlrisc ns32k pc532 pmax powerpc powerpc64 "+
                    801:                        "rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 "+
                    802:                        "} for the hardware architecture part of ONLY_FOR_PLATFORM.",
1.43      rillig    803:                "WARN: filename.mk:3: The pattern \"netbsd\" cannot match any of "+
1.40      rillig    804:                        "{ AIX BSDOS Bitrig Cygwin Darwin DragonFly FreeBSD FreeMiNT GNUkFreeBSD HPUX Haiku "+
                    805:                        "IRIX Interix Linux Minix MirBSD NetBSD OSF1 OpenBSD QNX SCO_SV SunOS UnixWare "+
                    806:                        "} for the operating system part of ONLY_FOR_PLATFORM.",
1.43      rillig    807:                "WARN: filename.mk:3: The pattern \"l*\" cannot match any of "+
1.40      rillig    808:                        "{ aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 "+
                    809:                        "cobalt coldfire convex dreamcast "+
                    810:                        "earm earmeb earmhf earmhfeb earmv4 earmv4eb "+
                    811:                        "earmv5 earmv5eb earmv6 earmv6eb earmv6hf "+
                    812:                        "earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 "+
                    813:                        "i386 i586 i686 ia64 m68000 m68k m88k "+
                    814:                        "mips mips64 mips64eb mips64el mipseb mipsel mipsn32 "+
                    815:                        "mlrisc ns32k pc532 pmax powerpc powerpc64 "+
                    816:                        "rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 "+
                    817:                        "} for the hardware architecture part of ONLY_FOR_PLATFORM.",
1.43      rillig    818:                "WARN: filename.mk:5: \"FreeBSD*\" is not a valid platform pattern.",
                    819:                "WARN: filename.mk:8: Please use \"[0-1].*\" instead of \"[0-1]*\" as the version pattern.")
1.9       rillig    820: }
                    821:
1.12      rillig    822: func (s *Suite) Test_VartypeCheck_MailAddress(c *check.C) {
1.31      rillig    823:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).MailAddress)
1.2       rillig    824:
1.31      rillig    825:        vt.Varname("MAINTAINER")
                    826:        vt.Values(
                    827:                "pkgsrc-users@netbsd.org",
                    828:                "tech-pkg@NetBSD.org",
                    829:                "packages@NetBSD.org",
                    830:                "user1@example.org,user2@example.org")
                    831:
                    832:        vt.Output(
1.43      rillig    833:                "WARN: filename.mk:1: Please write \"NetBSD.org\" instead of \"netbsd.org\".",
                    834:                "ERROR: filename.mk:2: This mailing list address is obsolete. Use pkgsrc-users@NetBSD.org instead.",
                    835:                "ERROR: filename.mk:3: This mailing list address is obsolete. Use pkgsrc-users@NetBSD.org instead.",
                    836:                "WARN: filename.mk:4: \"user1@example.org,user2@example.org\" is not a valid mail address.")
1.2       rillig    837: }
                    838:
1.12      rillig    839: func (s *Suite) Test_VartypeCheck_Message(c *check.C) {
1.31      rillig    840:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Message)
1.21      rillig    841:
1.31      rillig    842:        vt.Varname("SUBST_MESSAGE.id")
                    843:        vt.Values(
1.5       rillig    844:                "\"Correct paths\"",
                    845:                "Correct paths")
1.1       rillig    846:
1.31      rillig    847:        vt.Output(
1.43      rillig    848:                "WARN: filename.mk:1: SUBST_MESSAGE.id should not be quoted.")
1.5       rillig    849: }
1.1       rillig    850:
1.12      rillig    851: func (s *Suite) Test_VartypeCheck_Option(c *check.C) {
1.31      rillig    852:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Option)
1.21      rillig    853:
1.23      rillig    854:        G.Pkgsrc.PkgOptions["documented"] = "Option description"
                    855:        G.Pkgsrc.PkgOptions["undocumented"] = ""
1.1       rillig    856:
1.31      rillig    857:        vt.Varname("PKG_OPTIONS.pkgbase")
                    858:        vt.Values(
1.5       rillig    859:                "documented",
                    860:                "undocumented",
1.31      rillig    861:                "unknown",
                    862:                "underscore_is_deprecated",
                    863:                "UPPER")
                    864:
                    865:        vt.Output(
1.43      rillig    866:                "WARN: filename.mk:3: Unknown option \"unknown\".",
                    867:                "WARN: filename.mk:4: Use of the underscore character in option names is deprecated.",
                    868:                "ERROR: filename.mk:5: Invalid option name \"UPPER\". "+
1.31      rillig    869:                        "Option names must start with a lowercase letter and be all-lowercase.")
1.1       rillig    870: }
                    871:
1.12      rillig    872: func (s *Suite) Test_VartypeCheck_Pathlist(c *check.C) {
1.31      rillig    873:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Pathlist)
1.21      rillig    874:
1.31      rillig    875:        vt.Varname("PATH")
                    876:        vt.Values(
1.36      rillig    877:                "/usr/bin:/usr/sbin:.::${LOCALBASE}/bin:${HOMEPAGE:S,https://,,}:${TMPDIR}:${PREFIX}/!!!",
1.31      rillig    878:                "/directory with spaces")
1.1       rillig    879:
1.31      rillig    880:        vt.Output(
1.43      rillig    881:                "ERROR: filename.mk:1: The component \".\" of PATH must be an absolute path.",
                    882:                "ERROR: filename.mk:1: The component \"\" of PATH must be an absolute path.",
                    883:                "WARN: filename.mk:1: \"${PREFIX}/!!!\" is not a valid pathname.",
                    884:                "WARN: filename.mk:2: \"/directory with spaces\" is not a valid pathname.")
1.31      rillig    885: }
                    886:
1.35      rillig    887: func (s *Suite) Test_VartypeCheck_PathMask(c *check.C) {
                    888:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).PathMask)
1.31      rillig    889:
                    890:        vt.Varname("DISTDIRS")
                    891:        vt.Values(
                    892:                "/home/user/*",
                    893:                "src/*&*",
                    894:                "src/*/*")
                    895:
                    896:        vt.Output(
1.43      rillig    897:                "WARN: filename.mk:2: \"src/*&*\" is not a valid pathname mask.")
1.31      rillig    898:
                    899:        vt.Op(opUseMatch)
                    900:        vt.Values("any")
                    901:
                    902:        vt.OutputEmpty()
                    903: }
                    904:
1.36      rillig    905: func (s *Suite) Test_VartypeCheck_Pathname(c *check.C) {
                    906:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Pathname)
1.31      rillig    907:
                    908:        vt.Varname("EGDIR")
                    909:        vt.Values(
                    910:                "${PREFIX}/*",
                    911:                "${PREFIX}/share/locale",
                    912:                "share/locale",
                    913:                "/bin")
                    914:        vt.Op(opUseMatch)
                    915:        vt.Values(
                    916:                "anything")
                    917:
                    918:        vt.Output(
1.43      rillig    919:                "WARN: filename.mk:1: \"${PREFIX}/*\" is not a valid pathname.")
1.31      rillig    920: }
                    921:
                    922: func (s *Suite) Test_VartypeCheck_Perl5Packlist(c *check.C) {
                    923:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Perl5Packlist)
                    924:
                    925:        vt.Varname("PERL5_PACKLIST")
                    926:        vt.Values(
                    927:                "${PKGBASE}",
                    928:                "anything else")
                    929:
                    930:        vt.Output(
1.43      rillig    931:                "WARN: filename.mk:1: PERL5_PACKLIST should not depend on other variables.")
1.5       rillig    932: }
1.1       rillig    933:
1.10      rillig    934: func (s *Suite) Test_VartypeCheck_Perms(c *check.C) {
1.31      rillig    935:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Perms)
1.21      rillig    936:
1.31      rillig    937:        vt.Varname("CONF_FILES_PERMS")
                    938:        vt.Op(opAssignAppend)
                    939:        vt.Values(
1.10      rillig    940:                "root",
                    941:                "${ROOT_USER}",
                    942:                "ROOT_USER",
1.40      rillig    943:                "${REAL_ROOT_USER}",
                    944:                "${ROOT_GROUP}",
                    945:                "${REAL_ROOT_GROUP}")
1.10      rillig    946:
1.31      rillig    947:        vt.Output(
1.43      rillig    948:                "ERROR: filename.mk:2: ROOT_USER must not be used in permission definitions. Use REAL_ROOT_USER instead.",
                    949:                "ERROR: filename.mk:5: ROOT_GROUP must not be used in permission definitions. Use REAL_ROOT_GROUP instead.")
1.10      rillig    950: }
                    951:
1.26      rillig    952: func (s *Suite) Test_VartypeCheck_Pkgname(c *check.C) {
1.32      rillig    953:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Pkgname)
1.26      rillig    954:
1.31      rillig    955:        vt.Varname("PKGNAME")
                    956:        vt.Values(
1.26      rillig    957:                "pkgbase-0",
                    958:                "pkgbase-1.0",
                    959:                "pkgbase-1.1234567890",
                    960:                "pkgbase-1z",
                    961:                "pkgbase-client-11a",
                    962:                "pkgbase-client-1.a",
                    963:                "pkgbase-client-1_20180101",
                    964:                "pkgbase-z1",
                    965:                "pkgbase-3.1.4.1.5.9.2.6.5.3.5.8.9.7.9")
                    966:
1.31      rillig    967:        vt.Output(
1.43      rillig    968:                "WARN: filename.mk:8: \"pkgbase-z1\" is not a valid package name.")
1.40      rillig    969:
                    970:        vt.Op(opUseMatch)
                    971:        vt.Values(
                    972:                "pkgbase-[0-9]*")
                    973:
                    974:        vt.OutputEmpty()
1.26      rillig    975: }
                    976:
1.12      rillig    977: func (s *Suite) Test_VartypeCheck_PkgOptionsVar(c *check.C) {
1.31      rillig    978:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).PkgOptionsVar)
                    979:
                    980:        vt.Varname("PKG_OPTIONS_VAR.screen")
                    981:        vt.Values(
                    982:                "PKG_OPTIONS.${PKGBASE}",
                    983:                "PKG_OPTIONS.anypkgbase",
                    984:                "PKG_OPTS.mc")
                    985:
                    986:        vt.Output(
1.43      rillig    987:                "ERROR: filename.mk:1: PKGBASE must not be used in PKG_OPTIONS_VAR.",
                    988:                "ERROR: filename.mk:3: PKG_OPTIONS_VAR must be "+
1.40      rillig    989:                        "of the form \"PKG_OPTIONS.*\", not \"PKG_OPTS.mc\".")
1.31      rillig    990: }
                    991:
                    992: func (s *Suite) Test_VartypeCheck_PkgPath(c *check.C) {
1.21      rillig    993:        t := s.Init(c)
1.31      rillig    994:        vt := NewVartypeCheckTester(t, (*VartypeCheck).PkgPath)
1.21      rillig    995:
1.31      rillig    996:        t.CreateFileLines("category/other-package/Makefile")
                    997:        t.Chdir("category/package")
                    998:
                    999:        vt.Varname("PKGPATH")
                   1000:        vt.Values(
                   1001:                "category/other-package",
                   1002:                "${OTHER_VAR}",
                   1003:                "invalid",
                   1004:                "../../invalid/relative")
1.5       rillig   1005:
1.31      rillig   1006:        vt.Output(
1.46      rillig   1007:                "ERROR: filename.mk:3: Relative path \"../../invalid/Makefile\" does not exist.",
1.43      rillig   1008:                "WARN: filename.mk:3: \"../../invalid\" is not a valid relative package directory.",
1.46      rillig   1009:                "ERROR: filename.mk:4: Relative path \"../../../../invalid/relative/Makefile\" does not exist.",
1.43      rillig   1010:                "WARN: filename.mk:4: \"../../../../invalid/relative\" is not a valid relative package directory.")
1.1       rillig   1011: }
                   1012:
1.12      rillig   1013: func (s *Suite) Test_VartypeCheck_PkgRevision(c *check.C) {
1.31      rillig   1014:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).PkgRevision)
1.21      rillig   1015:
1.31      rillig   1016:        vt.Varname("PKGREVISION")
                   1017:        vt.Values(
1.5       rillig   1018:                "3a")
1.1       rillig   1019:
1.31      rillig   1020:        vt.Output(
1.43      rillig   1021:                "WARN: filename.mk:1: PKGREVISION must be a positive integer number.",
                   1022:                "ERROR: filename.mk:1: PKGREVISION only makes sense directly in the package Makefile.")
1.1       rillig   1023:
1.31      rillig   1024:        vt.File("Makefile")
                   1025:        vt.Values(
1.5       rillig   1026:                "3")
1.1       rillig   1027:
1.31      rillig   1028:        vt.OutputEmpty()
1.1       rillig   1029: }
                   1030:
1.12      rillig   1031: func (s *Suite) Test_VartypeCheck_PythonDependency(c *check.C) {
1.31      rillig   1032:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).PythonDependency)
1.21      rillig   1033:
1.31      rillig   1034:        vt.Varname("PYTHON_VERSIONED_DEPENDENCIES")
                   1035:        vt.Values(
1.5       rillig   1036:                "cairo",
                   1037:                "${PYDEP}",
                   1038:                "cairo,X")
                   1039:
1.31      rillig   1040:        vt.Output(
1.43      rillig   1041:                "WARN: filename.mk:2: Python dependencies should not contain variables.",
                   1042:                "WARN: filename.mk:3: Invalid Python dependency \"cairo,X\".")
1.5       rillig   1043: }
1.1       rillig   1044:
1.31      rillig   1045: func (s *Suite) Test_VartypeCheck_PrefixPathname(c *check.C) {
                   1046:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).PrefixPathname)
                   1047:
                   1048:        vt.Varname("PKGMANDIR")
                   1049:        vt.Values(
                   1050:                "man/man1",
                   1051:                "share/locale")
                   1052:
                   1053:        vt.Output(
1.43      rillig   1054:                "WARN: filename.mk:1: Please use \"${PKGMANDIR}/man1\" instead of \"man/man1\".")
1.31      rillig   1055: }
                   1056:
                   1057: func (s *Suite) Test_VartypeCheck_RelativePkgPath(c *check.C) {
                   1058:        t := s.Init(c)
                   1059:        vt := NewVartypeCheckTester(t, (*VartypeCheck).RelativePkgPath)
                   1060:
                   1061:        t.CreateFileLines("category/other-package/Makefile")
                   1062:        t.Chdir("category/package")
                   1063:
                   1064:        vt.Varname("DISTINFO_FILE")
                   1065:        vt.Values(
                   1066:                "category/other-package",
                   1067:                "../../category/other-package",
                   1068:                "${OTHER_VAR}",
                   1069:                "invalid",
                   1070:                "../../invalid/relative")
                   1071:
                   1072:        vt.Output(
1.43      rillig   1073:                "ERROR: filename.mk:1: Relative path \"category/other-package\" does not exist.",
                   1074:                "ERROR: filename.mk:4: Relative path \"invalid\" does not exist.",
                   1075:                "ERROR: filename.mk:5: Relative path \"../../invalid/relative\" does not exist.")
1.31      rillig   1076: }
                   1077:
1.12      rillig   1078: func (s *Suite) Test_VartypeCheck_Restricted(c *check.C) {
1.31      rillig   1079:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Restricted)
1.21      rillig   1080:
1.31      rillig   1081:        vt.Varname("NO_BIN_ON_CDROM")
                   1082:        vt.Values(
1.5       rillig   1083:                "May only be distributed free of charge")
1.1       rillig   1084:
1.31      rillig   1085:        vt.Output(
1.43      rillig   1086:                "WARN: filename.mk:1: The only valid value for NO_BIN_ON_CDROM is ${RESTRICTED}.")
1.5       rillig   1087: }
1.1       rillig   1088:
1.12      rillig   1089: func (s *Suite) Test_VartypeCheck_SedCommands(c *check.C) {
1.31      rillig   1090:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).SedCommands)
1.21      rillig   1091:
1.31      rillig   1092:        vt.Varname("SUBST_SED.dummy")
                   1093:        vt.Values(
1.5       rillig   1094:                "s,@COMPILER@,gcc,g",
                   1095:                "-e s,a,b, -e a,b,c,",
                   1096:                "-e \"s,#,comment ,\"",
1.31      rillig   1097:                "-e \"s,\\#,comment ,\"",
                   1098:                "-E",
                   1099:                "-n",
                   1100:                "-e 1d",
                   1101:                "1d",
1.40      rillig   1102:                "-e",
                   1103:                "-i s,from,to,",
                   1104:                "-e s,$${unclosedShellVar") // Just for code coverage.
1.1       rillig   1105:
1.31      rillig   1106:        vt.Output(
1.43      rillig   1107:                "NOTE: filename.mk:1: Please always use \"-e\" in sed commands, even if there is only one substitution.",
                   1108:                "NOTE: filename.mk:2: Each sed command should appear in an assignment of its own.",
                   1109:                "WARN: filename.mk:3: The # character starts a Makefile comment.",
                   1110:                "ERROR: filename.mk:3: Invalid shell words \"\\\"s,\" in sed commands.",
                   1111:                "WARN: filename.mk:8: Unknown sed command \"1d\".",
                   1112:                "ERROR: filename.mk:9: The -e option to sed requires an argument.",
                   1113:                "WARN: filename.mk:10: Unknown sed command \"-i\".",
                   1114:                "NOTE: filename.mk:10: Please always use \"-e\" in sed commands, even if there is only one substitution.",
1.46      rillig   1115:                // TODO: duplicate warning
                   1116:                "WARN: filename.mk:11: Unclosed shell variable starting at \"$${unclosedShellVar\".",
1.43      rillig   1117:                "WARN: filename.mk:11: Unclosed shell variable starting at \"$${unclosedShellVar\".")
1.31      rillig   1118: }
                   1119:
                   1120: func (s *Suite) Test_VartypeCheck_ShellCommand(c *check.C) {
1.35      rillig   1121:        t := s.Init(c)
1.40      rillig   1122:        t.SetUpVartypes()
1.35      rillig   1123:        vt := NewVartypeCheckTester(t, (*VartypeCheck).ShellCommand)
1.31      rillig   1124:
                   1125:        vt.Varname("INSTALL_CMD")
                   1126:        vt.Values(
                   1127:                "${INSTALL_DATA} -m 0644 ${WRKDIR}/source ${DESTDIR}${PREFIX}/target")
                   1128:
1.36      rillig   1129:        vt.Op(opUseMatch)
                   1130:        vt.Values("*")
                   1131:
1.31      rillig   1132:        vt.OutputEmpty()
1.1       rillig   1133: }
                   1134:
1.12      rillig   1135: func (s *Suite) Test_VartypeCheck_ShellCommands(c *check.C) {
1.35      rillig   1136:        t := s.Init(c)
1.40      rillig   1137:        t.SetUpVartypes()
                   1138:        t.SetUpTool("echo", "ECHO", AtRunTime)
1.35      rillig   1139:        vt := NewVartypeCheckTester(t, (*VartypeCheck).ShellCommands)
1.21      rillig   1140:
1.31      rillig   1141:        vt.Varname("GENERATE_PLIST")
                   1142:        vt.Values(
1.5       rillig   1143:                "echo bin/program",
                   1144:                "echo bin/program;")
1.1       rillig   1145:
1.31      rillig   1146:        vt.Output(
1.43      rillig   1147:                "WARN: filename.mk:1: This shell command list should end with a semicolon.")
1.5       rillig   1148: }
1.1       rillig   1149:
1.12      rillig   1150: func (s *Suite) Test_VartypeCheck_Stage(c *check.C) {
1.31      rillig   1151:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Stage)
1.21      rillig   1152:
1.31      rillig   1153:        vt.Varname("SUBST_STAGE.dummy")
                   1154:        vt.Values(
1.5       rillig   1155:                "post-patch",
                   1156:                "post-modern",
                   1157:                "pre-test")
1.1       rillig   1158:
1.31      rillig   1159:        vt.Output(
1.43      rillig   1160:                "WARN: filename.mk:2: Invalid stage name \"post-modern\". " +
1.21      rillig   1161:                        "Use one of {pre,do,post}-{extract,patch,configure,build,test,install}.")
1.5       rillig   1162: }
1.1       rillig   1163:
1.24      rillig   1164: func (s *Suite) Test_VartypeCheck_Tool(c *check.C) {
                   1165:        t := s.Init(c)
1.31      rillig   1166:        vt := NewVartypeCheckTester(t, (*VartypeCheck).Tool)
1.24      rillig   1167:
1.40      rillig   1168:        t.SetUpTool("tool1", "", AtRunTime)
                   1169:        t.SetUpTool("tool2", "", AtRunTime)
                   1170:        t.SetUpTool("tool3", "", AtRunTime)
1.31      rillig   1171:
                   1172:        vt.Varname("USE_TOOLS")
                   1173:        vt.Op(opAssignAppend)
                   1174:        vt.Values(
1.24      rillig   1175:                "tool3:run",
1.27      rillig   1176:                "tool2:unknown",
                   1177:                "${t}",
1.31      rillig   1178:                "mal:formed:tool",
                   1179:                "unknown")
1.24      rillig   1180:
1.31      rillig   1181:        vt.Output(
1.43      rillig   1182:                "ERROR: filename.mk:2: Invalid tool dependency \"unknown\". "+
1.27      rillig   1183:                        "Use one of \"bootstrap\", \"build\", \"pkgsrc\", \"run\" or \"test\".",
1.43      rillig   1184:                "ERROR: filename.mk:4: Invalid tool dependency \"mal:formed:tool\".",
                   1185:                "ERROR: filename.mk:5: Unknown tool \"unknown\".")
1.24      rillig   1186:
1.31      rillig   1187:        vt.Varname("USE_TOOLS.NetBSD")
                   1188:        vt.Op(opAssignAppend)
                   1189:        vt.Values(
1.24      rillig   1190:                "tool3:run",
                   1191:                "tool2:unknown")
                   1192:
1.31      rillig   1193:        vt.Output(
1.43      rillig   1194:                "ERROR: filename.mk:12: Invalid tool dependency \"unknown\". " +
1.27      rillig   1195:                        "Use one of \"bootstrap\", \"build\", \"pkgsrc\", \"run\" or \"test\".")
1.31      rillig   1196:
                   1197:        vt.Varname("TOOLS_NOOP")
                   1198:        vt.Op(opAssignAppend)
                   1199:        vt.Values(
                   1200:                "gmake:run")
                   1201:
1.40      rillig   1202:        vt.Varname("TOOLS_NOOP")
                   1203:        vt.Op(opAssign) // TODO: In a Makefile, this should be equivalent to opAssignAppend.
                   1204:        vt.Values(
                   1205:                "gmake:run")
                   1206:
                   1207:        vt.Output(
1.43      rillig   1208:                "ERROR: filename.mk:31: Unknown tool \"gmake\".")
1.40      rillig   1209:
                   1210:        vt.Varname("USE_TOOLS")
                   1211:        vt.Op(opUseMatch)
                   1212:        vt.Values(
                   1213:                "tool1",
1.46      rillig   1214:                "tool1\\:build",
                   1215:                "tool1\\:*",
                   1216:                "${t}\\:build")
1.40      rillig   1217:
1.31      rillig   1218:        vt.OutputEmpty()
                   1219: }
                   1220:
                   1221: func (s *Suite) Test_VartypeCheck_URL(c *check.C) {
                   1222:        t := s.Init(c)
                   1223:        vt := NewVartypeCheckTester(t, (*VartypeCheck).URL)
                   1224:
                   1225:        vt.Varname("HOMEPAGE")
                   1226:        vt.Values(
                   1227:                "# none",
                   1228:                "${OTHER_VAR}",
1.40      rillig   1229:                "https://www.NetBSD.org/",
1.31      rillig   1230:                "https://www.netbsd.org/",
                   1231:                "https://www.example.org",
1.40      rillig   1232:                "ftp://example.org/pub/",
                   1233:                "gopher://example.org/",
                   1234:
                   1235:                "",
                   1236:                "ftp://example.org/<",
                   1237:                "gopher://example.org/<",
                   1238:                "http://example.org/<",
                   1239:                "https://example.org/<",
1.31      rillig   1240:                "https://www.example.org/path with spaces",
1.40      rillig   1241:                "httpxs://www.example.org",
                   1242:                "mailto:someone@example.org",
1.31      rillig   1243:                "string with spaces")
                   1244:
                   1245:        vt.Output(
1.43      rillig   1246:                "WARN: filename.mk:4: Please write NetBSD.org instead of www.netbsd.org.",
                   1247:                "NOTE: filename.mk:5: For consistency, please add a trailing slash to \"https://www.example.org\".",
                   1248:                "WARN: filename.mk:8: \"\" is not a valid URL.",
                   1249:                "WARN: filename.mk:9: \"ftp://example.org/<\" is not a valid URL.",
                   1250:                "WARN: filename.mk:10: \"gopher://example.org/<\" is not a valid URL.",
                   1251:                "WARN: filename.mk:11: \"http://example.org/<\" is not a valid URL.",
                   1252:                "WARN: filename.mk:12: \"https://example.org/<\" is not a valid URL.",
                   1253:                "WARN: filename.mk:13: \"https://www.example.org/path with spaces\" is not a valid URL.",
                   1254:                "WARN: filename.mk:14: \"httpxs://www.example.org\" is not a valid URL. Only ftp, gopher, http, and https URLs are allowed here.",
                   1255:                "WARN: filename.mk:15: \"mailto:someone@example.org\" is not a valid URL.",
                   1256:                "WARN: filename.mk:16: \"string with spaces\" is not a valid URL.")
1.40      rillig   1257:
                   1258:        // Yes, even in 2019, some pkgsrc-wip packages really use a gopher HOMEPAGE.
                   1259:        vt.Values(
                   1260:                "gopher://bitreich.org/1/scm/geomyidae")
                   1261:        vt.OutputEmpty()
1.31      rillig   1262: }
                   1263:
                   1264: func (s *Suite) Test_VartypeCheck_UserGroupName(c *check.C) {
                   1265:        t := s.Init(c)
                   1266:        vt := NewVartypeCheckTester(t, (*VartypeCheck).UserGroupName)
                   1267:
                   1268:        vt.Varname("APACHE_USER")
                   1269:        vt.Values(
                   1270:                "user with spaces",
                   1271:                "typical_username",
                   1272:                "user123",
                   1273:                "domain\\user",
                   1274:                "${OTHER_VAR}")
                   1275:
                   1276:        vt.Output(
1.43      rillig   1277:                "WARN: filename.mk:1: Invalid user or group name \"user with spaces\".",
                   1278:                "WARN: filename.mk:4: Invalid user or group name \"domain\\\\user\".")
1.24      rillig   1279: }
                   1280:
1.12      rillig   1281: func (s *Suite) Test_VartypeCheck_VariableName(c *check.C) {
1.31      rillig   1282:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).VariableName)
1.21      rillig   1283:
1.31      rillig   1284:        vt.Varname("BUILD_DEFS")
                   1285:        vt.Values(
1.6       rillig   1286:                "VARBASE",
                   1287:                "VarBase",
                   1288:                "PKG_OPTIONS_VAR.pkgbase",
                   1289:                "${INDIRECT}")
                   1290:
1.31      rillig   1291:        vt.Output(
1.43      rillig   1292:                "WARN: filename.mk:2: \"VarBase\" is not a valid variable name.")
1.6       rillig   1293: }
                   1294:
1.13      rillig   1295: func (s *Suite) Test_VartypeCheck_Version(c *check.C) {
1.31      rillig   1296:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Version)
1.21      rillig   1297:
1.31      rillig   1298:        vt.Varname("PERL5_REQD")
                   1299:        vt.Op(opAssignAppend)
                   1300:        vt.Values(
1.13      rillig   1301:                "0",
                   1302:                "1.2.3.4.5.6",
                   1303:                "4.1nb17",
                   1304:                "4.1-SNAPSHOT",
1.40      rillig   1305:                "4pre7",
                   1306:                "${VER}")
1.31      rillig   1307:        vt.Output(
1.43      rillig   1308:                "WARN: filename.mk:4: Invalid version number \"4.1-SNAPSHOT\".")
1.13      rillig   1309:
1.31      rillig   1310:        vt.Op(opUseMatch)
                   1311:        vt.Values(
                   1312:                "a*",
                   1313:                "1.2/456",
1.32      rillig   1314:                "4*",
                   1315:                "?.??",
                   1316:                "1.[234]*",
                   1317:                "1.[2-7].*",
1.31      rillig   1318:                "[0-9]*")
                   1319:        vt.Output(
1.43      rillig   1320:                "WARN: filename.mk:11: Invalid version number pattern \"a*\".",
                   1321:                "WARN: filename.mk:12: Invalid version number pattern \"1.2/456\".",
                   1322:                "WARN: filename.mk:13: Please use \"4.*\" instead of \"4*\" as the version pattern.",
                   1323:                "WARN: filename.mk:15: Please use \"1.[234].*\" instead of \"1.[234]*\" as the version pattern.")
1.31      rillig   1324: }
                   1325:
                   1326: func (s *Suite) Test_VartypeCheck_WrapperReorder(c *check.C) {
                   1327:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).WrapperReorder)
                   1328:
                   1329:        vt.Varname("WRAPPER_REORDER")
                   1330:        vt.Op(opAssignAppend)
                   1331:        vt.Values(
                   1332:                "reorder:l:first:second",
                   1333:                "reorder:l:first",
                   1334:                "omit:first")
                   1335:        vt.Output(
1.43      rillig   1336:                "WARN: filename.mk:2: Unknown wrapper reorder command \"reorder:l:first\".",
                   1337:                "WARN: filename.mk:3: Unknown wrapper reorder command \"omit:first\".")
1.31      rillig   1338: }
                   1339:
                   1340: func (s *Suite) Test_VartypeCheck_WrapperTransform(c *check.C) {
                   1341:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).WrapperTransform)
                   1342:
1.40      rillig   1343:        vt.Varname("WRAPPER_TRANSFORM_CMDS")
1.31      rillig   1344:        vt.Op(opAssignAppend)
                   1345:        vt.Values(
                   1346:                "rm:-O3",
                   1347:                "opt:-option",
                   1348:                "rename:src:dst",
                   1349:                "rm-optarg:-option",
                   1350:                "rmdir:/usr/include",
                   1351:                "rpath:/usr/lib:/usr/pkg/lib",
                   1352:                "rpath:/usr/lib",
1.40      rillig   1353:                "unknown",
                   1354:                "-e 's,-Wall,-Wall -Wextra,'")
1.31      rillig   1355:        vt.Output(
1.43      rillig   1356:                "WARN: filename.mk:7: Unknown wrapper transform command \"rpath:/usr/lib\".",
                   1357:                "WARN: filename.mk:8: Unknown wrapper transform command \"unknown\".")
1.31      rillig   1358: }
                   1359:
                   1360: func (s *Suite) Test_VartypeCheck_WrksrcSubdirectory(c *check.C) {
                   1361:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).WrksrcSubdirectory)
                   1362:
                   1363:        vt.Varname("BUILD_DIRS")
                   1364:        vt.Op(opAssignAppend)
                   1365:        vt.Values(
                   1366:                "${WRKSRC}",
                   1367:                "${WRKSRC}/",
                   1368:                "${WRKSRC}/.",
                   1369:                "${WRKSRC}/subdir",
                   1370:                "${CONFIGURE_DIRS}",
1.40      rillig   1371:                "${WRKSRC}/directory with spaces", // This is a list of 3 directories.
                   1372:                "directory with spaces",           // This is a list of 3 directories.
                   1373:                "../other",
                   1374:                "${WRKDIR}/sub",
                   1375:                "${SRCDIR}/sub")
1.31      rillig   1376:        vt.Output(
1.43      rillig   1377:                "NOTE: filename.mk:1: You can use \".\" instead of \"${WRKSRC}\".",
                   1378:                "NOTE: filename.mk:2: You can use \".\" instead of \"${WRKSRC}/\".",
                   1379:                "NOTE: filename.mk:3: You can use \".\" instead of \"${WRKSRC}/.\".",
                   1380:                "NOTE: filename.mk:4: You can use \"subdir\" instead of \"${WRKSRC}/subdir\".",
                   1381:                "NOTE: filename.mk:6: You can use \"directory\" instead of \"${WRKSRC}/directory\".",
                   1382:                "WARN: filename.mk:8: \"../other\" is not a valid subdirectory of ${WRKSRC}.",
                   1383:                "WARN: filename.mk:9: \"${WRKDIR}/sub\" is not a valid subdirectory of ${WRKSRC}.",
                   1384:                "WARN: filename.mk:10: \"${SRCDIR}/sub\" is not a valid subdirectory of ${WRKSRC}.")
1.13      rillig   1385: }
                   1386:
1.12      rillig   1387: func (s *Suite) Test_VartypeCheck_Yes(c *check.C) {
1.31      rillig   1388:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Yes)
1.21      rillig   1389:
1.31      rillig   1390:        vt.Varname("APACHE_MODULE")
                   1391:        vt.Values(
1.5       rillig   1392:                "yes",
                   1393:                "no",
                   1394:                "${YESVAR}")
1.1       rillig   1395:
1.31      rillig   1396:        vt.Output(
1.43      rillig   1397:                "WARN: filename.mk:2: APACHE_MODULE should be set to YES or yes.",
                   1398:                "WARN: filename.mk:3: APACHE_MODULE should be set to YES or yes.")
1.7       rillig   1399:
1.31      rillig   1400:        vt.Varname("PKG_DEVELOPER")
                   1401:        vt.Op(opUseMatch)
                   1402:        vt.Values(
1.7       rillig   1403:                "yes",
                   1404:                "no",
                   1405:                "${YESVAR}")
                   1406:
1.31      rillig   1407:        vt.Output(
1.43      rillig   1408:                "WARN: filename.mk:11: PKG_DEVELOPER should only be used in a \".if defined(...)\" condition.",
                   1409:                "WARN: filename.mk:12: PKG_DEVELOPER should only be used in a \".if defined(...)\" condition.",
                   1410:                "WARN: filename.mk:13: PKG_DEVELOPER should only be used in a \".if defined(...)\" condition.")
1.5       rillig   1411: }
1.1       rillig   1412:
1.12      rillig   1413: func (s *Suite) Test_VartypeCheck_YesNo(c *check.C) {
1.31      rillig   1414:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).YesNo)
1.21      rillig   1415:
1.31      rillig   1416:        vt.Varname("GNU_CONFIGURE")
                   1417:        vt.Values(
1.6       rillig   1418:                "yes",
                   1419:                "no",
                   1420:                "ja",
                   1421:                "${YESVAR}")
                   1422:
1.31      rillig   1423:        vt.Output(
1.43      rillig   1424:                "WARN: filename.mk:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.",
                   1425:                "WARN: filename.mk:4: GNU_CONFIGURE should be set to YES, yes, NO, or no.")
1.6       rillig   1426: }
                   1427:
1.12      rillig   1428: func (s *Suite) Test_VartypeCheck_YesNoIndirectly(c *check.C) {
1.31      rillig   1429:        vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).YesNoIndirectly)
1.21      rillig   1430:
1.31      rillig   1431:        vt.Varname("GNU_CONFIGURE")
                   1432:        vt.Values(
1.6       rillig   1433:                "yes",
                   1434:                "no",
                   1435:                "ja",
                   1436:                "${YESVAR}")
                   1437:
1.31      rillig   1438:        vt.Output(
1.43      rillig   1439:                "WARN: filename.mk:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.")
1.6       rillig   1440: }
                   1441:
1.31      rillig   1442: // VartypeCheckTester helps to test the many different checks in VartypeCheck.
1.36      rillig   1443: // It keeps track of the current variable, operator, filename, line number,
1.31      rillig   1444: // so that the test can focus on the interesting details.
                   1445: type VartypeCheckTester struct {
                   1446:        tester   *Tester
                   1447:        checker  func(cv *VartypeCheck)
1.36      rillig   1448:        filename string
1.31      rillig   1449:        lineno   int
                   1450:        varname  string
                   1451:        op       MkOperator
                   1452: }
                   1453:
1.36      rillig   1454: // NewVartypeCheckTester starts the test with a filename of "filename", at line 1,
1.31      rillig   1455: // with "=" as the operator. The variable has to be initialized explicitly.
                   1456: func NewVartypeCheckTester(t *Tester, checker func(cv *VartypeCheck)) *VartypeCheckTester {
1.40      rillig   1457:
                   1458:        // This is necessary to know whether the variable name is a list type
                   1459:        // since in such a case each value is split into the list elements.
1.47    ! rillig   1460:        if G.Pkgsrc.VariableType(nil, "USE_CWRAPPERS") == nil {
        !          1461:                t.SetUpVartypes()
        !          1462:        }
1.40      rillig   1463:
1.31      rillig   1464:        return &VartypeCheckTester{
                   1465:                t,
                   1466:                checker,
1.43      rillig   1467:                "filename.mk",
1.31      rillig   1468:                1,
                   1469:                "",
                   1470:                opAssign}
                   1471: }
                   1472:
                   1473: func (vt *VartypeCheckTester) Varname(varname string) {
                   1474:        vt.varname = varname
                   1475:        vt.nextSection()
                   1476: }
                   1477:
1.36      rillig   1478: func (vt *VartypeCheckTester) File(filename string) {
                   1479:        vt.filename = filename
1.31      rillig   1480:        vt.lineno = 1
                   1481: }
                   1482:
                   1483: // Op sets the operator for the following tests.
                   1484: // The line number is advanced to the next number ending in 1, e.g. 11, 21, 31.
                   1485: func (vt *VartypeCheckTester) Op(op MkOperator) {
                   1486:        vt.op = op
                   1487:        vt.nextSection()
                   1488: }
                   1489:
                   1490: // Values feeds each of the values to the actual check.
                   1491: // Each value is interpreted as if it were written verbatim into a Makefile line.
1.46      rillig   1492: // That is, # starts a comment.
                   1493: //
                   1494: // For the opUseMatch operator, all colons and closing braces must be escaped.
1.31      rillig   1495: func (vt *VartypeCheckTester) Values(values ...string) {
1.44      rillig   1496:
                   1497:        toText := func(value string) string {
1.31      rillig   1498:                op := vt.op
                   1499:                opStr := op.String()
                   1500:                varname := vt.varname
                   1501:
1.44      rillig   1502:                if op == opUseMatch {
                   1503:                        return sprintf(".if ${%s:M%s} == \"\"", varname, value)
                   1504:                }
                   1505:
                   1506:                if !contains(opStr, "=") {
1.31      rillig   1507:                        panic("Invalid operator: " + opStr)
                   1508:                }
                   1509:
1.44      rillig   1510:                space := ifelseStr(hasSuffix(varname, "+") && opStr == "=", " ", "")
                   1511:                return varname + space + opStr + value
                   1512:        }
                   1513:
1.45      rillig   1514:        test := func(mklines MkLines, mkline MkLine, value string) {
1.44      rillig   1515:                varname := vt.varname
1.31      rillig   1516:                comment := ""
                   1517:                if mkline.IsVarassign() {
                   1518:                        mkline.Tokenize(value, true) // Produce some warnings as side-effects.
                   1519:                        comment = mkline.VarassignComment()
                   1520:                }
                   1521:
                   1522:                effectiveValue := value
                   1523:                if mkline.IsVarassign() {
                   1524:                        effectiveValue = mkline.Value()
                   1525:                }
                   1526:
1.45      rillig   1527:                vartype := G.Pkgsrc.VariableType(nil, varname)
1.40      rillig   1528:
                   1529:                // See MkLineChecker.checkVartype.
                   1530:                var lineValues []string
1.46      rillig   1531:                if vartype == nil || !vartype.List() {
1.40      rillig   1532:                        lineValues = []string{effectiveValue}
                   1533:                } else {
1.45      rillig   1534:                        lineValues = mkline.ValueFields(effectiveValue)
1.40      rillig   1535:                }
                   1536:
                   1537:                for _, lineValue := range lineValues {
                   1538:                        valueNovar := mkline.WithoutMakeVariables(lineValue)
1.45      rillig   1539:                        vc := VartypeCheck{mklines, mkline, varname, vt.op, lineValue, valueNovar, comment, false}
1.40      rillig   1540:                        vt.checker(&vc)
                   1541:                }
1.44      rillig   1542:        }
1.31      rillig   1543:
1.44      rillig   1544:        for _, value := range values {
                   1545:                text := toText(value)
                   1546:
                   1547:                line := vt.tester.NewLine(vt.filename, vt.lineno, text)
                   1548:                mklines := NewMkLines(NewLines(vt.filename, []Line{line}))
1.31      rillig   1549:                vt.lineno++
1.44      rillig   1550:
1.45      rillig   1551:                mklines.ForEach(func(mkline MkLine) { test(mklines, mkline, value) })
1.5       rillig   1552:        }
1.1       rillig   1553: }
                   1554:
1.31      rillig   1555: // Output checks that the output from all previous steps is
                   1556: // the same as the expectedLines.
                   1557: func (vt *VartypeCheckTester) Output(expectedLines ...string) {
                   1558:        vt.tester.CheckOutputLines(expectedLines...)
1.45      rillig   1559:        vt.nextSection()
1.31      rillig   1560: }
                   1561:
                   1562: func (vt *VartypeCheckTester) OutputEmpty() {
                   1563:        vt.tester.CheckOutputEmpty()
1.45      rillig   1564:        vt.nextSection()
1.7       rillig   1565: }
                   1566:
1.31      rillig   1567: func (vt *VartypeCheckTester) nextSection() {
                   1568:        if vt.lineno%10 != 1 {
                   1569:                vt.lineno = vt.lineno - vt.lineno%10 + 11
1.5       rillig   1570:        }
1.1       rillig   1571: }

CVSweb <webmaster@jp.NetBSD.org>