| |
| |
| |
|
|
| package main |
|
|
| import ( |
| "flag" |
| "fmt" |
| "internal/coverage/slicewriter" |
| "io" |
| "log" |
| "os" |
| "path/filepath" |
| "runtime/coverage" |
| "strings" |
| ) |
|
|
| var verbflag = flag.Int("v", 0, "Verbose trace output level") |
| var testpointflag = flag.String("tp", "", "Testpoint to run") |
| var outdirflag = flag.String("o", "", "Output dir into which to emit") |
|
|
| func emitToWriter() { |
| log.SetPrefix("emitToWriter: ") |
| var slwm slicewriter.WriteSeeker |
| if err := coverage.WriteMeta(&slwm); err != nil { |
| log.Fatalf("error: WriteMeta returns %v", err) |
| } |
| mf := filepath.Join(*outdirflag, "covmeta.0abcdef") |
| if err := os.WriteFile(mf, slwm.BytesWritten(), 0666); err != nil { |
| log.Fatalf("error: writing %s: %v", mf, err) |
| } |
| var slwc slicewriter.WriteSeeker |
| if err := coverage.WriteCounters(&slwc); err != nil { |
| log.Fatalf("error: WriteCounters returns %v", err) |
| } |
| cf := filepath.Join(*outdirflag, "covcounters.0abcdef.99.77") |
| if err := os.WriteFile(cf, slwc.BytesWritten(), 0666); err != nil { |
| log.Fatalf("error: writing %s: %v", cf, err) |
| } |
| } |
|
|
| func emitToDir() { |
| log.SetPrefix("emitToDir: ") |
| if err := coverage.WriteMetaDir(*outdirflag); err != nil { |
| log.Fatalf("error: WriteMetaDir returns %v", err) |
| } |
| if err := coverage.WriteCountersDir(*outdirflag); err != nil { |
| log.Fatalf("error: WriteCountersDir returns %v", err) |
| } |
| } |
|
|
| func emitToNonexistentDir() { |
| log.SetPrefix("emitToNonexistentDir: ") |
|
|
| want := []string{ |
| "no such file or directory", |
| "system cannot find the file specified", |
| "does not exist", |
| } |
|
|
| checkWant := func(which string, got string) { |
| found := false |
| for _, w := range want { |
| if strings.Contains(got, w) { |
| found = true |
| break |
| } |
| } |
| if !found { |
| log.Fatalf("%s emit to bad dir: got error:\n %v\nwanted error with one of:\n %+v", which, got, want) |
| } |
| } |
|
|
| |
| mangled := *outdirflag + "_MANGLED" |
| if err := coverage.WriteMetaDir(mangled); err == nil { |
| log.Fatal("expected error from WriteMetaDir to nonexistent dir") |
| } else { |
| got := fmt.Sprintf("%v", err) |
| checkWant("meta data", got) |
| } |
|
|
| |
| if err := coverage.WriteCountersDir(mangled); err == nil { |
| log.Fatal("expected error emitting counter data to bad dir") |
| } else { |
| got := fmt.Sprintf("%v", err) |
| checkWant("counter data", got) |
| } |
| } |
|
|
| func emitToUnwritableDir() { |
| log.SetPrefix("emitToUnwritableDir: ") |
|
|
| want := "permission denied" |
|
|
| if err := coverage.WriteMetaDir(*outdirflag); err == nil { |
| log.Fatal("expected error from WriteMetaDir to unwritable dir") |
| } else { |
| got := fmt.Sprintf("%v", err) |
| if !strings.Contains(got, want) { |
| log.Fatalf("meta-data emit to unwritable dir: wanted error containing %q got %q", want, got) |
| } |
| } |
|
|
| |
| if err := coverage.WriteCountersDir(*outdirflag); err == nil { |
| log.Fatal("expected error emitting counter data to unwritable dir") |
| } else { |
| got := fmt.Sprintf("%v", err) |
| if !strings.Contains(got, want) { |
| log.Fatalf("emitting counter data to unwritable dir: wanted error containing %q got %q", want, got) |
| } |
| } |
| } |
|
|
| func emitToNilWriter() { |
| log.SetPrefix("emitToWriter: ") |
| want := "nil writer" |
| var bad io.WriteSeeker |
| if err := coverage.WriteMeta(bad); err == nil { |
| log.Fatal("expected error passing nil writer for meta emit") |
| } else { |
| got := fmt.Sprintf("%v", err) |
| if !strings.Contains(got, want) { |
| log.Fatalf("emitting meta-data passing nil writer: wanted error containing %q got %q", want, got) |
| } |
| } |
|
|
| if err := coverage.WriteCounters(bad); err == nil { |
| log.Fatal("expected error passing nil writer for counter emit") |
| } else { |
| got := fmt.Sprintf("%v", err) |
| if !strings.Contains(got, want) { |
| log.Fatalf("emitting counter data passing nil writer: wanted error containing %q got %q", want, got) |
| } |
| } |
| } |
|
|
| type failingWriter struct { |
| writeCount int |
| writeLimit int |
| slws slicewriter.WriteSeeker |
| } |
|
|
| func (f *failingWriter) Write(p []byte) (n int, err error) { |
| c := f.writeCount |
| f.writeCount++ |
| if f.writeLimit < 0 || c < f.writeLimit { |
| return f.slws.Write(p) |
| } |
| return 0, fmt.Errorf("manufactured write error") |
| } |
|
|
| func (f *failingWriter) Seek(offset int64, whence int) (int64, error) { |
| return f.slws.Seek(offset, whence) |
| } |
|
|
| func (f *failingWriter) reset(lim int) { |
| f.writeCount = 0 |
| f.writeLimit = lim |
| f.slws = slicewriter.WriteSeeker{} |
| } |
|
|
| func writeStressTest(tag string, testf func(testf *failingWriter) error) { |
| |
| |
| fw := &failingWriter{writeLimit: -1} |
| testf(fw) |
|
|
| |
| |
| |
| |
| tot := fw.writeCount |
| for i := 0; i < tot; i++ { |
| fw.reset(i) |
| err := testf(fw) |
| if err == nil { |
| log.Fatalf("no error from write %d tag %s", i, tag) |
| } |
| } |
| } |
|
|
| func postClear() int { |
| return 42 |
| } |
|
|
| func preClear() int { |
| return 42 |
| } |
|
|
| |
| |
| |
| |
| |
| |
| func emitToFailingWriter() { |
| log.SetPrefix("emitToFailingWriter: ") |
|
|
| writeStressTest("emit-meta", func(f *failingWriter) error { |
| return coverage.WriteMeta(f) |
| }) |
| writeStressTest("emit-counter", func(f *failingWriter) error { |
| return coverage.WriteCounters(f) |
| }) |
| } |
|
|
| func emitWithCounterClear() { |
| log.SetPrefix("emitWitCounterClear: ") |
| preClear() |
| if err := coverage.ClearCounters(); err != nil { |
| log.Fatalf("clear failed: %v", err) |
| } |
| postClear() |
| if err := coverage.WriteMetaDir(*outdirflag); err != nil { |
| log.Fatalf("error: WriteMetaDir returns %v", err) |
| } |
| if err := coverage.WriteCountersDir(*outdirflag); err != nil { |
| log.Fatalf("error: WriteCountersDir returns %v", err) |
| } |
| } |
|
|
| func final() int { |
| println("I run last.") |
| return 43 |
| } |
|
|
| func main() { |
| log.SetFlags(0) |
| flag.Parse() |
| if *testpointflag == "" { |
| log.Fatalf("error: no testpoint (use -tp flag)") |
| } |
| if *outdirflag == "" { |
| log.Fatalf("error: no output dir specified (use -o flag)") |
| } |
| switch *testpointflag { |
| case "emitToDir": |
| emitToDir() |
| case "emitToWriter": |
| emitToWriter() |
| case "emitToNonexistentDir": |
| emitToNonexistentDir() |
| case "emitToUnwritableDir": |
| emitToUnwritableDir() |
| case "emitToNilWriter": |
| emitToNilWriter() |
| case "emitToFailingWriter": |
| emitToFailingWriter() |
| case "emitWithCounterClear": |
| emitWithCounterClear() |
| default: |
| log.Fatalf("error: unknown testpoint %q", *testpointflag) |
| } |
| final() |
| } |
|
|