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