Source file
src/cmd/covdata/tool_test.go
1
2
3
4
5 package main_test
6
7 import (
8 cmdcovdata "cmd/covdata"
9 "flag"
10 "fmt"
11 "internal/coverage/pods"
12 "internal/testenv"
13 "log"
14 "os"
15 "path/filepath"
16 "regexp"
17 "strconv"
18 "strings"
19 "sync"
20 "testing"
21 )
22
23
24 var testTempDir string
25
26
27 var preserveTmp = flag.Bool("preservetmp", false, "keep tmpdir files for debugging")
28
29
30
31
32 func TestMain(m *testing.M) {
33
34
35
36
37 if os.Getenv("CMDCOVDATA_TEST_RUN_MAIN") != "" {
38 cmdcovdata.Main()
39 os.Exit(0)
40 }
41 flag.Parse()
42 topTmpdir, err := os.MkdirTemp("", "cmd-covdata-test-")
43 if err != nil {
44 log.Fatal(err)
45 }
46 testTempDir = topTmpdir
47 if !*preserveTmp {
48 defer os.RemoveAll(topTmpdir)
49 } else {
50 fmt.Fprintf(os.Stderr, "debug: preserving tmpdir %s\n", topTmpdir)
51 }
52 os.Setenv("CMDCOVDATA_TEST_RUN_MAIN", "true")
53 os.Exit(m.Run())
54 }
55
56 var tdmu sync.Mutex
57 var tdcount int
58
59 func tempDir(t *testing.T) string {
60 tdmu.Lock()
61 dir := filepath.Join(testTempDir, fmt.Sprintf("%03d", tdcount))
62 tdcount++
63 if err := os.Mkdir(dir, 0777); err != nil {
64 t.Fatal(err)
65 }
66 defer tdmu.Unlock()
67 return dir
68 }
69
70 const debugtrace = false
71
72 func gobuild(t *testing.T, indir string, bargs []string) {
73 t.Helper()
74
75 if debugtrace {
76 if indir != "" {
77 t.Logf("in dir %s: ", indir)
78 }
79 t.Logf("cmd: %s %+v\n", testenv.GoToolPath(t), bargs)
80 }
81 cmd := testenv.Command(t, testenv.GoToolPath(t), bargs...)
82 cmd.Dir = indir
83 b, err := cmd.CombinedOutput()
84 if len(b) != 0 {
85 t.Logf("## build output:\n%s", b)
86 }
87 if err != nil {
88 t.Fatalf("build error: %v", err)
89 }
90 }
91
92 func emitFile(t *testing.T, dst, src string) {
93 payload, err := os.ReadFile(src)
94 if err != nil {
95 t.Fatalf("error reading %q: %v", src, err)
96 }
97 if err := os.WriteFile(dst, payload, 0666); err != nil {
98 t.Fatalf("writing %q: %v", dst, err)
99 }
100 }
101
102 const mainPkgPath = "prog"
103
104 func buildProg(t *testing.T, prog string, dir string, tag string, flags []string) (string, string) {
105
106 subdir := filepath.Join(dir, prog+"dir"+tag)
107 if err := os.Mkdir(subdir, 0777); err != nil {
108 t.Fatalf("can't create outdir %s: %v", subdir, err)
109 }
110 depdir := filepath.Join(subdir, "dep")
111 if err := os.Mkdir(depdir, 0777); err != nil {
112 t.Fatalf("can't create outdir %s: %v", depdir, err)
113 }
114
115
116 insrc := filepath.Join("testdata", prog+".go")
117 src := filepath.Join(subdir, prog+".go")
118 emitFile(t, src, insrc)
119 indep := filepath.Join("testdata", "dep.go")
120 dep := filepath.Join(depdir, "dep.go")
121 emitFile(t, dep, indep)
122
123
124 mod := filepath.Join(subdir, "go.mod")
125 modsrc := "\nmodule " + mainPkgPath + "\n\ngo 1.19\n"
126 if err := os.WriteFile(mod, []byte(modsrc), 0666); err != nil {
127 t.Fatal(err)
128 }
129 exepath := filepath.Join(subdir, prog+".exe")
130 bargs := []string{"build", "-cover", "-o", exepath}
131 bargs = append(bargs, flags...)
132 gobuild(t, subdir, bargs)
133 return exepath, subdir
134 }
135
136 type state struct {
137 dir string
138 exedir1 string
139 exedir2 string
140 exedir3 string
141 exepath1 string
142 exepath2 string
143 exepath3 string
144 tool string
145 outdirs [4]string
146 }
147
148 const debugWorkDir = false
149
150 func TestCovTool(t *testing.T) {
151 testenv.MustHaveGoBuild(t)
152 dir := tempDir(t)
153 if testing.Short() {
154 t.Skip()
155 }
156 if debugWorkDir {
157
158 dir = "/tmp/qqq"
159 os.RemoveAll(dir)
160 os.Mkdir(dir, 0777)
161 }
162
163 s := state{
164 dir: dir,
165 }
166 s.exepath1, s.exedir1 = buildProg(t, "prog1", dir, "", nil)
167 s.exepath2, s.exedir2 = buildProg(t, "prog2", dir, "", nil)
168 flags := []string{"-covermode=atomic"}
169 s.exepath3, s.exedir3 = buildProg(t, "prog1", dir, "atomic", flags)
170
171
172 s.tool = testenv.Executable(t)
173
174
175 for i := 0; i < 4; i++ {
176 d := filepath.Join(dir, fmt.Sprintf("covdata%d", i))
177 s.outdirs[i] = d
178 if err := os.Mkdir(d, 0777); err != nil {
179 t.Fatalf("can't create outdir %s: %v", d, err)
180 }
181 }
182
183
184
185
186
187
188
189
190
191 for m := 0; m < 2; m++ {
192 for k := 0; k < 2; k++ {
193 args := []string{}
194 if k != 0 {
195 args = append(args, "foo", "bar")
196 }
197 for i := 0; i <= k; i++ {
198 exepath := s.exepath1
199 if m != 0 {
200 exepath = s.exepath3
201 }
202 cmd := testenv.Command(t, exepath, args...)
203 cmd.Env = append(cmd.Env, "GOCOVERDIR="+s.outdirs[m*2+k])
204 b, err := cmd.CombinedOutput()
205 if len(b) != 0 {
206 t.Logf("## instrumented run output:\n%s", b)
207 }
208 if err != nil {
209 t.Fatalf("instrumented run error: %v", err)
210 }
211 }
212 }
213 }
214
215
216
217 t.Run("MergeSimple", func(t *testing.T) {
218 t.Parallel()
219 testMergeSimple(t, s, s.outdirs[0], s.outdirs[1], "set")
220 testMergeSimple(t, s, s.outdirs[2], s.outdirs[3], "atomic")
221 })
222 t.Run("MergeSelect", func(t *testing.T) {
223 t.Parallel()
224 testMergeSelect(t, s, s.outdirs[0], s.outdirs[1], "set")
225 testMergeSelect(t, s, s.outdirs[2], s.outdirs[3], "atomic")
226 })
227 t.Run("MergePcombine", func(t *testing.T) {
228 t.Parallel()
229 testMergeCombinePrograms(t, s)
230 })
231 t.Run("Dump", func(t *testing.T) {
232 t.Parallel()
233 testDump(t, s)
234 })
235 t.Run("Percent", func(t *testing.T) {
236 t.Parallel()
237 testPercent(t, s)
238 })
239 t.Run("PkgList", func(t *testing.T) {
240 t.Parallel()
241 testPkgList(t, s)
242 })
243 t.Run("Textfmt", func(t *testing.T) {
244 t.Parallel()
245 testTextfmt(t, s)
246 })
247 t.Run("Subtract", func(t *testing.T) {
248 t.Parallel()
249 testSubtract(t, s)
250 })
251 t.Run("Intersect", func(t *testing.T) {
252 t.Parallel()
253 testIntersect(t, s, s.outdirs[0], s.outdirs[1], "set")
254 testIntersect(t, s, s.outdirs[2], s.outdirs[3], "atomic")
255 })
256 t.Run("CounterClash", func(t *testing.T) {
257 t.Parallel()
258 testCounterClash(t, s)
259 })
260 t.Run("TestEmpty", func(t *testing.T) {
261 t.Parallel()
262 testEmpty(t, s)
263 })
264 t.Run("TestCommandLineErrors", func(t *testing.T) {
265 t.Parallel()
266 testCommandLineErrors(t, s, s.outdirs[0])
267 })
268 }
269
270 const showToolInvocations = true
271
272 func runToolOp(t *testing.T, s state, op string, args []string) []string {
273
274 t.Helper()
275 args = append([]string{op}, args...)
276 if showToolInvocations {
277 t.Logf("%s cmd is: %s %+v", op, s.tool, args)
278 }
279 cmd := testenv.Command(t, s.tool, args...)
280 b, err := cmd.CombinedOutput()
281 if err != nil {
282 fmt.Fprintf(os.Stderr, "## %s output: %s\n", op, b)
283 t.Fatalf("%q run error: %v", op, err)
284 }
285 output := strings.TrimSpace(string(b))
286 lines := strings.Split(output, "\n")
287 if len(lines) == 1 && lines[0] == "" {
288 lines = nil
289 }
290 return lines
291 }
292
293 func testDump(t *testing.T, s state) {
294
295 dargs := []string{"-pkg=" + mainPkgPath, "-live", "-i=" + s.outdirs[0] + "," + s.outdirs[1]}
296 lines := runToolOp(t, s, "debugdump", dargs)
297
298
299 testpoints := []struct {
300 tag string
301 re *regexp.Regexp
302 }{
303 {
304 "args",
305 regexp.MustCompile(`^data file .+ GOOS=.+ GOARCH=.+ program args: .+$`),
306 },
307 {
308 "main package",
309 regexp.MustCompile(`^Package path: ` + mainPkgPath + `\s*$`),
310 },
311 {
312 "main function",
313 regexp.MustCompile(`^Func: main\s*$`),
314 },
315 }
316
317 bad := false
318 for _, testpoint := range testpoints {
319 found := false
320 for _, line := range lines {
321 if m := testpoint.re.FindStringSubmatch(line); m != nil {
322 found = true
323 break
324 }
325 }
326 if !found {
327 t.Errorf("dump output regexp match failed for %q", testpoint.tag)
328 bad = true
329 }
330 }
331 if bad {
332 dumplines(lines)
333 }
334 }
335
336 func testPercent(t *testing.T, s state) {
337
338 dargs := []string{"-pkg=" + mainPkgPath, "-i=" + s.outdirs[0] + "," + s.outdirs[1]}
339 lines := runToolOp(t, s, "percent", dargs)
340
341
342 testpoints := []struct {
343 tag string
344 re *regexp.Regexp
345 }{
346 {
347 "statement coverage percent",
348 regexp.MustCompile(`coverage: \d+\.\d% of statements\s*$`),
349 },
350 }
351
352 bad := false
353 for _, testpoint := range testpoints {
354 found := false
355 for _, line := range lines {
356 if m := testpoint.re.FindStringSubmatch(line); m != nil {
357 found = true
358 break
359 }
360 }
361 if !found {
362 t.Errorf("percent output regexp match failed for %s", testpoint.tag)
363 bad = true
364 }
365 }
366 if bad {
367 dumplines(lines)
368 }
369 }
370
371 func testPkgList(t *testing.T, s state) {
372 dargs := []string{"-i=" + s.outdirs[0] + "," + s.outdirs[1]}
373 lines := runToolOp(t, s, "pkglist", dargs)
374
375 want := []string{mainPkgPath, mainPkgPath + "/dep"}
376 bad := false
377 if len(lines) != 2 {
378 t.Errorf("expect pkglist to return two lines")
379 bad = true
380 } else {
381 for i := 0; i < 2; i++ {
382 lines[i] = strings.TrimSpace(lines[i])
383 if want[i] != lines[i] {
384 t.Errorf("line %d want %s got %s", i, want[i], lines[i])
385 bad = true
386 }
387 }
388 }
389 if bad {
390 dumplines(lines)
391 }
392 }
393
394 func testTextfmt(t *testing.T, s state) {
395 outf := s.dir + "/" + "t.txt"
396 dargs := []string{"-pkg=" + mainPkgPath, "-i=" + s.outdirs[0] + "," + s.outdirs[1],
397 "-o", outf}
398 lines := runToolOp(t, s, "textfmt", dargs)
399
400
401 if len(lines) != 0 {
402 dumplines(lines)
403 t.Errorf("unexpected output from go tool covdata textfmt")
404 }
405
406
407 payload, err := os.ReadFile(outf)
408 if err != nil {
409 t.Errorf("opening %s: %v\n", outf, err)
410 }
411 lines = strings.Split(string(payload), "\n")
412 want0 := "mode: set"
413 if lines[0] != want0 {
414 dumplines(lines[0:10])
415 t.Errorf("textfmt: want %s got %s", want0, lines[0])
416 }
417 want1 := mainPkgPath + "/prog1.go:13.14,15.2 1 1"
418 if lines[1] != want1 {
419 dumplines(lines[0:10])
420 t.Errorf("textfmt: want %s got %s", want1, lines[1])
421 }
422 }
423
424 func dumplines(lines []string) {
425 for i := range lines {
426 fmt.Fprintf(os.Stderr, "%s\n", lines[i])
427 }
428 }
429
430 type dumpCheck struct {
431 tag string
432 re *regexp.Regexp
433 negate bool
434 nonzero bool
435 zero bool
436 }
437
438
439
440
441 func runDumpChecks(t *testing.T, s state, dir string, flags []string, checks []dumpCheck) {
442 dargs := []string{"-i", dir}
443 dargs = append(dargs, flags...)
444 lines := runToolOp(t, s, "debugdump", dargs)
445 if len(lines) == 0 {
446 t.Fatalf("dump run produced no output")
447 }
448
449 bad := false
450 for _, check := range checks {
451 found := false
452 for _, line := range lines {
453 if m := check.re.FindStringSubmatch(line); m != nil {
454 found = true
455 if check.negate {
456 t.Errorf("tag %q: unexpected match", check.tag)
457 bad = true
458
459 }
460 if check.nonzero || check.zero {
461 if len(m) < 2 {
462 t.Errorf("tag %s: submatch failed (short m)", check.tag)
463 bad = true
464 continue
465 }
466 if m[1] == "" {
467 t.Errorf("tag %s: submatch failed", check.tag)
468 bad = true
469 continue
470 }
471 i, err := strconv.Atoi(m[1])
472 if err != nil {
473 t.Errorf("tag %s: match Atoi failed on %s",
474 check.tag, m[1])
475 continue
476 }
477 if check.zero && i != 0 {
478 t.Errorf("tag %s: match zero failed on %s",
479 check.tag, m[1])
480 } else if check.nonzero && i == 0 {
481 t.Errorf("tag %s: match nonzero failed on %s",
482 check.tag, m[1])
483 }
484 }
485 break
486 }
487 }
488 if !found && !check.negate {
489 t.Errorf("dump output regexp match failed for %s", check.tag)
490 bad = true
491 }
492 }
493 if bad {
494 fmt.Printf("output from 'dump' run:\n")
495 dumplines(lines)
496 }
497 }
498
499 func testMergeSimple(t *testing.T, s state, indir1, indir2, tag string) {
500 outdir := filepath.Join(s.dir, "simpleMergeOut"+tag)
501 if err := os.Mkdir(outdir, 0777); err != nil {
502 t.Fatalf("can't create outdir %s: %v", outdir, err)
503 }
504
505
506 ins := fmt.Sprintf("-i=%s,%s", indir1, indir2)
507 out := fmt.Sprintf("-o=%s", outdir)
508 margs := []string{ins, out}
509 lines := runToolOp(t, s, "merge", margs)
510 if len(lines) != 0 {
511 t.Errorf("merge run produced %d lines of unexpected output", len(lines))
512 dumplines(lines)
513 }
514
515
516
517
518 podlist, err := pods.CollectPods([]string{outdir}, true)
519 if err != nil {
520 t.Fatal(err)
521 }
522 if len(podlist) != 1 {
523 t.Fatalf("expected 1 pod, got %d pods", len(podlist))
524 }
525 ncdfs := len(podlist[0].CounterDataFiles)
526 if ncdfs != 1 {
527 t.Fatalf("expected 1 counter data file, got %d", ncdfs)
528 }
529
530
531
532
533 testpoints := []dumpCheck{
534 {
535 tag: "first function",
536 re: regexp.MustCompile(`^Func: first\s*$`),
537 },
538 {
539 tag: "second function",
540 re: regexp.MustCompile(`^Func: second\s*$`),
541 },
542 {
543 tag: "third function",
544 re: regexp.MustCompile(`^Func: third\s*$`),
545 },
546 {
547 tag: "third function unit 0",
548 re: regexp.MustCompile(`^0: L23:C23 -- L24:C12 NS=1 = (\d+)$`),
549 nonzero: true,
550 },
551 {
552 tag: "third function unit 1",
553 re: regexp.MustCompile(`^1: L27:C2 -- L28:C10 NS=2 = (\d+)$`),
554 nonzero: true,
555 },
556 {
557 tag: "third function unit 2",
558 re: regexp.MustCompile(`^2: L24:C12 -- L26:C3 NS=1 = (\d+)$`),
559 nonzero: true,
560 },
561 }
562 flags := []string{"-live", "-pkg=" + mainPkgPath}
563 runDumpChecks(t, s, outdir, flags, testpoints)
564 }
565
566 func testMergeSelect(t *testing.T, s state, indir1, indir2 string, tag string) {
567 outdir := filepath.Join(s.dir, "selectMergeOut"+tag)
568 if err := os.Mkdir(outdir, 0777); err != nil {
569 t.Fatalf("can't create outdir %s: %v", outdir, err)
570 }
571
572
573
574 ins := fmt.Sprintf("-i=%s,%s", indir1, indir2)
575 out := fmt.Sprintf("-o=%s", outdir)
576 margs := []string{"-pkg=" + mainPkgPath + "/dep", ins, out}
577 lines := runToolOp(t, s, "merge", margs)
578 if len(lines) != 0 {
579 t.Errorf("merge run produced %d lines of unexpected output", len(lines))
580 dumplines(lines)
581 }
582
583
584
585 dargs := []string{"-i=" + outdir}
586 lines = runToolOp(t, s, "debugdump", dargs)
587 if len(lines) == 0 {
588 t.Fatalf("dump run produced no output")
589 }
590 want := map[string]int{
591 "Package path: " + mainPkgPath + "/dep": 0,
592 "Func: Dep1": 0,
593 "Func: PDep": 0,
594 }
595 bad := false
596 for _, line := range lines {
597 if v, ok := want[line]; ok {
598 if v != 0 {
599 t.Errorf("duplicate line %s", line)
600 bad = true
601 break
602 }
603 want[line] = 1
604 continue
605 }
606
607 if strings.HasPrefix(line, "Func:") || strings.HasPrefix(line, "Package path:") {
608 t.Errorf("unexpected line: %s", line)
609 bad = true
610 break
611 }
612 }
613 if bad {
614 dumplines(lines)
615 }
616 }
617
618 func testMergeCombinePrograms(t *testing.T, s state) {
619
620
621
622 runout := [2]string{}
623 for k := 0; k < 2; k++ {
624 runout[k] = filepath.Join(s.dir, fmt.Sprintf("newcovdata%d", k))
625 if err := os.Mkdir(runout[k], 0777); err != nil {
626 t.Fatalf("can't create outdir %s: %v", runout[k], err)
627 }
628 args := []string{}
629 if k != 0 {
630 args = append(args, "foo", "bar")
631 }
632 cmd := testenv.Command(t, s.exepath2, args...)
633 cmd.Env = append(cmd.Env, "GOCOVERDIR="+runout[k])
634 b, err := cmd.CombinedOutput()
635 if len(b) != 0 {
636 t.Logf("## instrumented run output:\n%s", b)
637 }
638 if err != nil {
639 t.Fatalf("instrumented run error: %v", err)
640 }
641 }
642
643
644 moutdir := filepath.Join(s.dir, "mergeCombineOut")
645 if err := os.Mkdir(moutdir, 0777); err != nil {
646 t.Fatalf("can't create outdir %s: %v", moutdir, err)
647 }
648
649
650
651 ins := fmt.Sprintf("-i=%s,%s,%s,%s", s.outdirs[0], s.outdirs[1],
652 runout[0], runout[1])
653 out := fmt.Sprintf("-o=%s", moutdir)
654 margs := []string{"-pcombine", ins, out}
655 lines := runToolOp(t, s, "merge", margs)
656 if len(lines) != 0 {
657 t.Errorf("merge run produced unexpected output: %v", lines)
658 }
659
660
661
662
663 podlist, err := pods.CollectPods([]string{moutdir}, true)
664 if err != nil {
665 t.Fatal(err)
666 }
667 if len(podlist) != 1 {
668 t.Fatalf("expected 1 pod, got %d pods", len(podlist))
669 }
670 ncdfs := len(podlist[0].CounterDataFiles)
671 if ncdfs != 1 {
672 t.Fatalf("expected 1 counter data file, got %d", ncdfs)
673 }
674
675
676 testpoints := []dumpCheck{
677 {
678 tag: "first function",
679 re: regexp.MustCompile(`^Func: first\s*$`),
680 },
681 {
682 tag: "sixth function",
683 re: regexp.MustCompile(`^Func: sixth\s*$`),
684 },
685 }
686
687 flags := []string{"-live", "-pkg=" + mainPkgPath}
688 runDumpChecks(t, s, moutdir, flags, testpoints)
689 }
690
691 func testSubtract(t *testing.T, s state) {
692
693 soutdir := filepath.Join(s.dir, "subtractOut")
694 if err := os.Mkdir(soutdir, 0777); err != nil {
695 t.Fatalf("can't create outdir %s: %v", soutdir, err)
696 }
697
698
699 ins := fmt.Sprintf("-i=%s,%s", s.outdirs[0], s.outdirs[1])
700 out := fmt.Sprintf("-o=%s", soutdir)
701 sargs := []string{ins, out}
702 lines := runToolOp(t, s, "subtract", sargs)
703 if len(lines) != 0 {
704 t.Errorf("subtract run produced unexpected output: %+v", lines)
705 }
706
707
708 dargs := []string{"-pkg=" + mainPkgPath, "-live", "-i=" + soutdir}
709 lines = runToolOp(t, s, "debugdump", dargs)
710 if len(lines) == 0 {
711 t.Errorf("dump run produced no output")
712 }
713
714
715 testpoints := []dumpCheck{
716 {
717 tag: "first function",
718 re: regexp.MustCompile(`^Func: first\s*$`),
719 },
720 {
721 tag: "dep function",
722 re: regexp.MustCompile(`^Func: Dep1\s*$`),
723 },
724 {
725 tag: "third function",
726 re: regexp.MustCompile(`^Func: third\s*$`),
727 },
728 {
729 tag: "third function unit 0",
730 re: regexp.MustCompile(`^0: L23:C23 -- L24:C12 NS=1 = (\d+)$`),
731 zero: true,
732 },
733 {
734 tag: "third function unit 1",
735 re: regexp.MustCompile(`^1: L27:C2 -- L28:C10 NS=2 = (\d+)$`),
736 nonzero: true,
737 },
738 {
739 tag: "third function unit 2",
740 re: regexp.MustCompile(`^2: L24:C12 -- L26:C3 NS=1 = (\d+)$`),
741 zero: true,
742 },
743 }
744 flags := []string{}
745 runDumpChecks(t, s, soutdir, flags, testpoints)
746 }
747
748 func testIntersect(t *testing.T, s state, indir1, indir2, tag string) {
749
750 ioutdir := filepath.Join(s.dir, "intersectOut"+tag)
751 if err := os.Mkdir(ioutdir, 0777); err != nil {
752 t.Fatalf("can't create outdir %s: %v", ioutdir, err)
753 }
754
755
756 ins := fmt.Sprintf("-i=%s,%s", indir1, indir2)
757 out := fmt.Sprintf("-o=%s", ioutdir)
758 sargs := []string{ins, out}
759 lines := runToolOp(t, s, "intersect", sargs)
760 if len(lines) != 0 {
761 t.Errorf("intersect run produced unexpected output: %+v", lines)
762 }
763
764
765 dargs := []string{"-pkg=" + mainPkgPath, "-live", "-i=" + ioutdir}
766 lines = runToolOp(t, s, "debugdump", dargs)
767 if len(lines) == 0 {
768 t.Errorf("dump run produced no output")
769 }
770
771
772 testpoints := []dumpCheck{
773 {
774 tag: "first function",
775 re: regexp.MustCompile(`^Func: first\s*$`),
776 negate: true,
777 },
778 {
779 tag: "third function",
780 re: regexp.MustCompile(`^Func: third\s*$`),
781 },
782 }
783 flags := []string{"-live"}
784 runDumpChecks(t, s, ioutdir, flags, testpoints)
785 }
786
787 func testCounterClash(t *testing.T, s state) {
788
789 ccoutdir := filepath.Join(s.dir, "ccOut")
790 if err := os.Mkdir(ccoutdir, 0777); err != nil {
791 t.Fatalf("can't create outdir %s: %v", ccoutdir, err)
792 }
793
794
795
796
797 ins := fmt.Sprintf("-i=%s,%s", s.outdirs[0], s.outdirs[3])
798 out := fmt.Sprintf("-o=%s", ccoutdir)
799 args := append([]string{}, "merge", ins, out, "-pcombine")
800 if debugtrace {
801 t.Logf("cc merge command is %s %v\n", s.tool, args)
802 }
803 cmd := testenv.Command(t, s.tool, args...)
804 b, err := cmd.CombinedOutput()
805 t.Logf("%% output: %s\n", string(b))
806 if err != nil {
807 t.Fatalf("clash merge failed: %v", err)
808 }
809
810
811
812 out = "-o=" + filepath.Join(ccoutdir, "file.txt")
813 args = append([]string{}, "textfmt", ins, out)
814 if debugtrace {
815 t.Logf("clash textfmt command is %s %v\n", s.tool, args)
816 }
817 cmd = testenv.Command(t, s.tool, args...)
818 b, err = cmd.CombinedOutput()
819 t.Logf("%% output: %s\n", string(b))
820 if err == nil {
821 t.Fatalf("expected mode clash")
822 }
823 got := string(b)
824 want := "counter mode clash while reading meta-data"
825 if !strings.Contains(got, want) {
826 t.Errorf("counter clash textfmt: wanted %s got %s", want, got)
827 }
828 }
829
830 func testEmpty(t *testing.T, s state) {
831
832
833 empty := filepath.Join(s.dir, "empty")
834 if err := os.Mkdir(empty, 0777); err != nil {
835 t.Fatalf("can't create dir %s: %v", empty, err)
836 }
837
838
839 eoutdir := filepath.Join(s.dir, "emptyOut")
840 if err := os.Mkdir(eoutdir, 0777); err != nil {
841 t.Fatalf("can't create outdir %s: %v", eoutdir, err)
842 }
843
844
845
846
847
848
849 scenarios := []struct {
850 tag string
851 args []string
852 }{
853 {
854 tag: "merge",
855 args: []string{"merge", "-o", eoutdir},
856 },
857 {
858 tag: "textfmt",
859 args: []string{"textfmt", "-o", filepath.Join(eoutdir, "foo.txt")},
860 },
861 {
862 tag: "func",
863 args: []string{"func"},
864 },
865 {
866 tag: "pkglist",
867 args: []string{"pkglist"},
868 },
869 {
870 tag: "debugdump",
871 args: []string{"debugdump"},
872 },
873 {
874 tag: "percent",
875 args: []string{"percent"},
876 },
877 }
878
879 for _, x := range scenarios {
880 ins := fmt.Sprintf("-i=%s", empty)
881 args := append([]string{}, x.args...)
882 args = append(args, ins)
883 if false {
884 t.Logf("cmd is %s %v\n", s.tool, args)
885 }
886 cmd := testenv.Command(t, s.tool, args...)
887 b, err := cmd.CombinedOutput()
888 t.Logf("%% output: %s\n", string(b))
889 if err != nil {
890 t.Fatalf("command %s %+v failed with %v",
891 s.tool, x.args, err)
892 }
893 }
894 }
895
896 func testCommandLineErrors(t *testing.T, s state, outdir string) {
897
898
899 eoutdir := filepath.Join(s.dir, "errorsOut")
900 if err := os.Mkdir(eoutdir, 0777); err != nil {
901 t.Fatalf("can't create outdir %s: %v", eoutdir, err)
902 }
903
904
905
906
907
908
909 scenarios := []struct {
910 tag string
911 args []string
912 exp string
913 }{
914 {
915 tag: "input missing",
916 args: []string{"merge", "-o", eoutdir, "-i", "not there"},
917 exp: "error: reading inputs: ",
918 },
919 {
920 tag: "badv",
921 args: []string{"textfmt", "-i", outdir, "-v=abc"},
922 },
923 }
924
925 for _, x := range scenarios {
926 args := append([]string{}, x.args...)
927 if false {
928 t.Logf("cmd is %s %v\n", s.tool, args)
929 }
930 cmd := testenv.Command(t, s.tool, args...)
931 b, err := cmd.CombinedOutput()
932 if err == nil {
933 t.Logf("%% output: %s\n", string(b))
934 t.Fatalf("command %s %+v unexpectedly succeeded",
935 s.tool, x.args)
936 } else {
937 if !strings.Contains(string(b), x.exp) {
938 t.Fatalf("command %s %+v:\ngot:\n%s\nwanted to see: %v\n",
939 s.tool, x.args, string(b), x.exp)
940 }
941 }
942 }
943 }
944
View as plain text