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