From 6efa794ab4bdfe6eae503b8d9702611c5962d04b Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Wed, 21 Jan 2015 18:45:37 +0000 Subject: [PATCH] some testing improvements - show complete call stack of failures (this does include some of the testing machinery, but a) is simple, and b) is guaranteed to not miss important stack frames) - add helper to run test with a timeout - add AssertEqualuint64 --- testing/util.go | 70 +++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/testing/util.go b/testing/util.go index ef6cf332..809cef36 100644 --- a/testing/util.go +++ b/testing/util.go @@ -1,70 +1,90 @@ package testing import ( - "fmt" "reflect" "runtime" - "strings" "testing" + "time" ) -func CallSite() string { - _, file, line, ok := runtime.Caller(2) - if ok { - // Truncate file name at last file name separator. - if index := strings.LastIndex(file, "/"); index >= 0 { - file = file[index+1:] - } else if index = strings.LastIndex(file, "\\"); index >= 0 { - file = file[index+1:] - } - } else { - file = "???" - line = 1 - } - return fmt.Sprintf("%s:%d: ", file, line) -} - func AssertNoErr(t *testing.T, err error) { if err != nil { - t.Fatal(CallSite(), err) + Fatalf(t, "Unexpected error: %s", err) + } +} + +func AssertEqualuint64(t *testing.T, got, wanted uint64, desc string) { + if got != wanted { + Fatalf(t, "Expected %s %d but got %d", desc, wanted, got) } } func AssertEqualInt(t *testing.T, got, wanted int, desc string) { if got != wanted { - t.Fatalf("%s: Expected %s %d but got %d", CallSite(), desc, wanted, got) + Fatalf(t, "Expected %s %d but got %d", desc, wanted, got) } } func AssertEqualString(t *testing.T, got, wanted string, desc string) { if got != wanted { - t.Fatalf("%s: Expected %s '%s' but got '%s'", CallSite(), desc, wanted, got) + Fatalf(t, "Expected %s '%s' but got '%s'", desc, wanted, got) } } func AssertStatus(t *testing.T, got int, wanted int, desc string) { if got != wanted { - t.Fatalf("%s: Expected %s %d but got %d", CallSite(), desc, wanted, got) + Fatalf(t, "Expected %s %d but got %d", desc, wanted, got) } } func AssertErrorInterface(t *testing.T, got interface{}, wanted interface{}, desc string) { gotT, wantedT := reflect.TypeOf(got), reflect.TypeOf(wanted).Elem() if !gotT.Implements(wantedT) { - t.Fatalf("%s: Expected %s but got %s (%s)", CallSite(), wantedT.String(), gotT.String(), desc) + Fatalf(t, "Expected %s but got %s (%s)", wantedT.String(), gotT.String(), desc) } } func AssertErrorType(t *testing.T, got interface{}, wanted interface{}, desc string) { gotT, wantedT := reflect.TypeOf(got), reflect.TypeOf(wanted).Elem() if gotT != wantedT { - t.Fatalf("%s: Expected %s but got %s (%s)", CallSite(), wantedT.String(), gotT.String(), desc) + Fatalf(t, "Expected %s but got %s (%s)", wantedT.String(), gotT.String(), desc) } } func AssertType(t *testing.T, got interface{}, wanted interface{}, desc string) { gotT, wantedT := reflect.TypeOf(got), reflect.TypeOf(wanted) if gotT != wantedT { - t.Fatalf("%s: Expected %s but got %s (%s)", CallSite(), wantedT.String(), gotT.String(), desc) + Fatalf(t, "Expected %s but got %s (%s)", wantedT.String(), gotT.String(), desc) } } + +// Like testing.Fatalf, but adds the stack trace of the current call +func Fatalf(t *testing.T, format string, args ...interface{}) { + t.Fatalf(format+"\n%s", append(args, StackTrace())...) +} + +func StackTrace() string { + return stackTrace(false) +} + +func stackTrace(all bool) string { + buf := make([]byte, 1<<20) + stacklen := runtime.Stack(buf, all) + return string(buf[:stacklen]) +} + +// Borrowed from net/http tests: +// goTimeout runs f, failing t if f takes more than d to complete. +func RunWithTimeout(t *testing.T, d time.Duration, f func()) { + ch := make(chan bool, 2) + timer := time.AfterFunc(d, func() { + t.Errorf("Timeout expired after %v: stacks:\n%s", d, stackTrace(true)) + ch <- true + }) + defer timer.Stop() + go func() { + defer func() { ch <- true }() + f() + }() + <-ch +}