|
5 | 5 | package gc
|
6 | 6 |
|
7 | 7 | import (
|
8 |
| - "bytes" |
| 8 | + "bufio" |
9 | 9 | "internal/testenv"
|
| 10 | + "io" |
10 | 11 | "os/exec"
|
| 12 | + "regexp" |
11 | 13 | "runtime"
|
| 14 | + "strings" |
12 | 15 | "testing"
|
13 | 16 | )
|
14 | 17 |
|
@@ -51,37 +54,57 @@ func TestIntendedInlining(t *testing.T) {
|
51 | 54 | want["runtime"] = append(want["runtime"], "nextFreeFast")
|
52 | 55 | }
|
53 | 56 |
|
54 |
| - m := make(map[string]bool) |
| 57 | + notInlinedReason := make(map[string]string) |
55 | 58 | pkgs := make([]string, 0, len(want))
|
56 | 59 | for pname, fnames := range want {
|
57 | 60 | pkgs = append(pkgs, pname)
|
58 | 61 | for _, fname := range fnames {
|
59 |
| - m[pname+"."+fname] = true |
| 62 | + notInlinedReason[pname+"."+fname] = "unknown reason" |
60 | 63 | }
|
61 | 64 | }
|
62 | 65 |
|
63 |
| - args := append([]string{"build", "-a", "-gcflags=-m"}, pkgs...) |
| 66 | + args := append([]string{"build", "-a", "-gcflags=-m -m"}, pkgs...) |
64 | 67 | cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), args...))
|
65 |
| - out, err := cmd.CombinedOutput() |
66 |
| - if err != nil { |
67 |
| - t.Logf("%s", out) |
68 |
| - t.Fatal(err) |
69 |
| - } |
70 |
| - lines := bytes.Split(out, []byte{'\n'}) |
| 68 | + pr, pw := io.Pipe() |
| 69 | + cmd.Stdout = pw |
| 70 | + cmd.Stderr = pw |
| 71 | + cmdErr := make(chan error, 1) |
| 72 | + go func() { |
| 73 | + cmdErr <- cmd.Run() |
| 74 | + pw.Close() |
| 75 | + }() |
| 76 | + scanner := bufio.NewScanner(pr) |
71 | 77 | curPkg := ""
|
72 |
| - for _, l := range lines { |
73 |
| - if bytes.HasPrefix(l, []byte("# ")) { |
74 |
| - curPkg = string(l[2:]) |
| 78 | + canInline := regexp.MustCompile(`: can inline ([^ ]*)`) |
| 79 | + cannotInline := regexp.MustCompile(`: cannot inline ([^ ]*): (.*)`) |
| 80 | + for scanner.Scan() { |
| 81 | + line := scanner.Text() |
| 82 | + if strings.HasPrefix(line, "# ") { |
| 83 | + curPkg = line[2:] |
| 84 | + continue |
| 85 | + } |
| 86 | + if m := canInline.FindStringSubmatch(line); m != nil { |
| 87 | + fname := m[1] |
| 88 | + delete(notInlinedReason, curPkg+"."+fname) |
| 89 | + continue |
75 | 90 | }
|
76 |
| - f := bytes.Split(l, []byte(": can inline ")) |
77 |
| - if len(f) < 2 { |
| 91 | + if m := cannotInline.FindStringSubmatch(line); m != nil { |
| 92 | + fname, reason := m[1], m[2] |
| 93 | + fullName := curPkg + "." + fname |
| 94 | + if _, ok := notInlinedReason[fullName]; ok { |
| 95 | + // cmd/compile gave us a reason why |
| 96 | + notInlinedReason[fullName] = reason |
| 97 | + } |
78 | 98 | continue
|
79 | 99 | }
|
80 |
| - fn := bytes.TrimSpace(f[1]) |
81 |
| - delete(m, curPkg+"."+string(fn)) |
82 | 100 | }
|
83 |
| - |
84 |
| - for s := range m { |
85 |
| - t.Errorf("function %s not inlined", s) |
| 101 | + if err := <-cmdErr; err != nil { |
| 102 | + t.Fatal(err) |
| 103 | + } |
| 104 | + if err := scanner.Err(); err != nil { |
| 105 | + t.Fatal(err) |
| 106 | + } |
| 107 | + for fullName, reason := range notInlinedReason { |
| 108 | + t.Errorf("%s was not inlined: %s", fullName, reason) |
86 | 109 | }
|
87 | 110 | }
|
0 commit comments