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"))
}
Example #2
0
func makeTarget(label string, deps ...string) *core.BuildTarget {
	target := core.NewBuildTarget(core.ParseBuildLabel(label, ""))
	for _, dep := range deps {
		target.AddDependency(core.ParseBuildLabel(dep, ""))
	}
	return target
}
func TestDiffGraphsChangedHash(t *testing.T) {
	changes := readAndDiffGraphs("src/misc/test_data/before.json", "src/misc/test_data/changed_hash.json", nil, nil, nil)
	expected := []core.BuildLabel{
		core.ParseBuildLabel("//:all_tools", ""),
		core.ParseBuildLabel("//src/cache/server:http_cache_server_bin", ""),
	}
	assert.Equal(t, expected, changes)
}
func TestDiffGraphsSimple(t *testing.T) {
	changes := readAndDiffGraphs("src/misc/test_data/before.json", "src/misc/test_data/after.json", nil, nil, nil)
	expected := []core.BuildLabel{
		core.ParseBuildLabel("//src/misc:plz_diff_graphs", ""),
		core.ParseBuildLabel("//src/misc:plz_diff_graphs_test", ""),
	}
	assert.Equal(t, expected, changes)
}
func TestDiffGraphsRemovedPackage2(t *testing.T) {
	changes := readAndDiffGraphs("src/misc/test_data/removed_package.json", "src/misc/test_data/before.json", nil, nil, nil)
	expected := []core.BuildLabel{
		core.ParseBuildLabel("//:all_tools", ""),
		core.ParseBuildLabel("//src/cache/tools:cache_cleaner", ""),
		core.ParseBuildLabel("//src/cache/tools:cache_cleaner_platform", ""),
	}
	assert.Equal(t, expected, changes)
}
func TestDiffGraphsIncludeLabels(t *testing.T) {
	changes := readAndDiffGraphs("src/misc/test_data/before.json", "src/misc/test_data/labels2.json", nil, []string{"py"}, nil)
	expected := []core.BuildLabel{
		core.ParseBuildLabel("//src/build/python:pex_import_test", ""),
	}
	assert.Equal(t, expected, changes)
}
Example #7
0
func TestQuerySingleTarget(t *testing.T) {
	graph := makeJSONGraph(makeGraph(), []core.BuildLabel{core.ParseBuildLabel("//package1:target2", "")})
	assert.Equal(t, 1, len(graph.Packages))
	pkg1 := graph.Packages["package1"]
	assert.Equal(t, 2, len(pkg1.Targets))
	assert.Equal(t, []string{"//package1:target1"}, pkg1.Targets["target2"].Deps)
}
Example #8
0
func getSubincludeFile(pkg *core.Package, labelStr string) string {
	label := core.ParseBuildLabel(labelStr, pkg.Name)
	if label.PackageName == pkg.Name {
		return fmt.Sprintf("__Can't subinclude :%s in %s; can't subinclude local targets.", label.Name, pkg.Name)
	}
	pkgLabel := core.BuildLabel{PackageName: pkg.Name, Name: "all"}
	target := core.State.Graph.Target(label)
	if target == nil {
		// Might not have been parsed yet. Check for that first.
		if subincludePackage := core.State.Graph.Package(label.PackageName); subincludePackage == nil {
			if deferParse(label, pkg) {
				return pyDeferParse // Not an error, they'll just have to wait.
			}
			target = core.State.Graph.TargetOrDie(label) // Should be there now.
		} else {
			return fmt.Sprintf("__Failed to subinclude %s; package %s has no target by that name", label, label.PackageName)
		}
	} else if tmp := core.NewBuildTarget(pkgLabel); !tmp.CanSee(target) {
		return fmt.Sprintf("__Can't subinclude %s from %s due to visibility constraints", label, pkg.Name)
	} else if len(target.Outputs()) != 1 {
		return fmt.Sprintf("__Can't subinclude %s, subinclude targets must have exactly one output", label)
	} else if target.State() < core.Built {
		if deferParse(label, pkg) {
			return pyDeferParse // Again, they'll have to wait for this guy to build.
		}
	}
	pkg.RegisterSubinclude(target.Label)
	// Well if we made it to here it's actually ready to go, so tell them where to get it.
	return path.Join(target.OutDir(), target.Outputs()[0])
}
func newState(label string) (*core.BuildState, *core.BuildTarget) {
	config, _ := core.ReadConfigFiles(nil)
	state := core.NewBuildState(1, nil, 4, config)
	target := core.NewBuildTarget(core.ParseBuildLabel(label, ""))
	target.Command = fmt.Sprintf("echo 'output of %s' > $OUT", target.Label)
	state.Graph.AddTarget(target)
	return state, target
}
Example #10
0
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
}
Example #11
0
func newPyFilegroup(state *core.BuildState, label, filename string) *core.BuildTarget {
	target := core.NewBuildTarget(core.ParseBuildLabel(label, ""))
	target.AddSource(core.FileLabel{File: filename, Package: target.Label.PackageName})
	target.AddOutput(filename)
	target.AddLabel("py")
	target.Command = "__FILEGROUP__" // magic
	state.Graph.AddTarget(target)
	return target
}
func TestMapKeysContainFullPathFromProjectRoot(t *testing.T) {
	core.State = &core.BuildState{}
	graph := core.NewGraph()
	makeTarget(graph, "package1", "target1", []string{"out1", "out2"})
	makeTarget(graph, "package1", "target2", []string{"out3"})
	makeTarget(graph, "package2", "target1", []string{"out4"})
	m := filesToLabelMap(graph)
	label1 := core.ParseBuildLabel("//package1:target1", "")
	label2 := core.ParseBuildLabel("//package1:target2", "")
	label3 := core.ParseBuildLabel("//package2:target1", "")

	p1 := graph.PackageOrDie("package1")
	p2 := graph.PackageOrDie("package2")

	assert.Equal(t, m[path.Join(p1.Targets["target1"].OutDir(), "out1")].String(), label1.String())
	assert.Equal(t, m[path.Join(p1.Targets["target1"].OutDir(), "out2")].String(), label1.String())
	assert.Equal(t, m[path.Join(p1.Targets["target2"].OutDir(), "out3")].String(), label2.String())
	assert.Equal(t, m[path.Join(p2.Targets["target1"].OutDir(), "out4")].String(), label3.String())
}
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")
}
func TestGetLabels(t *testing.T) {
	state := core.NewBuildState(10, nil, 2, core.DefaultConfiguration())
	target1 := core.NewBuildTarget(core.ParseBuildLabel("//src/parse:target1", ""))
	target2 := core.NewBuildTarget(core.ParseBuildLabel("//src/parse:target2", ""))
	target3 := core.NewBuildTarget(core.ParseBuildLabel("//src/parse:target3", ""))
	target1.AddLabel("go")
	target2.AddLabel("py")
	target3.AddLabel("cc")
	target1.AddDependency(target2.Label)
	target1.AddDependency(target3.Label)
	target2.AddDependency(target3.Label)
	state.Graph.AddTarget(target1)
	state.Graph.AddTarget(target2)
	state.Graph.AddTarget(target3)
	state.Graph.AddDependency(target1.Label, target2.Label)
	state.Graph.AddDependency(target1.Label, target3.Label)
	state.Graph.AddDependency(target2.Label, target3.Label)
	// Note labels always come out in sorted order.
	assert.Equal(t, []string{"cc", "go", "py"}, getLabels(target1, "", core.Inactive))
	assert.Equal(t, []string{"cc", "py"}, getLabels(target2, "", core.Inactive))
	assert.Equal(t, []string{"cc"}, getLabels(target3, "", core.Inactive))
	assert.Equal(t, []string{"y"}, getLabels(target1, "p", core.Inactive))
}
func TestConstructsMapFromGraph(t *testing.T) {
	core.State = &core.BuildState{}
	graph := core.NewGraph()
	m := filesToLabelMap(graph)
	assert.Equal(t, 0, len(m))

	label := core.ParseBuildLabel("//package1:target1", "")
	makeTarget(graph, "package1", "target1", []string{"out1", "out2"})
	m = filesToLabelMap(graph)
	assert.Equal(t, 2, len(m))
	for _, l := range m {
		assert.Equal(t, label.String(), l.String())
	}
}
func makeTarget(name string, command string, dep *core.BuildTarget) *core.BuildTarget {
	target := core.NewBuildTarget(core.ParseBuildLabel(name, ""))
	target.Command = command
	target.AddOutput(target.Label.Name + ".py")
	if dep != nil {
		target.AddDependency(dep.Label)
		// This is a bit awkward but I don't want to add a public interface just for a test.
		graph := core.NewGraph()
		graph.AddTarget(target)
		graph.AddTarget(dep)
		graph.AddDependency(target.Label, dep.Label)
	}
	return target
}
// Replaces a single escape sequence in a command.
func replaceSequence(target *core.BuildTarget, in string, runnable, multiple, dir, outPrefix, hash, test bool) string {
	if core.LooksLikeABuildLabel(in) {
		label := core.ParseBuildLabel(in, target.Label.PackageName)
		return replaceSequenceLabel(target, label, in, runnable, multiple, dir, outPrefix, hash, test, true)
	}
	for _, src := range target.AllSources() {
		if label := src.Label(); label != nil && src.String() == in {
			return replaceSequenceLabel(target, *label, in, runnable, multiple, dir, outPrefix, hash, test, false)
		}
	}
	if hash {
		return base64.RawURLEncoding.EncodeToString(mustPathHash(path.Join(target.Label.PackageName, in)))
	}
	return quote(path.Join(target.Label.PackageName, in))
}
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
}
Example #19
0
func assertPendingBuilds(t *testing.T, state *core.BuildState, targets ...string) {
	state.Stop(1)
	pending := []core.BuildLabel{}
	for {
		label, _, typ := state.NextTask()
		if typ == core.Stop {
			break
		} else if typ != core.Build && typ != core.SubincludeBuild {
			t.Errorf("Unexpected non-build task")
		} else {
			pending = append(pending, label)
		}
	}
	expected := []core.BuildLabel{}
	for _, target := range targets {
		expected = append(expected, core.ParseBuildLabel(target, ""))
	}
	assert.Equal(t, expected, pending)
}
Example #20
0
// depsChanged returns true if any of the transitive dependencies of this target have changed.
// It marks any changes in allChanges for efficiency.
func depsChanged(graph *query.JSONGraph, allChanges map[string]bool, pkgName, targetName string, recurse bool) bool {
	label := fmt.Sprintf("//%s:%s", pkgName, targetName)
	changed, present := allChanges[label]
	if present {
		return changed
	}
	target := graph.Packages[pkgName].Targets[targetName]
	if !recurse {
		return false
	}
	for _, dep := range target.Deps {
		depLabel := core.ParseBuildLabel(dep, "")
		if depsChanged(graph, allChanges, depLabel.PackageName, depLabel.Name, recurse) {
			allChanges[label] = true
			return true
		}
	}
	allChanges[label] = false
	return false
}
func TestFindGraphCycle(t *testing.T) {
	graph := core.NewGraph()
	graph.AddTarget(makeTarget("//src/output:target1", "//src/output:target2", "//src/output:target3", "//src/core:target2"))
	graph.AddTarget(makeTarget("//src/output:target2", "//src/output:target3", "//src/core:target1"))
	graph.AddTarget(makeTarget("//src/output:target3"))
	graph.AddTarget(makeTarget("//src/core:target1", "//third_party/go:target2", "//third_party/go:target3", "//src/core:target3"))
	graph.AddTarget(makeTarget("//src/core:target2", "//third_party/go:target3", "//src/output:target2"))
	graph.AddTarget(makeTarget("//src/core:target3", "//third_party/go:target2", "//src/output:target2"))
	graph.AddTarget(makeTarget("//third_party/go:target2", "//third_party/go:target1"))
	graph.AddTarget(makeTarget("//third_party/go:target3", "//third_party/go:target1"))
	graph.AddTarget(makeTarget("//third_party/go:target1"))
	updateDependencies(graph)

	cycle := findGraphCycle(graph, graph.TargetOrDie(core.ParseBuildLabel("//src/output:target1", "")))
	if len(cycle) == 0 {
		t.Fatalf("Failed to find cycle")
	} else if len(cycle) != 3 {
		t.Errorf("Found unexpected cycle of length %d", len(cycle))
	}
	assertTarget(t, cycle[0], "//src/output:target2")
	assertTarget(t, cycle[1], "//src/core:target1")
	assertTarget(t, cycle[2], "//src/core:target3")
}
func makeTarget(label string) *core.BuildTarget {
	return core.NewBuildTarget(core.ParseBuildLabel(label, ""))
}
func assertTarget(t *testing.T, target *core.BuildTarget, label string) {
	if target.Label != core.ParseBuildLabel(label, "") {
		t.Errorf("Unexpected target in detected cycle; expected %s, was %s", label, target.Label)
	}
}
Example #24
0
func bl(label string) core.BuildLabel {
	return core.ParseBuildLabel(label, "")
}
func label(i int) core.BuildLabel {
	return core.ParseBuildLabel(fmt.Sprintf("//pkg:target%d", i), "")
}
Example #26
0
func buildLabel(bl string) core.BuildLabel {
	return core.ParseBuildLabel(bl, "")
}
func TestDiffGraphsChangedFile(t *testing.T) {
	changedFile := []string{"src/build/java/net/thoughtmachine/please/test/TestCoverage.java"}
	changes := readAndDiffGraphs("src/misc/test_data/before.json", "src/misc/test_data/before.json", changedFile, nil, nil)
	expected := []core.BuildLabel{
		core.ParseBuildLabel("//:all_tools", ""),
		core.ParseBuildLabel("//src/build/java:_junit_runner#jar", ""),
		core.ParseBuildLabel("//src/build/java:junit_runner", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:_junit_runner_parameterized_test#jar", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:_junit_runner_parameterized_test#lib", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:_junit_runner_test#jar", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:_junit_runner_test#lib", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:_please_coverage_class_loader_test#jar", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:_please_coverage_class_loader_test#lib", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:_resources_root_test#jar", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:_resources_root_test#lib", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:_test_coverage_test#jar", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:_test_coverage_test#lib", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:junit_runner", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:junit_runner_parameterized_test", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:junit_runner_test", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:please_coverage_class_loader_test", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:resources_root_test", ""),
		core.ParseBuildLabel("//src/build/java/net/thoughtmachine/please/test:test_coverage_test", ""),
	}
	assert.Equal(t, expected, changes)
}