event: extract the benchmark helpers from the benchmarks

Change-Id: Id9f5cb34c9780b868b774281155721bceecb60be
Reviewed-on: https://go-review.googlesource.com/c/exp/+/325576
Trust: Ian Cottrell <iancottrell@google.com>
Run-TryBot: Ian Cottrell <iancottrell@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/event/bench/alloc_test.go b/event/bench/alloc_test.go
index 5996350..bcacac4 100644
--- a/event/bench/alloc_test.go
+++ b/event/bench/alloc_test.go
@@ -8,8 +8,10 @@
 
 import (
 	"testing"
+
+	"golang.org/x/exp/event/bench"
 )
 
 func TestLogEventAllocs(t *testing.T) {
-	testAllocs(t, eventPrint, eventLog, 0)
+	bench.TestAllocs(t, eventPrint, eventLog, 0)
 }
diff --git a/event/bench/bench_test.go b/event/bench/bench.go
similarity index 74%
rename from event/bench/bench_test.go
rename to event/bench/bench.go
index 1f158a6..8329ed8 100644
--- a/event/bench/bench_test.go
+++ b/event/bench/bench.go
@@ -2,18 +2,23 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package bench_test
+package bench
 
 import (
 	"context"
 	"io"
 	"strings"
 	"testing"
-	"time"
 
 	"github.com/google/go-cmp/cmp"
 )
 
+type Info struct {
+	Name string
+	Msg  string
+	Msgf string
+}
+
 type Hooks struct {
 	AStart func(ctx context.Context, a int) context.Context
 	AEnd   func(ctx context.Context)
@@ -32,17 +37,22 @@
 		"ı",
 		"prime count of values",
 	}
+
+	A = Info{
+		Name: "A",
+		Msg:  "a",
+		Msgf: "a where A=%d",
+	}
+
+	B = Info{
+		Name: "B",
+		Msg:  "b",
+		Msgf: "b where B=%q",
+	}
 )
 
 const (
-	aName = "A"
-	aMsg  = "a"
-	aMsgf = aMsg + " where " + aName + "=%d"
-	bName = "B"
-	bMsg  = "b"
-	bMsgf = bMsg + " where " + bName + "=%q"
-
-	timeFormat = "2006/01/02 15:04:05"
+	TimeFormat = "2006/01/02 15:04:05"
 )
 
 type namedBenchmark struct {
@@ -69,15 +79,14 @@
 	}
 }
 
-func runBenchmark(b *testing.B, ctx context.Context, hooks Hooks) {
-	//b.ReportAllocs()
+func RunBenchmark(b *testing.B, ctx context.Context, hooks Hooks) {
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		runOnce(ctx, hooks)
 	}
 }
 
-func testBenchmark(t *testing.T, f func(io.Writer) context.Context, hooks Hooks, expect string) {
+func TestBenchmark(t *testing.T, f func(io.Writer) context.Context, hooks Hooks, expect string) {
 	buf := strings.Builder{}
 	ctx := f(&buf)
 	runOnce(ctx, hooks)
@@ -88,7 +97,8 @@
 	}
 }
 
