github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/logopt/logopt_test.go (about) 1 // Copyright 2019 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 logopt 6 7 import ( 8 "github.com/gagliardetto/golang-go/not-internal/testenv" 9 "io/ioutil" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "runtime" 14 "strings" 15 "testing" 16 ) 17 18 const srcCode = `package x 19 type pair struct {a,b int} 20 func bar(y *pair) *int { 21 return &y.b 22 } 23 var a []int 24 func foo(w, z *pair) *int { 25 if *bar(w) > 0 { 26 return bar(z) 27 } 28 if a[1] > 0 { 29 a = a[:2] 30 } 31 return &a[0] 32 } 33 ` 34 35 func want(t *testing.T, out string, desired string) { 36 if !strings.Contains(out, desired) { 37 t.Errorf("did not see phrase %s in \n%s", desired, out) 38 } 39 } 40 41 func TestLogOpt(t *testing.T) { 42 t.Parallel() 43 44 testenv.MustHaveGoBuild(t) 45 46 dir, err := ioutil.TempDir("", "TestLogOpt") 47 if err != nil { 48 t.Fatal(err) 49 } 50 defer os.RemoveAll(dir) 51 52 dir = fixSlash(dir) // Normalize the directory name as much as possible, for Windows testing 53 src := filepath.Join(dir, "file.go") 54 if err := ioutil.WriteFile(src, []byte(srcCode), 0644); err != nil { 55 t.Fatal(err) 56 } 57 58 outfile := filepath.Join(dir, "file.o") 59 60 t.Run("JSON_fails", func(t *testing.T) { 61 // Test malformed flag 62 out, err := testLogOpt(t, "-json=foo", src, outfile) 63 if err == nil { 64 t.Error("-json=foo succeeded unexpectedly") 65 } 66 want(t, out, "option should be") 67 want(t, out, "number") 68 69 // Test a version number that is currently unsupported (and should remain unsupported for a while) 70 out, err = testLogOpt(t, "-json=9,foo", src, outfile) 71 if err == nil { 72 t.Error("-json=0,foo succeeded unexpectedly") 73 } 74 want(t, out, "version must be") 75 76 }) 77 78 // Some architectures don't fault on nil dereference, so nilchecks are eliminated differently. 79 if runtime.GOARCH != "amd64" { 80 return 81 } 82 83 t.Run("Success", func(t *testing.T) { 84 // This test is supposed to succeed 85 86 // replace d (dir) with t ("tmpdir") and convert path separators to '/' 87 normalize := func(out []byte, d, t string) string { 88 s := string(out) 89 s = strings.ReplaceAll(s, d, t) 90 s = strings.ReplaceAll(s, string(os.PathSeparator), "/") 91 return s 92 } 93 94 // Note 'file://' is the I-Know-What-I-Am-Doing way of specifying a file, also to deal with corner cases for Windows. 95 _, err := testLogOptDir(t, dir, "-json=0,file://log/opt", src, outfile) 96 if err != nil { 97 t.Error("-json=0,file://log/opt should have succeeded") 98 } 99 logged, err := ioutil.ReadFile(filepath.Join(dir, "log", "opt", "x", "file.json")) 100 if err != nil { 101 t.Error("-json=0,file://log/opt missing expected log file") 102 } 103 // All this delicacy with uriIfy and filepath.Join is to get this test to work right on Windows. 104 slogged := normalize(logged, string(uriIfy(dir)), string(uriIfy("tmpdir"))) 105 t.Logf("%s", slogged) 106 // below shows proper inlining and nilcheck 107 want(t, slogged, `{"range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}},"severity":3,"code":"nilcheck","source":"go compiler","message":"","relatedInformation":[{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"}]}`) 108 want(t, slogged, `{"range":{"start":{"line":11,"character":6},"end":{"line":11,"character":6}},"severity":3,"code":"isInBounds","source":"go compiler","message":""}`) 109 want(t, slogged, `{"range":{"start":{"line":7,"character":6},"end":{"line":7,"character":6}},"severity":3,"code":"canInlineFunction","source":"go compiler","message":"cost: 35"}`) 110 want(t, slogged, `{"range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}},"severity":3,"code":"inlineCall","source":"go compiler","message":"x.bar"}`) 111 want(t, slogged, `{"range":{"start":{"line":8,"character":9},"end":{"line":8,"character":9}},"severity":3,"code":"inlineCall","source":"go compiler","message":"x.bar"}`) 112 }) 113 } 114 115 func testLogOpt(t *testing.T, flag, src, outfile string) (string, error) { 116 run := []string{testenv.GoToolPath(t), "tool", "compile", flag, "-o", outfile, src} 117 t.Log(run) 118 cmd := exec.Command(run[0], run[1:]...) 119 out, err := cmd.CombinedOutput() 120 t.Logf("%s", out) 121 return string(out), err 122 } 123 124 func testLogOptDir(t *testing.T, dir, flag, src, outfile string) (string, error) { 125 // Notice the specified import path "x" 126 run := []string{testenv.GoToolPath(t), "tool", "compile", "-p", "x", flag, "-o", outfile, src} 127 t.Log(run) 128 cmd := exec.Command(run[0], run[1:]...) 129 cmd.Dir = dir 130 out, err := cmd.CombinedOutput() 131 t.Logf("%s", out) 132 return string(out), err 133 }