package pkglint import "gopkg.in/check.v1" func (s *Suite) Test_Tool_UsableAtLoadTime(c *check.C) { t := s.Init(c) nowhere := Tool{"nowhere", "", false, Nowhere, nil, nil, nil} t.CheckEquals(nowhere.UsableAtLoadTime(false), false) t.CheckEquals(nowhere.UsableAtLoadTime(true), false) load := Tool{"load", "", false, AfterPrefsMk, nil, nil, nil} t.CheckEquals(load.UsableAtLoadTime(false), false) t.CheckEquals(load.UsableAtLoadTime(true), true) run := Tool{"run", "", false, AtRunTime, nil, nil, nil} t.CheckEquals(run.UsableAtLoadTime(false), false) t.CheckEquals(run.UsableAtLoadTime(true), false) } func (s *Suite) Test_Tool_UsableAtLoadTime__pkgconfig_builtin_mk(c *check.C) { t := s.Init(c) t.SetUpCommandLine("-Wall", "--explain") t.SetUpTool("tool1", "TOOL1", AfterPrefsMk) t.SetUpTool("tool2", "TOOL2", AfterPrefsMk) t.SetUpPackage("category/package") t.CreateFileLines("mk/buildlink3/pkgconfig-builtin.mk") t.FinishSetUp() mklines := t.SetUpFileMkLines("category/package/filename.mk", MkCvsID, "", "OUT!=\t${TOOL1} ${OUT}", "", ".include \"../../mk/buildlink3/pkgconfig-builtin.mk\"", "", "OUT!=\t${TOOL2} ${OUT}") mklines.Check() t.CheckOutputLines( "WARN: ~/category/package/filename.mk:3: " + "To use the tool ${TOOL1} at load time, " + "bsd.prefs.mk has to be included before.") // Maybe an explanation might help here. // There is surprisingly little feedback on any of the explanations // though (about 0 in 10 years), therefore I don't even know // whether anyone reads them. } func (s *Suite) Test_Tool_UsableAtRunTime(c *check.C) { t := s.Init(c) nowhere := Tool{"nowhere", "", false, Nowhere, nil, nil, nil} t.CheckEquals(nowhere.UsableAtRunTime(), false) load := Tool{"load", "", false, AfterPrefsMk, nil, nil, nil} t.CheckEquals(load.UsableAtRunTime(), true) run := Tool{"run", "", false, AtRunTime, nil, nil, nil} t.CheckEquals(run.UsableAtRunTime(), true) } func (s *Suite) Test_Tools__USE_TOOLS_predefined_sed(c *check.C) { t := s.Init(c) t.SetUpPkgsrc() t.CreateFileLines("mk/bsd.prefs.mk", "USE_TOOLS+=\tsed:pkgsrc") t.CreateFileLines("mk/tools/defaults.mk", "_TOOLS_VARNAME.sed=\tSED") t.CreateFileLines("module.mk", MkCvsID, "", "do-build:", "\t${SED} < input > output", "\t${AWK} < input > output") t.Main("-Wall", "module.mk") // Since this test doesn't load the usual tool definitions via // G.Pkgsrc.loadTools, AWK is not known at all. t.CheckOutputLines( "WARN: ~/module.mk:5: Unknown shell command \"${AWK}\".", "WARN: ~/module.mk:5: AWK is used but not defined.", "2 warnings found.", t.Shquote("(Run \"pkglint -e -Wall %s\" to show explanations.)", "module.mk")) } // It may happen that a tool is first defined without knowing its // variable name. When trying to define the tool with its variable name // later, the existing definition is amended. func (s *Suite) Test_Tools__add_varname_later(c *check.C) { t := s.Init(c) mkline := t.NewMkLine("dummy.mk", 123, "DUMMY=\tvalue") tools := NewTools() tool := tools.Define("tool", "", mkline) t.CheckEquals(tool.Name, "tool") t.CheckEquals(tool.Varname, "") // Updates the existing tool definition. tools.Define("tool", "TOOL", mkline) t.CheckEquals(tool.Name, "tool") t.CheckEquals(tool.Varname, "TOOL") } func (s *Suite) Test_Tools__load_from_infrastructure(c *check.C) { t := s.Init(c) tools := NewTools() // Only used for variable lookup, which is irrelevant for this test. dummyMklines := t.NewMkLines("dummy.mk") createMklines := t.NewMkLines("create.mk", MkCvsID, "TOOLS_CREATE+= load", "TOOLS_CREATE+= run", "TOOLS_CREATE+= nowhere") createMklines.ForEach(func(mkline *MkLine) { tools.ParseToolLine(createMklines, mkline, true, false) }) // The references to the tools are stable, // the lookup methods always return the same objects. load := tools.ByName("load") run := tools.ByName("run") nowhere := tools.ByName("nowhere") // All tools are defined by name, but their variable names are not yet known. // At this point they may not be used, neither by the pkgsrc infrastructure nor by a package. t.CheckEquals(load.String(), "load:::AtRunTime") t.CheckEquals(run.String(), "run:::AtRunTime") t.CheckEquals(nowhere.String(), "nowhere:::AtRunTime") // The variable name RUN is reserved by pkgsrc, therefore RUN_CMD. varnamesMklines := t.NewMkLines("varnames.mk", MkCvsID, "_TOOLS_VARNAME.load= LOAD", "_TOOLS_VARNAME.run= RUN_CMD", "_TOOLS_VARNAME.nowhere= NOWHERE") varnamesMklines.ForEach(func(mkline *MkLine) { tools.ParseToolLine(varnamesMklines, mkline, true, false) }) // At this point the tools can be found by their variable names, too. // They still may not be used. t.CheckEquals(load.String(), "load:LOAD::AtRunTime") t.CheckEquals(run.String(), "run:RUN_CMD::AtRunTime") t.CheckEquals(nowhere.String(), "nowhere:NOWHERE::AtRunTime") t.CheckEquals(tools.ByVarname("LOAD"), load) t.CheckEquals(tools.ByVarname("RUN_CMD"), run) t.CheckEquals(tools.ByVarname("NOWHERE"), nowhere) t.CheckEquals(load.String(), "load:LOAD::AtRunTime") t.CheckEquals(run.String(), "run:RUN_CMD::AtRunTime") t.CheckEquals(nowhere.String(), "nowhere:NOWHERE::AtRunTime") tools.ParseToolLine(dummyMklines, t.NewMkLine("bsd.prefs.mk", 2, "USE_TOOLS+= load"), true, true) // Tools that are added to USE_TOOLS in bsd.prefs.mk may be used afterwards. // By variable name, they may be used both at load time as well as run time. // By plain name, they may be used only in {pre,do,post}-* targets. t.CheckEquals(load.String(), "load:LOAD::AfterPrefsMk") tools.ParseToolLine(dummyMklines, t.NewMkLine("bsd.pkg.mk", 2, "USE_TOOLS+= run"), true, true) // Tools that are added to USE_TOOLS in bsd.pkg.mk may be used afterwards at run time. // The {pre,do,post}-* targets may use both forms (${CAT} and cat). // All other targets must use the variable form (${CAT}). t.CheckEquals(run.String(), "run:RUN_CMD::AtRunTime") // That's all for parsing tool definitions from the pkgsrc infrastructure. // See Test_Tools__package_Makefile for a continuation. } func (s *Suite) Test_Tools__package_Makefile(c *check.C) { t := s.Init(c) t.SetUpPkgsrc() t.CreateFileLines("mk/tools/defaults.mk", "TOOLS_CREATE+= load", "TOOLS_CREATE+= run", "TOOLS_CREATE+= nowhere", "TOOLS_CREATE+= pkg-before-prefs", "TOOLS_CREATE+= pkg-after-prefs", "_TOOLS_VARNAME.load= LOAD", "_TOOLS_VARNAME.run= RUN_CMD", "_TOOLS_VARNAME.nowhere= NOWHERE", "_TOOLS_VARNAME.pkg-before-prefs= PKG_BEFORE_PREFS", "_TOOLS_VARNAME.pkg-after-prefs= PKG_AFTER_PREFS") t.CreateFileLines("mk/bsd.prefs.mk", "USE_TOOLS+= load") t.CreateFileLines("mk/bsd.pkg.mk", "USE_TOOLS+= run") t.FinishSetUp() tools := NewTools() tools.Fallback(G.Pkgsrc.Tools) load := tools.ByName("load") run := tools.ByName("run") nowhere := tools.ByName("nowhere") before := tools.ByName("pkg-before-prefs") after := tools.ByName("pkg-after-prefs") t.CheckEquals(load.UsableAtRunTime(), true) t.CheckEquals(run.UsableAtRunTime(), true) t.CheckEquals(nowhere.UsableAtRunTime(), true) // The seenPrefs variable is only relevant for the package Makefile. // All other files must not use the tools at load time. // For them, seenPrefs can be thought of as being true from the beginning. // Only used for variable lookup, which is irrelevant for this test. dummyMklines := t.NewMkLines("dummy.mk") tools.ParseToolLine(dummyMklines, t.NewMkLine("Makefile", 2, "USE_TOOLS+= pkg-before-prefs"), false, true) t.CheckEquals(before.Validity, AfterPrefsMk) t.CheckEquals(tools.SeenPrefs, false) tools.ParseToolLine(dummyMklines, t.NewMkLine("Makefile", 3, ".include \"../../mk/bsd.prefs.mk\""), false, true) t.CheckEquals(tools.SeenPrefs, true) tools.ParseToolLine(dummyMklines, t.NewMkLine("Makefile", 4, "USE_TOOLS+= pkg-after-prefs"), false, true) t.CheckEquals(after.Validity, AtRunTime) } func (s *Suite) Test_Tools__builtin_mk(c *check.C) { t := s.Init(c) t.SetUpPkgsrc() t.CreateFileLines("mk/tools/defaults.mk", "TOOLS_CREATE+= load", "TOOLS_CREATE+= run", "TOOLS_CREATE+= nowhere", "_TOOLS_VARNAME.load= LOAD", "_TOOLS_VARNAME.run= RUN_CMD", "_TOOLS_VARNAME.nowhere= NOWHERE") t.CreateFileLines("mk/bsd.prefs.mk", "USE_TOOLS+= load") t.CreateFileLines("mk/bsd.pkg.mk", "USE_TOOLS+= run") t.CreateFileLines("mk/buildlink3/bsd.builtin.mk") t.FinishSetUp() // Tools that are defined by pkgsrc as load-time tools // may be used in any file at load time. mklines := t.SetUpFileMkLines("category/package/builtin.mk", MkCvsID, "", "VAR!=\t${ECHO} 'too early'", "VAR!=\t${LOAD} 'too early'", "VAR!=\t${RUN_CMD} 'never allowed'", "VAR!=\t${NOWHERE} 'never allowed'", "", ".include \"../../mk/buildlink3/bsd.builtin.mk\"", "", "VAR!=\t${ECHO} 'valid'", "VAR!=\t${LOAD} 'valid'", "VAR!=\t${RUN_CMD} 'never allowed'", "VAR!=\t${NOWHERE} 'never allowed'", "", "VAR!=\t${VAR}") mklines.Check() t.CheckOutputLines( "WARN: ~/category/package/builtin.mk:3: To use the tool ${ECHO} at load time, bsd.prefs.mk has to be included before.", "WARN: ~/category/package/builtin.mk:4: To use the tool ${LOAD} at load time, bsd.prefs.mk has to be included before.", "WARN: ~/category/package/builtin.mk:5: The tool ${RUN_CMD} cannot be used at load time.", "WARN: ~/category/package/builtin.mk:6: The tool ${NOWHERE} cannot be used at load time.", "WARN: ~/category/package/builtin.mk:12: The tool ${RUN_CMD} cannot be used at load time.", "WARN: ~/category/package/builtin.mk:13: The tool ${NOWHERE} cannot be used at load time.") } func (s *Suite) Test_Tools__implicit_definition_in_bsd_pkg_mk(c *check.C) { t := s.Init(c) t.SetUpPkgsrc() t.CreateFileLines("mk/tools/defaults.mk", MkCvsID) // None t.CreateFileLines("mk/bsd.prefs.mk", "USE_TOOLS+= load") t.CreateFileLines("mk/bsd.pkg.mk", "USE_TOOLS+= run") // It's practically impossible that a tool is added to USE_TOOLS in // bsd.pkg.mk and not defined earlier in mk/tools/defaults.mk, but // the pkglint code is even prepared for these rare cases. // In other words, this test is only there for the code coverage. t.FinishSetUp() t.CheckEquals(G.Pkgsrc.Tools.ByName("run").String(), "run:::AtRunTime") } func (s *Suite) Test_Tools__both_prefs_and_pkg_mk(c *check.C) { t := s.Init(c) t.SetUpPkgsrc() t.CreateFileLines("mk/tools/defaults.mk", MkCvsID) t.CreateFileLines("mk/bsd.prefs.mk", "USE_TOOLS+= both") t.CreateFileLines("mk/bsd.pkg.mk", "USE_TOOLS+= both") // The echo tool is mentioned in both files. The file bsd.prefs.mk // grants more use cases (load time + run time), therefore it wins. t.FinishSetUp() t.CheckEquals(G.Pkgsrc.Tools.ByName("both").Validity, AfterPrefsMk) } func (s *Suite) Test_Tools__tools_having_the_same_variable_name(c *check.C) { t := s.Init(c) t.SetUpPkgsrc() t.CreateFileLines("mk/tools/defaults.mk", "_TOOLS_VARNAME.awk= AWK", "_TOOLS_VARNAME.gawk= AWK", "_TOOLS_VARNAME.gsed= SED", "_TOOLS_VARNAME.sed= SED") t.CreateFileLines("mk/bsd.prefs.mk", "USE_TOOLS+= awk sed") t.FinishSetUp() t.CheckEquals(G.Pkgsrc.Tools.ByName("awk").Validity, AfterPrefsMk) t.CheckEquals(G.Pkgsrc.Tools.ByName("sed").Validity, AfterPrefsMk) t.CheckEquals(G.Pkgsrc.Tools.ByName("gawk").Validity, Nowhere) t.CheckEquals(G.Pkgsrc.Tools.ByName("gsed").Validity, Nowhere) t.EnableTracingToLog() G.Pkgsrc.Tools.Trace() t.DisableTracing() t.CheckOutputLines( "TRACE: + (*Tools).Trace()", "TRACE: 1 tool awk:AWK::AfterPrefsMk", "TRACE: 1 tool echo:ECHO:var:AfterPrefsMk", "TRACE: 1 tool echo -n:ECHO_N:var:AfterPrefsMk", "TRACE: 1 tool false:FALSE:var:AtRunTime", "TRACE: 1 tool gawk:AWK::Nowhere", "TRACE: 1 tool gsed:SED::Nowhere", "TRACE: 1 tool sed:SED::AfterPrefsMk", "TRACE: 1 tool test:TEST:var:AfterPrefsMk", "TRACE: 1 tool true:TRUE:var:AfterPrefsMk", "TRACE: - (*Tools).Trace()") tools := NewTools() tools.Fallback(G.Pkgsrc.Tools) t.EnableTracingToLog() tools.Trace() t.DisableTracing() t.CheckOutputLines( "TRACE: + (*Tools).Trace()", "TRACE: 1 + (*Tools).Trace()", "TRACE: 1 2 tool awk:AWK::AfterPrefsMk", "TRACE: 1 2 tool echo:ECHO:var:AfterPrefsMk", "TRACE: 1 2 tool echo -n:ECHO_N:var:AfterPrefsMk", "TRACE: 1 2 tool false:FALSE:var:AtRunTime", "TRACE: 1 2 tool gawk:AWK::Nowhere", "TRACE: 1 2 tool gsed:SED::Nowhere", "TRACE: 1 2 tool sed:SED::AfterPrefsMk", "TRACE: 1 2 tool test:TEST:var:AfterPrefsMk", "TRACE: 1 2 tool true:TRUE:var:AfterPrefsMk", "TRACE: 1 - (*Tools).Trace()", "TRACE: - (*Tools).Trace()") } func (s *Suite) Test_Tools__var(c *check.C) { t := s.Init(c) t.SetUpPkgsrc() t.CreateFileLines("mk/tools/defaults.mk", "TOOLS_CREATE+= ln", "_TOOLS_VARNAME.ln= LN") t.CreateFileLines("mk/bsd.pkg.mk", "USE_TOOLS+= ln") t.FinishSetUp() mklines := t.NewMkLines("module.mk", MkCvsID, "", "pre-configure:", "\t${LN} from to") mklines.Check() t.CheckOutputEmpty() } func (s *Suite) Test_Tools__aliases(c *check.C) { t := s.Init(c) mklines := t.NewMkLines("mk/tools/replace.mk", MkCvsID, "TOOLS_CREATE+=\tsed", "TOOLS_PATH.sed=\t/bin/sed", "", "TOOLS_CREATE+=\tgsed", "TOOLS_PATH.gsed=\t/bin/gnu-sed", "TOOLS_ALIASES.gsed=\tsed ${tool}") infraTools := NewTools() mklines.ForEach(func(mkline *MkLine) { infraTools.ParseToolLine(mklines, mkline, false, false) }) t.CheckEquals(infraTools.ByName("sed").String(), "sed:::AtRunTime") t.CheckEquals(infraTools.ByName("gsed").String(), "gsed:::AtRunTime:sed") pkgTools := NewTools() pkgTools.Fallback(infraTools) t.CheckEquals(pkgTools.ByName("sed").String(), "sed:::AtRunTime") t.CheckEquals(pkgTools.ByName("gsed").String(), "gsed:::AtRunTime:sed") mkline := t.NewMkLine("Makefile", 123, "USE_TOOLS+=\tgsed") pkgTools.ParseToolLine(mklines, mkline, false, false) // Since sed is an alias of gsed, it gets the same validity. t.CheckEquals(pkgTools.ByName("sed").String(), "sed:::AfterPrefsMk") t.CheckEquals(pkgTools.ByName("gsed").String(), "gsed:::AfterPrefsMk:sed") } func (s *Suite) Test_Tools__aliases_in_for_loop(c *check.C) { t := s.Init(c) mklines := t.NewMkLines("mk/tools/replace.mk", MkCvsID, "_TOOLS_GREP=\tgrep egrep fgrep", "TOOLS_CREATE+=\tgrep egrep fgrep ggrep", ".for t in ${_TOOLS_GREP}", "TOOLS_ALIASES.ggrep+=\t${t}", ".endfor") mklines.collectVariables(false, true) // calls ParseToolLine internally t.CheckDeepEquals( mklines.Tools.ByName("ggrep").Aliases, []string{"grep", "egrep", "fgrep"}) } // The cmake tool is included conditionally. The condition is so simple that // pkglint could parse it but it depends on the particular package. // This is something that pkglint cannot do right now, since the global tools // are loaded once for all packages. // // Therefore there is a workaround for USE_CMAKE. // // See mk/tools/cmake.mk. func (s *Suite) Test_Tools__cmake(c *check.C) { t := s.Init(c) t.SetUpPackage("category/package", "USE_CMAKE=\tyes", "", "do-test:", "\tcd ${WRKSRC} && cmake") t.CreateFileLines("mk/tools/defaults.mk", ".if defined(USE_CMAKE)", "USE_TOOLS+=\tcmake cpack", ".endif") t.FinishSetUp() G.Check(t.File("category/package")) t.CheckOutputEmpty() } func (s *Suite) Test_Tools__gmake(c *check.C) { t := s.Init(c) t.SetUpPackage("category/package", "USE_TOOLS=\tgmake", "", "do-test:", "\tcd ${WRKSRC} && make tests") t.CreateFileLines("mk/tools/bsd.tools.mk", ".include \"defaults.mk\"", ".include \"replace.mk\"", ".include \"make.mk\"") t.CreateFileLines("mk/tools/make.mk", "TOOLS_CREATE+=\tmake", "TOOLS_PATH.make=\t/usr/bin/make") t.CreateFileLines("mk/tools/replace.mk", "TOOLS_CREATE+=\tgmake", "TOOLS_PATH.gmake=\t/usr/bin/gnu-make") t.FinishSetUp() G.Check(t.File("category/package")) t.CheckOutputEmpty() } func (s *Suite) Test_Tools__autoconf213(c *check.C) { t := s.Init(c) t.SetUpPackage("category/package", "USE_TOOLS=\tautoconf213", "", "do-test:", "\tautoconf") t.CreateFileLines("mk/tools/defaults.mk", "_TOOLS_DEPMETHOD.autoconf213=\tDEPENDS") t.FinishSetUp() G.Check(t.File("category/package")) // No warning, since autoconf213 defines autoconf implicitly. t.CheckOutputEmpty() } func (s *Suite) Test_Tools_Define__invalid_tool_name(c *check.C) { t := s.Init(c) mkline := t.NewMkLine("dummy.mk", 123, "DUMMY=\tvalue") reg := NewTools() t.CheckNil(reg.Define("tool_name", "", mkline)) t.CheckNil(reg.Define("tool:dependency", "", mkline)) t.CheckNil(reg.Define("tool:build", "", mkline)) // As of October 2018, the underscore is not used in any tool name. // If there should ever be such a case, just use a different character for testing. t.CheckOutputLines( "ERROR: dummy.mk:123: Invalid tool name \"tool_name\".", "ERROR: dummy.mk:123: Invalid tool name \"tool:dependency\".", "ERROR: dummy.mk:123: Invalid tool name \"tool:build\".") t.CheckLen(reg.byName, 0) } func (s *Suite) Test_Tools_Trace__coverage(c *check.C) { t := s.Init(c) t.DisableTracing() reg := NewTools() reg.Trace() t.CheckOutputEmpty() } // USE_TOOLS is an operating-system-dependent variable. // Many other tool variables have the form VARNAME.${tool}, // which confused an earlier version of pkglint into // thinking that the below definition was about a tool // called "NetBSD". func (s *Suite) Test_Tools_ParseToolLine__opsys(c *check.C) { t := s.Init(c) t.SetUpTool("tool1", "", Nowhere) t.SetUpVartypes() t.CreateFileLines("Makefile", MkCvsID, "", "USE_TOOLS.NetBSD+=\ttool1") CheckdirToplevel(t.File(".")) // No error about "Unknown tool \"NetBSD\"." t.CheckOutputEmpty() } func (s *Suite) Test_Tools_ParseToolLine__invalid_tool_name(c *check.C) { t := s.Init(c) t.SetUpVartypes() mklines := t.NewMkLines("Makefile", MkCvsID, "", ".for t in abc ${UNDEFINED}", "TOOLS_CREATE+=\t\t${t}", "_TOOLS_VARNAME.${t}=\tVARNAME", "TOOLS_PATH.${t}=\t/bin/${t}", "TOOLS_ALIASES.${t}=\t${t} ${u} ${t}-arm64", "TOOLS_ALIASES.tool=\t${t} ${u} ${t}-arm64", "_TOOLS.${t}=\t${t}", ".endfor") mklines.collectVariables(false, true) t.CheckLen(mklines.Tools.byName, 1) t.CheckEquals(mklines.Tools.ByName("tool").String(), "tool:::Nowhere:abc") t.CheckOutputEmpty() } func (s *Suite) Test_Tools_ParseToolLine__private_tool_undefined(c *check.C) { t := s.Init(c) t.SetUpVartypes() mklines := t.NewMkLines("filename.mk", MkCvsID, "", "\tmd5sum filename") mklines.Check() t.CheckOutputLines( "WARN: filename.mk:3: Unknown shell command \"md5sum\".") } // Tools that are defined by a package by adding to TOOLS_CREATE can // be used without adding them to USE_TOOLS again. func (s *Suite) Test_Tools_ParseToolLine__private_tool_defined(c *check.C) { t := s.Init(c) t.SetUpVartypes() mklines := t.NewMkLines("filename.mk", MkCvsID, "TOOLS_CREATE+=\tmd5sum", "", "\tmd5sum filename") mklines.Check() t.CheckOutputEmpty() } func (s *Suite) Test_Tools_parseUseTools(c *check.C) { t := s.Init(c) t.SetUpPkgsrc() t.CreateFileLines("mk/triple-tool.mk", MkCvsID, "", "USE_TOOLS+=\tunknown unknown unknown") t.FinishSetUp() t.CheckNil(G.Pkgsrc.Tools.ByName("unknown")) t.CheckOutputEmpty() } // Demonstrates how the Tools type handles tools that share the same // variable name. Of these tools, the GNU variant is preferred. // // In this realistic variant, the non-GNU tool is defined in bsd.prefs.mk // and the GNU tool is only defined but not made available. // // See also Pkglint.Tool. func (s *Suite) Test_Tools_Fallback__tools_having_the_same_variable_name_realistic(c *check.C) { t := s.Init(c) nonGnu := NewTools() nonGnu.def("sed", "SED", false, AfterPrefsMk, nil) gnu := NewTools() gnu.def("gsed", "SED", false, Nowhere, nil) local1 := NewTools() local1.def("sed", "SED", false, AfterPrefsMk, nil) local1.Fallback(gnu) t.CheckEquals(local1.ByName("sed").Validity, AfterPrefsMk) t.CheckEquals(local1.ByName("gsed").Validity, Nowhere) local2 := NewTools() local2.def("gsed", "SED", false, Nowhere, nil) local2.Fallback(nonGnu) t.CheckEquals(local2.ByName("sed").Validity, AfterPrefsMk) t.CheckEquals(local2.ByName("gsed").Validity, Nowhere) // No matter in which order the tool definitions are encountered, // the non-GNU version is always chosen since the GNU version is // not available at all. t.CheckEquals(local1.ByVarname("SED").String(), "sed:SED::AfterPrefsMk") t.CheckEquals(local2.ByVarname("SED").String(), "sed:SED::AfterPrefsMk") } // Demonstrates how the Tools type handles tools that share the same // variable name. Of these tools, the GNU variant is preferred. // // In this unrealistic variant, the GNU tool is defined in bsd.prefs.mk // and the non-GNU tool is only defined but not made available. // // See also Pkglint.Tool. func (s *Suite) Test_Tools_Fallback__tools_having_the_same_variable_name_unrealistic(c *check.C) { t := s.Init(c) // This simulates a tool defined in the tools framework but not added // to USE_TOOLS, neither by bsd.prefs.mk nor by bsd.pkg.mk. nonGnu := NewTools() nonGnu.def("sed", "SED", false, Nowhere, nil) // This simulates a tool that is added to USE_TOOLS in bsd.prefs.mk. gnu := NewTools() gnu.def("gsed", "SED", false, AfterPrefsMk, nil) gnu.ByName("gsed").Aliases = []string{"sed"} // This simulates a package that doesn't mention the sed tool at all. // The call to .def() is therefore unrealistic. // Nevertheless, since the GNU tools define the gsed tool as well, // it is available even though not explicitly mentioned in the package. local1 := NewTools() local1.def("sed", "SED", false, Nowhere, nil) local1.Fallback(gnu) t.CheckEquals(local1.ByName("sed").Validity, Nowhere) t.CheckEquals(local1.ByName("gsed").Validity, AfterPrefsMk) local2 := NewTools() local2.def("gsed", "SED", false, AfterPrefsMk, []string{"sed"}) local2.Fallback(nonGnu) t.CheckEquals(local2.ByName("sed").Validity, AfterPrefsMk) t.CheckEquals(local2.ByName("gsed").Validity, AfterPrefsMk) t.CheckEquals(local1.ByVarname("SED").String(), "sed:SED::AfterPrefsMk") t.CheckEquals(local2.ByVarname("SED").String(), "sed:SED::AfterPrefsMk") } func (s *Suite) Test_Tools_Fallback__called_twice(c *check.C) { t := s.Init(c) tools := NewTools() fallback := NewTools() tools.Fallback(fallback) t.ExpectAssert(func() { tools.Fallback(fallback) }) } func (s *Suite) Test_Tools_IsValidToolName(c *check.C) { t := s.Init(c) t.SetUpVartypes() t.SetUpTool("[", "", AtRunTime) t.SetUpTool("echo -n", "ECHO_N", AtRunTime) mklines := t.NewMkLines("filename.mk", MkCvsID, "", "USE_TOOLS+=\t[") mklines.Check() t.CheckOutputEmpty() } func (s *Suite) Test_ToolTime_String(c *check.C) { t := s.Init(c) t.CheckEquals(LoadTime.String(), "LoadTime") t.CheckEquals(RunTime.String(), "RunTime") }