-func testAllocs(t *testing.T, f func(io.Writer) context.Context, hooks Hooks, expect int) {
+func TestAllocs(t *testing.T, f func(io.Writer) context.Context, hooks Hooks, expect int) {
+	t.Helper()
 	var acc int
 	ctx := f(io.Discard)
 	got := int(testing.AllocsPerRun(5, func() {
@@ -100,12 +110,3 @@
 		t.Errorf("Got %d allocs, expect %d", got, expect)
 	}
 }
-
-func newTimer() func() time.Time {
-	nextTime, _ := time.Parse(time.RFC3339Nano, "2020-03-05T14:27:48Z")
-	return func() time.Time {
-		thisTime := nextTime
-		nextTime = nextTime.Add(time.Second)
-		return thisTime
-	}
-}
diff --git a/event/bench/event_enabled_test.go b/event/bench/event_enabled_test.go
index 8996ea8..0cd2af5 100644
--- a/event/bench/event_enabled_test.go
+++ b/event/bench/event_enabled_test.go
@@ -8,10 +8,12 @@
 
 import (
 	"testing"
+
+	"golang.org/x/exp/event/bench"
 )
 
 func TestLogEventf(t *testing.T) {
-	testBenchmark(t, eventPrint, eventLogf, `
+	bench.TestBenchmark(t, eventPrint, eventLogf, `
 time=2020-03-05T14:27:48 msg="a where A=0"
 time=2020-03-05T14:27:49 msg="b where B=\"A value\""
 time=2020-03-05T14:27:50 msg="a where A=1"
@@ -32,7 +34,7 @@
 }
 
 func TestLogEvent(t *testing.T) {
-	testBenchmark(t, eventPrint, eventLog, `
+	bench.TestBenchmark(t, eventPrint, eventLog, `
 time=2020-03-05T14:27:48 A=0 msg=a
 time=2020-03-05T14:27:49 B="A value" msg=b
 time=2020-03-05T14:27:50 A=1 msg=a
diff --git a/event/bench/event_test.go b/event/bench/event_test.go
index 1e8e59c..913545d 100644
--- a/event/bench/event_test.go
+++ b/event/bench/event_test.go
@@ -12,46 +12,47 @@
 	"golang.org/x/exp/event"
 	"golang.org/x/exp/event/adapter/eventtest"
 	"golang.org/x/exp/event/adapter/logfmt"
+	"golang.org/x/exp/event/bench"
 	"golang.org/x/exp/event/keys"
 )
 
 var (
-	aValue  = keys.Int(aName)
-	bValue  = keys.String(bName)
+	aValue  = keys.Int(bench.A.Name)
+	bValue  = keys.String(bench.B.Name)
 	aCount  = keys.Int64("aCount")
 	aStat   = keys.Int("aValue")
 	bCount  = keys.Int64("B")
 	bLength = keys.Int("BLen")
 
-	eventLog = Hooks{
+	eventLog = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
-			event.To(ctx).With(aValue.Of(a)).Log(aMsg)
+			event.To(ctx).With(aValue.Of(a)).Log(bench.A.Msg)
 			return ctx
 		},
 		AEnd: func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context {
-			event.To(ctx).With(bValue.Of(b)).Log(bMsg)
+			event.To(ctx).With(bValue.Of(b)).Log(bench.B.Msg)
 			return ctx
 		},
 		BEnd: func(ctx context.Context) {},
 	}
 
-	eventLogf = Hooks{
+	eventLogf = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
-			event.To(ctx).Logf(aMsgf, a)
+			event.To(ctx).Logf(bench.A.Msgf, a)
 			return ctx
 		},
 		AEnd: func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context {
-			event.To(ctx).Logf(bMsgf, b)
+			event.To(ctx).Logf(bench.B.Msgf, b)
 			return ctx
 		},
 		BEnd: func(ctx context.Context) {},
 	}
 
-	eventTrace = Hooks{
+	eventTrace = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
-			ctx, _ = event.To(ctx).Start(aMsg)
+			ctx, _ = event.To(ctx).Start(bench.A.Msg)
 			event.To(ctx).With(aValue.Of(a)).Annotate()
 			return ctx
 		},
@@ -59,7 +60,7 @@
 			event.To(ctx).End()
 		},
 		BStart: func(ctx context.Context, b string) context.Context {
-			ctx, _ = event.To(ctx).Start(bMsg)
+			ctx, _ = event.To(ctx).Start(bench.B.Msg)
 			event.To(ctx).With(bValue.Of(b)).Annotate()
 			return ctx
 		},
@@ -69,7 +70,7 @@
 	}
 
 	gauge       = event.NewFloatGauge("gauge", "a gauge")
-	eventMetric = Hooks{
+	eventMetric = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
 			event.To(ctx).With(aStat.Of(a)).Metric(gauge.Record(1))
 			event.To(ctx).With(aCount.Of(1)).Metric(gauge.Record(1))
@@ -98,33 +99,33 @@
 }
 
 func BenchmarkLogEventNoExporter(b *testing.B) {
-	runBenchmark(b, eventNoExporter(), eventLog)
+	bench.RunBenchmark(b, eventNoExporter(), eventLog)
 }
 
 func BenchmarkLogEventNoop(b *testing.B) {
-	runBenchmark(b, eventNoop(), eventLog)
+	bench.RunBenchmark(b, eventNoop(), eventLog)
 }
 
 func BenchmarkLogEventDiscard(b *testing.B) {
-	runBenchmark(b, eventPrint(io.Discard), eventLog)
+	bench.RunBenchmark(b, eventPrint(io.Discard), eventLog)
 }
 
 func BenchmarkLogEventfDiscard(b *testing.B) {
-	runBenchmark(b, eventPrint(io.Discard), eventLogf)
+	bench.RunBenchmark(b, eventPrint(io.Discard), eventLogf)
 }
 
 func BenchmarkTraceEventNoop(b *testing.B) {
-	runBenchmark(b, eventNoop(), eventTrace)
+	bench.RunBenchmark(b, eventNoop(), eventTrace)
 }
 
 func BenchmarkTraceEventDiscard(b *testing.B) {
-	runBenchmark(b, eventPrint(io.Discard), eventTrace)
+	bench.RunBenchmark(b, eventPrint(io.Discard), eventTrace)
 }
 
 func BenchmarkMetricEventNoop(b *testing.B) {
-	runBenchmark(b, eventNoop(), eventMetric)
+	bench.RunBenchmark(b, eventNoop(), eventMetric)
 }
 
 func BenchmarkMetricEventDiscard(b *testing.B) {
-	runBenchmark(b, eventPrint(io.Discard), eventMetric)
+	bench.RunBenchmark(b, eventPrint(io.Discard), eventMetric)
 }
diff --git a/event/bench/logrus_test.go b/event/bench/logrus_test.go
index 1755570..127554e 100644
--- a/event/bench/logrus_test.go
+++ b/event/bench/logrus_test.go
@@ -11,30 +11,32 @@
 	"time"
 
 	"github.com/sirupsen/logrus"
+	"golang.org/x/exp/event/adapter/eventtest"
+	"golang.org/x/exp/event/bench"
 )
 
 var (
-	logrusLog = Hooks{
+	logrusLog = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
-			logrusCtx(ctx).WithField(aName, a).Info(aMsg)
+			logrusCtx(ctx).WithField(bench.A.Name, a).Info(bench.A.Msg)
 			return ctx
 		},
 		AEnd: func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context {
-			logrusCtx(ctx).WithField(bName, b).Info(bMsg)
+			logrusCtx(ctx).WithField(bench.B.Name, b).Info(bench.B.Msg)
 			return ctx
 		},
 		BEnd: func(ctx context.Context) {},
 	}
 
-	logrusLogf = Hooks{
+	logrusLogf = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
-			logrusCtx(ctx).Infof(aMsgf, a)
+			logrusCtx(ctx).Infof(bench.A.Msgf, a)
 			return ctx
 		},
 		AEnd: func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context {
-			logrusCtx(ctx).Infof(bMsgf, b)
+			logrusCtx(ctx).Infof(bench.B.Msgf, b)
 			return ctx
 		},
 		BEnd: func(ctx context.Context) {},
@@ -61,10 +63,10 @@
 		Out:   w,
 		Level: logrus.InfoLevel,
 		Formatter: &logrusTimeFormatter{
-			now: newTimer(),
+			now: eventtest.ExporterOptions().Now,
 			wrapped: &logrus.TextFormatter{
 				FullTimestamp:   true,
-				TimestampFormat: timeFormat,
+				TimestampFormat: bench.TimeFormat,
 				DisableSorting:  true,
 				DisableColors:   true,
 			},
@@ -74,15 +76,15 @@
 }
 
 func BenchmarkLogrus(b *testing.B) {
-	runBenchmark(b, logrusPrint(io.Discard), logrusLog)
+	bench.RunBenchmark(b, logrusPrint(io.Discard), logrusLog)
 }
 
 func BenchmarkLogrusf(b *testing.B) {
-	runBenchmark(b, logrusPrint(io.Discard), logrusLogf)
+	bench.RunBenchmark(b, logrusPrint(io.Discard), logrusLogf)
 }
 
 func TestLogrusf(t *testing.T) {
-	testBenchmark(t, logrusPrint, logrusLogf, `
+	bench.TestBenchmark(t, logrusPrint, logrusLogf, `
 time="2020/03/05 14:27:48" level=info msg="a where A=0"
 time="2020/03/05 14:27:49" level=info msg="b where B=\"A value\""
 time="2020/03/05 14:27:50" level=info msg="a where A=1"
diff --git a/event/bench/stdlib_test.go b/event/bench/stdlib_test.go
index 1ab434b..a1be39e 100644
--- a/event/bench/stdlib_test.go
+++ b/event/bench/stdlib_test.go
@@ -11,37 +11,40 @@
 	"io/ioutil"
 	"log"
 	"testing"
+
+	"golang.org/x/exp/event/adapter/eventtest"
+	"golang.org/x/exp/event/bench"
 )
 
 var (
-	baseline = Hooks{
+	baseline = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context { return ctx },
 		AEnd:   func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context { return ctx },
 		BEnd:   func(ctx context.Context) {},
 	}
 
-	stdlibLog = Hooks{
+	stdlibLog = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
-			logCtx(ctx).Printf(aMsgf, a)
+			logCtx(ctx).Printf(bench.A.Msgf, a)
 			return ctx
 		},
 		AEnd: func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context {
-			logCtx(ctx).Printf(bMsgf, b)
+			logCtx(ctx).Printf(bench.B.Msgf, b)
 			return ctx
 		},
 		BEnd: func(ctx context.Context) {},
 	}
 
-	stdlibPrintf = Hooks{
+	stdlibPrintf = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
-			ctxPrintf(ctx, aMsgf, a)
+			ctxPrintf(ctx, bench.A.Msgf, a)
 			return ctx
 		},
 		AEnd: func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context {
-			ctxPrintf(ctx, bMsgf, b)
+			ctxPrintf(ctx, bench.B.Msgf, b)
 			return ctx
 		},
 		BEnd: func(ctx context.Context) {},
@@ -49,7 +52,7 @@
 )
 
 func BenchmarkBaseline(b *testing.B) {
-	runBenchmark(b, context.Background(), Hooks{
+	bench.RunBenchmark(b, context.Background(), bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context { return ctx },
 		AEnd:   func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context { return ctx },
@@ -81,10 +84,10 @@
 }
 
 func stdlibWriter(w io.Writer) context.Context {
-	now := newTimer()
+	now := eventtest.ExporterOptions().Now
 	return context.WithValue(context.Background(), writerKey{},
 		func(msg string, args ...interface{}) {
-			fmt.Fprint(w, now().Format(timeFormat), " ")
+			fmt.Fprint(w, now().Format(bench.TimeFormat), " ")
 			fmt.Fprintf(w, msg, args...)
 			fmt.Fprintln(w)
 		},
@@ -92,15 +95,15 @@
 }
 
 func BenchmarkLogStdlib(b *testing.B) {
-	runBenchmark(b, stdlibLogger(ioutil.Discard), stdlibLog)
+	bench.RunBenchmark(b, stdlibLogger(ioutil.Discard), stdlibLog)
 }
 
 func BenchmarkLogPrintf(b *testing.B) {
-	runBenchmark(b, stdlibWriter(io.Discard), stdlibPrintf)
+	bench.RunBenchmark(b, stdlibWriter(io.Discard), stdlibPrintf)
 }
 
 func TestLogStdlib(t *testing.T) {
-	testBenchmark(t, stdlibLoggerNoTime, stdlibLog, `
+	bench.TestBenchmark(t, stdlibLoggerNoTime, stdlibLog, `
 a where A=0
 b where B="A value"
 a where A=1
@@ -121,7 +124,7 @@
 }
 
 func TestLogPrintf(t *testing.T) {
-	testBenchmark(t, stdlibWriter, stdlibPrintf, `
+	bench.TestBenchmark(t, stdlibWriter, stdlibPrintf, `
 2020/03/05 14:27:48 a where A=0
 2020/03/05 14:27:49 b where B="A value"
 2020/03/05 14:27:50 a where A=1
diff --git a/event/bench/zap_test.go b/event/bench/zap_test.go
index 7cf6ab8..6ee3609 100644
--- a/event/bench/zap_test.go
+++ b/event/bench/zap_test.go
@@ -12,29 +12,31 @@
 
 	"go.uber.org/zap"
 	"go.uber.org/zap/zapcore"
+	"golang.org/x/exp/event/adapter/eventtest"
+	"golang.org/x/exp/event/bench"
 )
 
 var (
-	zapLog = Hooks{
+	zapLog = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
-			zapCtx(ctx).Info(aMsg, zap.Int(aName, a))
+			zapCtx(ctx).Info(bench.A.Msg, zap.Int(bench.A.Name, a))
 			return ctx
 		},
 		AEnd: func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context {
-			zapCtx(ctx).Info(bMsg, zap.String(bName, b))
+			zapCtx(ctx).Info(bench.B.Msg, zap.String(bench.B.Name, b))
 			return ctx
 		},
 		BEnd: func(ctx context.Context) {},
 	}
-	zapLogf = Hooks{
+	zapLogf = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
-			zapCtx(ctx).Sugar().Infof(aMsgf, a)
+			zapCtx(ctx).Sugar().Infof(bench.A.Msgf, a)
 			return ctx
 		},
 		AEnd: func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context {
-			zapCtx(ctx).Sugar().Infof(bMsgf, b)
+			zapCtx(ctx).Sugar().Infof(bench.B.Msgf, b)
 			return ctx
 		},
 		BEnd: func(ctx context.Context) {},
@@ -48,10 +50,10 @@
 }
 
 func zapPrint(w io.Writer) context.Context {
-	now := newTimer()
+	now := eventtest.ExporterOptions().Now
 	ec := zap.NewProductionEncoderConfig()
 	ec.EncodeDuration = zapcore.NanosDurationEncoder
-	timeEncoder := zapcore.TimeEncoderOfLayout(timeFormat)
+	timeEncoder := zapcore.TimeEncoderOfLayout(bench.TimeFormat)
 	ec.EncodeTime = func(t time.Time, a zapcore.PrimitiveArrayEncoder) {
 		timeEncoder(now(), a)
 	}
@@ -65,15 +67,15 @@
 }
 
 func BenchmarkLogZap(b *testing.B) {
-	runBenchmark(b, zapPrint(io.Discard), zapLog)
+	bench.RunBenchmark(b, zapPrint(io.Discard), zapLog)
 }
 
 func BenchmarkLogZapf(b *testing.B) {
-	runBenchmark(b, zapPrint(io.Discard), zapLogf)
+	bench.RunBenchmark(b, zapPrint(io.Discard), zapLogf)
 }
 
 func TestLogZapf(t *testing.T) {
-	testBenchmark(t, zapPrint, zapLogf, `
+	bench.TestBenchmark(t, zapPrint, zapLogf, `
 2020/03/05 14:27:48	info	a where A=0
 2020/03/05 14:27:49	info	b where B="A value"
 2020/03/05 14:27:50	info	a where A=1
@@ -93,7 +95,7 @@
 `)
 }
 func TestLogZap(t *testing.T) {
-	testBenchmark(t, zapPrint, zapLog, `
+	bench.TestBenchmark(t, zapPrint, zapLog, `
 2020/03/05 14:27:48	info	a	{"A": 0}
 2020/03/05 14:27:49	info	b	{"B": "A value"}
 2020/03/05 14:27:50	info	a	{"A": 1}
diff --git a/event/bench/zerolog_test.go b/event/bench/zerolog_test.go
index 8d1ed46..5a944cb 100644
--- a/event/bench/zerolog_test.go
+++ b/event/bench/zerolog_test.go
@@ -10,30 +10,32 @@
 	"testing"
 
 	"github.com/rs/zerolog"
+	"golang.org/x/exp/event/adapter/eventtest"
+	"golang.org/x/exp/event/bench"
 )
 
 var (
-	zerologMsg = Hooks{
+	zerologMsg = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
-			zerolog.Ctx(ctx).Info().Int(aName, a).Msg(aMsg)
+			zerolog.Ctx(ctx).Info().Int(bench.A.Name, a).Msg(bench.A.Msg)
 			return ctx
 		},
 		AEnd: func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context {
-			zerolog.Ctx(ctx).Info().Str(bName, b).Msg(bMsg)
+			zerolog.Ctx(ctx).Info().Str(bench.B.Name, b).Msg(bench.B.Msg)
 			return ctx
 		},
 		BEnd: func(ctx context.Context) {},
 	}
 
-	zerologMsgf = Hooks{
+	zerologMsgf = bench.Hooks{
 		AStart: func(ctx context.Context, a int) context.Context {
-			zerolog.Ctx(ctx).Info().Msgf(aMsgf, a)
+			zerolog.Ctx(ctx).Info().Msgf(bench.A.Msgf, a)
 			return ctx
 		},
 		AEnd: func(ctx context.Context) {},
 		BStart: func(ctx context.Context, b string) context.Context {
-			zerolog.Ctx(ctx).Info().Msgf(bMsgf, b)
+			zerolog.Ctx(ctx).Info().Msgf(bench.B.Msgf, b)
 			return ctx
 		},
 		BEnd: func(ctx context.Context) {},
@@ -41,22 +43,22 @@
 )
 
 func zerologPrint(w io.Writer) context.Context {
-	zerolog.TimeFieldFormat = timeFormat
-	zerolog.TimestampFunc = newTimer()
+	zerolog.TimeFieldFormat = bench.TimeFormat
+	zerolog.TimestampFunc = eventtest.ExporterOptions().Now
 	logger := zerolog.New(zerolog.SyncWriter(w)).With().Timestamp().Logger()
 	return logger.WithContext(context.Background())
 }
 
 func BenchmarkLogZerolog(b *testing.B) {
-	runBenchmark(b, zerologPrint(io.Discard), zerologMsg)
+	bench.RunBenchmark(b, zerologPrint(io.Discard), zerologMsg)
 }
 
 func BenchmarkLogZerologf(b *testing.B) {
-	runBenchmark(b, zerologPrint(io.Discard), zerologMsgf)
+	bench.RunBenchmark(b, zerologPrint(io.Discard), zerologMsgf)
 }
 
 func TestLogZerologf(t *testing.T) {
-	testBenchmark(t, zerologPrint, zerologMsgf, `
+	bench.TestBenchmark(t, zerologPrint, zerologMsgf, `
 {"level":"info","time":"2020/03/05 14:27:48","message":"a where A=0"}
 {"level":"info","time":"2020/03/05 14:27:49","message":"b where B=\"A value\""}
 {"level":"info","time":"2020/03/05 14:27:50","message":"a where A=1"}