]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/pack: handle very long lines in pkgdef
authorIan Lance Taylor <iant@golang.org>
Thu, 17 Apr 2014 18:47:12 +0000 (11:47 -0700)
committerIan Lance Taylor <iant@golang.org>
Thu, 17 Apr 2014 18:47:12 +0000 (11:47 -0700)
LGTM=rsc, bradfitz
R=golang-codereviews, rsc, bradfitz
CC=golang-codereviews
https://golang.org/cl/88170049

src/cmd/pack/pack.go
src/cmd/pack/pack_test.go

index 468104deb6c0d7bceb5006a0b817a185de6cba35..594433712d960d49af1f76ca5dbc7755dff90812 100644 (file)
@@ -406,20 +406,22 @@ func readPkgdef(file string) (data []byte, err error) {
        // Read from file, collecting header for __.PKGDEF.
        // The header is from the beginning of the file until a line
        // containing just "!". The first line must begin with "go object ".
-       var buf bytes.Buffer
-       scan := bufio.NewScanner(f)
-       for scan.Scan() {
-               line := scan.Text()
-               if buf.Len() == 0 && !strings.HasPrefix(line, "go object ") {
+       rbuf := bufio.NewReader(f)
+       var wbuf bytes.Buffer
+       for {
+               line, err := rbuf.ReadBytes('\n')
+               if err != nil {
+                       return nil, err
+               }
+               if wbuf.Len() == 0 && !bytes.HasPrefix(line, []byte("go object ")) {
                        return nil, errors.New("not a Go object file")
                }
-               if line == "!" {
+               if bytes.Equal(line, []byte("!\n")) {
                        break
                }
-               buf.WriteString(line)
-               buf.WriteString("\n")
+               wbuf.Write(line)
        }
-       return buf.Bytes(), nil
+       return wbuf.Bytes(), nil
 }
 
 // exactly16Bytes truncates the string if necessary so it is at most 16 bytes long,
index 9389349187677bd2af5818703cd269479c660b2e..bd4b224aff33de2988cb10b6a307f3cf4f3ecf25 100644 (file)
@@ -198,17 +198,97 @@ func TestHello(t *testing.T) {
                t.Fatal(err)
        }
 
+       char := findChar(t, dir)
+
        run := func(args ...string) string {
-               cmd := exec.Command(args[0], args[1:]...)
-               cmd.Dir = dir
-               out, err := cmd.CombinedOutput()
+               return doRun(t, dir, args...)
+       }
+
+       run("go", "build", "cmd/pack") // writes pack binary to dir
+       run("go", "tool", char+"g", "hello.go")
+       run("./pack", "grc", "hello.a", "hello."+char)
+       run("go", "tool", char+"l", "-o", "a.out", "hello.a")
+       out := run("./a.out")
+       if out != "hello world\n" {
+               t.Fatal("incorrect output: %q, want %q", out, "hello world\n")
+       }
+}
+
+// Test that pack works with very long lines in PKGDEF.
+func TestLargeDefs(t *testing.T) {
+       dir := tmpDir(t)
+       defer os.RemoveAll(dir)
+       large := filepath.Join(dir, "large.go")
+       f, err := os.Create(large)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       printf := func(format string, args ...interface{}) {
+               _, err := fmt.Fprintf(f, format, args...)
                if err != nil {
-                       t.Fatalf("%v: %v\n%s", args, err, string(out))
+                       t.Fatalf("Writing to %s: %v", large, err)
                }
-               return string(out)
        }
 
-       out := run("go", "env")
+       printf("package large\n\ntype T struct {\n")
+       for i := 0; i < 10000; i++ {
+               printf("f%d int `tag:\"", i)
+               for j := 0; j < 100; j++ {
+                       printf("t%d=%d,", j, j)
+               }
+               printf("\"`\n")
+       }
+       printf("}\n")
+       if err = f.Close(); err != nil {
+               t.Fatal(err)
+       }
+
+       main := filepath.Join(dir, "main.go")
+       prog := `
+               package main
+               import "./large"
+               var V large.T
+               func main() {
+                       println("ok")
+               }
+       `
+       err = ioutil.WriteFile(main, []byte(prog), 0666)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       char := findChar(t, dir)
+
+       run := func(args ...string) string {
+               return doRun(t, dir, args...)
+       }
+
+       run("go", "build", "cmd/pack") // writes pack binary to dir
+       run("go", "tool", char+"g", "large.go")
+       run("./pack", "grc", "large.a", "large."+char)
+       run("go", "tool", char+"g", "main.go")
+       run("go", "tool", char+"l", "-o", "a.out", "main."+char)
+       out := run("./a.out")
+       if out != "ok\n" {
+               t.Fatal("incorrect output: %q, want %q", out, "ok\n")
+       }
+}
+
+// doRun runs a program in a directory and returns the output.
+func doRun(t *testing.T, dir string, args ...string) string {
+       cmd := exec.Command(args[0], args[1:]...)
+       cmd.Dir = dir
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("%v: %v\n%s", args, err, string(out))
+       }
+       return string(out)
+}
+
+// findChar returns the architecture character for the go command.
+func findChar(t *testing.T, dir string) string {
+       out := doRun(t, dir, "go", "env")
        re, err := regexp.Compile(`\s*GOCHAR=['"]?(\w)['"]?`)
        if err != nil {
                t.Fatal(err)
@@ -217,15 +297,7 @@ func TestHello(t *testing.T) {
        if fields == nil {
                t.Fatal("cannot find GOCHAR in 'go env' output:\n", out)
        }
-       char := fields[1]
-       run("go", "build", "cmd/pack") // writes pack binary to dir
-       run("go", "tool", char+"g", "hello.go")
-       run("./pack", "grc", "hello.a", "hello."+char)
-       run("go", "tool", char+"l", "-o", "a.out", "hello.a")
-       out = run("./a.out")
-       if out != "hello world\n" {
-               t.Fatal("incorrect output: %q, want %q", out, "hello world\n")
-       }
+       return fields[1]
 }
 
 // Fake implementation of files.