func TestParser(t *testing.T) { for _, tt := range bTests { b, _ := parse.ParseLine(tt.line) name, arg, _, _ := parseNameArgThread(b.Name) if name != tt.name { t.Errorf("parseNameArgThread(%s): expected %s, actual %s", b.Name, tt.name, name) } if arg != tt.arg { t.Errorf("parseNameArgThread(%s): expected %s, actual %s", b.Name, tt.arg, arg) } if b.NsPerOp != tt.nsperop { t.Errorf("parseNameArgThread(%s): expected %f, actual %f", b.Name, tt.nsperop, b.NsPerOp) } } }
func (b *benchRunner) run() error { stderrPipe, err := b.cmd.StderrPipe() if err != nil { return err } stderrReader := io.TeeReader(stderrPipe, os.Stderr) stdoutPipe, err := b.cmd.StdoutPipe() if err != nil { return err } stdoutReader := io.TeeReader(stdoutPipe, os.Stderr) reader := io.MultiReader(stdoutReader, stderrReader) if err := b.cmd.Start(); err != nil { return err } out, err := ioutil.ReadAll(reader) if err != nil { return err } err = b.cmd.Wait() if err != nil { return err } outs := strings.Split(string(out), "\n") b.output = make([]float64, len(benchmarks)) for _, s := range outs { if !strings.HasPrefix(s, "Benchmark") { continue } res, err := parse.ParseLine(s) if err != nil { return err } name := strings.Split(res.Name, "-")[0] for i, benchmark := range benchmarks { if benchmark.name == name { b.output[i] = res.NsPerOp } } } fmt.Fprintf(os.Stderr, "%#v\n", b.output) return nil }
func main() { flag.Parse() if *format != "xml" && *format != "json" { log.Fatalf("Unsupported output format: %q", *format) } r, w, err := os.Pipe() if err != nil { log.Fatal(err) } go func() { if _, err := io.Copy(io.MultiWriter(w, os.Stderr), os.Stdin); err != nil { log.Fatal(err) } if err := w.Close(); err != nil { log.Fatal(err) } }() var ( results []*testCase lastTest *testCase benchmarks []*parse.Benchmark ) s := bufio.NewScanner(r) for s.Scan() { if err := s.Err(); err == io.EOF { break } else if err != nil { log.Fatal(err) } ss := testCaseRE.FindStringSubmatch(s.Text()) if len(ss) > 0 { if fixed := strings.TrimSuffix(ss[3], " seconds"); fixed != ss[3] { // Before // https://github.com/golang/go/commit/0e92b538a9f6e337b8e48f47f38803e8245c03cc, // this duration format wasn't compatible with time.ParseDuration. This // works around the difference. ss[3] = fixed + "s" } dur, err := time.ParseDuration(ss[3]) if err != nil { log.Fatal(err) } lastTest = &testCase{ Name: ss[2], Duration: dur, Status: status(ss[1]), } results = append(results, lastTest) } else if lastTest != nil && strings.HasPrefix(s.Text(), logPrefix) { lastTest.Log = append(lastTest.Log, strings.TrimPrefix(s.Text(), logPrefix)) } else { lastTest = nil if strings.HasPrefix(s.Text(), "Benchmark") { b, err := parse.ParseLine(s.Text()) if err != nil { log.Fatal(err) } benchmarks = append(benchmarks, b) } } } f, err := os.Create(*outputFile) if err != nil { log.Fatalf("Failure to create output file %q: %v", *outputFile, err) } switch *format { case "xml": if err := xml.NewEncoder(f).EncodeElement(makeTestSuite(results, benchmarks), xml.StartElement{ Name: xml.Name{Local: "testsuite"}, }); err != nil { log.Fatalf("Error encoding XML: %v", err) } case "json": if err := json.NewEncoder(f).Encode(struct { Tests []*testCase Benchmarks []*parse.Benchmark `json:",omitempty"` }{results, benchmarks}); err != nil { log.Fatalf("Error encoding JSON: %v", err) } default: panic("unsupported output format: " + *format) } if err := f.Close(); err != nil { log.Fatalf("Error closing output file %q: %v", *outputFile, err) } }
func main() { var oBenchNames, oBenchArgs stringList // graph elements will be ordered as in benchmark output by default - unless the order was specified here flag.Var(&oBenchNames, "obn", "comma-separated list of benchmark names") flag.Var(&oBenchArgs, "oba", "comma-separated list of benchmark arguments") title := flag.String("title", "Graph: Benchmark results in ns/op", "title of a graph") apiUrl := flag.String("apiurl", "http://benchgraph.codingberg.com", "url to server api") flag.Parse() var skipBenchNamesParsing, skipBenchArgsParsing bool if oBenchNames.Len() > 0 { skipBenchNamesParsing = true } if oBenchArgs.Len() > 0 { skipBenchArgsParsing = true } benchResults := make(BenchNameSet) // parse Golang benchmark results, line by line scan := bufio.NewScanner(os.Stdin) green := color.New(color.FgGreen).SprintfFunc() red := color.New(color.FgRed).SprintFunc() for scan.Scan() { line := scan.Text() mark := green("√") b, err := parse.ParseLine(line) if err != nil { mark = red("?") } // read bench name and arguments if b != nil { name, arg, _, err := parseNameArgThread(b.Name) if err != nil { mark = red("!") fmt.Printf("%s %s\n", mark, line) continue } if !skipBenchNamesParsing && !oBenchNames.stringInList(name) { oBenchNames.Add(name) } if !skipBenchArgsParsing && !oBenchArgs.stringInList(arg) { oBenchArgs.Add(arg) } if _, ok := benchResults[name]; !ok { benchResults[name] = make(BenchArgSet) } benchResults[name][arg] = b.NsPerOp } fmt.Printf("%s %s\n", mark, line) } if err := scan.Err(); err != nil { fmt.Fprintf(os.Stderr, "reading standard input: %v", err) os.Exit(1) } if len(benchResults) == 0 { fmt.Fprintf(os.Stderr, "no data to show.\n\n") os.Exit(1) } fmt.Println() fmt.Println("Waiting for server response ...") data := graphData(benchResults, oBenchNames, oBenchArgs) graphUrl, err := uploadData(*apiUrl, string(data), *title) if err != nil { fmt.Fprintf(os.Stderr, "uploading data: %v", err) os.Exit(1) } fmt.Println("=========================================") fmt.Println() fmt.Println(graphUrl) fmt.Println() fmt.Println("=========================================") }