github.com/sercand/please@v13.4.0+incompatible/src/core/build_target_test.go (about)

     1  // Tests on specific functions in build_target.go
     2  package core
     3  
     4  import (
     5  	"fmt"
     6  	"os"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  func TestTmpDir(t *testing.T) {
    13  	target := makeTarget("//mickey/donald:goofy", "")
    14  	assert.Equal(t, "plz-out/tmp/mickey/donald/goofy._build", target.TmpDir())
    15  }
    16  
    17  func TestOutDir(t *testing.T) {
    18  	target := makeTarget("//mickey/donald:goofy", "")
    19  	assert.Equal(t, "plz-out/gen/mickey/donald", target.OutDir())
    20  	target.IsBinary = true
    21  	assert.Equal(t, "plz-out/bin/mickey/donald", target.OutDir())
    22  }
    23  
    24  func TestTestDir(t *testing.T) {
    25  	target := makeTarget("//mickey/donald:goofy", "")
    26  	assert.Equal(t, "plz-out/tmp/mickey/donald/goofy._test", target.TestDir())
    27  }
    28  
    29  func TestTmpDirSubrepo(t *testing.T) {
    30  	target := makeTarget("@test_x86//mickey/donald:goofy", "")
    31  	assert.Equal(t, "plz-out/tmp/test_x86/mickey/donald/goofy._build", target.TmpDir())
    32  }
    33  
    34  func TestOutDirSubrepo(t *testing.T) {
    35  	target := makeTarget("@test_x86//mickey/donald:goofy", "")
    36  	assert.Equal(t, "plz-out/gen/test_x86/mickey/donald", target.OutDir())
    37  	target.IsBinary = true
    38  	assert.Equal(t, "plz-out/bin/test_x86/mickey/donald", target.OutDir())
    39  }
    40  
    41  func TestTestDirSubrepo(t *testing.T) {
    42  	target := makeTarget("@test_x86//mickey/donald:goofy", "")
    43  	assert.Equal(t, "plz-out/tmp/test_x86/mickey/donald/goofy._test", target.TestDir())
    44  }
    45  
    46  func TestCanSee(t *testing.T) {
    47  	state := NewDefaultBuildState()
    48  	target1 := makeTarget("//src/build/python:lib1", "")
    49  	target2 := makeTarget("//src/build/python:lib2", "PUBLIC")
    50  	target3 := makeTarget("//src/test/python:lib3", "//src/test/...")
    51  	target4 := makeTarget("//src/test/python/moar:lib4", "")
    52  
    53  	// target2 is public so anything can import it
    54  	assert.True(t, target3.CanSee(state, target2), "couldn't see public target")
    55  	assert.True(t, target4.CanSee(state, target2), "couldn't see public target")
    56  
    57  	// target1 is not public, other things can't import it
    58  	assert.False(t, target3.CanSee(state, target1), "could see private target")
    59  	assert.False(t, target4.CanSee(state, target1), "could see private target")
    60  
    61  	// target2 is in the same package as target1 so can implicitly see it
    62  	assert.True(t, target2.CanSee(state, target1), "couldn't see target in the same package")
    63  
    64  	// target3 is only visible to a subtree, things outside it can't see it
    65  	assert.False(t, target1.CanSee(state, target3), "could see target with restricted visibility")
    66  	assert.False(t, target2.CanSee(state, target3), "could see target with restricted visibility")
    67  
    68  	// Targets in that subtree can though.
    69  	assert.True(t, target4.CanSee(state, target3), "couldn't see target within its visibility spec")
    70  
    71  	// Sub-targets can see things visible to their parents.
    72  	target5 := makeTarget("//src/build/python:lib5", "//src/test/python:test5")
    73  	target6 := makeTarget("//src/test/python:_test5#pex", "")
    74  	assert.True(t, target6.CanSee(state, target5))
    75  	assert.False(t, target5.CanSee(state, target6))
    76  }
    77  
    78  func TestCanSeeExperimental(t *testing.T) {
    79  	config := DefaultConfiguration()
    80  	config.Parse.ExperimentalDir = []string{"experimental"}
    81  	state := NewBuildState(1, nil, 1, config)
    82  
    83  	target1 := makeTarget("//src/core:target1", "")
    84  	target2 := makeTarget("//experimental/user:target2", "PUBLIC")
    85  
    86  	// target2 can see target1 since it's in experimental, which suppress normal visibility constraints.
    87  	assert.True(t, target2.CanSee(state, target1))
    88  	// target1 can't see target2 because it's in experimental, even though it's public.
    89  	assert.False(t, target1.CanSee(state, target2))
    90  }
    91  
    92  func TestCheckDependencyVisibility(t *testing.T) {
    93  	target1 := makeTarget("//src/build/python:lib1", "")
    94  	target2 := makeTarget("//src/build/python:lib2", "PUBLIC", target1)
    95  	target3 := makeTarget("//src/test/python:lib3", "//src/test/...", target2)
    96  	target4 := makeTarget("//src/test/python/moar:lib4", "//src/test/...", target3)
    97  	target5 := makeTarget("//third_party/python:mock", "PUBLIC")
    98  	target5.TestOnly = true
    99  	target6 := makeTarget("//src/test/python:test_lib", "", target5)
   100  	target6.TestOnly = true
   101  	target7 := makeTarget("//src/test/python:test1", "", target5, target4)
   102  	target7.IsTest = true
   103  
   104  	state := NewDefaultBuildState()
   105  	state.Graph.AddTarget(target1)
   106  	state.Graph.AddTarget(target2)
   107  	state.Graph.AddTarget(target3)
   108  	state.Graph.AddTarget(target4)
   109  	state.Graph.AddTarget(target5)
   110  	state.Graph.AddTarget(target6)
   111  	state.Graph.AddTarget(target7)
   112  
   113  	// Deps should all be correct at this point
   114  	assert.NoError(t, target1.CheckDependencyVisibility(state))
   115  	assert.NoError(t, target2.CheckDependencyVisibility(state))
   116  	assert.NoError(t, target3.CheckDependencyVisibility(state))
   117  	assert.NoError(t, target4.CheckDependencyVisibility(state))
   118  	assert.NoError(t, target5.CheckDependencyVisibility(state))
   119  	assert.NoError(t, target6.CheckDependencyVisibility(state))
   120  	assert.NoError(t, target7.CheckDependencyVisibility(state))
   121  
   122  	// Now if we add a dep on this mock library, lib2 will fail because it's not a test.
   123  	target2.resolveDependency(target5.Label, target5)
   124  	assert.Error(t, target2.CheckDependencyVisibility(state))
   125  
   126  	// Similarly to above test, if we add a dep on something that can't be seen, we should
   127  	// get errors back from this function.
   128  	target3.resolveDependency(target1.Label, target1)
   129  	assert.Error(t, target3.CheckDependencyVisibility(state))
   130  }
   131  
   132  func TestAddOutput(t *testing.T) {
   133  	target := makeTarget("//src/test/python:lib1", "")
   134  	target.AddOutput("thingy.py")
   135  	target.AddOutput("thingy2.py")
   136  	target.AddOutput("thingy.py")
   137  	if len(target.Outputs()) != 2 {
   138  		t.Errorf("Incorrect output length; should be 2, was %d", len(target.Outputs()))
   139  	}
   140  }
   141  
   142  func TestAddOutputSorting(t *testing.T) {
   143  	target := makeTarget("//src/test/python:lib1", "")
   144  	target.AddOutput("1.py")
   145  	target.AddOutput("2.py")
   146  	target.AddOutput("1.py")
   147  	target.AddOutput("3.py")
   148  	target.AddOutput("1.pyx")
   149  	target.AddOutput("x.pyx")
   150  	expected := []string{
   151  		"1.py",
   152  		"1.pyx",
   153  		"2.py",
   154  		"3.py",
   155  		"x.pyx",
   156  	}
   157  	assert.Equal(t, expected, target.Outputs())
   158  }
   159  
   160  func TestAddOutputPanics(t *testing.T) {
   161  	target := makeTarget("//src/test/python:lib1", "")
   162  	assert.Panics(t, func() { target.AddOutput("") })
   163  	assert.Panics(t, func() { target.AddOptionalOutput("") })
   164  	assert.Panics(t, func() { target.AddTestOutput("") })
   165  	assert.Panics(t, func() { target.AddNamedOutput("", "") })
   166  }
   167  
   168  func TestAddSource(t *testing.T) {
   169  	target := makeTarget("//src/test/python:lib1", "")
   170  	target.AddSource(ParseBuildLabel("//src/test/python:lib2", ""))
   171  	target.AddSource(ParseBuildLabel("//src/test/python:lib3", ""))
   172  	target.AddSource(ParseBuildLabel("//src/test/python:lib2", ""))
   173  	assert.Equal(t, 2, len(target.Sources))
   174  	assert.Equal(t, 2, len(target.DeclaredDependencies()))
   175  }
   176  
   177  func TestSetContainerSettings(t *testing.T) {
   178  	target := makeTarget("//src/test/python:lib1", "")
   179  
   180  	target.SetContainerSetting("dockerimage", "tm/special_image:v2")
   181  	assert.Equal(t, "tm/special_image:v2", target.ContainerSettings.DockerImage)
   182  
   183  	target.SetContainerSetting("dockeruser", "")
   184  	assert.Equal(t, "", target.ContainerSettings.DockerUser)
   185  }
   186  
   187  func TestOutputs(t *testing.T) {
   188  	target1 := makeTarget("//src/core:target1", "PUBLIC")
   189  	target1.AddOutput("file1.go")
   190  	target1.AddOutput("file2.go")
   191  	target2 := makeFilegroup("//src/test:target2", "PUBLIC", target1)
   192  	target2.AddSource(target1.Label)
   193  	addFilegroupSource(target2, "file3.go")
   194  	target3 := makeFilegroup("//src/test:target3", "PUBLIC", target2)
   195  	target3.AddSource(target2.Label)
   196  	addFilegroupSource(target3, "file4.go")
   197  
   198  	assert.Equal(t, []string{"file1.go", "file2.go"}, target1.Outputs())
   199  	assert.Equal(t, []string{"file1.go", "file2.go", "file3.go"}, target2.Outputs())
   200  	assert.Equal(t, []string{"file1.go", "file2.go", "file3.go", "file4.go"}, target3.Outputs())
   201  }
   202  
   203  func TestFullOutputs(t *testing.T) {
   204  	target := makeTarget("//src/core:target1", "PUBLIC")
   205  	target.AddOutput("file1.go")
   206  	target.AddOutput("file2.go")
   207  	assert.Equal(t, []string{"plz-out/gen/src/core/file1.go", "plz-out/gen/src/core/file2.go"}, target.FullOutputs())
   208  }
   209  
   210  func TestProvideFor(t *testing.T) {
   211  	// target1 is provided directly since they have a simple dependency
   212  	target1 := makeTarget("//src/core:target1", "PUBLIC")
   213  	target2 := makeTarget("//src/core:target2", "PUBLIC", target1)
   214  	assert.Equal(t, []BuildLabel{target1.Label}, target1.ProvideFor(target2))
   215  	// Now have target2 provide target1. target3 will get target1 instead.
   216  	target2.Provides = map[string]BuildLabel{"whatevs": target1.Label}
   217  	target3 := makeTarget("//src/core:target3", "PUBLIC", target2)
   218  	target3.Requires = append(target3.Requires, "whatevs")
   219  	assert.Equal(t, []BuildLabel{target1.Label}, target2.ProvideFor(target3))
   220  	// Now target4 has a data dependency on target2. It has the same requirement as target3 but
   221  	// it gets target2 instead of target1, because that's just how data deps work.
   222  	target4 := makeTarget("//src/core:target4", "PUBLIC", target2)
   223  	target4.Data = append(target4.Data, target2.Label)
   224  	target4.Requires = append(target4.Requires, "whatevs")
   225  	assert.Equal(t, []BuildLabel{target2.Label}, target2.ProvideFor(target4))
   226  }
   227  
   228  func TestAddProvide(t *testing.T) {
   229  	target1 := makeTarget("//src/core:target1", "PUBLIC")
   230  	target2 := makeTarget("//src/core:target2", "PUBLIC", target1)
   231  	target3 := makeTarget("//src/core:target3", "PUBLIC", target2)
   232  	target2.AddDependency(target1.Label)
   233  	target2.AddProvide("go", ParseBuildLabel(":target1", "src/core"))
   234  	target3.Requires = append(target3.Requires, "go")
   235  	assert.Equal(t, []BuildLabel{target1.Label}, target2.ProvideFor(target3))
   236  }
   237  
   238  func TestAddDatum(t *testing.T) {
   239  	target1 := makeTarget("//src/core:target1", "PUBLIC")
   240  	target2 := makeTarget("//src/core:target2", "PUBLIC")
   241  	target1.AddDatum(target2.Label)
   242  	assert.Equal(t, target1.Data, []BuildInput{target2.Label})
   243  	assert.True(t, target1.dependencies[0].data)
   244  	// Now we add it as a dependency too, which unsets the data label
   245  	target1.AddMaybeExportedDependency(target2.Label, false, false)
   246  	assert.False(t, target1.dependencies[0].data)
   247  }
   248  
   249  func TestCheckDuplicateOutputs(t *testing.T) {
   250  	target1 := makeFilegroup("//src/core:target1", "PUBLIC")
   251  	target3 := makeFilegroup("//src/core:target3", "PUBLIC")
   252  	target2 := makeFilegroup("//src/core:target2", "PUBLIC", target1, target3)
   253  	addFilegroupSource(target1, "thingy.txt")
   254  	addFilegroupSource(target3, "thingy.txt")
   255  	assert.NoError(t, target1.CheckDuplicateOutputs())
   256  	target2.AddSource(target1.Label)
   257  	target2.AddSource(target1.Label)
   258  	// Not an error yet because AddOutput deduplicates trivially identical outputs.
   259  	assert.NoError(t, target2.CheckDuplicateOutputs())
   260  	// Will fail now we add the same output to another target.
   261  	target2.AddSource(target3.Label)
   262  	assert.Error(t, target2.CheckDuplicateOutputs())
   263  }
   264  
   265  func TestLabels(t *testing.T) {
   266  	target := makeTarget("//src/core:target1", "PUBLIC")
   267  	assert.False(t, target.HasLabel("py"))
   268  	assert.False(t, target.HasAnyLabel([]string{"py", "go"}))
   269  	target.AddLabel("py")
   270  	assert.True(t, target.HasLabel("py"))
   271  	assert.True(t, target.HasAnyLabel([]string{"py", "go"}))
   272  	target.AddLabel("py")
   273  	target.AddLabel("go")
   274  	assert.Equal(t, 2, len(target.Labels))
   275  	// "test" label is implicit on tests.
   276  	assert.False(t, target.HasLabel("test"))
   277  	target.IsTest = true
   278  	assert.True(t, target.HasLabel("test"))
   279  }
   280  
   281  func TestGetCommandConfig(t *testing.T) {
   282  	target := makeTarget("//src/core:target1", "PUBLIC")
   283  	target.Command = "test1"
   284  	assert.Equal(t, "test1", target.GetCommandConfig(""))
   285  	target.Command = ""
   286  	target.AddCommand("opt", "test3")
   287  	target.AddCommand("dbg", "test4")
   288  	assert.Equal(t, "test3", target.GetCommandConfig("opt"))
   289  	assert.Equal(t, "test4", target.GetCommandConfig("dbg"))
   290  }
   291  
   292  func TestGetCommand(t *testing.T) {
   293  	state := NewDefaultBuildState()
   294  	state.Config.Build.Config = "dbg"
   295  	state.Config.Build.FallbackConfig = "opt"
   296  	target := makeTarget("//src/core:target1", "PUBLIC")
   297  	target.Command = "test1"
   298  	assert.Equal(t, "test1", target.GetCommand(state))
   299  	assert.Panics(t, func() { target.AddCommand("opt", "test2") },
   300  		"Should panic when adding a config command to a target with a command already")
   301  	target.Command = ""
   302  	target.AddCommand("opt", "test3")
   303  	target.AddCommand("dbg", "test4")
   304  	assert.Equal(t, "test4", target.GetCommand(state), "Current config is dbg")
   305  	state.Config.Build.Config = "opt"
   306  	assert.Equal(t, "test3", target.GetCommand(state), "Current config is opt")
   307  	state.Config.Build.Config = "fast"
   308  	assert.Equal(t, "test3", target.GetCommand(state), "Default config is opt, should fall back to that")
   309  }
   310  
   311  func TestGetTestCommand(t *testing.T) {
   312  	state := NewDefaultBuildState()
   313  	state.Config.Build.Config = "dbg"
   314  	state.Config.Build.FallbackConfig = "opt"
   315  	target := makeTarget("//src/core:target1", "PUBLIC")
   316  	target.TestCommand = "test1"
   317  	assert.Equal(t, "test1", target.GetTestCommand(state))
   318  	assert.Panics(t, func() { target.AddTestCommand("opt", "test2") },
   319  		"Should panic when adding a config command to a target with a command already")
   320  	target.TestCommand = ""
   321  	target.AddTestCommand("opt", "test3")
   322  	target.AddTestCommand("dbg", "test4")
   323  	assert.Equal(t, "test4", target.GetTestCommand(state), "Current config is dbg")
   324  	state.Config.Build.Config = "opt"
   325  	assert.Equal(t, "test3", target.GetTestCommand(state), "Current config is opt")
   326  	state.Config.Build.Config = "fast"
   327  	assert.Equal(t, "test3", target.GetTestCommand(state), "Default config is opt, should fall back to that")
   328  }
   329  
   330  func TestHasSource(t *testing.T) {
   331  	target := makeTarget("//src/core:target1", "")
   332  	target.Sources = append(target.Sources, FileLabel{File: "file1.go"})
   333  	target.AddNamedSource("wevs", FileLabel{File: "file2.go"})
   334  	assert.True(t, target.HasSource("file1.go"))
   335  	assert.True(t, target.HasSource("file2.go"))
   336  	assert.False(t, target.HasSource("file3.go"))
   337  }
   338  
   339  func TestHasAbsoluteSource(t *testing.T) {
   340  	target := makeTarget("//src/core:target1", "")
   341  	target.Sources = append(target.Sources, FileLabel{File: "file1.go"})
   342  	target.AddNamedSource("wevs", FileLabel{File: "file2.go"})
   343  	assert.False(t, target.HasSource("src/core/file1.go"))
   344  	assert.True(t, target.HasAbsoluteSource("src/core/file1.go"))
   345  	assert.True(t, target.HasAbsoluteSource("src/core/file2.go"))
   346  	assert.False(t, target.HasSource("src/core/file3.go"))
   347  }
   348  
   349  func TestToolPath(t *testing.T) {
   350  	target := makeTarget("//src/core:target1", "")
   351  	target.AddOutput("file1.go")
   352  	target.AddOutput("file2.go")
   353  	wd, _ := os.Getwd()
   354  	root := wd + "/plz-out/gen/src/core"
   355  	assert.Equal(t, fmt.Sprintf("%s/file1.go %s/file2.go", root, root), target.toolPath())
   356  }
   357  
   358  func TestDependencies(t *testing.T) {
   359  	target1 := makeTarget("//src/core:target1", "")
   360  	target2 := makeTarget("//src/core:target2", "", target1)
   361  	target3 := makeTarget("//src/core:target3", "", target1, target2)
   362  	assert.Equal(t, []BuildLabel{}, target1.DeclaredDependencies())
   363  	assert.Equal(t, []*BuildTarget{}, target1.Dependencies())
   364  	assert.Equal(t, []BuildLabel{target1.Label}, target2.DeclaredDependencies())
   365  	assert.Equal(t, []*BuildTarget{target1}, target2.Dependencies())
   366  	assert.Equal(t, []BuildLabel{target1.Label, target2.Label}, target3.DeclaredDependencies())
   367  	assert.Equal(t, []*BuildTarget{target1, target2}, target3.Dependencies())
   368  }
   369  
   370  func TestBuildDependencies(t *testing.T) {
   371  	target1 := makeTarget("//src/core:target1", "")
   372  	target2 := makeTarget("//src/core:target2", "", target1)
   373  	target3 := makeTarget("//src/core:target3", "", target2)
   374  	target3.AddDatum(target1.Label)
   375  	assert.Equal(t, []*BuildTarget{}, target1.BuildDependencies())
   376  	assert.Equal(t, []*BuildTarget{target1}, target2.BuildDependencies())
   377  	assert.Equal(t, []*BuildTarget{target2}, target3.BuildDependencies())
   378  }
   379  
   380  func TestDeclaredDependenciesStrict(t *testing.T) {
   381  	target1 := makeTarget("//src/core:target1", "")
   382  	target2 := makeTarget("//src/core:target2", "", target1)
   383  	target3 := makeTarget("//src/core:target3", "", target2)
   384  	target3.AddMaybeExportedDependency(target1.Label, true, false)
   385  	assert.Equal(t, []BuildLabel{}, target1.DeclaredDependenciesStrict())
   386  	assert.Equal(t, []BuildLabel{target1.Label}, target2.DeclaredDependenciesStrict())
   387  	assert.Equal(t, []BuildLabel{target2.Label}, target3.DeclaredDependenciesStrict())
   388  }
   389  
   390  func TestAddDependency(t *testing.T) {
   391  	target1 := makeTarget("//src/core:target1", "")
   392  	target2 := makeTarget("//src/core:target2", "")
   393  	assert.Equal(t, []BuildLabel{}, target2.DeclaredDependencies())
   394  	assert.Equal(t, []BuildLabel{}, target2.ExportedDependencies())
   395  	target2.AddDependency(target1.Label)
   396  	assert.Equal(t, []BuildLabel{target1.Label}, target2.DeclaredDependencies())
   397  	assert.Equal(t, []BuildLabel{}, target2.ExportedDependencies())
   398  	target2.AddMaybeExportedDependency(target1.Label, true, false)
   399  	assert.Equal(t, []BuildLabel{target1.Label}, target2.DeclaredDependencies())
   400  	assert.Equal(t, []BuildLabel{target1.Label}, target2.ExportedDependencies())
   401  	assert.Equal(t, []*BuildTarget{}, target2.Dependencies())
   402  	target2.resolveDependency(target1.Label, target1)
   403  	assert.Equal(t, []*BuildTarget{target1}, target2.Dependencies())
   404  }
   405  
   406  func TestAddDependencySource(t *testing.T) {
   407  	target1 := makeTarget("//src/core:target1", "")
   408  	target2 := makeTarget("//src/core:target2", "")
   409  	target2.AddMaybeExportedDependency(target1.Label, true, true)
   410  	assert.True(t, target2.IsSourceOnlyDep(target1.Label))
   411  	// N.B. It's important that calling this again cancels the source flag.
   412  	target2.AddMaybeExportedDependency(target1.Label, true, false)
   413  	assert.False(t, target2.IsSourceOnlyDep(target1.Label))
   414  }
   415  
   416  func TestDependencyFor(t *testing.T) {
   417  	target1 := makeTarget("//src/core:target1", "")
   418  	target2 := makeTarget("//src/core:target2", "", target1)
   419  	assert.Equal(t, []*BuildTarget{target1}, target2.DependenciesFor(target1.Label))
   420  	assert.Equal(t, []*BuildTarget(nil), target2.DependenciesFor(target2.Label))
   421  	assert.Equal(t, 1, len(target2.dependencies))
   422  }
   423  
   424  func TestParent(t *testing.T) {
   425  	// "grandchild" is of course a misnomer since we only really have a concept of
   426  	// one level of parent-child relationship.
   427  	grandchild := makeTarget("//src/core:__target1#child#grandchild", "")
   428  	child := makeTarget("//src/core:_target1#child", "", grandchild)
   429  	parent := makeTarget("//src/core:target1", "", child)
   430  	graph := NewGraph()
   431  	graph.AddTarget(grandchild)
   432  	graph.AddTarget(child)
   433  	graph.AddTarget(parent)
   434  
   435  	assert.Equal(t, parent.Label, grandchild.Label.Parent())
   436  	assert.Equal(t, parent.Label, child.Label.Parent())
   437  	assert.Equal(t, parent.Label, parent.Label.Parent())
   438  	assert.Equal(t, parent, grandchild.Parent(graph))
   439  	assert.Equal(t, parent, child.Parent(graph))
   440  	assert.Equal(t, (*BuildTarget)(nil), parent.Parent(graph))
   441  }
   442  
   443  func TestHasParent(t *testing.T) {
   444  	grandchild := makeTarget("//src/core:__target1#child#grandchild", "")
   445  	child := makeTarget("//src/core:_target1#child", "", grandchild)
   446  	parent := makeTarget("//src/core:target1", "", child)
   447  	assert.True(t, grandchild.HasParent())
   448  	assert.True(t, child.HasParent())
   449  	assert.False(t, parent.HasParent())
   450  }
   451  
   452  func TestOutMode(t *testing.T) {
   453  	// Check that output modes match the binary flag correctly.
   454  	// This feels a little fatuous but it's hard to have any less specific assertions on it.
   455  	target := makeTarget("//src/core:target1", "")
   456  	assert.Equal(t, os.FileMode(0444), target.OutMode())
   457  	target.IsBinary = true
   458  	assert.Equal(t, os.FileMode(0555), target.OutMode())
   459  }
   460  
   461  func TestOutputOrdering(t *testing.T) {
   462  	// Check that outputs come out ordered, this is important for hash stability; previously
   463  	// we preserved the original order, but tools like buildifier may reorder them assuming
   464  	// that the order of arguments is not important.
   465  	target1 := makeTarget("//src/core:target1", "")
   466  	target1.AddOutput("file1.txt")
   467  	target1.AddOutput("file2.txt")
   468  	target2 := makeTarget("//src/core:target2", "")
   469  	target2.AddOutput("file2.txt")
   470  	target2.AddOutput("file1.txt")
   471  	assert.Equal(t, target1.DeclaredOutputs(), target2.DeclaredOutputs())
   472  	assert.Equal(t, target1.Outputs(), target2.Outputs())
   473  }
   474  
   475  func TestNamedOutputs(t *testing.T) {
   476  	target := makeTarget("//src/core:target1", "")
   477  	target.AddOutput("a.txt")
   478  	target.AddOutput("z.txt")
   479  	target.AddNamedOutput("srcs", "src1.c")
   480  	target.AddNamedOutput("srcs", "src2.c")
   481  	target.AddNamedOutput("hdrs", "hdr1.h")
   482  	target.AddNamedOutput("hdrs", "hdr2.h")
   483  	target.AddNamedOutput("hdrs", "hdr2.h") // deliberate duplicate
   484  	assert.Equal(t, []string{"a.txt", "hdr1.h", "hdr2.h", "src1.c", "src2.c", "z.txt"}, target.Outputs())
   485  	assert.Equal(t, []string{"a.txt", "z.txt"}, target.DeclaredOutputs())
   486  	assert.Equal(t, map[string][]string{"srcs": {"src1.c", "src2.c"}, "hdrs": {"hdr1.h", "hdr2.h"}}, target.DeclaredNamedOutputs())
   487  	assert.Equal(t, []string{"hdr1.h", "hdr2.h"}, target.NamedOutputs("hdrs"))
   488  	assert.Equal(t, []string{"src1.c", "src2.c"}, target.NamedOutputs("srcs"))
   489  	assert.Equal(t, 0, len(target.NamedOutputs("go_srcs")))
   490  	assert.Equal(t, []string{"hdrs", "srcs"}, target.DeclaredOutputNames())
   491  }
   492  
   493  func TestAllLocalSources(t *testing.T) {
   494  	target := makeTarget("//src/core:target1", "")
   495  	target.AddSource(FileLabel{File: "target1.go", Package: "src/core"})
   496  	target.AddSource(BuildLabel{Name: "target2", PackageName: "src/core"})
   497  	target.AddSource(SystemFileLabel{Path: "/usr/bin/bash"})
   498  	assert.Equal(t, []string{"src/core/target1.go"}, target.AllLocalSources())
   499  }
   500  
   501  func TestCheckSecrets(t *testing.T) {
   502  	target := makeTarget("//src/core:target1", "")
   503  	assert.NoError(t, target.CheckSecrets())
   504  	target.Secrets = append(target.Secrets, "/bin/sh")
   505  	assert.NoError(t, target.CheckSecrets())
   506  	// Checking for files in the home directory is awkward because nothing is really
   507  	// guaranteed to exist. We just check the directory itself for now.
   508  	target.Secrets = append(target.Secrets, "~/")
   509  	assert.NoError(t, target.CheckSecrets())
   510  	target.Secrets = append(target.Secrets, "/doesnt_exist")
   511  	assert.Error(t, target.CheckSecrets())
   512  }
   513  
   514  func TestAddTool(t *testing.T) {
   515  	target1 := makeTarget("//src/core:target1", "")
   516  	target2 := makeTarget("//src/core:target2", "")
   517  	target1.AddTool(target2.Label)
   518  	assert.Equal(t, []BuildInput{target2.Label}, target1.Tools)
   519  	assert.True(t, target1.HasDependency(target2.Label))
   520  }
   521  
   522  func TestAddNamedTool(t *testing.T) {
   523  	target1 := makeTarget("//src/core:target1", "")
   524  	target2 := makeTarget("//src/core:target2", "")
   525  	target1.AddNamedTool("test", target2.Label)
   526  	assert.Equal(t, 0, len(target1.Tools))
   527  	assert.Equal(t, []BuildInput{target2.Label}, target1.NamedTools("test"))
   528  	assert.True(t, target1.HasDependency(target2.Label))
   529  }
   530  
   531  func TestAllTools(t *testing.T) {
   532  	target1 := makeTarget("//src/core:target1", "")
   533  	target2 := makeTarget("//src/core:target2", "")
   534  	target3 := makeTarget("//src/core:target3", "")
   535  	target4 := makeTarget("//src/core:target4", "")
   536  	target1.AddTool(target2.Label)
   537  	target1.AddNamedTool("test1", target4.Label)
   538  	target1.AddNamedTool("test2", target3.Label)
   539  	assert.Equal(t, []BuildInput{target2.Label, target4.Label, target3.Label}, target1.AllTools())
   540  }
   541  
   542  func TestContainerSettingsToMap(t *testing.T) {
   543  	s := TargetContainerSettings{
   544  		DockerImage: "alpine:3.5",
   545  		DockerUser:  "test",
   546  	}
   547  	expected := map[string]string{
   548  		"docker_image": "alpine:3.5",
   549  		"docker_user":  "test",
   550  	}
   551  	assert.Equal(t, expected, s.ToMap())
   552  }
   553  
   554  func TestShouldIncludeSimple(t *testing.T) {
   555  	target := makeTargetWithLabels("//src/core:target1", "a", "b", "c")
   556  	excludes := []string{}
   557  	includes := []string{"a"}
   558  	assert.True(t, target.ShouldInclude(includes, excludes))
   559  
   560  	includes = []string{"b"}
   561  	assert.True(t, target.ShouldInclude(includes, excludes))
   562  
   563  	includes = []string{"c"}
   564  	assert.True(t, target.ShouldInclude(includes, excludes))
   565  }
   566  
   567  func TestShouldIncludeNonMatchingInclude(t *testing.T) {
   568  	target := makeTargetWithLabels("//src/core:target1", "a", "b", "c")
   569  	excludes := []string{}
   570  	includes := []string{"d"}
   571  	assert.False(t, target.ShouldInclude(includes, excludes))
   572  }
   573  
   574  func TestShouldIncludeWithExclude(t *testing.T) {
   575  	target := makeTargetWithLabels("//src/core:target1", "a", "b", "c")
   576  	includes := []string{}
   577  	excludes := []string{"a"}
   578  	assert.False(t, target.ShouldInclude(includes, excludes))
   579  
   580  	excludes = []string{"b"}
   581  	assert.False(t, target.ShouldInclude(includes, excludes))
   582  
   583  	excludes = []string{"c"}
   584  	assert.False(t, target.ShouldInclude(includes, excludes))
   585  }
   586  
   587  func TestShouldIncludeWithIncludeAndExclude(t *testing.T) {
   588  	target := makeTargetWithLabels("//src/core:target1", "a", "b", "c")
   589  	includes := []string{"a"}
   590  	excludes := []string{"b"}
   591  	assert.False(t, target.ShouldInclude(includes, excludes))
   592  }
   593  
   594  func TestShouldIncludeWithCompoundInclude(t *testing.T) {
   595  	target := makeTargetWithLabels("//src/core:target1", "a", "b", "c")
   596  	includes := []string{"a,b"}
   597  	excludes := []string{}
   598  	assert.True(t, target.ShouldInclude(includes, excludes))
   599  
   600  	includes = []string{"a,d", "a"}
   601  	assert.True(t, target.ShouldInclude(includes, excludes))
   602  
   603  	includes = []string{"a,d"}
   604  	assert.False(t, target.ShouldInclude(includes, excludes))
   605  }
   606  
   607  func TestShouldIncludeWithCompoundExclude(t *testing.T) {
   608  	target := makeTargetWithLabels("//src/core:target1", "a", "b", "c")
   609  	includes := []string{}
   610  	excludes := []string{"a,d"}
   611  	assert.True(t, target.ShouldInclude(includes, excludes))
   612  
   613  	excludes = []string{"a,b", "d"}
   614  	assert.False(t, target.ShouldInclude(includes, excludes))
   615  }
   616  
   617  func TestShouldIncludeWithCompoundIncludeAndExclude(t *testing.T) {
   618  	target := makeTargetWithLabels("//src/core:target1", "a", "b", "c")
   619  	includes := []string{"a,b"}
   620  	excludes := []string{"a,d"}
   621  	assert.True(t, target.ShouldInclude(includes, excludes))
   622  
   623  	includes = []string{"a,b"}
   624  	excludes = []string{"a,c"}
   625  	assert.False(t, target.ShouldInclude(includes, excludes))
   626  }
   627  
   628  func TestShouldIncludeManual(t *testing.T) {
   629  	target := makeTargetWithLabels("//src/core:target1", "a", "manual")
   630  	// Doesn't include because "manual" overrides it
   631  	assert.False(t, target.ShouldInclude([]string{"a"}, nil))
   632  
   633  	target = makeTargetWithLabels("//src/core:target1", "a", "manual:test_armhf")
   634  	// Does include because it's a different architecture
   635  	assert.True(t, target.ShouldInclude([]string{"a"}, nil))
   636  
   637  	target = makeTargetWithLabels("//src/core:target1", "a", "manual:"+OsArch)
   638  	// Doesn't include because it's manual for this architecture.
   639  	assert.False(t, target.ShouldInclude([]string{"a"}, nil))
   640  }
   641  
   642  func makeTarget(label, visibility string, deps ...*BuildTarget) *BuildTarget {
   643  	target := NewBuildTarget(ParseBuildLabel(label, ""))
   644  	if visibility == "PUBLIC" {
   645  		target.Visibility = append(target.Visibility, BuildLabel{PackageName: "", Name: "..."})
   646  	} else if visibility != "" {
   647  		target.Visibility = append(target.Visibility, ParseBuildLabel(visibility, ""))
   648  	}
   649  	for _, dep := range deps {
   650  		target.AddDependency(dep.Label)
   651  		target.resolveDependency(dep.Label, dep)
   652  	}
   653  	return target
   654  }
   655  
   656  func makeTargetWithLabels(name string, labels ...string) *BuildTarget {
   657  	target := makeTarget(name, "")
   658  	for _, label := range labels {
   659  		target.AddLabel(label)
   660  	}
   661  	return target
   662  }
   663  
   664  func makeFilegroup(label, visibility string, deps ...*BuildTarget) *BuildTarget {
   665  	target := makeTarget(label, visibility, deps...)
   666  	target.IsFilegroup = true
   667  	return target
   668  }
   669  
   670  func addFilegroupSource(target *BuildTarget, source string) {
   671  	target.AddSource(FileLabel{Package: target.Label.PackageName, File: source})
   672  }