Skip to content

Commit

Permalink
Ensure TB.Helper() and TB.Name() are always usable
Browse files Browse the repository at this point in the history
Closes #58.
  • Loading branch information
flyingmutant committed Aug 8, 2023
1 parent f4756c7 commit 83e77bf
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 12 deletions.
41 changes: 31 additions & 10 deletions engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ func findBug(tb tb, deadline time.Time, checks int, seed uint64, prop func(*T))
}

func checkOnce(t *T, prop func(*T)) (err *testError) {
if t.tbLog && t.tb != nil {
if t.tbLog {
t.tb.Helper()
}
defer func() { err = panicToError(recover(), 3) }()
Expand Down Expand Up @@ -477,6 +477,23 @@ type TB interface {

type tb TB // tb is a private copy of TB, made to avoid T having public fields

type nilTB struct{}

func (nilTB) Helper() {}
func (nilTB) Name() string { return "" }
func (nilTB) Logf(string, ...any) {}
func (nilTB) Log(...any) {}
func (nilTB) Skipf(string, ...any) { panic("call to TB.Skipf() outside a test") }
func (nilTB) Skip(...any) { panic("call to TB.Skip() outside a test") }
func (nilTB) SkipNow() { panic("call to TB.SkipNow() outside a test") }
func (nilTB) Errorf(string, ...any) { panic("call to TB.Errorf() outside a test") }
func (nilTB) Error(...any) { panic("call to TB.Error() outside a test") }
func (nilTB) Fatalf(string, ...any) { panic("call to TB.Fatalf() outside a test") }
func (nilTB) Fatal(...any) { panic("call to TB.Fatal() outside a test") }
func (nilTB) FailNow() { panic("call to TB.FailNow() outside a test") }
func (nilTB) Fail() { panic("call to TB.Fail() outside a test") }
func (nilTB) Failed() bool { panic("call to TB.Failed() outside a test") }

// T is similar to [testing.T], but with extra bookkeeping for property-based tests.
//
// For tests to be reproducible, they should generally run in a single goroutine.
Expand All @@ -494,6 +511,10 @@ type T struct {
}

func newT(tb tb, s bitStream, tbLog bool, rawLog *log.Logger, refDraws ...any) *T {
if tb == nil {
tb = nilTB{}
}

t := &T{
tb: tb,
tbLog: tbLog,
Expand All @@ -515,13 +536,13 @@ func newT(tb tb, s bitStream, tbLog bool, rawLog *log.Logger, refDraws ...any) *
}

func (t *T) shouldLog() bool {
return t.rawLog != nil || (t.tbLog && t.tb != nil)
return t.rawLog != nil || t.tbLog
}

func (t *T) Logf(format string, args ...any) {
if t.rawLog != nil {
t.rawLog.Printf(format, args...)
} else if t.tbLog && t.tb != nil {
} else if t.tbLog {
t.tb.Helper()
t.tb.Logf(format, args...)
}
Expand All @@ -530,15 +551,15 @@ func (t *T) Logf(format string, args ...any) {
func (t *T) Log(args ...any) {
if t.rawLog != nil {
t.rawLog.Print(args...)
} else if t.tbLog && t.tb != nil {
} else if t.tbLog {
t.tb.Helper()
t.tb.Log(args...)
}
}

// Skipf is equivalent to [T.Logf] followed by [T.SkipNow].
func (t *T) Skipf(format string, args ...any) {
if t.tbLog && t.tb != nil {
if t.tbLog {
t.tb.Helper()
}
t.Logf(format, args...)
Expand All @@ -547,7 +568,7 @@ func (t *T) Skipf(format string, args ...any) {

// Skip is equivalent to [T.Log] followed by [T.SkipNow].
func (t *T) Skip(args ...any) {
if t.tbLog && t.tb != nil {
if t.tbLog {
t.tb.Helper()
}
t.Log(args...)
Expand All @@ -567,7 +588,7 @@ func (t *T) SkipNow() {

// Errorf is equivalent to [T.Logf] followed by [T.Fail].
func (t *T) Errorf(format string, args ...any) {
if t.tbLog && t.tb != nil {
if t.tbLog {
t.tb.Helper()
}
t.Logf(format, args...)
Expand All @@ -576,7 +597,7 @@ func (t *T) Errorf(format string, args ...any) {

// Error is equivalent to [T.Log] followed by [T.Fail].
func (t *T) Error(args ...any) {
if t.tbLog && t.tb != nil {
if t.tbLog {
t.tb.Helper()
}
t.Log(args...)
Expand All @@ -585,7 +606,7 @@ func (t *T) Error(args ...any) {

// Fatalf is equivalent to [T.Logf] followed by [T.FailNow].
func (t *T) Fatalf(format string, args ...any) {
if t.tbLog && t.tb != nil {
if t.tbLog {
t.tb.Helper()
}
t.Logf(format, args...)
Expand All @@ -594,7 +615,7 @@ func (t *T) Fatalf(format string, args ...any) {

// Fatal is equivalent to [T.Log] followed by [T.FailNow].
func (t *T) Fatal(args ...any) {
if t.tbLog && t.tb != nil {
if t.tbLog {
t.tb.Helper()
}
t.Log(args...)
Expand Down
4 changes: 2 additions & 2 deletions generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (g *Generator[V]) String() string {

// Draw produces a value from the generator.
func (g *Generator[V]) Draw(t *T, label string) V {
if t.tbLog && t.tb != nil {
if t.tbLog {
t.tb.Helper()
}

Expand All @@ -58,7 +58,7 @@ func (g *Generator[V]) Draw(t *T, label string) V {
label = fmt.Sprintf("#%v", t.draws)
}

if t.tbLog && t.tb != nil {
if t.tbLog {
t.tb.Helper()
}
t.Logf("[rapid] draw %v: %#v", label, v)
Expand Down
9 changes: 9 additions & 0 deletions generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,12 @@ func BenchmarkGenerator_Value(b *testing.B) {
g.value(t)
}
}

func TestExampleHelper(t *testing.T) {
g := Custom(func(t *T) int {
t.Helper()
return Int().Draw(t, t.Name())
})

g.Example(0)
}

0 comments on commit 83e77bf

Please sign in to comment.