github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/cmd/pack/pack_test.go (about) 1 // Copyright 2014 The Go 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 "bufio" 9 "bytes" 10 "fmt" 11 "internal/testenv" 12 "io" 13 "io/ioutil" 14 "os" 15 "os/exec" 16 "path/filepath" 17 "testing" 18 "time" 19 "unicode/utf8" 20 ) 21 22 func TestExactly16Bytes(t *testing.T) { 23 var tests = []string{ 24 "", 25 "a", 26 "日本語", 27 "1234567890123456", 28 "12345678901234567890", 29 "1234567890123本語4567890", 30 "12345678901234日本語567890", 31 "123456789012345日本語67890", 32 "1234567890123456日本語7890", 33 "1234567890123456日本語7日本語890", 34 } 35 for _, str := range tests { 36 got := exactly16Bytes(str) 37 if len(got) != 16 { 38 t.Errorf("exactly16Bytes(%q) is %q, length %d", str, got, len(got)) 39 } 40 // Make sure it is full runes. 41 for _, c := range got { 42 if c == utf8.RuneError { 43 t.Errorf("exactly16Bytes(%q) is %q, has partial rune", str, got) 44 } 45 } 46 } 47 } 48 49 // tmpDir creates a temporary directory and returns its name. 50 func tmpDir(t *testing.T) string { 51 name, err := ioutil.TempDir("", "pack") 52 if err != nil { 53 t.Fatal(err) 54 } 55 return name 56 } 57 58 // testCreate creates an archive in the specified directory. 59 func testCreate(t *testing.T, dir string) { 60 name := filepath.Join(dir, "pack.a") 61 ar := archive(name, os.O_RDWR, nil) 62 // Add an entry by hand. 63 ar.addFile(helloFile.Reset()) 64 ar.fd.Close() 65 // Now check it. 66 ar = archive(name, os.O_RDONLY, []string{helloFile.name}) 67 var buf bytes.Buffer 68 stdout = &buf 69 verbose = true 70 defer func() { 71 stdout = os.Stdout 72 verbose = false 73 }() 74 ar.scan(ar.printContents) 75 ar.fd.Close() 76 result := buf.String() 77 // Expect verbose output plus file contents. 78 expect := fmt.Sprintf("%s\n%s", helloFile.name, helloFile.contents) 79 if result != expect { 80 t.Fatalf("expected %q got %q", expect, result) 81 } 82 } 83 84 // Test that we can create an archive, write to it, and get the same contents back. 85 // Tests the rv and then the pv command on a new archive. 86 func TestCreate(t *testing.T) { 87 dir := tmpDir(t) 88 defer os.RemoveAll(dir) 89 testCreate(t, dir) 90 } 91 92 // Test that we can create an archive twice with the same name (Issue 8369). 93 func TestCreateTwice(t *testing.T) { 94 dir := tmpDir(t) 95 defer os.RemoveAll(dir) 96 testCreate(t, dir) 97 testCreate(t, dir) 98 } 99 100 // Test that we can create an archive, put some files in it, and get back a correct listing. 101 // Tests the tv command. 102 func TestTableOfContents(t *testing.T) { 103 dir := tmpDir(t) 104 defer os.RemoveAll(dir) 105 name := filepath.Join(dir, "pack.a") 106 ar := archive(name, os.O_RDWR, nil) 107 108 // Add some entries by hand. 109 ar.addFile(helloFile.Reset()) 110 ar.addFile(goodbyeFile.Reset()) 111 ar.fd.Close() 112 113 // Now print it. 114 ar = archive(name, os.O_RDONLY, nil) 115 var buf bytes.Buffer 116 stdout = &buf 117 verbose = true 118 defer func() { 119 stdout = os.Stdout 120 verbose = false 121 }() 122 ar.scan(ar.tableOfContents) 123 ar.fd.Close() 124 result := buf.String() 125 // Expect verbose listing. 126 expect := fmt.Sprintf("%s\n%s\n", helloFile.Entry(), goodbyeFile.Entry()) 127 if result != expect { 128 t.Fatalf("expected %q got %q", expect, result) 129 } 130 131 // Do it again without verbose. 132 verbose = false 133 buf.Reset() 134 ar = archive(name, os.O_RDONLY, nil) 135 ar.scan(ar.tableOfContents) 136 ar.fd.Close() 137 result = buf.String() 138 // Expect non-verbose listing. 139 expect = fmt.Sprintf("%s\n%s\n", helloFile.name, goodbyeFile.name) 140 if result != expect { 141 t.Fatalf("expected %q got %q", expect, result) 142 } 143 144 // Do it again with file list arguments. 145 verbose = false 146 buf.Reset() 147 ar = archive(name, os.O_RDONLY, []string{helloFile.name}) 148 ar.scan(ar.tableOfContents) 149 ar.fd.Close() 150 result = buf.String() 151 // Expect only helloFile. 152 expect = fmt.Sprintf("%s\n", helloFile.name) 153 if result != expect { 154 t.Fatalf("expected %q got %q", expect, result) 155 } 156 } 157 158 // Test that we can create an archive, put some files in it, and get back a file. 159 // Tests the x command. 160 func TestExtract(t *testing.T) { 161 dir := tmpDir(t) 162 defer os.RemoveAll(dir) 163 name := filepath.Join(dir, "pack.a") 164 ar := archive(name, os.O_RDWR, nil) 165 // Add some entries by hand. 166 ar.addFile(helloFile.Reset()) 167 ar.addFile(goodbyeFile.Reset()) 168 ar.fd.Close() 169 // Now extract one file. We chdir to the directory of the archive for simplicity. 170 pwd, err := os.Getwd() 171 if err != nil { 172 t.Fatal("os.Getwd: ", err) 173 } 174 err = os.Chdir(dir) 175 if err != nil { 176 t.Fatal("os.Chdir: ", err) 177 } 178 defer func() { 179 err := os.Chdir(pwd) 180 if err != nil { 181 t.Fatal("os.Chdir: ", err) 182 } 183 }() 184 ar = archive(name, os.O_RDONLY, []string{goodbyeFile.name}) 185 ar.scan(ar.extractContents) 186 ar.fd.Close() 187 data, err := ioutil.ReadFile(goodbyeFile.name) 188 if err != nil { 189 t.Fatal(err) 190 } 191 // Expect contents of file. 192 result := string(data) 193 expect := goodbyeFile.contents 194 if result != expect { 195 t.Fatalf("expected %q got %q", expect, result) 196 } 197 } 198 199 // Test that pack-created archives can be understood by the tools. 200 func TestHello(t *testing.T) { 201 testenv.MustHaveGoBuild(t) 202 203 dir := tmpDir(t) 204 defer os.RemoveAll(dir) 205 hello := filepath.Join(dir, "hello.go") 206 prog := ` 207 package main 208 func main() { 209 println("hello world") 210 } 211 ` 212 err := ioutil.WriteFile(hello, []byte(prog), 0666) 213 if err != nil { 214 t.Fatal(err) 215 } 216 217 run := func(args ...string) string { 218 return doRun(t, dir, args...) 219 } 220 221 goBin := testenv.GoToolPath(t) 222 run(goBin, "build", "cmd/pack") // writes pack binary to dir 223 run(goBin, "tool", "compile", "hello.go") 224 run("./pack", "grc", "hello.a", "hello.o") 225 run(goBin, "tool", "link", "-o", "a.out", "hello.a") 226 out := run("./a.out") 227 if out != "hello world\n" { 228 t.Fatalf("incorrect output: %q, want %q", out, "hello world\n") 229 } 230 } 231 232 // Test that pack works with very long lines in PKGDEF. 233 func TestLargeDefs(t *testing.T) { 234 testenv.MustHaveGoBuild(t) 235 236 dir := tmpDir(t) 237 defer os.RemoveAll(dir) 238 large := filepath.Join(dir, "large.go") 239 f, err := os.Create(large) 240 if err != nil { 241 t.Fatal(err) 242 } 243 b := bufio.NewWriter(f) 244 245 printf := func(format string, args ...interface{}) { 246 _, err := fmt.Fprintf(b, format, args...) 247 if err != nil { 248 t.Fatalf("Writing to %s: %v", large, err) 249 } 250 } 251 252 printf("package large\n\ntype T struct {\n") 253 for i := 0; i < 1000; i++ { 254 printf("f%d int `tag:\"", i) 255 for j := 0; j < 100; j++ { 256 printf("t%d=%d,", j, j) 257 } 258 printf("\"`\n") 259 } 260 printf("}\n") 261 if err = b.Flush(); err != nil { 262 t.Fatal(err) 263 } 264 if err = f.Close(); err != nil { 265 t.Fatal(err) 266 } 267 268 main := filepath.Join(dir, "main.go") 269 prog := ` 270 package main 271 import "large" 272 var V large.T 273 func main() { 274 println("ok") 275 } 276 ` 277 err = ioutil.WriteFile(main, []byte(prog), 0666) 278 if err != nil { 279 t.Fatal(err) 280 } 281 282 run := func(args ...string) string { 283 return doRun(t, dir, args...) 284 } 285 286 goBin := testenv.GoToolPath(t) 287 run(goBin, "build", "cmd/pack") // writes pack binary to dir 288 run(goBin, "tool", "compile", "large.go") 289 run("./pack", "grc", "large.a", "large.o") 290 run(goBin, "tool", "compile", "-I", ".", "main.go") 291 run(goBin, "tool", "link", "-L", ".", "-o", "a.out", "main.o") 292 out := run("./a.out") 293 if out != "ok\n" { 294 t.Fatalf("incorrect output: %q, want %q", out, "ok\n") 295 } 296 } 297 298 // doRun runs a program in a directory and returns the output. 299 func doRun(t *testing.T, dir string, args ...string) string { 300 cmd := exec.Command(args[0], args[1:]...) 301 cmd.Dir = dir 302 out, err := cmd.CombinedOutput() 303 if err != nil { 304 t.Fatalf("%v: %v\n%s", args, err, string(out)) 305 } 306 return string(out) 307 } 308 309 // Fake implementation of files. 310 311 var helloFile = &FakeFile{ 312 name: "hello", 313 contents: "hello world", // 11 bytes, an odd number. 314 mode: 0644, 315 } 316 317 var goodbyeFile = &FakeFile{ 318 name: "goodbye", 319 contents: "Sayonara, Jim", // 13 bytes, another odd number. 320 mode: 0644, 321 } 322 323 // FakeFile implements FileLike and also os.FileInfo. 324 type FakeFile struct { 325 name string 326 contents string 327 mode os.FileMode 328 offset int 329 } 330 331 // Reset prepares a FakeFile for reuse. 332 func (f *FakeFile) Reset() *FakeFile { 333 f.offset = 0 334 return f 335 } 336 337 // FileLike methods. 338 339 func (f *FakeFile) Name() string { 340 // A bit of a cheat: we only have a basename, so that's also ok for FileInfo. 341 return f.name 342 } 343 344 func (f *FakeFile) Stat() (os.FileInfo, error) { 345 return f, nil 346 } 347 348 func (f *FakeFile) Read(p []byte) (int, error) { 349 if f.offset >= len(f.contents) { 350 return 0, io.EOF 351 } 352 n := copy(p, f.contents[f.offset:]) 353 f.offset += n 354 return n, nil 355 } 356 357 func (f *FakeFile) Close() error { 358 return nil 359 } 360 361 // os.FileInfo methods. 362 363 func (f *FakeFile) Size() int64 { 364 return int64(len(f.contents)) 365 } 366 367 func (f *FakeFile) Mode() os.FileMode { 368 return f.mode 369 } 370 371 func (f *FakeFile) ModTime() time.Time { 372 return time.Time{} 373 } 374 375 func (f *FakeFile) IsDir() bool { 376 return false 377 } 378 379 func (f *FakeFile) Sys() interface{} { 380 return nil 381 } 382 383 // Special helpers. 384 385 func (f *FakeFile) Entry() *Entry { 386 return &Entry{ 387 name: f.name, 388 mtime: 0, // Defined to be zero. 389 uid: 0, // Ditto. 390 gid: 0, // Ditto. 391 mode: f.mode, 392 size: int64(len(f.contents)), 393 } 394 }