Source file
src/cmd/doc/doc_test.go
1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "flag"
10 "log"
11 "os"
12 "path/filepath"
13 "regexp"
14 "runtime"
15 "strings"
16 "testing"
17 )
18
19 func TestMain(m *testing.M) {
20
21 buildCtx.GOPATH = ""
22 testGOPATH = true
23
24
25
26
27 testdataDir, err := filepath.Abs("testdata")
28 if err != nil {
29 panic(err)
30 }
31 dirsInit(
32 Dir{importPath: "testdata", dir: testdataDir},
33 Dir{importPath: "testdata/nested", dir: filepath.Join(testdataDir, "nested")},
34 Dir{importPath: "testdata/nested/nested", dir: filepath.Join(testdataDir, "nested", "nested")})
35
36 os.Exit(m.Run())
37 }
38
39 func maybeSkip(t *testing.T) {
40 if runtime.GOOS == "ios" {
41 t.Skip("iOS does not have a full file tree")
42 }
43 }
44
45 type isDotSlashTest struct {
46 str string
47 result bool
48 }
49
50 var isDotSlashTests = []isDotSlashTest{
51 {``, false},
52 {`x`, false},
53 {`...`, false},
54 {`.../`, false},
55 {`...\`, false},
56
57 {`.`, true},
58 {`./`, true},
59 {`.\`, true},
60 {`./x`, true},
61 {`.\x`, true},
62
63 {`..`, true},
64 {`../`, true},
65 {`..\`, true},
66 {`../x`, true},
67 {`..\x`, true},
68 }
69
70 func TestIsDotSlashPath(t *testing.T) {
71 for _, test := range isDotSlashTests {
72 if result := isDotSlash(test.str); result != test.result {
73 t.Errorf("isDotSlash(%q) = %t; expected %t", test.str, result, test.result)
74 }
75 }
76 }
77
78 type test struct {
79 name string
80 args []string
81 yes []string
82 no []string
83 }
84
85 const p = "cmd/doc/testdata"
86
87 var tests = []test{
88
89 {
90 "sanity check",
91 []string{p},
92 []string{`type ExportedType struct`},
93 nil,
94 },
95
96
97 {
98 "package clause",
99 []string{p},
100 []string{`package pkg.*cmd/doc/testdata`},
101 nil,
102 },
103
104
105
106 {
107 "full package",
108 []string{p},
109 []string{
110 `Package comment`,
111 `const ExportedConstant = 1`,
112 `const ConstOne = 1`,
113 `const ConstFive ...`,
114 `var ExportedVariable = 1`,
115 `var VarOne = 1`,
116 `func ExportedFunc\(a int\) bool`,
117 `func ReturnUnexported\(\) unexportedType`,
118 `type ExportedType struct{ ... }`,
119 `const ExportedTypedConstant ExportedType = iota`,
120 `const ExportedTypedConstant_unexported unexportedType`,
121 `const ConstLeft2 uint64 ...`,
122 `const ConstGroup1 unexportedType = iota ...`,
123 `const ConstGroup4 ExportedType = ExportedType{}`,
124 `const MultiLineConst = ...`,
125 `var MultiLineVar = map\[struct{ ... }\]struct{ ... }{ ... }`,
126 `func MultiLineFunc\(x interface{ ... }\) \(r struct{ ... }\)`,
127 `var LongLine = newLongLine\(("someArgument[1-4]", ){4}...\)`,
128 `type T1 = T2`,
129 `type SimpleConstraint interface{ ... }`,
130 `type TildeConstraint interface{ ... }`,
131 `type StructConstraint interface{ ... }`,
132 },
133 []string{
134 `const internalConstant = 2`,
135 `var internalVariable = 2`,
136 `func internalFunc(a int) bool`,
137 `Comment about exported constant`,
138 `Comment about exported variable`,
139 `Comment about block of constants`,
140 `Comment about block of variables`,
141 `Comment before ConstOne`,
142 `Comment before VarOne`,
143 `ConstTwo = 2`,
144 `VarTwo = 2`,
145 `VarFive = 5`,
146 `type unexportedType`,
147 `unexportedTypedConstant`,
148 `\bField`,
149 `Method`,
150 `someArgument[5-8]`,
151 `type T1 T2`,
152 },
153 },
154
155 {
156 "full package",
157 []string{"-all", p},
158 []string{
159 `package pkg .*import`,
160 `Package comment`,
161 `CONSTANTS`,
162 `Comment before ConstOne`,
163 `ConstOne = 1`,
164 `ConstTwo = 2 // Comment on line with ConstTwo`,
165 `ConstFive`,
166 `ConstSix`,
167 `Const block where first entry is unexported`,
168 `ConstLeft2, constRight2 uint64`,
169 `constLeft3, ConstRight3`,
170 `ConstLeft4, ConstRight4`,
171 `Duplicate = iota`,
172 `const CaseMatch = 1`,
173 `const Casematch = 2`,
174 `const ExportedConstant = 1`,
175 `const MultiLineConst = `,
176 `MultiLineString1`,
177 `VARIABLES`,
178 `Comment before VarOne`,
179 `VarOne = 1`,
180 `Comment about block of variables`,
181 `VarFive = 5`,
182 `var ExportedVariable = 1`,
183 `var ExportedVarOfUnExported unexportedType`,
184 `var LongLine = newLongLine\(`,
185 `var MultiLineVar = map\[struct {`,
186 `FUNCTIONS`,
187 `func ExportedFunc\(a int\) bool`,
188 `Comment about exported function`,
189 `func MultiLineFunc\(x interface`,
190 `func ReturnUnexported\(\) unexportedType`,
191 `TYPES`,
192 `type ExportedInterface interface`,
193 `type ExportedStructOneField struct`,
194 `type ExportedType struct`,
195 `Comment about exported type`,
196 `const ConstGroup4 ExportedType = ExportedType`,
197 `ExportedTypedConstant ExportedType = iota`,
198 `Constants tied to ExportedType`,
199 `func ExportedTypeConstructor\(\) \*ExportedType`,
200 `Comment about constructor for exported type`,
201 `func ReturnExported\(\) ExportedType`,
202 `func \(ExportedType\) ExportedMethod\(a int\) bool`,
203 `Comment about exported method`,
204 `type T1 = T2`,
205 `type T2 int`,
206 `type SimpleConstraint interface {`,
207 `type TildeConstraint interface {`,
208 `type StructConstraint interface {`,
209 },
210 []string{
211 `constThree`,
212 `_, _ uint64 = 2 \* iota, 1 << iota`,
213 `constLeft1, constRight1`,
214 `duplicate`,
215 `varFour`,
216 `func internalFunc`,
217 `unexportedField`,
218 `func \(unexportedType\)`,
219 },
220 },
221
222 {
223 "only package declaration",
224 []string{"-all", p + "/nested/empty"},
225 []string{`package empty .*import`},
226 nil,
227 },
228
229 {
230 "full package with -short",
231 []string{`-short`, p},
232 []string{
233 `const ExportedConstant = 1`,
234 `func ReturnUnexported\(\) unexportedType`,
235 },
236 []string{
237 `MultiLine(String|Method|Field)`,
238 },
239 },
240
241 {
242 "full package with u",
243 []string{`-u`, p},
244 []string{
245 `const ExportedConstant = 1`,
246 `const internalConstant = 2`,
247 `func internalFunc\(a int\) bool`,
248 `func ReturnUnexported\(\) unexportedType`,
249 },
250 []string{
251 `Comment about exported constant`,
252 `Comment about block of constants`,
253 `Comment about internal function`,
254 `MultiLine(String|Method|Field)`,
255 },
256 },
257
258 {
259 "full package",
260 []string{"-u", "-all", p},
261 []string{
262 `package pkg .*import`,
263 `Package comment`,
264 `CONSTANTS`,
265 `Comment before ConstOne`,
266 `ConstOne += 1`,
267 `ConstTwo += 2 // Comment on line with ConstTwo`,
268 `constThree = 3 // Comment on line with constThree`,
269 `ConstFive`,
270 `const internalConstant += 2`,
271 `Comment about internal constant`,
272 `VARIABLES`,
273 `Comment before VarOne`,
274 `VarOne += 1`,
275 `Comment about block of variables`,
276 `varFour += 4`,
277 `VarFive += 5`,
278 `varSix += 6`,
279 `var ExportedVariable = 1`,
280 `var LongLine = newLongLine\(`,
281 `var MultiLineVar = map\[struct {`,
282 `var internalVariable = 2`,
283 `Comment about internal variable`,
284 `FUNCTIONS`,
285 `func ExportedFunc\(a int\) bool`,
286 `Comment about exported function`,
287 `func MultiLineFunc\(x interface`,
288 `func internalFunc\(a int\) bool`,
289 `Comment about internal function`,
290 `func newLongLine\(ss .*string\)`,
291 `TYPES`,
292 `type ExportedType struct`,
293 `type T1 = T2`,
294 `type T2 int`,
295 `type unexportedType int`,
296 `Comment about unexported type`,
297 `ConstGroup1 unexportedType = iota`,
298 `ConstGroup2`,
299 `ConstGroup3`,
300 `ExportedTypedConstant_unexported unexportedType = iota`,
301 `Constants tied to unexportedType`,
302 `const unexportedTypedConstant unexportedType = 1`,
303 `func ReturnUnexported\(\) unexportedType`,
304 `func \(unexportedType\) ExportedMethod\(\) bool`,
305 `func \(unexportedType\) unexportedMethod\(\) bool`,
306 },
307 nil,
308 },
309
310
311 {
312 "single constant",
313 []string{p, `ExportedConstant`},
314 []string{
315 `Comment about exported constant`,
316 `const ExportedConstant = 1`,
317 },
318 nil,
319 },
320
321 {
322 "single constant with -u",
323 []string{`-u`, p, `internalConstant`},
324 []string{
325 `Comment about internal constant`,
326 `const internalConstant = 2`,
327 },
328 nil,
329 },
330
331 {
332 "block of constants",
333 []string{p, `ConstTwo`},
334 []string{
335 `Comment before ConstOne.\n.*ConstOne = 1`,
336 `ConstTwo = 2.*Comment on line with ConstTwo`,
337 `Comment about block of constants`,
338 },
339 []string{
340 `constThree`,
341 },
342 },
343
344 {
345 "block of constants with -u",
346 []string{"-u", p, `constThree`},
347 []string{
348 `constThree = 3.*Comment on line with constThree`,
349 },
350 nil,
351 },
352
353 {
354 "block of constants with -src",
355 []string{"-src", p, `ConstTwo`},
356 []string{
357 `Comment about block of constants`,
358 `ConstOne.*=.*1`,
359 `ConstTwo.*=.*2.*Comment on line with ConstTwo`,
360 `constThree`,
361 },
362 nil,
363 },
364
365 {
366 "block of constants with carryover type",
367 []string{p, `ConstLeft2`},
368 []string{
369 `ConstLeft2, constRight2 uint64`,
370 `constLeft3, ConstRight3`,
371 `ConstLeft4, ConstRight4`,
372 },
373 nil,
374 },
375
376 {
377 "block of constants with carryover type",
378 []string{"-u", p, `ConstLeft2`},
379 []string{
380 `_, _ uint64 = 2 \* iota, 1 << iota`,
381 `constLeft1, constRight1`,
382 `ConstLeft2, constRight2`,
383 `constLeft3, ConstRight3`,
384 `ConstLeft4, ConstRight4`,
385 },
386 nil,
387 },
388
389
390 {
391 "single variable",
392 []string{p, `ExportedVariable`},
393 []string{
394 `ExportedVariable`,
395 `var ExportedVariable = 1`,
396 },
397 nil,
398 },
399
400 {
401 "single variable with -u",
402 []string{`-u`, p, `internalVariable`},
403 []string{
404 `Comment about internal variable`,
405 `var internalVariable = 2`,
406 },
407 nil,
408 },
409
410 {
411 "block of variables",
412 []string{p, `VarTwo`},
413 []string{
414 `Comment before VarOne.\n.*VarOne = 1`,
415 `VarTwo = 2.*Comment on line with VarTwo`,
416 `Comment about block of variables`,
417 },
418 []string{
419 `varThree= 3`,
420 },
421 },
422
423 {
424 "block of variables with -u",
425 []string{"-u", p, `varThree`},
426 []string{
427 `varThree = 3.*Comment on line with varThree`,
428 },
429 nil,
430 },
431
432
433 {
434 "function",
435 []string{p, `ExportedFunc`},
436 []string{
437 `Comment about exported function`,
438 `func ExportedFunc\(a int\) bool`,
439 },
440 nil,
441 },
442
443 {
444 "function with -u",
445 []string{"-u", p, `internalFunc`},
446 []string{
447 `Comment about internal function`,
448 `func internalFunc\(a int\) bool`,
449 },
450 nil,
451 },
452
453 {
454 "function with -src",
455 []string{"-src", p, `ExportedFunc`},
456 []string{
457 `Comment about exported function`,
458 `func ExportedFunc\(a int\) bool`,
459 `return true != false`,
460 },
461 nil,
462 },
463
464
465 {
466 "type",
467 []string{p, `ExportedType`},
468 []string{
469 `Comment about exported type`,
470 `type ExportedType struct`,
471 `Comment before exported field.*\n.*ExportedField +int` +
472 `.*Comment on line with exported field`,
473 `ExportedEmbeddedType.*Comment on line with exported embedded field`,
474 `Has unexported fields`,
475 `func \(ExportedType\) ExportedMethod\(a int\) bool`,
476 `const ExportedTypedConstant ExportedType = iota`,
477 `func ExportedTypeConstructor\(\) \*ExportedType`,
478 `io.Reader.*Comment on line with embedded Reader`,
479 },
480 []string{
481 `unexportedField`,
482 `int.*embedded`,
483 `Comment about exported method`,
484 `unexportedMethod`,
485 `unexportedTypedConstant`,
486 `error`,
487 },
488 },
489
490 {
491 "type",
492 []string{"-src", p, `ExportedType`},
493 []string{
494 `Comment about exported type`,
495 `type ExportedType struct`,
496 `Comment before exported field`,
497 `ExportedField.*Comment on line with exported field`,
498 `ExportedEmbeddedType.*Comment on line with exported embedded field`,
499 `unexportedType.*Comment on line with unexported embedded field`,
500 `func \(ExportedType\) ExportedMethod\(a int\) bool`,
501 `const ExportedTypedConstant ExportedType = iota`,
502 `func ExportedTypeConstructor\(\) \*ExportedType`,
503 `io.Reader.*Comment on line with embedded Reader`,
504 },
505 []string{
506 `Comment about exported method`,
507 `unexportedMethod`,
508 `unexportedTypedConstant`,
509 },
510 },
511
512 {
513 "type",
514 []string{"-all", p, `ExportedType`},
515 []string{
516 `type ExportedType struct {`,
517 `Comment about exported type`,
518 `const ConstGroup4 ExportedType = ExportedType\{\}`,
519 `ExportedTypedConstant ExportedType = iota`,
520 `Constants tied to ExportedType`,
521 `func ExportedTypeConstructor\(\) \*ExportedType`,
522 `Comment about constructor for exported type.`,
523 `func ReturnExported\(\) ExportedType`,
524 `func \(ExportedType\) ExportedMethod\(a int\) bool`,
525 `Comment about exported method.`,
526 `func \(ExportedType\) Uncommented\(a int\) bool\n\n`,
527 },
528 []string{
529 `unexportedType`,
530 },
531 },
532
533 {
534 "type T1",
535 []string{p + ".T1"},
536 []string{
537 `type T1 = T2`,
538 },
539 []string{
540 `type T1 T2`,
541 `type ExportedType`,
542 },
543 },
544
545 {
546 "type with unexported fields and -u",
547 []string{"-u", p, `ExportedType`},
548 []string{
549 `Comment about exported type`,
550 `type ExportedType struct`,
551 `Comment before exported field.*\n.*ExportedField +int`,
552 `unexportedField.*int.*Comment on line with unexported field`,
553 `ExportedEmbeddedType.*Comment on line with exported embedded field`,
554 `\*ExportedEmbeddedType.*Comment on line with exported embedded \*field`,
555 `\*qualified.ExportedEmbeddedType.*Comment on line with exported embedded \*selector.field`,
556 `unexportedType.*Comment on line with unexported embedded field`,
557 `\*unexportedType.*Comment on line with unexported embedded \*field`,
558 `io.Reader.*Comment on line with embedded Reader`,
559 `error.*Comment on line with embedded error`,
560 `func \(ExportedType\) unexportedMethod\(a int\) bool`,
561 `unexportedTypedConstant`,
562 },
563 []string{
564 `Has unexported fields`,
565 },
566 },
567
568 {
569 "unexported type with -u",
570 []string{"-u", p, `unexportedType`},
571 []string{
572 `Comment about unexported type`,
573 `type unexportedType int`,
574 `func \(unexportedType\) ExportedMethod\(\) bool`,
575 `func \(unexportedType\) unexportedMethod\(\) bool`,
576 `ExportedTypedConstant_unexported unexportedType = iota`,
577 `const unexportedTypedConstant unexportedType = 1`,
578 },
579 nil,
580 },
581
582
583 {
584 "interface type",
585 []string{p, `ExportedInterface`},
586 []string{
587 `Comment about exported interface`,
588 `type ExportedInterface interface`,
589 `Comment before exported method.\n.*//\n.*// // Code block showing how to use ExportedMethod\n.*// func DoSomething\(\) error {\n.*// ExportedMethod\(\)\n.*// return nil\n.*// }\n.*//.*\n.*ExportedMethod\(\)` +
590 `.*Comment on line with exported method`,
591 `io.Reader.*Comment on line with embedded Reader`,
592 `error.*Comment on line with embedded error`,
593 `Has unexported methods`,
594 },
595 []string{
596 `unexportedField`,
597 `Comment about exported method`,
598 `unexportedMethod`,
599 `unexportedTypedConstant`,
600 },
601 },
602
603 {
604 "interface type with unexported methods and -u",
605 []string{"-u", p, `ExportedInterface`},
606 []string{
607 `Comment about exported interface`,
608 `type ExportedInterface interface`,
609 `Comment before exported method.\n.*//\n.*// // Code block showing how to use ExportedMethod\n.*// func DoSomething\(\) error {\n.*// ExportedMethod\(\)\n.*// return nil\n.*// }\n.*//.*\n.*ExportedMethod\(\)` + `.*Comment on line with exported method`,
610 `unexportedMethod\(\).*Comment on line with unexported method`,
611 `io.Reader.*Comment on line with embedded Reader`,
612 `error.*Comment on line with embedded error`,
613 },
614 []string{
615 `Has unexported methods`,
616 },
617 },
618
619
620 {
621 "interface method",
622 []string{p, `ExportedInterface.ExportedMethod`},
623 []string{
624 `Comment before exported method.\n.*//\n.*// // Code block showing how to use ExportedMethod\n.*// func DoSomething\(\) error {\n.*// ExportedMethod\(\)\n.*// return nil\n.*// }\n.*//.*\n.*ExportedMethod\(\)` +
625 `.*Comment on line with exported method`,
626 },
627 []string{
628 `Comment about exported interface`,
629 },
630 },
631
632 {
633 "interface method at package level",
634 []string{p, `ExportedMethod`},
635 []string{
636 `func \(ExportedType\) ExportedMethod\(a int\) bool`,
637 `Comment about exported method`,
638 },
639 []string{
640 `Comment before exported method.*\n.*ExportedMethod\(\)` +
641 `.*Comment on line with exported method`,
642 },
643 },
644
645
646 {
647 "method",
648 []string{p, `ExportedType.ExportedMethod`},
649 []string{
650 `func \(ExportedType\) ExportedMethod\(a int\) bool`,
651 `Comment about exported method`,
652 },
653 nil,
654 },
655
656 {
657 "method with -u",
658 []string{"-u", p, `ExportedType.unexportedMethod`},
659 []string{
660 `func \(ExportedType\) unexportedMethod\(a int\) bool`,
661 `Comment about unexported method`,
662 },
663 nil,
664 },
665
666 {
667 "method with -src",
668 []string{"-src", p, `ExportedType.ExportedMethod`},
669 []string{
670 `func \(ExportedType\) ExportedMethod\(a int\) bool`,
671 `Comment about exported method`,
672 `return true != true`,
673 },
674 nil,
675 },
676
677
678 {
679 "field",
680 []string{p, `ExportedType.ExportedField`},
681 []string{
682 `type ExportedType struct`,
683 `ExportedField int`,
684 `Comment before exported field`,
685 `Comment on line with exported field`,
686 `other fields elided`,
687 },
688 nil,
689 },
690
691
692 {
693 "method with -u",
694 []string{"-u", p, `ExportedType.unexportedField`},
695 []string{
696 `unexportedField int`,
697 `Comment on line with unexported field`,
698 },
699 nil,
700 },
701
702
703 {
704 "single-field struct",
705 []string{p, `ExportedStructOneField.OnlyField`},
706 []string{`the only field`},
707 []string{`other fields elided`},
708 },
709
710
711 {
712 "case matching off",
713 []string{p, `casematch`},
714 []string{
715 `CaseMatch`,
716 `Casematch`,
717 },
718 nil,
719 },
720
721
722 {
723 "case matching on",
724 []string{"-c", p, `Casematch`},
725 []string{
726 `Casematch`,
727 },
728 []string{
729 `CaseMatch`,
730 },
731 },
732
733
734 {
735 "merge comments with -src A",
736 []string{"-src", p + "/merge", `A`},
737 []string{
738 `A doc`,
739 `func A`,
740 `A comment`,
741 },
742 []string{
743 `Package A doc`,
744 `Package B doc`,
745 `B doc`,
746 `B comment`,
747 `B doc`,
748 },
749 },
750 {
751 "merge comments with -src B",
752 []string{"-src", p + "/merge", `B`},
753 []string{
754 `B doc`,
755 `func B`,
756 `B comment`,
757 },
758 []string{
759 `Package A doc`,
760 `Package B doc`,
761 `A doc`,
762 `A comment`,
763 `A doc`,
764 },
765 },
766
767
768 {
769 "case matching on, no dups",
770 []string{"-u", p, `duplicate`},
771 []string{
772 `Duplicate`,
773 `duplicate`,
774 },
775 []string{
776 "\\)\n+const",
777 },
778 },
779 {
780 "non-imported: pkg.sym",
781 []string{"nested.Foo"},
782 []string{"Foo struct"},
783 nil,
784 },
785 {
786 "non-imported: pkg only",
787 []string{"nested"},
788 []string{"Foo struct"},
789 nil,
790 },
791 {
792 "non-imported: pkg sym",
793 []string{"nested", "Foo"},
794 []string{"Foo struct"},
795 nil,
796 },
797 {
798 "formatted doc on function",
799 []string{p, "ExportedFormattedDoc"},
800 []string{
801 `func ExportedFormattedDoc\(a int\) bool`,
802 ` Comment about exported function with formatting\.
803
804 Example
805
806 fmt\.Println\(FormattedDoc\(\)\)
807
808 Text after pre-formatted block\.`,
809 },
810 nil,
811 },
812 {
813 "formatted doc on type field",
814 []string{p, "ExportedFormattedType.ExportedField"},
815 []string{
816 `type ExportedFormattedType struct`,
817 ` // Comment before exported field with formatting\.
818 //[ ]
819 // Example
820 //[ ]
821 // a\.ExportedField = 123
822 //[ ]
823 // Text after pre-formatted block\.`,
824 `ExportedField int`,
825 },
826 nil,
827 },
828 }
829
830 func TestDoc(t *testing.T) {
831 maybeSkip(t)
832 defer log.SetOutput(log.Writer())
833 for _, test := range tests {
834 var b bytes.Buffer
835 var flagSet flag.FlagSet
836 var logbuf bytes.Buffer
837 log.SetOutput(&logbuf)
838 err := do(&b, &flagSet, test.args)
839 if err != nil {
840 t.Fatalf("%s %v: %s\n", test.name, test.args, err)
841 }
842 if logbuf.Len() > 0 {
843 t.Errorf("%s %v: unexpected log messages:\n%s", test.name, test.args, logbuf.Bytes())
844 }
845 output := b.Bytes()
846 failed := false
847 for j, yes := range test.yes {
848 re, err := regexp.Compile(yes)
849 if err != nil {
850 t.Fatalf("%s.%d: compiling %#q: %s", test.name, j, yes, err)
851 }
852 if !re.Match(output) {
853 t.Errorf("%s.%d: no match for %s %#q", test.name, j, test.args, yes)
854 failed = true
855 }
856 }
857 for j, no := range test.no {
858 re, err := regexp.Compile(no)
859 if err != nil {
860 t.Fatalf("%s.%d: compiling %#q: %s", test.name, j, no, err)
861 }
862 if re.Match(output) {
863 t.Errorf("%s.%d: incorrect match for %s %#q", test.name, j, test.args, no)
864 failed = true
865 }
866 }
867 if bytes.Count(output, []byte("TYPES\n")) > 1 {
868 t.Fatalf("%s: repeating headers", test.name)
869 }
870 if failed {
871 t.Logf("\n%s", output)
872 }
873 }
874 }
875
876
877
878
879
880 func TestMultiplePackages(t *testing.T) {
881 if testing.Short() {
882 t.Skip("scanning file system takes too long")
883 }
884 maybeSkip(t)
885 var b bytes.Buffer
886
887 {
888 var flagSet flag.FlagSet
889 err := do(&b, &flagSet, []string{"crypto/rand.float64"})
890 if err == nil {
891 t.Errorf("expected error from crypto/rand.float64")
892 } else if !strings.Contains(err.Error(), "no symbol float64") {
893 t.Errorf("unexpected error %q from crypto/rand.float64", err)
894 }
895 }
896
897 {
898 var flagSet flag.FlagSet
899 err := do(&b, &flagSet, []string{"math/rand.float64"})
900 if err != nil {
901 t.Errorf("unexpected error %q from math/rand.float64", err)
902 }
903 }
904
905 {
906 var flagSet flag.FlagSet
907 err := do(&b, &flagSet, []string{"rand.float64"})
908 if err != nil {
909 t.Errorf("unexpected error %q from rand.float64", err)
910 }
911 }
912
913 {
914 var flagSet flag.FlagSet
915 err := do(&b, &flagSet, []string{"rand.doesnotexit"})
916 if err == nil {
917 t.Errorf("expected error from rand.doesnotexit")
918 } else {
919 errStr := err.Error()
920 if !strings.Contains(errStr, "no symbol") {
921 t.Errorf("error %q should contain 'no symbol", errStr)
922 }
923 if !strings.Contains(errStr, "crypto/rand") {
924 t.Errorf("error %q should contain crypto/rand", errStr)
925 }
926 if !strings.Contains(errStr, "math/rand") {
927 t.Errorf("error %q should contain math/rand", errStr)
928 }
929 }
930 }
931 }
932
933
934
935
936
937
938
939
940
941 func TestTwoArgLookup(t *testing.T) {
942 if testing.Short() {
943 t.Skip("scanning file system takes too long")
944 }
945 maybeSkip(t)
946 var b bytes.Buffer
947 {
948 var flagSet flag.FlagSet
949 err := do(&b, &flagSet, []string{"binary", "BigEndian"})
950 if err != nil {
951 t.Errorf("unexpected error %q from binary BigEndian", err)
952 }
953 }
954 {
955 var flagSet flag.FlagSet
956 err := do(&b, &flagSet, []string{"rand", "Float64"})
957 if err != nil {
958 t.Errorf("unexpected error %q from rand Float64", err)
959 }
960 }
961 {
962 var flagSet flag.FlagSet
963 err := do(&b, &flagSet, []string{"bytes", "Foo"})
964 if err == nil {
965 t.Errorf("expected error from bytes Foo")
966 } else if !strings.Contains(err.Error(), "no symbol Foo") {
967 t.Errorf("unexpected error %q from bytes Foo", err)
968 }
969 }
970 {
971 var flagSet flag.FlagSet
972 err := do(&b, &flagSet, []string{"nosuchpackage", "Foo"})
973 if err == nil {
974
975 } else if !strings.Contains(err.Error(), "no such package") {
976 t.Errorf("unexpected error %q from nosuchpackage Foo", err)
977 }
978 }
979 }
980
981
982
983
984 func TestDotSlashLookup(t *testing.T) {
985 if testing.Short() {
986 t.Skip("scanning file system takes too long")
987 }
988 maybeSkip(t)
989 where, err := os.Getwd()
990 if err != nil {
991 t.Fatal(err)
992 }
993 defer func() {
994 if err := os.Chdir(where); err != nil {
995 t.Fatal(err)
996 }
997 }()
998 if err := os.Chdir(filepath.Join(buildCtx.GOROOT, "src", "text")); err != nil {
999 t.Fatal(err)
1000 }
1001 var b bytes.Buffer
1002 var flagSet flag.FlagSet
1003 err = do(&b, &flagSet, []string{"./template"})
1004 if err != nil {
1005 t.Errorf("unexpected error %q from ./template", err)
1006 }
1007
1008 const want = `package template // import "text/template"`
1009 output := b.String()
1010 if !strings.HasPrefix(output, want) {
1011 t.Fatalf("wrong package: %.*q...", len(want), output)
1012 }
1013 }
1014
1015
1016
1017 func TestNoPackageClauseWhenNoMatch(t *testing.T) {
1018 maybeSkip(t)
1019 var b bytes.Buffer
1020 var flagSet flag.FlagSet
1021 err := do(&b, &flagSet, []string{"template.ZZZ"})
1022
1023 if err == nil {
1024 t.Error("expect an error for template.zzz")
1025 }
1026
1027 const dontWant = `package template // import `
1028 output := b.String()
1029 if strings.Contains(output, dontWant) {
1030 t.Fatalf("improper package clause printed:\n%s", output)
1031 }
1032 }
1033
1034 type trimTest struct {
1035 path string
1036 prefix string
1037 result string
1038 ok bool
1039 }
1040
1041 var trimTests = []trimTest{
1042 {"", "", "", true},
1043 {"/usr/gopher", "/usr/gopher", "/usr/gopher", true},
1044 {"/usr/gopher/bar", "/usr/gopher", "bar", true},
1045 {"/usr/gopherflakes", "/usr/gopher", "/usr/gopherflakes", false},
1046 {"/usr/gopher/bar", "/usr/zot", "/usr/gopher/bar", false},
1047 }
1048
1049 func TestTrim(t *testing.T) {
1050 for _, test := range trimTests {
1051 result, ok := trim(test.path, test.prefix)
1052 if ok != test.ok {
1053 t.Errorf("%s %s expected %t got %t", test.path, test.prefix, test.ok, ok)
1054 continue
1055 }
1056 if result != test.result {
1057 t.Errorf("%s %s expected %q got %q", test.path, test.prefix, test.result, result)
1058 continue
1059 }
1060 }
1061 }
1062
View as plain text