Source file
src/go/doc/doc_test.go
Documentation: go/doc
1
2
3
4
5 package doc
6
7 import (
8 "bytes"
9 "flag"
10 "fmt"
11 "go/ast"
12 "go/parser"
13 "go/printer"
14 "go/token"
15 "io/fs"
16 "os"
17 "path/filepath"
18 "regexp"
19 "strings"
20 "testing"
21 "text/template"
22 )
23
24 var update = flag.Bool("update", false, "update golden (.out) files")
25 var files = flag.String("files", "", "consider only Go test files matching this regular expression")
26
27 const dataDir = "testdata"
28
29 var templateTxt = readTemplate("template.txt")
30
31 func readTemplate(filename string) *template.Template {
32 t := template.New(filename)
33 t.Funcs(template.FuncMap{
34 "node": nodeFmt,
35 "synopsis": synopsisFmt,
36 "indent": indentFmt,
37 })
38 return template.Must(t.ParseFiles(filepath.Join(dataDir, filename)))
39 }
40
41 func nodeFmt(node interface{}, fset *token.FileSet) string {
42 var buf bytes.Buffer
43 printer.Fprint(&buf, fset, node)
44 return strings.ReplaceAll(strings.TrimSpace(buf.String()), "\n", "\n\t")
45 }
46
47 func synopsisFmt(s string) string {
48 const n = 64
49 if len(s) > n {
50
51 s = s[0:n]
52 if i := strings.LastIndexAny(s, "\t\n "); i >= 0 {
53 s = s[0:i]
54 }
55 s = strings.TrimSpace(s) + " ..."
56 }
57 return "// " + strings.ReplaceAll(s, "\n", " ")
58 }
59
60 func indentFmt(indent, s string) string {
61 end := ""
62 if strings.HasSuffix(s, "\n") {
63 end = "\n"
64 s = s[:len(s)-1]
65 }
66 return indent + strings.ReplaceAll(s, "\n", "\n"+indent) + end
67 }
68
69 func isGoFile(fi fs.FileInfo) bool {
70 name := fi.Name()
71 return !fi.IsDir() &&
72 len(name) > 0 && name[0] != '.' &&
73 filepath.Ext(name) == ".go"
74 }
75
76 type bundle struct {
77 *Package
78 FSet *token.FileSet
79 }
80
81 func test(t *testing.T, mode Mode) {
82
83 filter := isGoFile
84 if *files != "" {
85 rx, err := regexp.Compile(*files)
86 if err != nil {
87 t.Fatal(err)
88 }
89 filter = func(fi fs.FileInfo) bool {
90 return isGoFile(fi) && rx.MatchString(fi.Name())
91 }
92 }
93
94
95 fset := token.NewFileSet()
96 pkgs, err := parser.ParseDir(fset, dataDir, filter, parser.ParseComments)
97 if err != nil {
98 t.Fatal(err)
99 }
100
101
102 for _, pkg := range pkgs {
103 importPath := dataDir + "/" + pkg.Name
104 var files []*ast.File
105 for _, f := range pkg.Files {
106 files = append(files, f)
107 }
108 doc, err := NewFromFiles(fset, files, importPath, mode)
109 if err != nil {
110 t.Error(err)
111 continue
112 }
113
114
115 for i, filename := range doc.Filenames {
116 doc.Filenames[i] = filepath.ToSlash(filename)
117 }
118
119
120 var buf bytes.Buffer
121 if err := templateTxt.Execute(&buf, bundle{doc, fset}); err != nil {
122 t.Error(err)
123 continue
124 }
125 got := buf.Bytes()
126
127
128 golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
129 if *update {
130 err := os.WriteFile(golden, got, 0644)
131 if err != nil {
132 t.Error(err)
133 }
134 continue
135 }
136
137
138 want, err := os.ReadFile(golden)
139 if err != nil {
140 t.Error(err)
141 continue
142 }
143
144
145 if !bytes.Equal(got, want) {
146 t.Errorf("package %s\n\tgot:\n%s\n\twant:\n%s", pkg.Name, got, want)
147 }
148 }
149 }
150
151 func Test(t *testing.T) {
152 test(t, 0)
153 test(t, AllDecls)
154 test(t, AllMethods)
155 }
156
157 func TestAnchorID(t *testing.T) {
158 const in = "Important Things 2 Know & Stuff"
159 const want = "hdr-Important_Things_2_Know___Stuff"
160 got := anchorID(in)
161 if got != want {
162 t.Errorf("anchorID(%q) = %q; want %q", in, got, want)
163 }
164 }
165
View as plain text