func TestAddTarget(t *testing.T) { pkg := core.NewPackage("src/parse") addTargetTest1 := func(name string, binary, container, test bool, testCmd string) *core.BuildTarget { return addTarget(uintptr(unsafe.Pointer(pkg)), name, "true", testCmd, binary, test, false, false, container, false, false, false, 0, 0, 0, "Building...") } addTargetTest := func(name string, binary, container bool) *core.BuildTarget { return addTargetTest1(name, binary, container, false, "") } // Test that labels are correctly applied target1 := addTargetTest("target1", false, false) assert.False(t, target1.HasLabel("bin")) assert.False(t, target1.HasLabel("container")) target2 := addTargetTest("target2", true, false) assert.True(t, target2.HasLabel("bin")) assert.False(t, target2.HasLabel("container")) target3 := addTargetTest("target3", true, true) assert.True(t, target3.HasLabel("bin")) assert.True(t, target3.HasLabel("container")) assert.Panics(t, func() { addTargetTest(":target1", false, false) }, "Should return nil attempting to add a target with an illegal name") assert.Nil(t, addTargetTest("target1", false, false), "Should return nil attempting to add a new target with the same name") assert.Nil(t, core.State.Graph.Target(core.ParseBuildLabel("//src/parse:target1", "")), "Shouldn't have added target to the graph yet") core.State.Graph.AddPackage(pkg) addTargetTest("target6", true, false) target6 := core.State.Graph.Target(core.ParseBuildLabel("//src/parse:target6", "")) assert.NotNil(t, target6, "Should have been added to the graph since the package is added") assert.True(t, target6.HasLabel("bin")) }
func TestBuildLotsOfTargets(t *testing.T) { config, _ := core.ReadConfigFiles(nil) state := core.NewBuildState(numWorkers, nil, 4, config) pkg := core.NewPackage("pkg") state.Graph.AddPackage(pkg) for i := 1; i <= size; i++ { addTarget(state, i) } var wg sync.WaitGroup wg.Add(numWorkers) for i := 0; i < numWorkers; i++ { go func() { please(i, state) wg.Done() }() } // Consume and discard any results go func() { for result := range state.Results { assert.NotEqual(t, core.TargetBuildFailed, result.Status) log.Info("%s", result.Description) } }() state.TaskDone() // Initial target adding counts as one. wg.Wait() }
func makePackage(name string, targets ...string) *core.Package { pkg := core.NewPackage(name) for _, target := range targets { pkg.Targets[target] = nil } return pkg }
func loadSubincludePackage() { pkg := core.NewPackage(subincludePackage) // Set up a builtin package for remote subincludes. cPackageName := C.CString(pkg.Name) C.ParseCode(nil, cPackageName, sizep(pkg)) C.free(unsafe.Pointer(cPackageName)) core.State.Graph.AddPackage(pkg) }
func makeGraph() *core.BuildGraph { core.State = &core.BuildState{} graph := core.NewGraph() pkg1 := core.NewPackage("package1") pkg1.Targets["target1"] = makeTarget("//package1:target1") pkg1.Targets["target2"] = makeTarget("//package1:target2", "//package1:target1") graph.AddPackage(pkg1) graph.AddTarget(pkg1.Targets["target1"]) graph.AddTarget(pkg1.Targets["target2"]) pkg2 := core.NewPackage("package2") pkg2.Targets["target3"] = makeTarget("//package2:target3", "//package1:target2") graph.AddPackage(pkg2) graph.AddTarget(pkg2.Targets["target3"]) graph.AddDependency(core.ParseBuildLabel("//package1:target2", ""), core.ParseBuildLabel("//package1:target1", "")) graph.AddDependency(core.ParseBuildLabel("//package2:target3", ""), core.ParseBuildLabel("//package1:target2", "")) return graph }
func TestGetSubincludeFile(t *testing.T) { assertError := func(t *testing.T, ret, msg string) { assert.True(t, strings.HasPrefix(ret, "__"), msg) } state := core.NewBuildState(10, nil, 2, core.DefaultConfiguration()) pkg := core.NewPackage("src/parse") pkg2 := core.NewPackage("src/core") assert.Equal(t, pyDeferParse, getSubincludeFile(pkg, "//src/core:target"), "Package not loaded yet, should defer") assertError(t, getSubincludeFile(pkg, "//src/parse:target"), "Should produce an error on attempts for local subincludes.") assertError(t, getSubincludeFile(pkg, ":target"), "Should produce an error on attempts for local subincludes.") state.Graph.AddPackage(pkg) state.Graph.AddPackage(pkg2) assertError(t, getSubincludeFile(pkg, "//src/core:target"), "Produces an error, target does not exist in package.") target := core.NewBuildTarget(core.ParseBuildLabel("//src/core:target", "")) state.Graph.AddTarget(target) assertError(t, getSubincludeFile(pkg, "//src/core:target"), "Errors, target is not visible to subincluding package.") target.Visibility = []core.BuildLabel{core.ParseBuildLabel("//src/parse:all", "")} assertError(t, getSubincludeFile(pkg, "//src/core:target"), "Errors, target doesn't have any outputs to include.") target.AddOutput("test.py") assert.Equal(t, pyDeferParse, getSubincludeFile(pkg, "//src/core:target"), "Target isn't built yet, so still deferred") target.SetState(core.Built) assert.Equal(t, "plz-out/gen/src/core/test.py", getSubincludeFile(pkg, "//src/core:target"), "Success at last") }
// makeState creates a new build state with optionally one or two packages in it. // Used in various tests above. func makeState(withPackage1, withPackage2 bool) *core.BuildState { state := core.NewBuildState(5, nil, 4, core.DefaultConfiguration()) if withPackage1 { pkg := core.NewPackage("package1") state.Graph.AddPackage(pkg) pkg.Targets["target1"] = makeTarget("//package1:target1", "//package1:target2", "//package2:target1") pkg.Targets["target2"] = makeTarget("//package1:target2", "//package2:target1") pkg.Targets["target3"] = makeTarget("//package1:target3", "//package2:target2") state.Graph.AddTarget(pkg.Targets["target1"]) state.Graph.AddTarget(pkg.Targets["target2"]) state.Graph.AddTarget(pkg.Targets["target3"]) addDeps(state.Graph, pkg) } if withPackage2 { pkg := core.NewPackage("package2") state.Graph.AddPackage(pkg) pkg.Targets["target1"] = makeTarget("//package2:target1", "//package2:target2", "//package1:target3") pkg.Targets["target2"] = makeTarget("//package2:target2") state.Graph.AddTarget(pkg.Targets["target1"]) state.Graph.AddTarget(pkg.Targets["target2"]) addDeps(state.Graph, pkg) } return state }
func makeTarget(g *core.BuildGraph, packageName string, labelName string, outputs []string) *core.BuildTarget { l := core.ParseBuildLabel(fmt.Sprintf("//%s:%s", packageName, labelName), "") t := core.NewBuildTarget(l) p := g.Package(packageName) if p == nil { p = core.NewPackage(packageName) g.AddPackage(p) } for _, out := range outputs { t.AddOutput(out) p.MustRegisterOutput(out, t) } p.Targets[labelName] = t g.AddTarget(t) return t }
// parsePackage performs the initial parse of a package. // It's assumed that the caller used firstToParse to ascertain that they only call this once per package. func parsePackage(state *core.BuildState, label, dependor core.BuildLabel) *core.Package { packageName := label.PackageName pkg := core.NewPackage(packageName) if pkg.Filename = buildFileName(state, packageName); pkg.Filename == "" { exists := core.PathExists(packageName) // Handle quite a few cases to provide more obvious error messages. if dependor != core.OriginalTarget && exists { panic(fmt.Sprintf("%s depends on %s, but there's no BUILD file in %s/", dependor, label, packageName)) } else if dependor != core.OriginalTarget { panic(fmt.Sprintf("%s depends on %s, but the directory %s doesn't exist", dependor, label, packageName)) } else if exists { panic(fmt.Sprintf("Can't build %s; there's no BUILD file in %s/", label, packageName)) } panic(fmt.Sprintf("Can't build %s; the directory %s doesn't exist", label, packageName)) } if parsePackageFile(state, pkg.Filename, pkg) { return nil // Indicates deferral } for _, target := range pkg.Targets { state.Graph.AddTarget(target) for _, out := range target.DeclaredOutputs() { pkg.MustRegisterOutput(out, target) } for _, out := range target.TestOutputs { if !core.IsGlob(out) { pkg.MustRegisterOutput(out, target) } } } // Do this in a separate loop so we get intra-package dependencies right now. for _, target := range pkg.Targets { for _, dep := range target.DeclaredDependencies() { state.Graph.AddDependency(target.Label, dep) } } state.Graph.AddPackage(pkg) // Calling this means nobody else will add entries to pendingTargets for this package. return pkg }