Skip to content

Commit

Permalink
testr: use an interface to make it work with *testing.B and *testing.…
Browse files Browse the repository at this point in the history
…F in addition to *testing.T
  • Loading branch information
jeandeaual committed Jun 4, 2022
1 parent 47e013c commit a6dbdbc
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 13 deletions.
109 changes: 97 additions & 12 deletions testr/testr.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,26 @@ func NewWithOptions(t *testing.T, opts Options) logr.Logger {
return logr.New(l)
}

// TestingT is an interface wrapper around testing.T, testing.B and testing.F.
type TestingT interface {
Helper()
Log(args ...interface{})
}

// NewWithInterface returns a logr.Logger that prints through a
// TestingT object.
// In contrast to the simpler New, output formatting can be configured.
func NewWithInterface(t TestingT, opts Options) logr.Logger {
l := &testloggerInterface{
Formatter: funcr.NewFormatter(funcr.Options{
LogTimestamp: opts.LogTimestamp,
Verbosity: opts.Verbosity,
}),
t: t,
}
return logr.New(l)
}

// Underlier exposes access to the underlying testing.T instance. Since
// callers only have a logr.Logger, they have to know which
// implementation is in use, so this interface is less of an
Expand All @@ -67,6 +87,44 @@ type Underlier interface {
GetUnderlying() *testing.T
}

// UnderlierInterface exposes access to the underlying TestingT instance. Since
// callers only have a logr.Logger, they have to know which
// implementation is in use, so this interface is less of an
// abstraction and more of a way to test type conversion.
type UnderlierInterface interface {
GetUnderlying() TestingT
}

func logInfo(
t TestingT,
formatInfo func(int, string, []interface{}) (string, string),
level int,
msg string,
kvList ...interface{},
) {
prefix, args := formatInfo(level, msg, kvList)
t.Helper()
if prefix != "" {
args = prefix + ": " + args
}
t.Log(args)
}

func logError(
t TestingT,
formatError func(error, string, []interface{}) (string, string),
err error,
msg string,
kvList ...interface{},
) {
prefix, args := formatError(err, msg, kvList)
t.Helper()
if prefix != "" {
args = prefix + ": " + args
}
t.Log(args)
}

type testlogger struct {
funcr.Formatter
t *testing.T
Expand All @@ -87,30 +145,57 @@ func (l testlogger) GetCallStackHelper() func() {
}

func (l testlogger) Info(level int, msg string, kvList ...interface{}) {
prefix, args := l.FormatInfo(level, msg, kvList)
l.t.Helper()
if prefix != "" {
l.t.Logf("%s: %s", prefix, args)
} else {
l.t.Log(args)
}
logInfo(l.t, l.FormatInfo, level, msg, kvList...)
}

func (l testlogger) Error(err error, msg string, kvList ...interface{}) {
prefix, args := l.FormatError(err, msg, kvList)
l.t.Helper()
if prefix != "" {
l.t.Logf("%s: %s", prefix, args)
} else {
l.t.Log(args)
}
logError(l.t, l.FormatError, err, msg, kvList...)
}

func (l testlogger) GetUnderlying() *testing.T {
return l.t
}

type testloggerInterface struct {
funcr.Formatter
t TestingT
}

func (l testloggerInterface) WithName(name string) logr.LogSink {
l.Formatter.AddName(name)
return &l
}

func (l testloggerInterface) WithValues(kvList ...interface{}) logr.LogSink {
l.Formatter.AddValues(kvList)
return &l
}

func (l testloggerInterface) GetCallStackHelper() func() {
return l.t.Helper
}

func (l testloggerInterface) Info(level int, msg string, kvList ...interface{}) {
l.t.Helper()
logInfo(l.t, l.FormatInfo, level, msg, kvList...)
}

func (l testloggerInterface) Error(err error, msg string, kvList ...interface{}) {
l.t.Helper()
logError(l.t, l.FormatError, err, msg, kvList...)
}

func (l testloggerInterface) GetUnderlying() TestingT {
return l.t
}

// Assert conformance to the interfaces.
var _ logr.LogSink = &testlogger{}
var _ logr.CallStackHelperLogSink = &testlogger{}
var _ Underlier = &testlogger{}

var _ logr.LogSink = &testloggerInterface{}
var _ logr.CallStackHelperLogSink = &testloggerInterface{}
var _ UnderlierInterface = &testloggerInterface{}
62 changes: 61 additions & 1 deletion testr/testr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,74 @@ func TestLogger(t *testing.T) {
log.V(0).Info("V(0).info")
log.V(1).Info("v(1).info")
log.Error(fmt.Errorf("error"), "error")
log.WithName("testing").Info("with prefix")
log.WithName("testing").WithValues("value", "test").Info("with prefix")
log.WithName("testing").Error(fmt.Errorf("error"), "with prefix")
Helper(log, "hello world")

log = NewWithOptions(t, Options{
LogTimestamp: true,
Verbosity: 1,
})
log.V(1).Info("v(1).info with options")

if underlier, ok := log.GetSink().(Underlier); ok {
if t != underlier.GetUnderlying() {
t.Error("invalid underlier")
}
} else {
t.Error("couldn't get underlier")
}
}

func TestLoggerInterface(t *testing.T) {
log := NewWithInterface(t, Options{})
log.Info("info")
log.V(0).Info("V(0).info")
log.V(1).Info("v(1).info")
log.Error(fmt.Errorf("error"), "error")
log.WithName("testing").WithValues("value", "test").Info("with prefix")
log.WithName("testing").Error(fmt.Errorf("error"), "with prefix")
Helper(log, "hello world")

if underlier, ok := log.GetSink().(UnderlierInterface); ok {
if underlierT, ok := underlier.GetUnderlying().(*testing.T); ok {
if t != underlierT {
t.Error("invalid underlier")
}
} else {
t.Error("couldn't get underlying *testing.T")
}
} else {
t.Error("couldn't get underlier")
}
}

func BenchmarkLogger(b *testing.B) {
log := NewWithInterface(b, Options{
LogTimestamp: true,
})

for n := 0; n < b.N; n++ {
log.Info("info")
log.V(0).Info("V(0).info")
log.V(1).Info("v(1).info")
log.Error(fmt.Errorf("error"), "error")
log.WithName("testing").WithValues("value", "test").Info("with prefix")
log.WithName("testing").Error(fmt.Errorf("error"), "with prefix")
Helper(log, "hello world")
}

if underlier, ok := log.GetSink().(UnderlierInterface); ok {
if underlierB, ok := underlier.GetUnderlying().(*testing.B); ok {
if b != underlierB {
b.Error("invalid underlier")
}
} else {
b.Error("couldn't get underlying *testing.B")
}
} else {
b.Error("couldn't get underlier")
}
}

func Helper(log logr.Logger, msg string) {
Expand Down

0 comments on commit a6dbdbc

Please sign in to comment.