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>