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