github.com/TrenchBoot/u-root@v6.0.1-0.20200623220532-550e36da3258+incompatible/uroot_test.go (about) 1 // Copyright 2015-2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "bytes" 9 "crypto/sha256" 10 "fmt" 11 "io" 12 "io/ioutil" 13 "os" 14 "os/exec" 15 "path/filepath" 16 "testing" 17 18 "github.com/u-root/u-root/pkg/cpio" 19 "github.com/u-root/u-root/pkg/testutil" 20 itest "github.com/u-root/u-root/pkg/uroot/initramfs/test" 21 ) 22 23 var twocmds = []string{ 24 "github.com/u-root/u-root/cmds/core/ls", 25 "github.com/u-root/u-root/cmds/core/init", 26 } 27 28 var srcmds = []string{ 29 "github.com/u-root/u-root/cmds/core/ls", 30 "github.com/u-root/u-root/cmds/core/init", 31 "github.com/u-root/u-root/cmds/core/installcommand", 32 } 33 34 type buildSourceValidator struct { 35 gopath string 36 goroot string 37 env []string 38 } 39 40 func (b buildSourceValidator) Validate(a *cpio.Archive) error { 41 dir, err := ioutil.TempDir("", "u-root-source-") 42 if err != nil { 43 return err 44 } 45 defer os.RemoveAll(dir) 46 47 if err := os.Mkdir(filepath.Join(dir, "tmp"), 0755); err != nil { 48 return err 49 } 50 51 // Unpack into dir. 52 err = cpio.ForEachRecord(a.Reader(), func(r cpio.Record) error { 53 return cpio.CreateFileInRoot(r, dir, false) 54 }) 55 if err != nil { 56 return err 57 } 58 59 goroot := filepath.Join(dir, b.goroot) 60 gopath := filepath.Join(dir, b.gopath) 61 // go build ./src/... 62 c := exec.Command(filepath.Join(goroot, "bin/go"), "build", filepath.Join(gopath, "src/...")) 63 c.Env = append(b.env, 64 fmt.Sprintf("GOPATH=%s", gopath), 65 fmt.Sprintf("GOCACHE=%s", filepath.Join(dir, "tmp")), 66 fmt.Sprintf("GOROOT=%s", goroot), 67 "CGO_ENABLED=0") 68 out, err := c.CombinedOutput() 69 if err != nil { 70 return fmt.Errorf("could not build go source %v; output\n%s", err, out) 71 } 72 return nil 73 } 74 75 func TestUrootCmdline(t *testing.T) { 76 samplef, err := ioutil.TempFile("", "u-root-sample-") 77 if err != nil { 78 t.Fatal(err) 79 } 80 samplef.Close() 81 defer os.RemoveAll(samplef.Name()) 82 83 for _, tt := range []struct { 84 name string 85 env []string 86 args []string 87 err error 88 validators []itest.ArchiveValidator 89 }{ 90 { 91 name: "include one extra file", 92 args: []string{"-nocmd", "-files=/bin/bash"}, 93 err: nil, 94 validators: []itest.ArchiveValidator{ 95 itest.HasFile{"bin/bash"}, 96 }, 97 }, 98 { 99 name: "uinitcmd", 100 args: []string{"-build=bb", "-uinitcmd=echo foobar fuzz", "-defaultsh=", "./cmds/core/init", "./cmds/core/echo"}, 101 err: nil, 102 validators: []itest.ArchiveValidator{ 103 itest.HasRecord{cpio.Symlink("bin/uinit", "../bbin/echo")}, 104 itest.HasContent{ 105 Path: "etc/uinit.flags", 106 Content: "\"foobar\"\n\"fuzz\"", 107 }, 108 }, 109 }, 110 { 111 name: "fix usage of an absolute path", 112 args: []string{"-nocmd", "-files=/bin:/bin"}, 113 err: nil, 114 validators: []itest.ArchiveValidator{ 115 itest.HasFile{"bin/bash"}, 116 }, 117 }, 118 { 119 name: "include multiple extra files", 120 args: []string{"-nocmd", "-files=/bin/bash", "-files=/bin/ls", fmt.Sprintf("-files=%s", samplef.Name())}, 121 validators: []itest.ArchiveValidator{ 122 itest.HasFile{"bin/bash"}, 123 itest.HasFile{"bin/ls"}, 124 itest.HasFile{samplef.Name()}, 125 }, 126 }, 127 { 128 name: "include one extra file with rename", 129 args: []string{"-nocmd", "-files=/bin/bash:bin/bush"}, 130 validators: []itest.ArchiveValidator{ 131 itest.HasFile{"bin/bush"}, 132 }, 133 }, 134 { 135 name: "hosted source mode", 136 args: append([]string{"-build=source", "-base=/dev/null", "-defaultsh=", "-initcmd="}, srcmds...), 137 }, 138 { 139 name: "hosted bb mode", 140 args: append([]string{"-build=bb", "-base=/dev/null", "-defaultsh=", "-initcmd="}, twocmds...), 141 }, 142 { 143 name: "AMD64 bb build", 144 env: []string{"GOARCH=amd64"}, 145 args: []string{"-build=bb", "all"}, 146 }, 147 { 148 name: "AMD64 source build", 149 env: []string{"GOARCH=amd64"}, 150 args: []string{"-build=source", "all"}, 151 validators: []itest.ArchiveValidator{ 152 buildSourceValidator{ 153 goroot: "/go", 154 gopath: ".", 155 env: []string{"GOARCH=amd64"}, 156 }, 157 }, 158 }, 159 { 160 name: "MIPS bb build", 161 env: []string{"GOARCH=mips"}, 162 args: []string{"-build=bb", "all"}, 163 }, 164 { 165 name: "MIPSLE bb build", 166 env: []string{"GOARCH=mipsle"}, 167 args: []string{"-build=bb", "all"}, 168 }, 169 { 170 name: "MIPS64 bb build", 171 env: []string{"GOARCH=mips64"}, 172 args: []string{"-build=bb", "all"}, 173 }, 174 { 175 name: "MIPS64LE bb build", 176 env: []string{"GOARCH=mips64le"}, 177 args: []string{"-build=bb", "all"}, 178 }, 179 { 180 name: "ARM7 bb build", 181 env: []string{"GOARCH=arm", "GOARM=7"}, 182 args: []string{"-build=bb", "all"}, 183 }, 184 { 185 name: "ARM64 bb build", 186 env: []string{"GOARCH=arm64"}, 187 args: []string{"-build=bb", "all"}, 188 }, 189 { 190 name: "386 (32 bit) bb build", 191 env: []string{"GOARCH=386"}, 192 args: []string{"-build=bb", "all"}, 193 }, 194 { 195 name: "Power 64bit bb build", 196 env: []string{"GOARCH=ppc64le"}, 197 args: []string{"-build=bb", "all"}, 198 }, 199 } { 200 t.Run(tt.name, func(t *testing.T) { 201 delFiles := true 202 f, sum1 := buildIt(t, tt.args, tt.env, tt.err) 203 defer func() { 204 if delFiles { 205 os.RemoveAll(f.Name()) 206 } 207 }() 208 209 a, err := itest.ReadArchive(f.Name()) 210 if err != nil { 211 t.Fatal(err) 212 } 213 214 for _, v := range tt.validators { 215 if err := v.Validate(a); err != nil { 216 t.Errorf("validator failed: %v / archive:\n%s", err, a) 217 } 218 } 219 220 f2, sum2 := buildIt(t, tt.args, tt.env, tt.err) 221 defer func() { 222 if delFiles { 223 os.RemoveAll(f2.Name()) 224 } 225 }() 226 if !bytes.Equal(sum1, sum2) { 227 delFiles = false 228 t.Errorf("not reproducible, hashes don't match") 229 t.Errorf("env: %v args: %v", tt.env, tt.args) 230 t.Errorf("file1: %v file2: %v", f.Name(), f2.Name()) 231 } 232 }) 233 } 234 } 235 236 func buildIt(t *testing.T, args, env []string, want error) (*os.File, []byte) { 237 f, err := ioutil.TempFile("", "u-root-") 238 if err != nil { 239 t.Fatal(err) 240 } 241 242 arg := append([]string{"-o", f.Name()}, args...) 243 c := testutil.Command(t, arg...) 244 t.Logf("Commandline: %v", arg) 245 c.Env = append(c.Env, env...) 246 if out, err := c.CombinedOutput(); err != want { 247 t.Fatalf("Error: %v\nOutput:\n%s", err, out) 248 } else if err != nil { 249 h1 := sha256.New() 250 if _, err := io.Copy(h1, f); err != nil { 251 t.Fatal() 252 } 253 return f, h1.Sum(nil) 254 } 255 return f, nil 256 } 257 258 func TestMain(m *testing.M) { 259 testutil.Run(m, main) 260 }