github.com/mergetb/u-root@v4.0.1-0.20190719191109-b70b86b73e5b+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 out, err := c.CombinedOutput() 68 if err != nil { 69 return fmt.Errorf("could not build go source %v; output\n%s", err, out) 70 } 71 return nil 72 } 73 74 func TestUrootCmdline(t *testing.T) { 75 samplef, err := ioutil.TempFile("", "u-root-sample-") 76 if err != nil { 77 t.Fatal(err) 78 } 79 samplef.Close() 80 defer os.RemoveAll(samplef.Name()) 81 82 for _, tt := range []struct { 83 name string 84 env []string 85 args []string 86 err error 87 validators []itest.ArchiveValidator 88 }{ 89 { 90 name: "include one extra file", 91 args: []string{"-nocmd", "-files=/bin/bash"}, 92 err: nil, 93 validators: []itest.ArchiveValidator{ 94 itest.HasFile{"bin/bash"}, 95 }, 96 }, 97 { 98 name: "fix usage of an absolute path", 99 args: []string{"-nocmd", "-files=/bin:/bin"}, 100 err: nil, 101 validators: []itest.ArchiveValidator{ 102 itest.HasFile{"bin/bash"}, 103 }, 104 }, 105 { 106 name: "include multiple extra files", 107 args: []string{"-nocmd", "-files=/bin/bash", "-files=/bin/ls", fmt.Sprintf("-files=%s", samplef.Name())}, 108 validators: []itest.ArchiveValidator{ 109 itest.HasFile{"bin/bash"}, 110 itest.HasFile{"bin/ls"}, 111 itest.HasFile{samplef.Name()}, 112 }, 113 }, 114 { 115 name: "include one extra file with rename", 116 args: []string{"-nocmd", "-files=/bin/bash:bin/bush"}, 117 validators: []itest.ArchiveValidator{ 118 itest.HasFile{"bin/bush"}, 119 }, 120 }, 121 { 122 name: "hosted source mode", 123 args: append([]string{"-build=source", "-base=/dev/null", "-defaultsh=", "-initcmd="}, srcmds...), 124 }, 125 { 126 name: "hosted bb mode", 127 args: append([]string{"-build=bb", "-base=/dev/null", "-defaultsh=", "-initcmd="}, twocmds...), 128 }, 129 { 130 name: "AMD64 bb build", 131 env: []string{"GOARCH=amd64"}, 132 args: []string{"-build=bb"}, 133 }, 134 { 135 name: "AMD64 source build", 136 env: []string{"GOARCH=amd64"}, 137 args: []string{"-build=source"}, 138 validators: []itest.ArchiveValidator{ 139 buildSourceValidator{ 140 goroot: "/go", 141 gopath: ".", 142 env: []string{"GOARCH=amd64"}, 143 }, 144 }, 145 }, 146 { 147 name: "ARM7 bb build", 148 env: []string{"GOARCH=arm", "GOARM=7"}, 149 args: []string{"-build=bb"}, 150 }, 151 { 152 name: "ARM64 bb build", 153 env: []string{"GOARCH=arm64"}, 154 args: []string{"-build=bb"}, 155 }, 156 { 157 name: "Power 64bit bb build", 158 env: []string{"GOARCH=ppc64le"}, 159 args: []string{"-build=bb"}, 160 }, 161 } { 162 t.Run(tt.name, func(t *testing.T) { 163 delFiles := true 164 f, sum1 := buildIt(t, tt.args, tt.env, tt.err) 165 defer func() { 166 if delFiles { 167 os.RemoveAll(f.Name()) 168 } 169 }() 170 171 a, err := itest.ReadArchive(f.Name()) 172 if err != nil { 173 t.Fatal(err) 174 } 175 176 for _, v := range tt.validators { 177 if err := v.Validate(a); err != nil { 178 t.Errorf("validator failed: %v / archive:\n%s", err, a) 179 } 180 } 181 182 f2, sum2 := buildIt(t, tt.args, tt.env, tt.err) 183 defer func() { 184 if delFiles { 185 os.RemoveAll(f2.Name()) 186 } 187 }() 188 if !bytes.Equal(sum1, sum2) { 189 delFiles = false 190 t.Errorf("not reproducible, hashes don't match") 191 t.Errorf("env: %v args: %v", tt.env, tt.args) 192 t.Errorf("file1: %v file2: %v", f.Name(), f2.Name()) 193 } 194 }) 195 } 196 } 197 198 func buildIt(t *testing.T, args, env []string, want error) (*os.File, []byte) { 199 f, err := ioutil.TempFile("", "u-root-") 200 if err != nil { 201 t.Fatal(err) 202 } 203 204 arg := append([]string{"-o", f.Name()}, args...) 205 c := testutil.Command(t, arg...) 206 t.Logf("Commandline: %v", arg) 207 c.Env = append(c.Env, env...) 208 if out, err := c.CombinedOutput(); err != want { 209 t.Fatalf("Error: %v\nOutput:\n%s", err, out) 210 } else if err != nil { 211 h1 := sha256.New() 212 if _, err := io.Copy(h1, f); err != nil { 213 t.Fatal() 214 } 215 return f, h1.Sum(nil) 216 } 217 return f, nil 218 } 219 220 func TestMain(m *testing.M) { 221 testutil.Run(m, main) 222 }