diff --git a/bench/benchmark.go b/bench/benchmark.go index 91945ff..ff625df 100644 --- a/bench/benchmark.go +++ b/bench/benchmark.go @@ -1,5 +1,9 @@ package bench +import ( + "sort" +) + // RunHistory is a sort.Interface that sorts the most recent run first type RunHistory []Run @@ -13,6 +17,11 @@ func (r RunHistory) Swap(i, j int) { r[j] = tmp } +func (r RunHistory) Latest() Run { + sort.Sort(r) + return r[0] +} + // Run denotes one run of gobenchdata, useful for grouping benchmark records type Run struct { Version string `json:",omitempty"` diff --git a/bench/benchmark_test.go b/bench/benchmark_test.go index 88ec18d..3ffeecc 100644 --- a/bench/benchmark_test.go +++ b/bench/benchmark_test.go @@ -4,9 +4,11 @@ import ( "sort" "testing" "time" + + "github.com/stretchr/testify/assert" ) -func TestRunHistory_Sort(t *testing.T) { +func TestRunHistorySort(t *testing.T) { hist := RunHistory{ {Date: time.Now().Add(-5 * time.Minute).Unix()}, {Date: time.Now().Add(5 * time.Minute).Unix()}, @@ -18,3 +20,14 @@ func TestRunHistory_Sort(t *testing.T) { t.Fail() } } + +func TestRunHistoryLatest(t *testing.T) { + ts := time.Now().Add(5 * time.Minute).Unix() + hist := RunHistory{ + {Date: time.Now().Add(-5 * time.Minute).Unix()}, + {Date: time.Now().Unix()}, + {Date: ts}, + } + latest := hist.Latest() + assert.Equal(t, ts, latest.Date) +} diff --git a/checks/evaluate.go b/checks/evaluate.go index 517597d..c954080 100644 --- a/checks/evaluate.go +++ b/checks/evaluate.go @@ -2,9 +2,9 @@ package checks import ( "encoding/json" + "errors" "fmt" "io/ioutil" - "sort" "github.com/antonmedv/expr" "github.com/antonmedv/expr/vm" @@ -96,8 +96,10 @@ func Evaluate(checks []Check, base bench.RunHistory, current bench.RunHistory, o } out := internal.Printer{Debug: debug} - sort.Sort(current) - currentRun := current[current.Len()-1] + if current.Len() == 0 { + return nil, errors.New("no benchmark runs in current") + } + currentRun := current.Latest() if base.Len() == 0 { out.Print("base benchmarks has no runs - passing automatically") @@ -108,8 +110,8 @@ func Evaluate(checks []Check, base bench.RunHistory, current bench.RunHistory, o Checks: nil, }, nil } - sort.Sort(base) - baseRun := base[base.Len()-1] + baseRun := base.Latest() + out.Printf("comparing versions base='%s', current='%s'", baseRun.Version, currentRun.Version) // set up results diff --git a/checks/evaluate_test.go b/checks/evaluate_test.go index cfaf214..a29c9ef 100644 --- a/checks/evaluate_test.go +++ b/checks/evaluate_test.go @@ -1,10 +1,13 @@ package checks import ( - "reflect" "testing" + "time" "github.com/antonmedv/expr" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.bobheadxi.dev/gobenchdata/bench" "go.bobheadxi.dev/gobenchdata/internal" ) @@ -155,6 +158,65 @@ func TestEvaluate(t *testing.T) { Thresholds: thresholdsSimple, }}, }, false}, + {"simple pass on latest", args{ + []Check{{ + Name: "C", + DiffFunc: "base.NsPerOp - current.NsPerOp", + Thresholds: thresholdsSimple, + }}, + bench.RunHistory{{ + Version: "base-old", + Date: time.Now().Add(-5 * time.Minute).Unix(), + Suites: []bench.Suite{ + {Pkg: "P", Benchmarks: []bench.Benchmark{{ + Name: "B", + NsPerOp: 999, + }}}, + }, + }, { + // This is the run we want + Version: "base", + Date: time.Now().Unix(), + Suites: []bench.Suite{ + {Pkg: "P", Benchmarks: []bench.Benchmark{{ + Name: "B", + NsPerOp: 1, + }}}, + }, + }, { + Version: "base-older", + Date: time.Now().Add(-10 * time.Minute).Unix(), + Suites: []bench.Suite{ + {Pkg: "P", Benchmarks: []bench.Benchmark{{ + Name: "B", + NsPerOp: 999, + }}}, + }, + }}, + bench.RunHistory{{ + Version: "current", + Suites: []bench.Suite{ + {Pkg: "P", Benchmarks: []bench.Benchmark{{ + Name: "B", + NsPerOp: 1, + }}}, + }, + }}, + }, &Report{ + Status: StatusPass, + Base: "base", + Current: "current", + Checks: map[string]*CheckResult{"C": { + Status: StatusPass, + Diffs: []DiffResult{{ + Status: StatusPass, + Package: "P", + Benchmark: "B", + Value: 0, + }}, + Thresholds: thresholdsSimple, + }}, + }, false}, {"simple pass because of no thresholds", args{ []Check{{ Name: "C", @@ -317,19 +379,9 @@ func TestEvaluate(t *testing.T) { got, err := Evaluate(tt.args.checks, tt.args.base, tt.args.current, &EvaluateOptions{ Debug: true, }) - if (err != nil) != tt.wantErr { - t.Errorf("Evaluate() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Evaluate() = %+v, want %+v", got, tt.want) - // report deep diff properly - for c, v := range tt.want.Checks { - if !reflect.DeepEqual(got.Checks[c], v) { - t.Errorf("check %s: got %+v\nwant %+v", c, got.Checks[c], v) - } - } - } + require.NoError(t, err) + + assert.Equal(t, tt.want, got) }) } } diff --git a/go.mod b/go.mod index aaaafa3..506a514 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/sourcegraph/run v0.9.0 github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.7.0 golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 golang.org/x/net v0.0.0-20220607020251-c690dde0001d gopkg.in/yaml.v2 v2.4.0 @@ -21,6 +22,7 @@ require ( github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/bmatcuk/doublestar v1.3.4 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/djherbis/buffer v1.2.0 // indirect github.com/djherbis/nio/v3 v3.0.1 // indirect github.com/gizak/termui/v3 v3.1.0 // indirect @@ -34,6 +36,7 @@ require ( github.com/mattn/go-runewidth v0.0.13 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/nsf/termbox-go v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.1 // indirect @@ -43,4 +46,5 @@ require ( golang.org/x/text v0.3.7 // indirect golang.org/x/tools v0.1.11 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect )