github.com/tiagovtristao/plz@v13.4.0+incompatible/src/parse/parse_step_test.go (about) 1 // Tests for general parse functions. 2 3 package parse 4 5 import ( 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 10 "github.com/thought-machine/please/src/core" 11 ) 12 13 var empty = []string{} 14 15 func TestAddDepSimple(t *testing.T) { 16 // Simple case with only one package parsed and one target added 17 state := makeState(true, false) 18 activateTarget(state, nil, buildLabel("//package1:target1"), core.OriginalTarget, false, empty, empty) 19 assertPendingParses(t, state, "//package2:target1", "//package2:target1") 20 assertPendingBuilds(t, state) // None until package2 parses 21 assert.Equal(t, 5, state.NumActive()) 22 } 23 24 func TestAddDepMultiple(t *testing.T) { 25 // Similar to above but doing all targets in that package 26 state := makeState(true, false) 27 activateTarget(state, nil, buildLabel("//package1:target1"), core.OriginalTarget, false, empty, empty) 28 activateTarget(state, nil, buildLabel("//package1:target2"), core.OriginalTarget, false, empty, empty) 29 activateTarget(state, nil, buildLabel("//package1:target3"), core.OriginalTarget, false, empty, empty) 30 // We get an additional dep on target2, but not another on package2:target1 because target2 31 // is already activated since package1:target1 depends on it 32 assertPendingParses(t, state, "//package2:target1", "//package2:target1", "//package2:target2") 33 assertPendingBuilds(t, state) // None until package2 parses 34 assert.Equal(t, 7, state.NumActive()) 35 } 36 37 func TestAddDepMultiplePackages(t *testing.T) { 38 // This time we already have package2 parsed 39 state := makeState(true, true) 40 activateTarget(state, nil, buildLabel("//package1:target1"), core.OriginalTarget, false, empty, empty) 41 assertPendingBuilds(t, state, "//package2:target2") // This is the only candidate target 42 assertPendingParses(t, state) // None, we have both packages already 43 assert.Equal(t, 6, state.NumActive()) 44 } 45 46 func TestAddDepNoBuild(t *testing.T) { 47 // Tag state as not needing build. We shouldn't get any pending builds at this point. 48 state := makeState(true, true) 49 state.NeedBuild = false 50 activateTarget(state, nil, buildLabel("//package1:target1"), core.OriginalTarget, false, empty, empty) 51 assertPendingParses(t, state) // None, we have both packages already 52 assertPendingBuilds(t, state) // Nothing because we don't need to build. 53 assert.Equal(t, 1, state.NumActive()) // Parses only 54 } 55 56 func TestAddParseDep(t *testing.T) { 57 // Tag state as not needing build. Any target that needs to be built to complete parse 58 // should still get queued for build though. Recall that we indicate this with :all... 59 state := makeState(true, true) 60 state.NeedBuild = false 61 activateTarget(state, nil, buildLabel("//package2:target2"), buildLabel("//package3:all"), false, empty, empty) 62 assertPendingBuilds(t, state, "//package2:target2") // Queued because it's needed for parse 63 assertPendingParses(t, state) // None, we have both packages already 64 assert.Equal(t, 2, state.NumActive()) 65 } 66 67 func TestAddDepRescan(t *testing.T) { 68 // Simulate a post-build function and rescan. 69 state := makeState(true, true) 70 activateTarget(state, nil, buildLabel("//package1:target1"), core.OriginalTarget, false, empty, empty) 71 assertPendingBuilds(t, state, "//package2:target2") // This is the only candidate target 72 assertPendingParses(t, state) // None, we have both packages already 73 assert.Equal(t, 6, state.NumActive()) 74 75 // Add new target & dep to target1 76 target4 := makeTarget("//package1:target4") 77 state.Graph.Package("package1", "").AddTarget(target4) 78 state.Graph.AddTarget(target4) 79 target1 := state.Graph.TargetOrDie(buildLabel("//package1:target1")) 80 target1.AddDependency(buildLabel("//package1:target4")) 81 state.Graph.AddDependency(buildLabel("//package1:target1"), buildLabel("//package1:target4")) 82 83 // Fake test: calling this now should have no effect because rescan is not true. 84 addDep(state, buildLabel("//package1:target1"), core.OriginalTarget, false, false) 85 assertPendingParses(t, state) 86 assertPendingBuilds(t, state) // Note that the earlier call to assertPendingBuilds cleared it. 87 88 // Now running this should activate it 89 rescanDeps(state, map[*core.BuildTarget]struct{}{target1: {}}) 90 assertPendingBuilds(t, state, "//package1:target4") 91 assertPendingParses(t, state) 92 assert.True(t, state.Graph.AllDependenciesResolved(target1)) 93 } 94 95 func TestAddParseDepDeferred(t *testing.T) { 96 // Similar to TestAddParseDep but where we scan the package once and come back later because 97 // something else asserts a dependency on it. 98 state := makeState(true, true) 99 state.NeedBuild = false 100 assert.Equal(t, 1, state.NumActive()) 101 activateTarget(state, nil, buildLabel("//package2:target2"), core.OriginalTarget, false, empty, empty) 102 assertPendingParses(t, state) 103 assertPendingBuilds(t, state) // Not yet. 104 105 // Now the undefer kicks off... 106 activateTarget(state, nil, buildLabel("//package2:target2"), buildLabel("//package1:all"), false, empty, empty) 107 assertPendingBuilds(t, state, "//package2:target2") // This time! 108 assertPendingParses(t, state) 109 assert.Equal(t, 2, state.NumActive()) 110 } 111 112 func makeTarget(label string, deps ...string) *core.BuildTarget { 113 target := core.NewBuildTarget(core.ParseBuildLabel(label, "")) 114 for _, dep := range deps { 115 target.AddDependency(core.ParseBuildLabel(dep, "")) 116 } 117 return target 118 } 119 120 // makeState creates a new build state with optionally one or two packages in it. 121 // Used in various tests above. 122 func makeState(withPackage1, withPackage2 bool) *core.BuildState { 123 state := core.NewBuildState(5, nil, 4, core.DefaultConfiguration()) 124 if withPackage1 { 125 pkg := core.NewPackage("package1") 126 state.Graph.AddPackage(pkg) 127 pkg.AddTarget(makeTarget("//package1:target1", "//package1:target2", "//package2:target1")) 128 pkg.AddTarget(makeTarget("//package1:target2", "//package2:target1")) 129 pkg.AddTarget(makeTarget("//package1:target3", "//package2:target2")) 130 state.Graph.AddTarget(pkg.Target("target1")) 131 state.Graph.AddTarget(pkg.Target("target2")) 132 state.Graph.AddTarget(pkg.Target("target3")) 133 addDeps(state.Graph, pkg) 134 } 135 if withPackage2 { 136 pkg := core.NewPackage("package2") 137 state.Graph.AddPackage(pkg) 138 pkg.AddTarget(makeTarget("//package2:target1", "//package2:target2", "//package1:target3")) 139 pkg.AddTarget(makeTarget("//package2:target2")) 140 state.Graph.AddTarget(pkg.Target("target1")) 141 state.Graph.AddTarget(pkg.Target("target2")) 142 addDeps(state.Graph, pkg) 143 } 144 return state 145 } 146 147 func addDeps(graph *core.BuildGraph, pkg *core.Package) { 148 for _, target := range pkg.AllTargets() { 149 for _, dep := range target.DeclaredDependencies() { 150 graph.AddDependency(target.Label, dep) 151 } 152 } 153 } 154 155 func assertPendingParses(t *testing.T, state *core.BuildState, targets ...string) { 156 state.Stop(1) 157 pending := []core.BuildLabel{} 158 for { 159 label, _, typ := state.NextTask() 160 if typ == core.Stop { 161 break 162 } else if typ != core.Parse && typ != core.SubincludeParse { 163 t.Errorf("Unexpected non-parse task") 164 } else { 165 pending = append(pending, label) 166 } 167 } 168 expected := []core.BuildLabel{} 169 for _, target := range targets { 170 expected = append(expected, core.ParseBuildLabel(target, "")) 171 } 172 assert.Equal(t, expected, pending) 173 } 174 175 func assertPendingBuilds(t *testing.T, state *core.BuildState, targets ...string) { 176 state.Stop(1) 177 pending := []core.BuildLabel{} 178 for { 179 label, _, typ := state.NextTask() 180 if typ == core.Stop { 181 break 182 } else if typ != core.Build && typ != core.SubincludeBuild { 183 t.Errorf("Unexpected non-build task") 184 } else { 185 pending = append(pending, label) 186 } 187 } 188 expected := []core.BuildLabel{} 189 for _, target := range targets { 190 expected = append(expected, core.ParseBuildLabel(target, "")) 191 } 192 assert.Equal(t, expected, pending) 193 } 194 195 func buildLabel(bl string) core.BuildLabel { 196 return core.ParseBuildLabel(bl, "") 197 }