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  }