github.com/Benchkram/bob@v0.0.0-20220321080157-7c8f3876e225/test/e2e/multilevelbuild/multilevelbuild_test.go (about) 1 package multilevelbuildtest 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "time" 12 13 "github.com/Benchkram/bob/bob" 14 "github.com/Benchkram/bob/bob/playbook" 15 "github.com/Benchkram/bob/pkg/file" 16 "github.com/Benchkram/errz" 17 18 . "github.com/onsi/ginkgo" 19 . "github.com/onsi/gomega" 20 ) 21 22 type binaryOutputFixture struct { 23 path string 24 output string 25 } 26 27 type requiresRebuildFixture struct { 28 taskname string 29 requiresRebuild bool 30 } 31 32 var _ = Describe("Test bob multilevel build", func() { 33 Context("in a fresh environment", func() { 34 35 It("initializes bob playground", func() { 36 Expect(bob.CreatePlayground(dir)).NotTo(HaveOccurred()) 37 }) 38 39 It("runs build all", func() { 40 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) 41 Expect(b.Build(ctx, bob.BuildAllTargetName)).NotTo(HaveOccurred()) 42 cancel() 43 }) 44 45 binaries := []binaryOutputFixture{ 46 { 47 path: filepath.Join(dir, "run"), 48 output: "Hello Playground v1\nByebye Playground v1\n", 49 }, 50 { 51 path: filepath.Join(dir, bob.SecondLevelDir, "runsecondlevel"), 52 output: "Hello Playground v2\nByebye Playground v2\n", 53 }, 54 { 55 path: filepath.Join(dir, bob.SecondLevelDir, bob.ThirdLevelDir, "runthirdlevel"), 56 output: "Hello Playground v3\nByebye Playground v3\n", 57 }, 58 } 59 60 It("checks that the built binaries exist", func() { 61 for _, b := range binaries { 62 Expect(file.Exists(b.path)).To(BeTrue(), fmt.Sprintf("%s doesn't exist", b.path)) 63 } 64 }) 65 66 It("checks that the built binaries produce the expected output", func() { 67 for _, b := range binaries { 68 cmd := exec.Command("./" + b.path) 69 var stdout, stderr bytes.Buffer 70 cmd.Stdout = &stdout 71 cmd.Stderr = &stderr 72 73 // The binarys are waiting for a ctrl-c 74 // to shutdown. 75 go func() { 76 time.Sleep(500 * time.Millisecond) 77 err := cmd.Process.Signal(os.Interrupt) 78 Expect(err).NotTo(HaveOccurred()) 79 }() 80 81 err := cmd.Run() 82 Expect(err).NotTo(HaveOccurred()) 83 84 Expect(b.output).To(Equal(stderr.String())) 85 } 86 }) 87 88 It("runs build multilinetouch", func() { 89 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) 90 Expect(b.Build(ctx, "multilinetouch")).NotTo(HaveOccurred()) 91 cancel() 92 }) 93 94 It("checks that the touched files really exist", func() { 95 files := []string{ 96 "multilinefile1", 97 "multilinefile2", 98 "multilinefile3", 99 "multilinefile4", 100 "multilinefile5", 101 } 102 103 for _, f := range files { 104 Expect(file.Exists(f)).To(BeTrue(), fmt.Sprintf("%s doesn't exist", f)) 105 } 106 }) 107 108 It("checks that we do not require a rebuild of any of the levels", func() { 109 fixtures := []requiresRebuildFixture{ 110 { 111 taskname: bob.BuildAllTargetName, 112 requiresRebuild: false, 113 }, 114 { 115 taskname: "second-level/build2", 116 requiresRebuild: false, 117 }, 118 { 119 taskname: "second-level/third-level/build3", 120 requiresRebuild: false, 121 }, 122 } 123 124 requiresRebuildMustMatchFixtures(b, fixtures) 125 }) 126 127 It("changes a file of the second-level", func() { 128 f := filepath.Join(dir, bob.SecondLevelDir, "main2.go") 129 c, err := ioutil.ReadFile(f) 130 Expect(err).NotTo(HaveOccurred()) 131 132 c = append(c, []byte("// some random comment so the file content is changed")...) 133 134 err = ioutil.WriteFile(f, c, 0644) 135 Expect(err).NotTo(HaveOccurred()) 136 }) 137 138 It("checks that we now require a rebuild of the second- and first-level, but not the third-level", func() { 139 fixtures := []requiresRebuildFixture{ 140 { 141 taskname: bob.BuildAllTargetName, 142 requiresRebuild: true, 143 }, 144 { 145 taskname: "second-level/build2", 146 requiresRebuild: true, 147 }, 148 { 149 taskname: "second-level/third-level/build3", 150 requiresRebuild: false, 151 }, 152 } 153 154 requiresRebuildMustMatchFixtures(b, fixtures) 155 }) 156 157 It("runs build all again", func() { 158 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) 159 Expect(b.Build(ctx, bob.BuildAllTargetName)).NotTo(HaveOccurred()) 160 cancel() 161 }) 162 163 It("checks that we do not require a rebuild of any of the levels", func() { 164 fixtures := []requiresRebuildFixture{ 165 { 166 taskname: bob.BuildAllTargetName, 167 requiresRebuild: false, 168 }, 169 { 170 taskname: "second-level/build2", 171 requiresRebuild: false, 172 }, 173 { 174 taskname: "second-level/third-level/build3", 175 requiresRebuild: false, 176 }, 177 } 178 179 requiresRebuildMustMatchFixtures(b, fixtures) 180 }) 181 182 It("changes a file of the third-level", func() { 183 f := filepath.Join(dir, bob.SecondLevelDir, bob.ThirdLevelDir, "main3.go") 184 c, err := ioutil.ReadFile(f) 185 Expect(err).NotTo(HaveOccurred()) 186 187 c = append(c, []byte("// some random comment so the file content is changed")...) 188 189 err = ioutil.WriteFile(f, c, 0644) 190 Expect(err).NotTo(HaveOccurred()) 191 }) 192 193 It("checks that we now require a rebuild of the third-, second- and first-level", func() { 194 fixtures := []requiresRebuildFixture{ 195 { 196 taskname: bob.BuildAllTargetName, 197 requiresRebuild: true, 198 }, 199 { 200 taskname: "second-level/build2", 201 requiresRebuild: true, 202 }, 203 { 204 taskname: "second-level/third-level/build3", 205 requiresRebuild: true, 206 }, 207 } 208 209 err := artifactsClean() 210 Expect(err).NotTo(HaveOccurred()) 211 requiresRebuildMustMatchFixtures(b, fixtures) 212 }) 213 }) 214 }) 215 216 func requiresRebuildMustMatchFixtures(b *bob.B, fixtures []requiresRebuildFixture) { 217 aggregate, err := b.Aggregate() 218 Expect(err).NotTo(HaveOccurred()) 219 pb, err := aggregate.Playbook(bob.BuildAllTargetName) 220 Expect(err).NotTo(HaveOccurred()) 221 222 err = pb.Build(context.Background()) 223 errz.Log(err) 224 Expect(err).NotTo(HaveOccurred()) 225 226 for _, f := range fixtures { 227 ts, err := pb.TaskStatus(f.taskname) 228 Expect(err).NotTo(HaveOccurred()) 229 requiresRebuild := ts.State() != playbook.StateNoRebuildRequired 230 231 Expect(f.requiresRebuild).To(Equal(requiresRebuild), fmt.Sprintf("task's %q rebuild requirement differ, got: %t, want: %t", f.taskname, requiresRebuild, f.requiresRebuild)) 232 } 233 }