| // Copyright 2021 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package main | |
| import ( | |
| "bytes" | |
| "os" | |
| "os/exec" | |
| "path/filepath" | |
| "strings" | |
| "testing" | |
| ) | |
| func TestCSV(t *testing.T) { | |
| golden(t, "csvOldNew", "-format", "csv", "old.txt", "new.txt") | |
| golden(t, "csvErrors", "-format", "csv", "-row", ".name", "new.txt") | |
| } | |
| func TestCRC(t *testing.T) { | |
| // These have a "note" that "unexpectedly" splits the tables, | |
| // and also two units. | |
| golden(t, "crcOldNew", "crc-old.txt", "crc-new.txt") | |
| // "Fix" the split by note. | |
| golden(t, "crcIgnore", "-ignore", "note", "crc-old.txt", "crc-new.txt") | |
| // Filter to aligned, put size on the X axis and poly on the Y axis. | |
| golden(t, "crcSizeVsPoly", "-filter", "/align:0", "-row", "/size", "-col", "/poly", "crc-new.txt") | |
| } | |
| func TestUnits(t *testing.T) { | |
| // Test unit metadata. This tests exact assumptions and | |
| // warnings for inexact distributions. | |
| golden(t, "units", "-col", "note", "units.txt") | |
| } | |
| func TestZero(t *testing.T) { | |
| // Test printing of near-zero deltas. | |
| golden(t, "zero", "-col", "note", "zero.txt") | |
| } | |
| func TestSmallSample(t *testing.T) { | |
| // These benchmarks don't have enough samples to compute a CI | |
| // or delta. | |
| golden(t, "smallSample", "-col", "note", "smallSample.txt") | |
| } | |
| func TestIssue19565(t *testing.T) { | |
| // Benchmark sets are inconsistent between columns. We show | |
| // all results, but warn that the geomeans may not be | |
| // comparable. To further stress things, the columns have the | |
| // same *number* of benchmarks, but different sets. | |
| golden(t, "issue19565", "-col", "note", "issue19565.txt") | |
| } | |
| func TestIssue19634(t *testing.T) { | |
| golden(t, "issue19634", "-col", "note", "issue19634.txt") | |
| } | |
| func golden(t *testing.T, name string, args ...string) { | |
| t.Helper() | |
| // TODO: If benchfmt.Files supported fs.FS, we wouldn't need this. | |
| if err := os.Chdir("testdata"); err != nil { | |
| t.Fatal(err) | |
| } | |
| defer os.Chdir("..") | |
| // Get the benchstat output. | |
| var got, gotErr bytes.Buffer | |
| t.Logf("benchstat %s", strings.Join(args, " ")) | |
| if err := benchstat(&got, &gotErr, args); err != nil { | |
| t.Fatalf("unexpected error: %s", err) | |
| } | |
| // Compare to the golden output. | |
| compare(t, name, "stdout", got.Bytes()) | |
| compare(t, name, "stderr", gotErr.Bytes()) | |
| } | |
| func compare(t *testing.T, name, sub string, got []byte) { | |
| t.Helper() | |
| wantPath := name + "." + sub | |
| want, err := os.ReadFile(wantPath) | |
| if err != nil { | |
| if os.IsNotExist(err) { | |
| // Treat a missing file as empty. | |
| want = nil | |
| } else { | |
| t.Fatal(err) | |
| } | |
| } | |
| if !diff(t, want, got) { | |
| return | |
| } | |
| // diff printed the error. | |
| // Write a "got" file for reference. | |
| gotPath := name + ".got-" + sub | |
| if err := os.WriteFile(gotPath, got, 0666); err != nil { | |
| t.Fatalf("error writing %s: %s", gotPath, err) | |
| } | |
| } | |
| func diff(t *testing.T, want, got []byte) bool { | |
| t.Helper() | |
| if bytes.Equal(want, got) { | |
| return false | |
| } | |
| d := t.TempDir() | |
| wantPath, gotPath := filepath.Join(d, "want"), filepath.Join(d, "got") | |
| if err := os.WriteFile(wantPath, want, 0666); err != nil { | |
| t.Fatalf("error writing %s: %s", wantPath, err) | |
| } | |
| if err := os.WriteFile(gotPath, got, 0666); err != nil { | |
| t.Fatalf("error writing %s: %s", gotPath, err) | |
| } | |
| cmd := exec.Command("diff", "-Nu", "want", "got") | |
| cmd.Dir = d | |
| data, _ := cmd.CombinedOutput() | |
| if len(data) > 0 { | |
| t.Errorf("\n%s", data) | |
| } else { | |
| // Most likely, "diff not found" so print the bad | |
| // output so there is something. | |
| t.Errorf("want:\n%sgot:\n%s", want, got) | |
| } | |
| return true | |
| } |