github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/go/doc/doc_test.go (about) 1 // Copyright 2012 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 doc 6 7 import ( 8 "bytes" 9 "flag" 10 "fmt" 11 "go/parser" 12 "go/printer" 13 "go/token" 14 "io/ioutil" 15 "os" 16 "path/filepath" 17 "regexp" 18 "strings" 19 "testing" 20 "text/template" 21 ) 22 23 var update = flag.Bool("update", false, "update golden (.out) files") 24 var files = flag.String("files", "", "consider only Go test files matching this regular expression") 25 26 const dataDir = "testdata" 27 28 var templateTxt *template.Template 29 30 func readTemplate(filename string) *template.Template { 31 t := template.New(filename) 32 t.Funcs(template.FuncMap{ 33 "node": nodeFmt, 34 "synopsis": synopsisFmt, 35 "indent": indentFmt, 36 }) 37 return template.Must(t.ParseFiles(filepath.Join(dataDir, filename))) 38 } 39 40 func nodeFmt(node interface{}, fset *token.FileSet) string { 41 var buf bytes.Buffer 42 printer.Fprint(&buf, fset, node) 43 return strings.Replace(strings.TrimSpace(buf.String()), "\n", "\n\t", -1) 44 } 45 46 func synopsisFmt(s string) string { 47 const n = 64 48 if len(s) > n { 49 // cut off excess text and go back to a word boundary 50 s = s[0:n] 51 if i := strings.LastIndexAny(s, "\t\n "); i >= 0 { 52 s = s[0:i] 53 } 54 s = strings.TrimSpace(s) + " ..." 55 } 56 return "// " + strings.Replace(s, "\n", " ", -1) 57 } 58 59 func indentFmt(indent, s string) string { 60 end := "" 61 if strings.HasSuffix(s, "\n") { 62 end = "\n" 63 s = s[:len(s)-1] 64 } 65 return indent + strings.Replace(s, "\n", "\n"+indent, -1) + end 66 } 67 68 func isGoFile(fi os.FileInfo) bool { 69 name := fi.Name() 70 return !fi.IsDir() && 71 len(name) > 0 && name[0] != '.' && // ignore .files 72 filepath.Ext(name) == ".go" 73 } 74 75 type bundle struct { 76 *Package 77 FSet *token.FileSet 78 } 79 80 func test(t *testing.T, mode Mode) { 81 // determine file filter 82 filter := isGoFile 83 if *files != "" { 84 rx, err := regexp.Compile(*files) 85 if err != nil { 86 t.Fatal(err) 87 } 88 filter = func(fi os.FileInfo) bool { 89 return isGoFile(fi) && rx.MatchString(fi.Name()) 90 } 91 } 92 93 // get packages 94 fset := token.NewFileSet() 95 pkgs, err := parser.ParseDir(fset, dataDir, filter, parser.ParseComments) 96 if err != nil { 97 t.Fatal(err) 98 } 99 if templateTxt == nil { 100 templateTxt = readTemplate("template.txt") 101 } 102 103 // test packages 104 for _, pkg := range pkgs { 105 importpath := dataDir + "/" + pkg.Name 106 doc := New(pkg, importpath, mode) 107 108 // golden files always use / in filenames - canonicalize them 109 for i, filename := range doc.Filenames { 110 doc.Filenames[i] = filepath.ToSlash(filename) 111 } 112 113 // print documentation 114 var buf bytes.Buffer 115 if err := templateTxt.Execute(&buf, bundle{doc, fset}); err != nil { 116 t.Error(err) 117 continue 118 } 119 got := buf.Bytes() 120 121 // update golden file if necessary 122 golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode)) 123 if *update { 124 err := ioutil.WriteFile(golden, got, 0644) 125 if err != nil { 126 t.Error(err) 127 } 128 continue 129 } 130 131 // get golden file 132 want, err := ioutil.ReadFile(golden) 133 if err != nil { 134 t.Error(err) 135 continue 136 } 137 138 // compare 139 if !bytes.Equal(got, want) { 140 t.Errorf("package %s\n\tgot:\n%s\n\twant:\n%s", pkg.Name, got, want) 141 } 142 } 143 } 144 145 func Test(t *testing.T) { 146 test(t, 0) 147 test(t, AllDecls) 148 test(t, AllMethods) 149 }