1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package doc
16
17 import (
18 "bufio"
19 "bytes"
20 "fmt"
21 "io/ioutil"
22 "os"
23 "path/filepath"
24 "strings"
25 "testing"
26
27 "github.com/spf13/cobra"
28 )
29
30 func assertNoErr(t *testing.T, e error) {
31 if e != nil {
32 t.Error(e)
33 }
34 }
35
36 func translate(in string) string {
37 return strings.ReplaceAll(in, "-", "\\-")
38 }
39
40 func TestGenManDoc(t *testing.T) {
41 header := &GenManHeader{
42 Title: "Project",
43 Section: "2",
44 }
45
46
47 buf := new(bytes.Buffer)
48 if err := GenMan(echoCmd, header, buf); err != nil {
49 t.Fatal(err)
50 }
51 output := buf.String()
52
53
54 parentPath := echoCmd.Parent().CommandPath()
55 dashParentPath := strings.ReplaceAll(parentPath, " ", "-")
56 expected := translate(dashParentPath)
57 expected = expected + "(" + header.Section + ")"
58 checkStringContains(t, output, expected)
59
60 checkStringContains(t, output, translate(echoCmd.Name()))
61 checkStringContains(t, output, translate(echoCmd.Name()))
62 checkStringContains(t, output, "boolone")
63 checkStringContains(t, output, "rootflag")
64 checkStringContains(t, output, translate(rootCmd.Name()))
65 checkStringContains(t, output, translate(echoSubCmd.Name()))
66 checkStringOmits(t, output, translate(deprecatedCmd.Name()))
67 checkStringContains(t, output, translate("Auto generated"))
68 }
69
70 func TestGenManNoHiddenParents(t *testing.T) {
71 header := &GenManHeader{
72 Title: "Project",
73 Section: "2",
74 }
75
76
77 for _, name := range []string{"rootflag", "strtwo"} {
78 f := rootCmd.PersistentFlags().Lookup(name)
79 f.Hidden = true
80 defer func() { f.Hidden = false }()
81 }
82 buf := new(bytes.Buffer)
83 if err := GenMan(echoCmd, header, buf); err != nil {
84 t.Fatal(err)
85 }
86 output := buf.String()
87
88
89 parentPath := echoCmd.Parent().CommandPath()
90 dashParentPath := strings.ReplaceAll(parentPath, " ", "-")
91 expected := translate(dashParentPath)
92 expected = expected + "(" + header.Section + ")"
93 checkStringContains(t, output, expected)
94
95 checkStringContains(t, output, translate(echoCmd.Name()))
96 checkStringContains(t, output, translate(echoCmd.Name()))
97 checkStringContains(t, output, "boolone")
98 checkStringOmits(t, output, "rootflag")
99 checkStringContains(t, output, translate(rootCmd.Name()))
100 checkStringContains(t, output, translate(echoSubCmd.Name()))
101 checkStringOmits(t, output, translate(deprecatedCmd.Name()))
102 checkStringContains(t, output, translate("Auto generated"))
103 checkStringOmits(t, output, "OPTIONS INHERITED FROM PARENT COMMANDS")
104 }
105
106 func TestGenManNoGenTag(t *testing.T) {
107 echoCmd.DisableAutoGenTag = true
108 defer func() { echoCmd.DisableAutoGenTag = false }()
109
110 header := &GenManHeader{
111 Title: "Project",
112 Section: "2",
113 }
114
115
116 buf := new(bytes.Buffer)
117 if err := GenMan(echoCmd, header, buf); err != nil {
118 t.Fatal(err)
119 }
120 output := buf.String()
121
122 unexpected := translate("#HISTORY")
123 checkStringOmits(t, output, unexpected)
124 unexpected = translate("Auto generated by spf13/cobra")
125 checkStringOmits(t, output, unexpected)
126 }
127
128 func TestGenManSeeAlso(t *testing.T) {
129 rootCmd := &cobra.Command{Use: "root", Run: emptyRun}
130 aCmd := &cobra.Command{Use: "aaa", Run: emptyRun, Hidden: true}
131 bCmd := &cobra.Command{Use: "bbb", Run: emptyRun}
132 cCmd := &cobra.Command{Use: "ccc", Run: emptyRun}
133 rootCmd.AddCommand(aCmd, bCmd, cCmd)
134
135 buf := new(bytes.Buffer)
136 header := &GenManHeader{}
137 if err := GenMan(rootCmd, header, buf); err != nil {
138 t.Fatal(err)
139 }
140 scanner := bufio.NewScanner(buf)
141
142 if err := assertLineFound(scanner, ".SH SEE ALSO"); err != nil {
143 t.Fatalf("Couldn't find SEE ALSO section header: %v", err)
144 }
145 if err := assertNextLineEquals(scanner, ".PP"); err != nil {
146 t.Fatalf("First line after SEE ALSO wasn't break-indent: %v", err)
147 }
148 if err := assertNextLineEquals(scanner, `\fBroot-bbb(1)\fP, \fBroot-ccc(1)\fP`); err != nil {
149 t.Fatalf("Second line after SEE ALSO wasn't correct: %v", err)
150 }
151 }
152
153 func TestManPrintFlagsHidesShortDeprecated(t *testing.T) {
154 c := &cobra.Command{}
155 c.Flags().StringP("foo", "f", "default", "Foo flag")
156 assertNoErr(t, c.Flags().MarkShorthandDeprecated("foo", "don't use it no more"))
157
158 buf := new(bytes.Buffer)
159 manPrintFlags(buf, c.Flags())
160
161 got := buf.String()
162 expected := "**--foo**=\"default\"\n\tFoo flag\n\n"
163 if got != expected {
164 t.Errorf("Expected %v, got %v", expected, got)
165 }
166 }
167
168 func TestGenManTree(t *testing.T) {
169 c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"}
170 header := &GenManHeader{Section: "2"}
171 tmpdir, err := ioutil.TempDir("", "test-gen-man-tree")
172 if err != nil {
173 t.Fatalf("Failed to create tmpdir: %s", err.Error())
174 }
175 defer os.RemoveAll(tmpdir)
176
177 if err := GenManTree(c, header, tmpdir); err != nil {
178 t.Fatalf("GenManTree failed: %s", err.Error())
179 }
180
181 if _, err := os.Stat(filepath.Join(tmpdir, "do.2")); err != nil {
182 t.Fatalf("Expected file 'do.2' to exist")
183 }
184
185 if header.Title != "" {
186 t.Fatalf("Expected header.Title to be unmodified")
187 }
188 }
189
190 func assertLineFound(scanner *bufio.Scanner, expectedLine string) error {
191 for scanner.Scan() {
192 line := scanner.Text()
193 if line == expectedLine {
194 return nil
195 }
196 }
197
198 if err := scanner.Err(); err != nil {
199 return fmt.Errorf("scan failed: %s", err)
200 }
201
202 return fmt.Errorf("hit EOF before finding %v", expectedLine)
203 }
204
205 func assertNextLineEquals(scanner *bufio.Scanner, expectedLine string) error {
206 if scanner.Scan() {
207 line := scanner.Text()
208 if line == expectedLine {
209 return nil
210 }
211 return fmt.Errorf("got %v, not %v", line, expectedLine)
212 }
213
214 if err := scanner.Err(); err != nil {
215 return fmt.Errorf("scan failed: %v", err)
216 }
217
218 return fmt.Errorf("hit EOF before finding %v", expectedLine)
219 }
220
221 func BenchmarkGenManToFile(b *testing.B) {
222 file, err := ioutil.TempFile("", "")
223 if err != nil {
224 b.Fatal(err)
225 }
226 defer os.Remove(file.Name())
227 defer file.Close()
228
229 b.ResetTimer()
230 for i := 0; i < b.N; i++ {
231 if err := GenMan(rootCmd, nil, file); err != nil {
232 b.Fatal(err)
233 }
234 }
235 }
236
View as plain text