Skip to content

Commit 5753fe8

Browse files
authored
Fix -validate and add -name flags (#176)
* main: Add -name flag This flag allows selecting a subset of benchmarks to run when generating the report or validating benchmarks. This is useful during development in order to verify only newly added benchmarks as opposed to all benchmarks. * main: Verify benchmark finished when validating Unfortunately, benchmarks ran with testing.Benchmark() do not return an error, panic or otherwise make their calling goroutine exit early in order to signal failure. This could cause validation errors to be silently ignored when running with -validate specified. This commit addresses this issue by using a flag to detect when the test was prematurely finished to report it as an error, with a message for the user to re-run the test in a way that can actually report the error. * goserbench: Add validation for Money field This validation was missing from the code.
1 parent bce37a8 commit 5753fe8

4 files changed

Lines changed: 52 additions & 5 deletions

File tree

benchmark.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/json"
77
"fmt"
88
"os"
9+
"regexp"
910
"strings"
1011
"testing"
1112

@@ -35,19 +36,32 @@ type reportLine struct {
3536
Notes string `json:"notes"`
3637
}
3738

38-
func BenchAndReportSerializers(generateReport bool, validate bool) error {
39+
func BenchAndReportSerializers(generateReport bool, validate bool, namesRe *regexp.Regexp) error {
3940
data := make([]reportLine, len(benchmarkCases))
4041
for i, bench := range benchmarkCases {
42+
if namesRe != nil && !namesRe.MatchString(bench.Name) {
43+
continue
44+
}
45+
4146
marshalRes := testing.Benchmark(func(b *testing.B) {
4247
goserbench.BenchMarshalSmallStruct(b, bench.New())
4348
})
4449
fmt.Printf("%10s - Marshal - %s %s\n", bench.Name, marshalRes.String(),
4550
marshalRes.MemString())
51+
52+
unmarshalOk := false
4653
unmarshalRes := testing.Benchmark(func(b *testing.B) {
4754
goserbench.BenchUnmarshalSmallStruct(b, bench.New(), validate)
55+
unmarshalOk = true
4856
})
49-
fmt.Printf("%10s - Unmarshal - %s %s\n", bench.Name, unmarshalRes.String(),
50-
unmarshalRes.MemString())
57+
if !unmarshalOk {
58+
fmt.Printf("\nUnmarshal benchmark of %q did not complete successfully\n", bench.Name)
59+
fmt.Printf("Test with go test -validate -run Bench -bench BenchmarkSerializers/unmarshal/%s\n\n", bench.Name)
60+
return fmt.Errorf("benchmark %s failed", bench.Name)
61+
} else {
62+
fmt.Printf("%10s - Unmarshal - %s %s\n", bench.Name, unmarshalRes.String(),
63+
unmarshalRes.MemString())
64+
}
5165

5266
data[i] = reportLine{
5367
Name: bench.Name,

genreport_test.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package main
66

77
import (
88
"fmt"
9+
"os"
10+
"regexp"
911
"testing"
1012
)
1113

@@ -19,7 +21,17 @@ Re-Generating Report = true
1921
2022
`, *validate)
2123

22-
err := BenchAndReportSerializers(true, *validate)
24+
var nameRe *regexp.Regexp
25+
if *nameFlag != "" {
26+
var err error
27+
nameRe, err = regexp.Compile(*nameFlag)
28+
if err != nil {
29+
fmt.Printf("Error compiling -name regexp: %v\n", err)
30+
os.Exit(1)
31+
}
32+
}
33+
34+
err := BenchAndReportSerializers(true, *validate, nameRe)
2335
if err != nil {
2436
t.Fatal(err)
2537
}

goserbench/goserbench.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ func BenchUnmarshalSmallStruct(b *testing.B, s Serializer, validate bool) {
139139
if !o.BirthDay.Equal(i.BirthDay) {
140140
b.Fatalf("wrong birthday: got %v, want %v", o.BirthDay, i.BirthDay)
141141
}
142+
if o.Money != i.Money {
143+
b.Fatalf("wrong money: got %v, want %v", o.Money, i.Money)
144+
}
142145
}
143146
}
144147
}

main.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ package main
33
import (
44
"flag"
55
"fmt"
6+
"os"
7+
"regexp"
8+
"testing"
69
)
710

811
var (
912
validate = flag.Bool("validate", false, "to validate the correctness of the serializers")
1013
genReport = flag.Bool("genreport", false, "to re-generate the report")
14+
nameFlag = flag.String("name", "", "restrict benchmarks to run only if they match this regexp")
1115
)
1216

1317
func main() {
@@ -22,7 +26,21 @@ Re-Generating Report = %t
2226
2327
`, *validate, *genReport)
2428

25-
err := BenchAndReportSerializers(*genReport, *validate)
29+
var nameRe *regexp.Regexp
30+
if *nameFlag != "" {
31+
var err error
32+
nameRe, err = regexp.Compile(*nameFlag)
33+
if err != nil {
34+
fmt.Printf("Error compiling -name regexp: %v\n", err)
35+
os.Exit(1)
36+
}
37+
}
38+
39+
// Manually call testing.Init(), otherwise validation errors may cause
40+
// internal panics.
41+
testing.Init()
42+
43+
err := BenchAndReportSerializers(*genReport, *validate, nameRe)
2644
if err != nil {
2745
panic(err)
2846
}

0 commit comments

Comments
 (0)