github.com/jackie-feng/tools@v0.0.0-20191231093943-4ebd680984ae/refactor/eg/eg_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 // No testdata on Android. 6 7 // +build !android 8 9 package eg_test 10 11 import ( 12 "bytes" 13 "flag" 14 "go/constant" 15 "go/parser" 16 "go/token" 17 "go/types" 18 "io/ioutil" 19 "os" 20 "os/exec" 21 "path/filepath" 22 "runtime" 23 "strings" 24 "testing" 25 26 "github.com/jackie-feng/tools/go/loader" 27 "github.com/jackie-feng/tools/internal/testenv" 28 "github.com/jackie-feng/tools/refactor/eg" 29 ) 30 31 // TODO(adonovan): more tests: 32 // - of command-line tool 33 // - of all parts of syntax 34 // - of applying a template to a package it imports: 35 // the replacement syntax should use unqualified names for its objects. 36 37 var ( 38 updateFlag = flag.Bool("update", false, "update the golden files") 39 verboseFlag = flag.Bool("verbose", false, "show matcher information") 40 ) 41 42 func Test(t *testing.T) { 43 testenv.NeedsTool(t, "go") 44 45 switch runtime.GOOS { 46 case "windows": 47 t.Skipf("skipping test on %q (no /usr/bin/diff)", runtime.GOOS) 48 } 49 50 conf := loader.Config{ 51 Fset: token.NewFileSet(), 52 ParserMode: parser.ParseComments, 53 } 54 55 // Each entry is a single-file package. 56 // (Multi-file packages aren't interesting for this test.) 57 // Order matters: each non-template package is processed using 58 // the preceding template package. 59 for _, filename := range []string{ 60 "testdata/A.template", 61 "testdata/A1.go", 62 "testdata/A2.go", 63 64 "testdata/B.template", 65 "testdata/B1.go", 66 67 "testdata/C.template", 68 "testdata/C1.go", 69 70 "testdata/D.template", 71 "testdata/D1.go", 72 73 "testdata/E.template", 74 "testdata/E1.go", 75 76 "testdata/F.template", 77 "testdata/F1.go", 78 79 "testdata/G.template", 80 "testdata/G1.go", 81 82 "testdata/H.template", 83 "testdata/H1.go", 84 85 "testdata/I.template", 86 "testdata/I1.go", 87 88 "testdata/J.template", 89 "testdata/J1.go", 90 91 "testdata/bad_type.template", 92 "testdata/no_before.template", 93 "testdata/no_after_return.template", 94 "testdata/type_mismatch.template", 95 "testdata/expr_type_mismatch.template", 96 } { 97 pkgname := strings.TrimSuffix(filepath.Base(filename), ".go") 98 conf.CreateFromFilenames(pkgname, filename) 99 } 100 iprog, err := conf.Load() 101 if err != nil { 102 t.Fatal(err) 103 } 104 105 var xform *eg.Transformer 106 for _, info := range iprog.Created { 107 file := info.Files[0] 108 filename := iprog.Fset.File(file.Pos()).Name() // foo.go 109 110 if strings.HasSuffix(filename, "template") { 111 // a new template 112 shouldFail, _ := info.Pkg.Scope().Lookup("shouldFail").(*types.Const) 113 xform, err = eg.NewTransformer(iprog.Fset, info.Pkg, file, &info.Info, *verboseFlag) 114 if err != nil { 115 if shouldFail == nil { 116 t.Errorf("NewTransformer(%s): %s", filename, err) 117 } else if want := constant.StringVal(shouldFail.Val()); !strings.Contains(err.Error(), want) { 118 t.Errorf("NewTransformer(%s): got error %q, want error %q", filename, err, want) 119 } 120 } else if shouldFail != nil { 121 t.Errorf("NewTransformer(%s) succeeded unexpectedly; want error %q", 122 filename, shouldFail.Val()) 123 } 124 continue 125 } 126 127 if xform == nil { 128 t.Errorf("%s: no previous template", filename) 129 continue 130 } 131 132 // apply previous template to this package 133 n := xform.Transform(&info.Info, info.Pkg, file) 134 if n == 0 { 135 t.Errorf("%s: no matches", filename) 136 continue 137 } 138 139 gotf, err := ioutil.TempFile("", filepath.Base(filename)+"t") 140 if err != nil { 141 t.Fatal(err) 142 } 143 got := gotf.Name() // foo.got 144 golden := filename + "lden" // foo.golden 145 146 // Write actual output to foo.got. 147 if err := eg.WriteAST(iprog.Fset, got, file); err != nil { 148 t.Error(err) 149 } 150 defer os.Remove(got) 151 152 // Compare foo.got with foo.golden. 153 var cmd *exec.Cmd 154 switch runtime.GOOS { 155 case "plan9": 156 cmd = exec.Command("/bin/diff", "-c", golden, got) 157 default: 158 cmd = exec.Command("/usr/bin/diff", "-u", golden, got) 159 } 160 buf := new(bytes.Buffer) 161 cmd.Stdout = buf 162 cmd.Stderr = os.Stderr 163 if err := cmd.Run(); err != nil { 164 t.Errorf("eg tests for %s failed: %s.\n%s\n", filename, err, buf) 165 166 if *updateFlag { 167 t.Logf("Updating %s...", golden) 168 if err := exec.Command("/bin/cp", got, golden).Run(); err != nil { 169 t.Errorf("Update failed: %s", err) 170 } 171 } 172 } 173 } 174 }