This fixes a bunch of failing tests on Windows.

Specifically, a lot of tests were asserting something like:

FAIL: filename.go ...

While on Windows, the full paths are given:

FAIL: C:/dev/go/gocheck/filename.go

I dug into it, and it turns out that nicePath was comparing
function.FileLine() to os.Getwd(). However, function.FileLine() returns
'C:/path/to/foo' while 'os.Getwd()' returns 'C:\path\to\foo'.

I also did one more quick change, which was to always append the trailing '/'.
That way we don't have to do that on every call to nicePath() (and I checked
that only nicePath uses initWD).

At the moment, there are only 2 remaining tests failing. Both because the
failure messages don't include the module name. This is with golang r58. So it
is possible that golang changed something (so it needs to be fixed anyway), or
it is possible it just works differently on Windows :(.
diff --git a/TODO b/TODO
index d00a5e6..3349827 100644
--- a/TODO
+++ b/TODO
@@ -1,17 +1,2 @@
 - Assert(slice, Contains, item)
-
-- GoTest prefix support, for running parallel tests
-- Benchmark support
-- Improved logging of multiline strings:
-
----------------------------------------------------------------------
-FAIL: filename:line:TestMethod
-
-... CheckEqual: A != B
-... A: <string below>
-
-... A: <end>
-... B: <string below>
-
-... B
-
+- Parallel test support
diff --git a/benchmark.go b/benchmark.go
new file mode 100644
index 0000000..58fc41a
--- /dev/null
+++ b/benchmark.go
@@ -0,0 +1,176 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gocheck
+
+import (
+	"fmt"
+	"reflect"
+	"runtime"
+	"time"
+)
+
+// testingB is a type passed to Benchmark functions to manage benchmark
+// timing and to specify the number of iterations to run.
+type timer struct {
+	start     time.Time // Time test or benchmark started
+	duration  time.Duration
+	N         int
+	bytes     int64
+	timerOn   bool
+	benchTime time.Duration
+}
+
+// StartTimer starts timing a test. This function is called automatically
+// before a benchmark starts, but it can also used to resume timing after
+// a call to StopTimer.
+func (c *C) StartTimer() {
+	if !c.timerOn {
+		c.start = time.Now()
+		c.timerOn = true
+	}
+}
+
+// StopTimer stops timing a test. This can be used to pause the timer
+// while performing complex initialization that you don't
+// want to measure.
+func (c *C) StopTimer() {
+	if c.timerOn {
+		c.duration += time.Now().Sub(c.start)
+		c.timerOn = false
+	}
+}
+
+// ResetTimer sets the elapsed benchmark time to zero.
+// It does not affect whether the timer is running.
+func (c *C) ResetTimer() {
+	if c.timerOn {
+		c.start = time.Now()
+	}
+	c.duration = 0
+}
+
+// SetBytes informs the number of bytes that the benchmark processes
+// on each iteration. If this is called in a benchmark it will also
+// report MB/s.
+func (c *C) SetBytes(n int64) {
+	c.bytes = n
+}
+
+func (c *C) nsPerOp() int64 {
+	if c.N <= 0 {
+		return 0
+	}
+	return c.duration.Nanoseconds() / int64(c.N)
+}
+
+func (c *C) mbPerSec() float64 {
+	if c.bytes <= 0 || c.duration <= 0 || c.N <= 0 {
+		return 0
+	}
+	return (float64(c.bytes) * float64(c.N) / 1e6) / c.duration.Seconds()
+}
+
+func (c *C) timerString() string {
+	if c.N <= 0 {
+		return fmt.Sprintf("%3.3fs", float64(c.duration.Nanoseconds())/1e9)
+	}
+	mbs := c.mbPerSec()
+	mb := ""
+	if mbs != 0 {
+		mb = fmt.Sprintf("\t%7.2f MB/s", mbs)
+	}
+	nsop := c.nsPerOp()
+	ns := fmt.Sprintf("%10d ns/op", nsop)
+	if c.N > 0 && nsop < 100 {
+		// The format specifiers here make sure that
+		// the ones digits line up for all three possible formats.
+		if nsop < 10 {
+			ns = fmt.Sprintf("%13.2f ns/op", float64(c.duration.Nanoseconds())/float64(c.N))
+		} else {
+			ns = fmt.Sprintf("%12.1f ns/op", float64(c.duration.Nanoseconds())/float64(c.N))
+		}
+	}
+	return fmt.Sprintf("%8d\t%s%s", c.N, ns, mb)
+}
+
+func min(x, y int) int {
+	if x > y {
+		return y
+	}
+	return x
+}
+
+func max(x, y int) int {
+	if x < y {
+		return y
+	}
+	return x
+}
+
+// roundDown10 rounds a number down to the nearest power of 10.
+func roundDown10(n int) int {
+	var tens = 0
+	// tens = floor(log_10(n))
+	for n > 10 {
+		n = n / 10
+		tens++
+	}
+	// result = 10^tens
+	result := 1
+	for i := 0; i < tens; i++ {
+		result *= 10
+	}
+	return result
+}
+
+// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
+func roundUp(n int) int {
+	base := roundDown10(n)
+	if n < (2 * base) {
+		return 2 * base
+	}
+	if n < (5 * base) {
+		return 5 * base
+	}
+	return 10 * base
+}
+
+// benchmarkN runs a single benchmark for the specified number of iterations.
+func benchmarkN(c *C, n int) {
+	// Try to get a comparable environment for each run
+	// by clearing garbage from previous runs.
+	runtime.GC()
+	c.N = n
+	c.ResetTimer()
+	c.StartTimer()
+	c.method.Call([]reflect.Value{reflect.ValueOf(c)})
+	c.StopTimer()
+}
+
+// benchmark runs the benchmark function.  It gradually increases the number
+// of benchmark iterations until the benchmark runs for a second in order
+// to get a reasonable measurement.
+func benchmark(c *C) {
+	// Run the benchmark for a single iteration in case it's expensive.
+	n := 1
+	benchmarkN(c, n)
+	// Run the benchmark for at least the specified amount of time.
+	for c.status == succeededSt && c.duration < c.benchTime && n < 1e9 {
+		last := n
+		// Predict iterations/sec.
+		if c.nsPerOp() == 0 {
+			n = 1e9
+		} else {
+			n = int(c.benchTime.Nanoseconds() / c.nsPerOp())
+		}
+		// Run more iterations than we think we'll need for a second (1.5x).
+		// Don't grow too fast in case we had timing errors previously.
+		// Be sure to run at least one more than last time.
+		n = max(min(n+n/2, 100*last), last+1)
+		// Round up to something easy to read.
+		n = roundUp(n)
+		benchmarkN(c, n)
+	}
+}
diff --git a/benchmark_test.go b/benchmark_test.go
new file mode 100644
index 0000000..6d2b009
--- /dev/null
+++ b/benchmark_test.go
@@ -0,0 +1,69 @@
+// These tests verify the test running logic.
+
+package gocheck_test
+
+import (
+	. "launchpad.net/gocheck"
+	"time"
+)
+
+var benchmarkS = Suite(&BenchmarkS{})
+
+type BenchmarkS struct{}
+
+func (s *BenchmarkS) TestCountSuite(c *C) {
+	suitesRun += 1
+}
+
+func (s *BenchmarkS) TestBasicTestTiming(c *C) {
+	helper := FixtureHelper{sleepOn: "Test1", sleep: 1000000 * time.Nanosecond}
+	output := String{}
+	runConf := RunConf{Output: &output, Verbose: true}
+	Run(&helper, &runConf)
+
+	expected := "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test1\t0\\.001s\n" +
+		"PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test2\t0\\.000s\n"
+	c.Assert(output.value, Matches, expected)
+}
+
+func (s *BenchmarkS) TestStreamTestTiming(c *C) {
+	helper := FixtureHelper{sleepOn: "SetUpSuite", sleep: 1000000 * time.Nanosecond}
+	output := String{}
+	runConf := RunConf{Output: &output, Stream: true}
+	Run(&helper, &runConf)
+
+	expected := "(?s).*\nPASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.SetUpSuite\t *0\\.001s\n.*"
+	c.Assert(output.value, Matches, expected)
+}
+
+// Quite unfortunate that these two tests alone account for most of the 
+
+func (s *BenchmarkS) TestBenchmark(c *C) {
+	helper := FixtureHelper{sleep: 100000}
+	output := String{}
+	runConf := RunConf{
+		Output: &output,
+		Benchmark: true,
+		BenchmarkTime: 10000000,
+		Filter: "Benchmark1",
+	}
+	Run(&helper, &runConf)
+
+	expected := "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Benchmark1\t *100\t *[12][0-9]{5} ns/op\n"
+	c.Assert(output.value, Matches, expected)
+}
+
+func (s *BenchmarkS) TestBenchmarkBytes(c *C) {
+	helper := FixtureHelper{sleep: 100000}
+	output := String{}
+	runConf := RunConf{
+		Output: &output,
+		Benchmark: true,
+		BenchmarkTime: 10000000,
+		Filter: "Benchmark2",
+	}
+	Run(&helper, &runConf)
+
+	expected := "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Benchmark2\t *100\t *[12][0-9]{5} ns/op\t *[4-9]\\.[0-9]{2} MB/s\n"
+	c.Assert(output.value, Matches, expected)
+}
diff --git a/bootstrap_test.go b/bootstrap_test.go
index 81e26d1..de93b6d 100644
--- a/bootstrap_test.go
+++ b/bootstrap_test.go
@@ -12,14 +12,12 @@
 
 package gocheck_test
 
-
 import (
 	"launchpad.net/gocheck"
 	"strings"
 	"fmt"
 )
 
-
 type BootstrapS struct{}
 
 var boostrapS = gocheck.Suite(&BootstrapS{})
diff --git a/checkers.go b/checkers.go
index 8aee6aa..e6e72c4 100644
--- a/checkers.go
+++ b/checkers.go
@@ -6,44 +6,47 @@
 	"fmt"
 )
 
-
 // -----------------------------------------------------------------------
-// BugInfo and Bug() helper, to attach extra information to checks.
+// CommentInterface and Commentf helper, to attach extra information to checks.
 
-type bugInfo struct {
+type comment struct {
 	format string
 	args   []interface{}
 }
 
-// Bug enables attaching some information to Assert() or Check() calls.
+// Commentf returns an infomational value to use with Assert or Check calls.
 // If the checker test fails, the provided arguments will be passed to
-// fmt.Sprintf(), and will be presented next to the logged failure.
+// fmt.Sprintf, and will be presented next to the logged failure.
 //
 // For example:
 //
-//     c.Assert(l, Equals, 8192, Bug("Buffer size is incorrect, bug #123"))
-//     c.Assert(v, Equals, 42, Bug("Iteration #%d", i))
+//     c.Assert(v, Equals, 42, Commentf("Iteration #%d failed.", i))
 //
-func Bug(format string, args ...interface{}) BugInfo {
-	return &bugInfo{format, args}
+// Note that if the comment is constant, a better option is to
+// simply use a normal comment right above or next to the line, as
+// it will also get printed with any errors:
+//
+//     c.Assert(l, Equals, 8192) // Ensure buffer size is correct (bug #123)
+//
+func Commentf(format string, args ...interface{}) CommentInterface {
+	return &comment{format, args}
 }
 
-// BugInfo is the interface which must be supported for attaching extra
-// information to checks.  See the Bug() function for details.
-type BugInfo interface {
-	GetBugInfo() string
+// CommentInterface must be implemented by types that attach extra
+// information to failed checks. See the Commentf function for details.
+type CommentInterface interface {
+	CheckCommentString() string
 }
 
-func (bug *bugInfo) GetBugInfo() string {
-	return fmt.Sprintf(bug.format, bug.args...)
+func (c *comment) CheckCommentString() string {
+	return fmt.Sprintf(c.format, c.args...)
 }
 
-
 // -----------------------------------------------------------------------
 // The Checker interface.
 
 // The Checker interface must be provided by checkers used with
-// the c.Assert() and c.Check() verification methods.
+// the Assert and Check verification methods.
 type Checker interface {
 	Info() *CheckerInfo
 	Check(params []interface{}, names []string) (result bool, error string)
@@ -51,7 +54,7 @@
 
 // See the Checker interface.
 type CheckerInfo struct {
-	Name string
+	Name   string
 	Params []string
 }
 
@@ -60,9 +63,9 @@
 }
 
 // -----------------------------------------------------------------------
-// Not() checker logic inverter.
+// Not checker logic inverter.
 
-// The Not() checker inverts the logic of the provided checker.  The
+// The Not checker inverts the logic of the provided checker.  The
 // resulting checker will succeed where the original one failed, and
 // vice-versa.
 //
@@ -90,11 +93,10 @@
 	return
 }
 
-
 // -----------------------------------------------------------------------
 // IsNil checker.
 
-type isNilChecker struct{
+type isNilChecker struct {
 	*CheckerInfo
 }
 
@@ -108,7 +110,6 @@
 	&CheckerInfo{Name: "IsNil", Params: []string{"value"}},
 }
 
-
 func (checker *isNilChecker) Check(params []interface{}, names []string) (result bool, error string) {
 	return isNil(params[0]), ""
 }
@@ -125,11 +126,10 @@
 	return
 }
 
-
 // -----------------------------------------------------------------------
 // NotNil checker. Alias for Not(IsNil), since it's so common.
 
-type notNilChecker struct{
+type notNilChecker struct {
 	*CheckerInfo
 }
 
@@ -150,37 +150,130 @@
 	return !isNil(params[0]), ""
 }
 
-
 // -----------------------------------------------------------------------
 // Equals checker.
 
-type equalsChecker struct{
+type equalsChecker struct {
 	*CheckerInfo
 }
 
-// The Equals checker verifies that the obtained value is deep-equal to
-// the expected value.  The check will work correctly even when facing
-// arrays, interfaces, and values of different types (which always fail
-// the test).
+// The Equals checker verifies that the obtained value is equal to
+// the expected value, according to usual Go semantics for ==.
 //
 // For example:
 //
 //     c.Assert(value, Equals, 42)
-//     c.Assert(array, Equals, []string{"hi", "there"})
 //
 var Equals Checker = &equalsChecker{
 	&CheckerInfo{Name: "Equals", Params: []string{"obtained", "expected"}},
 }
 
 func (checker *equalsChecker) Check(params []interface{}, names []string) (result bool, error string) {
+	defer func() {
+		if v := recover(); v != nil {
+			result = false
+			error = fmt.Sprint(v)
+		}
+	}()
+	return params[0] == params[1], ""
+}
+
+// -----------------------------------------------------------------------
+// DeepEquals checker.
+
+type deepEqualsChecker struct {
+	*CheckerInfo
+}
+
+// The DeepEquals checker verifies that the obtained value is deep-equal to
+// the expected value.  The check will work correctly even when facing
+// slices, interfaces, and values of different types (which always fail
+// the test).
+//
+// For example:
+//
+//     c.Assert(value, DeepEquals, 42)
+//     c.Assert(array, DeepEquals, []string{"hi", "there"})
+//
+var DeepEquals Checker = &deepEqualsChecker{
+	&CheckerInfo{Name: "DeepEquals", Params: []string{"obtained", "expected"}},
+}
+
+func (checker *deepEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) {
 	return reflect.DeepEqual(params[0], params[1]), ""
 }
 
+// -----------------------------------------------------------------------
+// HasLen checker.
+
+type hasLenChecker struct {
+	*CheckerInfo
+}
+
+// The HasLen checker verifies that the obtained value has the
+// provided length. In many cases this is superior to using Equals
+// in conjuction with the len function because in case the check
+// fails the value itself will be printed, instead of its length,
+// providing more details for figuring the problem.
+//
+// For example:
+//
+//     c.Assert(list, HasLen, 5)
+//
+var HasLen Checker = &hasLenChecker{
+	&CheckerInfo{Name: "HasLen", Params: []string{"obtained", "n"}},
+}
+
+func (checker *hasLenChecker) Check(params []interface{}, names []string) (result bool, error string) {
+	n, ok := params[1].(int)
+	if !ok {
+		return false, "n must be an int"
+	}
+	value := reflect.ValueOf(params[0])
+	switch value.Kind() {
+	case reflect.Map, reflect.Array, reflect.Slice, reflect.Chan, reflect.String:
+	default:
+		return false, "obtained value type has no length"
+	}
+	return value.Len() == n, ""
+}
+
 
 // -----------------------------------------------------------------------
+// ErrorMatches checker.
+
+type errorMatchesChecker struct {
+	*CheckerInfo
+}
+
+// The ErrorMatches checker verifies that the error value
+// is non nil and matches the regular expression provided.
+//
+// For example:
+//
+//     c.Assert(err, ErrorMatches, "perm.*denied")
+//
+var ErrorMatches Checker = errorMatchesChecker{
+	&CheckerInfo{Name: "ErrorMatches", Params: []string{"value", "regex"}},
+}
+
+func (checker errorMatchesChecker) Check(params []interface{}, names []string) (result bool, errStr string) {
+	if params[0] == nil {
+		return false, "Error value is nil"
+	}
+	err, ok := params[0].(error)
+	if !ok {
+		return false, "Value is not an error"
+	}
+	params[0] = err.Error()
+	names[0] = "error"
+	return matches(params[0], params[1])
+}
+
+// -----------------------------------------------------------------------
 // Matches checker.
 
-type matchesChecker struct{
+type matchesChecker struct {
 	*CheckerInfo
 }
 
@@ -207,14 +300,14 @@
 	}
 	valueStr, valueIsStr := value.(string)
 	if !valueIsStr {
-		if valueWithStr, valueHasStr := value.(hasString); valueHasStr {
+		if valueWithStr, valueHasStr := value.(fmt.Stringer); valueHasStr {
 			valueStr, valueIsStr = valueWithStr.String(), true
 		}
 	}
 	if valueIsStr {
 		matches, err := regexp.MatchString("^"+reStr+"$", valueStr)
 		if err != nil {
-			return false, "Can't compile regex: " + err.String()
+			return false, "Can't compile regex: " + err.Error()
 		}
 		return matches, ""
 	}
@@ -224,7 +317,7 @@
 // -----------------------------------------------------------------------
 // Panics checker.
 
-type panicsChecker struct{
+type panicsChecker struct {
 	*CheckerInfo
 }
 
@@ -233,11 +326,8 @@
 //
 // For example:
 //
-//     c.Assert(func() { f(1, 2) }, Panics, os.NewError("BOOM")).
+//     c.Assert(func() { f(1, 2) }, Panics, &SomeErrorType{"BOOM"}).
 //
-// If the provided value is a plain string, it will also be attempted
-// to be matched as a regular expression against the String() value of
-// the panic.
 //
 var Panics Checker = &panicsChecker{
 	&CheckerInfo{Name: "Panics", Params: []string{"function", "expected"}},
@@ -249,24 +339,65 @@
 		return false, "Function must take zero arguments"
 	}
 	defer func() {
-		obtained := recover()
-		expected := params[1]
-		result = reflect.DeepEqual(obtained, expected)
-		if _, ok := expected.(string); !result && ok {
-			result, _ = matches(obtained, expected)
+		// If the function has not panicked, then don't do the check.
+		if error != "" {
+			return
 		}
-		params[0] = obtained
+		params[0] = recover()
 		names[0] = "panic"
+		result = reflect.DeepEqual(params[0], params[1])
 	}()
 	f.Call(nil)
 	return false, "Function has not panicked"
 }
 
+type panicMatchesChecker struct {
+	*CheckerInfo
+}
+
+// The PanicMatches checker verifies that calling the provided zero-argument
+// function will cause a panic with an error value matching
+// the regular expression provided.
+//
+// For example:
+//
+//     c.Assert(func() { f(1, 2) }, PanicMatches, `open.*: no such file or directory`).
+//
+//
+var PanicMatches Checker = &panicMatchesChecker{
+	&CheckerInfo{Name: "PanicMatches", Params: []string{"function", "expected"}},
+}
+
+func (checker *panicMatchesChecker) Check(params []interface{}, names []string) (result bool, errmsg string) {
+	f := reflect.ValueOf(params[0])
+	if f.Kind() != reflect.Func || f.Type().NumIn() != 0 {
+		return false, "Function must take zero arguments"
+	}
+	defer func() {
+		// If the function has not panicked, then don't do the check.
+		if errmsg != "" {
+			return
+		}
+		obtained := recover()
+		names[0] = "panic"
+		if e, ok := obtained.(error); ok {
+			params[0] = e.Error()
+		} else if _, ok := obtained.(string); ok {
+			params[0] = obtained
+		} else {
+			errmsg = "Panic value is not a string or an error"
+			return
+		}
+		result, errmsg = matches(params[0], params[1])
+	}()
+	f.Call(nil)
+	return false, "Function has not panicked"
+}
 
 // -----------------------------------------------------------------------
 // FitsTypeOf checker.
 
-type fitsTypeChecker struct{
+type fitsTypeChecker struct {
 	*CheckerInfo
 }
 
@@ -295,11 +426,10 @@
 	return obtained.Type().AssignableTo(sample.Type()), ""
 }
 
-
 // -----------------------------------------------------------------------
 // Implements checker.
 
-type implementsChecker struct{
+type implementsChecker struct {
 	*CheckerInfo
 }
 
diff --git a/checkers_test.go b/checkers_test.go
index f997399..0945491 100644
--- a/checkers_test.go
+++ b/checkers_test.go
@@ -1,18 +1,16 @@
 package gocheck_test
 
 import (
+	"errors"
 	"launchpad.net/gocheck"
-	"os"
 	"reflect"
 	"runtime"
 )
 
-
 type CheckersS struct{}
 
 var _ = gocheck.Suite(&CheckersS{})
 
-
 func testInfo(c *gocheck.C, checker gocheck.Checker, name string, paramNames []string) {
 	info := checker.Info()
 	if info.Name != name {
@@ -25,6 +23,9 @@
 
 func testCheck(c *gocheck.C, checker gocheck.Checker, result bool, error string, params ...interface{}) ([]interface{}, []string) {
 	info := checker.Info()
+	if len(params) != len(info.Params) {
+		c.Fatalf("unexpected param count in test; expected %d got %d", len(info.Params), len(params))
+	}
 	names := append([]string{}, info.Params...)
 	result_, error_ := checker.Check(params, names)
 	if result_ != result || error_ != error {
@@ -34,39 +35,39 @@
 	return params, names
 }
 
-func (s *CheckersS) TestBug(c *gocheck.C) {
-	bug := gocheck.Bug("a %d bc", 42)
-	info := bug.GetBugInfo()
-	if info != "a 42 bc" {
-		c.Fatalf("Bug() returned %#v", info)
+func (s *CheckersS) TestComment(c *gocheck.C) {
+	bug := gocheck.Commentf("a %d bc", 42)
+	comment := bug.CheckCommentString()
+	if comment != "a 42 bc" {
+		c.Fatalf("Commentf returned %#v", comment)
 	}
 }
 
 func (s *CheckersS) TestIsNil(c *gocheck.C) {
 	testInfo(c, gocheck.IsNil, "IsNil", []string{"value"})
 
-	testCheck(c, gocheck.IsNil, true, "", nil, nil, true, "")
-	testCheck(c, gocheck.IsNil, false, "", "a", nil, false, "")
+	testCheck(c, gocheck.IsNil, true, "", nil)
+	testCheck(c, gocheck.IsNil, false, "", "a")
 
-	testCheck(c, gocheck.IsNil, true, "", (chan int)(nil), nil)
-	testCheck(c, gocheck.IsNil, false, "", make(chan int), nil)
-	testCheck(c, gocheck.IsNil, true, "", (os.Error)(nil), nil)
-	testCheck(c, gocheck.IsNil, false, "", os.NewError(""), nil)
-	testCheck(c, gocheck.IsNil, true, "", ([]int)(nil), nil)
-	testCheck(c, gocheck.IsNil, false, "", make([]int, 1), nil)
-	testCheck(c, gocheck.IsNil, false, "", int(0), nil)
+	testCheck(c, gocheck.IsNil, true, "", (chan int)(nil))
+	testCheck(c, gocheck.IsNil, false, "", make(chan int))
+	testCheck(c, gocheck.IsNil, true, "", (error)(nil))
+	testCheck(c, gocheck.IsNil, false, "", errors.New(""))
+	testCheck(c, gocheck.IsNil, true, "", ([]int)(nil))
+	testCheck(c, gocheck.IsNil, false, "", make([]int, 1))
+	testCheck(c, gocheck.IsNil, false, "", int(0))
 }
 
 func (s *CheckersS) TestNotNil(c *gocheck.C) {
 	testInfo(c, gocheck.NotNil, "NotNil", []string{"value"})
 
-	testCheck(c, gocheck.NotNil, false, "", nil, nil)
-	testCheck(c, gocheck.NotNil, true, "", "a", nil)
+	testCheck(c, gocheck.NotNil, false, "", nil)
+	testCheck(c, gocheck.NotNil, true, "", "a")
 
 	testCheck(c, gocheck.NotNil, false, "", (chan int)(nil))
 	testCheck(c, gocheck.NotNil, true, "", make(chan int))
-	testCheck(c, gocheck.NotNil, false, "", (os.Error)(nil))
-	testCheck(c, gocheck.NotNil, true, "", os.NewError(""))
+	testCheck(c, gocheck.NotNil, false, "", (error)(nil))
+	testCheck(c, gocheck.NotNil, true, "", errors.New(""))
 	testCheck(c, gocheck.NotNil, false, "", ([]int)(nil))
 	testCheck(c, gocheck.NotNil, true, "", make([]int, 1))
 }
@@ -78,7 +79,6 @@
 	testCheck(c, gocheck.Not(gocheck.IsNil), true, "", "a")
 }
 
-
 type simpleStruct struct {
 	i int
 }
@@ -96,19 +96,69 @@
 	// With nil.
 	testCheck(c, gocheck.Equals, false, "", 42, nil)
 
-	// Arrays
-	testCheck(c, gocheck.Equals, true, "", []byte{1, 2}, []byte{1, 2})
-	testCheck(c, gocheck.Equals, false, "", []byte{1, 2}, []byte{1, 3})
+	// Slices
+	testCheck(c, gocheck.Equals, false, "runtime error: comparing uncomparable type []uint8", []byte{1, 2}, []byte{1, 2})
 
 	// Struct values
 	testCheck(c, gocheck.Equals, true, "", simpleStruct{1}, simpleStruct{1})
 	testCheck(c, gocheck.Equals, false, "", simpleStruct{1}, simpleStruct{2})
 
 	// Struct pointers
-	testCheck(c, gocheck.Equals, true, "", &simpleStruct{1}, &simpleStruct{1})
+	testCheck(c, gocheck.Equals, false, "", &simpleStruct{1}, &simpleStruct{1})
 	testCheck(c, gocheck.Equals, false, "", &simpleStruct{1}, &simpleStruct{2})
 }
 
+func (s *CheckersS) TestDeepEquals(c *gocheck.C) {
+	testInfo(c, gocheck.DeepEquals, "DeepEquals", []string{"obtained", "expected"})
+
+	// The simplest.
+	testCheck(c, gocheck.DeepEquals, true, "", 42, 42)
+	testCheck(c, gocheck.DeepEquals, false, "", 42, 43)
+
+	// Different native types.
+	testCheck(c, gocheck.DeepEquals, false, "", int32(42), int64(42))
+
+	// With nil.
+	testCheck(c, gocheck.DeepEquals, false, "", 42, nil)
+
+	// Slices
+	testCheck(c, gocheck.DeepEquals, true, "", []byte{1, 2}, []byte{1, 2})
+	testCheck(c, gocheck.DeepEquals, false, "", []byte{1, 2}, []byte{1, 3})
+
+	// Struct values
+	testCheck(c, gocheck.DeepEquals, true, "", simpleStruct{1}, simpleStruct{1})
+	testCheck(c, gocheck.DeepEquals, false, "", simpleStruct{1}, simpleStruct{2})
+
+	// Struct pointers
+	testCheck(c, gocheck.DeepEquals, true, "", &simpleStruct{1}, &simpleStruct{1})
+	testCheck(c, gocheck.DeepEquals, false, "", &simpleStruct{1}, &simpleStruct{2})
+}
+
+func (s *CheckersS) TestHasLen(c *gocheck.C) {
+	testInfo(c, gocheck.HasLen, "HasLen", []string{"obtained", "n"})
+
+	testCheck(c, gocheck.HasLen, true, "", "abcd", 4)
+	testCheck(c, gocheck.HasLen, true, "", []int{1, 2}, 2)
+	testCheck(c, gocheck.HasLen, false, "", []int{1, 2}, 3)
+
+	testCheck(c, gocheck.HasLen, false, "n must be an int", []int{1, 2}, "2")
+	testCheck(c, gocheck.HasLen, false, "obtained value type has no length", nil, 2)
+}
+
+func (s *CheckersS) TestErrorMatches(c *gocheck.C) {
+	testInfo(c, gocheck.ErrorMatches, "ErrorMatches", []string{"value", "regex"})
+
+	testCheck(c, gocheck.ErrorMatches, false, "Error value is nil", nil, "some error")
+	testCheck(c, gocheck.ErrorMatches, false, "Value is not an error", 1, "some error")
+	testCheck(c, gocheck.ErrorMatches, true, "", errors.New("some error"), "some error")
+	testCheck(c, gocheck.ErrorMatches, true, "", errors.New("some error"), "so.*or")
+
+	// Verify params mutation
+	params, names := testCheck(c, gocheck.ErrorMatches, false, "", errors.New("some error"), "other error")
+	c.Assert(params[0], gocheck.Equals, "some error")
+	c.Assert(names[0], gocheck.Equals, "error")
+}
+
 func (s *CheckersS) TestMatches(c *gocheck.C) {
 	testInfo(c, gocheck.Matches, "Matches", []string{"value", "regex"})
 
@@ -121,38 +171,67 @@
 	testCheck(c, gocheck.Matches, false, "", "abc", "bc")
 
 	// String()-enabled values accepted
-	testCheck(c, gocheck.Matches, true, "", os.NewError("abc"), "a.c")
-	testCheck(c, gocheck.Matches, false, "", os.NewError("abc"), "a.d")
+	testCheck(c, gocheck.Matches, true, "", reflect.ValueOf("abc"), "a.c")
+	testCheck(c, gocheck.Matches, false, "", reflect.ValueOf("abc"), "a.d")
 
 	// Some error conditions.
 	testCheck(c, gocheck.Matches, false, "Obtained value is not a string and has no .String()", 1, "a.c")
-	testCheck(c, gocheck.Matches, false, "Can't compile regex: regexp: unmatched '['", "abc", "a[c")
+	testCheck(c, gocheck.Matches, false, "Can't compile regex: error parsing regexp: missing closing ]: `[c$`", "abc", "a[c")
 }
 
 func (s *CheckersS) TestPanics(c *gocheck.C) {
 	testInfo(c, gocheck.Panics, "Panics", []string{"function", "expected"})
 
-	// Plain strings.
-	testCheck(c, gocheck.Panics, true, "", func() { panic("BOOM") }, "BOOM", true, "")
-	testCheck(c, gocheck.Panics, false, "", func() { panic("KABOOM") }, "BOOM", false, "")
-	testCheck(c, gocheck.Panics, true, "", func() bool { panic("BOOM") }, "BOOM", true, "")
-
-	// Error values.
-	testCheck(c, gocheck.Panics, true, "", func() { panic(os.NewError("BOOM")) }, os.NewError("BOOM"), true, "")
-	testCheck(c, gocheck.Panics, false, "", func() { panic(os.NewError("KABOOM")) }, os.NewError("BOOM"), false, "")
-
-	// String matching.
-	testCheck(c, gocheck.Panics, true, "", func() { panic(os.NewError("BOOM")) }, "BO.M", true, "")
-	testCheck(c, gocheck.Panics, false, "", func() { panic(os.NewError("KABOOM")) }, "BO.M", false, "")
-
 	// Some errors.
 	testCheck(c, gocheck.Panics, false, "Function has not panicked", func() bool { return false }, "BOOM")
 	testCheck(c, gocheck.Panics, false, "Function must take zero arguments", 1, "BOOM")
 
+	// Plain strings.
+	testCheck(c, gocheck.Panics, true, "", func() { panic("BOOM") }, "BOOM")
+	testCheck(c, gocheck.Panics, false, "", func() { panic("KABOOM") }, "BOOM")
+	testCheck(c, gocheck.Panics, true, "", func() bool { panic("BOOM") }, "BOOM")
+
+	// Error values.
+	testCheck(c, gocheck.Panics, true, "", func() { panic(errors.New("BOOM")) }, errors.New("BOOM"))
+	testCheck(c, gocheck.Panics, false, "", func() { panic(errors.New("KABOOM")) }, errors.New("BOOM"))
+
+	type deep struct{ i int }
+	// Deep value
+	testCheck(c, gocheck.Panics, true, "", func() { panic(&deep{99}) }, &deep{99})
+
 	// Verify params/names mutation
-	params, names := testCheck(c, gocheck.Panics, false, "", func() { panic(os.NewError("KABOOM")) }, os.NewError("BOOM"), false, "")
-	c.Assert(params[0], gocheck.Equals, os.NewError("KABOOM"))
+	params, names := testCheck(c, gocheck.Panics, false, "", func() { panic(errors.New("KABOOM")) }, errors.New("BOOM"))
+	c.Assert(params[0], gocheck.ErrorMatches, "KABOOM")
 	c.Assert(names[0], gocheck.Equals, "panic")
+
+	// Verify a nil panic
+	testCheck(c, gocheck.Panics, true, "", func() { panic(nil) }, nil)
+	testCheck(c, gocheck.Panics, false, "", func() { panic(nil) }, "NOPE")
+}
+
+func (s *CheckersS) TestPanicMatches(c *gocheck.C) {
+	testInfo(c, gocheck.PanicMatches, "PanicMatches", []string{"function", "expected"})
+
+	// Error matching.
+	testCheck(c, gocheck.PanicMatches, true, "", func() { panic(errors.New("BOOM")) }, "BO.M")
+	testCheck(c, gocheck.PanicMatches, false, "", func() { panic(errors.New("KABOOM")) }, "BO.M")
+
+	// Some errors.
+	testCheck(c, gocheck.PanicMatches, false, "Function has not panicked", func() bool { return false }, "BOOM")
+	testCheck(c, gocheck.PanicMatches, false, "Function must take zero arguments", 1, "BOOM")
+
+	// Plain strings.
+	testCheck(c, gocheck.PanicMatches, true, "", func() { panic("BOOM") }, "BO.M")
+	testCheck(c, gocheck.PanicMatches, false, "", func() { panic("KABOOM") }, "BOOM")
+	testCheck(c, gocheck.PanicMatches, true, "", func() bool { panic("BOOM") }, "BO.M")
+
+	// Verify params/names mutation
+	params, names := testCheck(c, gocheck.PanicMatches, false, "", func() { panic(errors.New("KABOOM")) }, "BOOM")
+	c.Assert(params[0], gocheck.Equals, "KABOOM")
+	c.Assert(names[0], gocheck.Equals, "panic")
+
+	// Verify a nil panic
+	testCheck(c, gocheck.PanicMatches, false, "Panic value is not a string or an error", func() { panic(nil) }, "")
 }
 
 func (s *CheckersS) TestFitsTypeOf(c *gocheck.C) {
@@ -163,9 +242,9 @@
 	testCheck(c, gocheck.FitsTypeOf, false, "", 1, int64(0))
 
 	// Aliases
-	testCheck(c, gocheck.FitsTypeOf, false, "", 1, os.NewError(""))
-	testCheck(c, gocheck.FitsTypeOf, false, "", "error", os.NewError(""))
-	testCheck(c, gocheck.FitsTypeOf, true, "", os.NewError("error"), os.NewError(""))
+	testCheck(c, gocheck.FitsTypeOf, false, "", 1, errors.New(""))
+	testCheck(c, gocheck.FitsTypeOf, false, "", "error", errors.New(""))
+	testCheck(c, gocheck.FitsTypeOf, true, "", errors.New("error"), errors.New(""))
 
 	// Structures
 	testCheck(c, gocheck.FitsTypeOf, false, "", 1, simpleStruct{})
@@ -181,13 +260,13 @@
 func (s *CheckersS) TestImplements(c *gocheck.C) {
 	testInfo(c, gocheck.Implements, "Implements", []string{"obtained", "ifaceptr"})
 
-	var e os.Error
+	var e error
 	var re runtime.Error
-	testCheck(c, gocheck.Implements, true, "", os.NewError(""), &e)
-	testCheck(c, gocheck.Implements, false, "", os.NewError(""), &re)
+	testCheck(c, gocheck.Implements, true, "", errors.New(""), &e)
+	testCheck(c, gocheck.Implements, false, "", errors.New(""), &re)
 
 	// Some bad values
-	testCheck(c, gocheck.Implements, false, "ifaceptr should be a pointer to an interface variable", 0, os.NewError(""))
+	testCheck(c, gocheck.Implements, false, "ifaceptr should be a pointer to an interface variable", 0, errors.New(""))
 	testCheck(c, gocheck.Implements, false, "ifaceptr should be a pointer to an interface variable", 0, interface{}(nil))
 	testCheck(c, gocheck.Implements, false, "", interface{}(nil), &e)
 }
diff --git a/export_test.go b/export_test.go
index affc6d7..ad29621 100644
--- a/export_test.go
+++ b/export_test.go
@@ -1,10 +1,6 @@
 package gocheck
 
-import (
-	"os"
-)
-
-func PrintLine(filename string, line int) (string, os.Error) {
+func PrintLine(filename string, line int) (string, error) {
 	return printLine(filename, line)
 }
 
diff --git a/fixture_test.go b/fixture_test.go
index 4d124bb..cd66118 100644
--- a/fixture_test.go
+++ b/fixture_test.go
@@ -2,12 +2,10 @@
 
 package gocheck_test
 
-
 import (
 	. "launchpad.net/gocheck"
 )
 
-
 // -----------------------------------------------------------------------
 // Fixture test suite.
 
@@ -19,7 +17,6 @@
 	suitesRun += 1
 }
 
-
 // -----------------------------------------------------------------------
 // Basic fixture ordering verification.
 
@@ -37,7 +34,6 @@
 	c.Check(helper.n, Equals, 8)
 }
 
-
 // -----------------------------------------------------------------------
 // Check the behavior when panics occur within tests and fixtures.
 
@@ -59,7 +55,7 @@
 		"PANIC: gocheck_test\\.go:[0-9]+: FixtureHelper.Test1\n\n" +
 		"\\.\\.\\. Panic: Test1 \\(PC=[xA-F0-9]+\\)\n\n" +
 		".+:[0-9]+\n" +
-		"  in runtime.panic\n" +
+		"  in panic\n" +
 		".*gocheck_test.go:[0-9]+\n" +
 		"  in FixtureHelper.trace\n" +
 		".*gocheck_test.go:[0-9]+\n" +
@@ -83,7 +79,7 @@
 		"FixtureHelper\\.SetUpTest\n\n" +
 		"\\.\\.\\. Panic: SetUpTest \\(PC=[xA-F0-9]+\\)\n\n" +
 		".+:[0-9]+\n" +
-		"  in runtime.panic\n" +
+		"  in panic\n" +
 		".*gocheck_test.go:[0-9]+\n" +
 		"  in FixtureHelper.trace\n" +
 		".*gocheck_test.go:[0-9]+\n" +
@@ -113,7 +109,7 @@
 		"FixtureHelper.TearDownTest\n\n" +
 		"\\.\\.\\. Panic: TearDownTest \\(PC=[xA-F0-9]+\\)\n\n" +
 		".+:[0-9]+\n" +
-		"  in runtime.panic\n" +
+		"  in panic\n" +
 		".*gocheck_test.go:[0-9]+\n" +
 		"  in FixtureHelper.trace\n" +
 		".*gocheck_test.go:[0-9]+\n" +
@@ -140,7 +136,7 @@
 		"FixtureHelper.SetUpSuite\n\n" +
 		"\\.\\.\\. Panic: SetUpSuite \\(PC=[xA-F0-9]+\\)\n\n" +
 		".+:[0-9]+\n" +
-		"  in runtime.panic\n" +
+		"  in panic\n" +
 		".*gocheck_test.go:[0-9]+\n" +
 		"  in FixtureHelper.trace\n" +
 		".*gocheck_test.go:[0-9]+\n" +
@@ -168,7 +164,7 @@
 		"FixtureHelper.TearDownSuite\n\n" +
 		"\\.\\.\\. Panic: TearDownSuite \\(PC=[xA-F0-9]+\\)\n\n" +
 		".+:[0-9]+\n" +
-		"  in runtime.panic\n" +
+		"  in panic\n" +
 		".*gocheck_test.go:[0-9]+\n" +
 		"  in FixtureHelper.trace\n" +
 		".*gocheck_test.go:[0-9]+\n" +
@@ -177,7 +173,6 @@
 	c.Check(output.value, Matches, expected)
 }
 
-
 // -----------------------------------------------------------------------
 // A wrong argument on a test or fixture will produce a nice error.
 
@@ -235,7 +230,6 @@
 	c.Check(output.value, Matches, expected)
 }
 
-
 // -----------------------------------------------------------------------
 // Nice errors also when tests or fixture have wrong arg count.
 
@@ -293,7 +287,6 @@
 	c.Check(output.value, Matches, expected)
 }
 
-
 // -----------------------------------------------------------------------
 // Helper test suites with wrong function arguments.
 
@@ -339,7 +332,6 @@
 func (s *WrongSetUpSuiteArgCountHelper) SetUpSuite(c *C, i int) {
 }
 
-
 // -----------------------------------------------------------------------
 // Ensure fixture doesn't run without tests.
 
@@ -362,7 +354,6 @@
 	c.Check(helper.hasRun, Equals, false)
 }
 
-
 // -----------------------------------------------------------------------
 // Verify that checks and assertions work correctly inside the fixture.
 
@@ -425,7 +416,6 @@
 	c.Assert(helper.completed, Equals, false)
 }
 
-
 // -----------------------------------------------------------------------
 // Verify that logging within SetUpTest() persists within the test log itself.
 
@@ -460,7 +450,6 @@
 			"1\n2\n3\n4\n5\n")
 }
 
-
 // -----------------------------------------------------------------------
 // Skip() within fixture methods.
 
diff --git a/foundation_test.go b/foundation_test.go
index b5152af..d59b99e 100644
--- a/foundation_test.go
+++ b/foundation_test.go
@@ -11,9 +11,10 @@
 	"strings"
 	"regexp"
 	"fmt"
+	"log"
+	"os"
 )
 
-
 // -----------------------------------------------------------------------
 // Foundation test suite.
 
@@ -150,7 +151,6 @@
 	c.Log("Fatalf() didn't stop the test")
 }
 
-
 func (s *FoundationS) TestCallerLoggingInsideTest(c *gocheck.C) {
 	log := fmt.Sprintf(""+
 		"foundation_test.go:%d:\n"+
@@ -242,7 +242,7 @@
 
 	expected := "" +
 		"FAIL EXPECTED: foundation_test\\.go:[0-9]+:" +
-		" ExpectFailureSucceedHelper\\.TestSucceed \\(It booms!\\)\n"
+		" ExpectFailureSucceedHelper\\.TestSucceed \\(It booms!\\)\t *[.0-9]+s\n"
 
 	matched, err := regexp.MatchString(expected, output.value)
 	if err != nil {
@@ -254,7 +254,6 @@
 	c.Assert(result.ExpectedFailures, gocheck.Equals, 1)
 }
 
-
 // -----------------------------------------------------------------------
 // Skip() allows stopping a test without positive/negative results.
 
@@ -291,6 +290,28 @@
 }
 
 // -----------------------------------------------------------------------
+// Check minimum *log.Logger interface provided by *gocheck.C.
+
+type minLogger interface {
+	Output(calldepth int, s string) error
+}
+
+func (s *BootstrapS) TestMinLogger(c *gocheck.C) {
+	var logger minLogger
+	logger = log.New(os.Stderr, "", 0)
+	logger = c
+	logger.Output(0, "Hello there")
+	expected := "\\[LOG\\] [.0-9]+ Hello there\n"
+	output := c.GetTestLog()
+	matched, err := regexp.MatchString(expected, output)
+	if err != nil {
+		c.Error("Bad expression: ", expected)
+	} else if !matched {
+		c.Error("Output() didn't log properly:\n", output)
+	}
+}
+
+// -----------------------------------------------------------------------
 // Ensure that suites with embedded types are working fine, including the
 // the workaround for issue 906.
 
@@ -314,8 +335,6 @@
 
 func (s *EmbeddedS) TestMethod(c *gocheck.C) {
 	// http://code.google.com/p/go/issues/detail?id=906
-	c.Check(s.called, gocheck.Equals, false,
-		gocheck.Bug("The bug described in issue 906 is "+
-			"affecting the runner"))
+	c.Check(s.called, gocheck.Equals, false) // Go issue 906 is affecting the runner?
 	s.called = true
 }
diff --git a/gocheck.go b/gocheck.go
index 0e69156..e26e7cb 100644
--- a/gocheck.go
+++ b/gocheck.go
@@ -2,27 +2,28 @@
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
 	"io"
+	"math/rand"
 	"os"
 	"path"
-	"rand"
+	"path/filepath"
 	"reflect"
 	"regexp"
 	"runtime"
 	"strconv"
 	"strings"
 	"sync"
+	"time"
 )
 
-
 // -----------------------------------------------------------------------
 // Internal type which deals with suite method calling.
 
 const (
 	fixtureKd = iota
 	testKd
-	benchmarkKd
 )
 
 type funcKind int
@@ -62,20 +63,13 @@
 	reason   string
 	mustFail bool
 	tempDir  *tempDir
-}
-
-func newC(method *methodType, kind funcKind, logb *bytes.Buffer, logw io.Writer, tempDir *tempDir) *C {
-	if logb == nil {
-		logb = bytes.NewBuffer(nil)
-	}
-	return &C{method: method, kind: kind, logb: logb, logw: logw, tempDir: tempDir, done: make(chan *C, 1)}
+	timer
 }
 
 func (c *C) stopNow() {
 	runtime.Goexit()
 }
 
-
 // -----------------------------------------------------------------------
 // Handling of temporary files and directories.
 
@@ -89,7 +83,7 @@
 	td.Lock()
 	defer td.Unlock()
 	if td._path == "" {
-		var err os.Error
+		var err error
 		for i := 0; i != 100; i++ {
 			path := fmt.Sprintf("%s/gocheck-%d", os.TempDir(), rand.Int())
 			if err = os.Mkdir(path, 0700); err == nil {
@@ -98,7 +92,7 @@
 			}
 		}
 		if td._path == "" {
-			panic("Couldn't create temporary directory: " + err.String())
+			panic("Couldn't create temporary directory: " + err.Error())
 		}
 	}
 	result := path.Join(td._path, strconv.Itoa(td._counter))
@@ -112,7 +106,7 @@
 	if td._path != "" {
 		err := os.RemoveAll(td._path)
 		if err != nil {
-			println("WARNING: Error cleaning up temporaries: " + err.String())
+			fmt.Fprintf(os.Stderr, "WARNING: Error cleaning up temporaries: "+err.Error())
 		}
 	}
 }
@@ -122,61 +116,98 @@
 func (c *C) MkDir() string {
 	path := c.tempDir.newPath()
 	if err := os.Mkdir(path, 0700); err != nil {
-		panic(fmt.Sprintf("Couldn't create temporary directory %s: %s", path, err.String()))
+		panic(fmt.Sprintf("Couldn't create temporary directory %s: %s", path, err.Error()))
 	}
 	return path
 }
 
-
 // -----------------------------------------------------------------------
 // Low-level logging functions.
 
 func (c *C) log(args ...interface{}) {
-	c.writeLog(fmt.Sprint(args...) + "\n")
+	c.writeLog([]byte(fmt.Sprint(args...) + "\n"))
 }
 
 func (c *C) logf(format string, args ...interface{}) {
-	c.writeLog(fmt.Sprintf(format+"\n", args...))
+	c.writeLog([]byte(fmt.Sprintf(format+"\n", args...)))
 }
 
 func (c *C) logNewLine() {
-	c.writeLog("\n")
+	c.writeLog([]byte{'\n'})
 }
 
-func (c *C) writeLog(content string) {
-	contentb := []byte(content)
-	c.logb.Write(contentb)
+func (c *C) writeLog(buf []byte) {
+	c.logb.Write(buf)
 	if c.logw != nil {
-		c.logw.Write(contentb)
+		c.logw.Write(buf)
 	}
 }
 
-type hasString interface {
-	String() string
+func hasStringOrError(x interface{}) (ok bool) {
+	_, ok = x.(fmt.Stringer)
+	if ok {
+		return
+	}
+	_, ok = x.(error)
+	return
 }
 
 func (c *C) logValue(label string, value interface{}) {
 	if label == "" {
-		if v, ok := value.(hasString); ok {
-			c.logf("... %#v (%q)", value, v.String())
+		if hasStringOrError(value) {
+			c.logf("... %#v (%q)", value, value)
 		} else {
 			c.logf("... %#v", value)
 		}
 	} else if value == nil {
 		c.logf("... %s = nil", label)
 	} else {
-		if v, ok := value.(hasString); ok {
+		if hasStringOrError(value) {
 			fv := fmt.Sprintf("%#v", value)
-			qv := fmt.Sprintf("%q", v.String())
+			qv := fmt.Sprintf("%q", value)
 			if fv != qv {
-				c.logf("... %s %s = %s (%s)", label, reflect.TypeOf(value).String(), fv, qv)
+				c.logf("... %s %s = %s (%s)", label, reflect.TypeOf(value), fv, qv)
 				return
 			}
 		}
-		c.logf("... %s %s = %#v", label, reflect.TypeOf(value).String(), value)
+		if s, ok := value.(string); ok && isMultiLine(s) {
+			c.logf(`... %s %s = "" +`, label, reflect.TypeOf(value))
+			c.logMultiLine(s)
+		} else {
+			c.logf("... %s %s = %#v", label, reflect.TypeOf(value), value)
+		}
 	}
 }
 
+func (c *C) logMultiLine(s string) {
+	b := make([]byte, 0, len(s)*2)
+	i := 0
+	n := len(s)
+	for i < n {
+		j := i + 1
+		for j < n && s[j-1] != '\n' {
+			j++
+		}
+		b = append(b, "...     "...)
+		b = strconv.AppendQuote(b, s[i:j])
+		if j < n {
+			b = append(b, " +"...)
+		}
+		b = append(b, '\n')
+		i = j
+	}
+	c.writeLog(b)
+}
+
+func isMultiLine(s string) bool {
+	for i := 0; i+1 < len(s); i++ {
+		if s[i] == '\n' {
+			return true
+		}
+	}
+	return false
+}
+
 func (c *C) logString(issue string) {
 	c.log("... ", issue)
 }
@@ -219,12 +250,14 @@
 	if code == "" {
 		code = "..." // XXX Open the file and take the raw line.
 		if err != nil {
-			code += err.String()
+			code += err.Error()
 		}
 	}
 	c.log(indent(code, "    "))
 }
 
+var valueGo = filepath.Join("reflect", "value.go")
+
 func (c *C) logPanic(skip int, value interface{}) {
 	skip += 1 // Our own frame.
 	initialSkip := skip
@@ -234,7 +267,8 @@
 				c.logf("... Panic: %s (PC=0x%X)\n", value, pc)
 			}
 			name := niceFuncName(pc)
-			if name == "reflect.internalValue.call" || name == "gocheck.forkTest" {
+			path := nicePath(file)
+			if name == "Value.call" && strings.HasSuffix(path, valueGo) {
 				break
 			}
 			c.logf("%s:%d\n  in %s", nicePath(file), line, name)
@@ -254,7 +288,6 @@
 		niceFuncName(method.PC()), expectedType)
 }
 
-
 // -----------------------------------------------------------------------
 // Some simple formatting helpers.
 
@@ -288,21 +321,25 @@
 	function := runtime.FuncForPC(pc)
 	if function != nil {
 		name := path.Base(function.Name())
-		if strings.HasPrefix(name, "_xtest_.*") {
-			name = name[9:]
+		if i := strings.Index(name, "."); i > 0 {
+			name = name[i+1:]
+		}
+		if strings.HasPrefix(name, "(*") {
+			if i := strings.Index(name, ")"); i > 0 {
+				name = name[2:i] + name[i+1:]
+			}
 		}
 		if i := strings.LastIndex(name, ".*"); i != -1 {
-			name = name[0:i] + "." + name[i+2:]
+			name = name[:i] + "." + name[i+2:]
 		}
 		if i := strings.LastIndex(name, "·"); i != -1 {
-			name = name[0:i] + "." + name[i+2:]
+			name = name[:i] + "." + name[i+2:]
 		}
 		return name
 	}
 	return "<unknown function>"
 }
 
-
 // -----------------------------------------------------------------------
 // Result tracker to aggregate call results.
 
@@ -313,8 +350,8 @@
 	Panicked         int
 	FixturePanicked  int
 	ExpectedFailures int
-	Missed           int      // Not even tried to run, related to a panic in the fixture.
-	RunError         os.Error // Houston, we've got a problem.
+	Missed           int   // Not even tried to run, related to a panic in the fixture.
+	RunError         error // Houston, we've got a problem.
 }
 
 type resultTracker struct {
@@ -403,7 +440,6 @@
 	}
 }
 
-
 // -----------------------------------------------------------------------
 // The underlying suite runner.
 
@@ -416,48 +452,52 @@
 	tempDir                   *tempDir
 	output                    *outputWriter
 	reportedProblemLast       bool
+	benchTime                 time.Duration
 }
 
 type RunConf struct {
-	Output  io.Writer
-	Stream  bool
-	Verbose bool
-	Filter  string
+	Output        io.Writer
+	Stream        bool
+	Verbose       bool
+	Filter        string
+	Benchmark     bool
+	BenchmarkTime time.Duration // Defaults to 1 second
 }
 
 // Create a new suiteRunner able to run all methods in the given suite.
 func newSuiteRunner(suite interface{}, runConf *RunConf) *suiteRunner {
-	var writer io.Writer
-	var stream, verbose bool
-	var filter string
-
-	writer = os.Stdout
-
+	var conf RunConf
 	if runConf != nil {
-		if runConf.Output != nil {
-			writer = runConf.Output
-		}
-		stream = runConf.Stream
-		verbose = runConf.Verbose
-		filter = runConf.Filter
+		conf = *runConf
+	}
+	if conf.Output == nil {
+		conf.Output = os.Stdout
+	}
+	if conf.Benchmark {
+		conf.Verbose = true
 	}
 
 	suiteType := reflect.TypeOf(suite)
 	suiteNumMethods := suiteType.NumMethod()
 	suiteValue := reflect.ValueOf(suite)
 
-	runner := &suiteRunner{suite: suite,
-		output:  newOutputWriter(writer, stream, verbose),
-		tracker: newResultTracker()}
-	runner.tests = make([]*methodType, suiteNumMethods)
+	runner := &suiteRunner{
+		suite:     suite,
+		output:    newOutputWriter(conf.Output, conf.Stream, conf.Verbose),
+		tracker:   newResultTracker(),
+		benchTime: conf.BenchmarkTime,
+	}
+	runner.tests = make([]*methodType, 0, suiteNumMethods)
 	runner.tempDir = new(tempDir)
-	testsLen := 0
+	if runner.benchTime == 0 {
+		runner.benchTime = 1 * time.Second
+	}
 
 	var filterRegexp *regexp.Regexp
-	if filter != "" {
-		if regexp, err := regexp.Compile(filter); err != nil {
-			msg := "Bad filter expression: " + err.String()
-			runner.tracker.result.RunError = os.NewError(msg)
+	if conf.Filter != "" {
+		if regexp, err := regexp.Compile(conf.Filter); err != nil {
+			msg := "Bad filter expression: " + err.Error()
+			runner.tracker.result.RunError = errors.New(msg)
 			return runner
 		} else {
 			filterRegexp = regexp
@@ -492,31 +532,33 @@
 		case "TearDownTest":
 			runner.tearDownTest = method
 		default:
-			if isWantedTest(suiteName, method.Info.Name, filterRegexp) {
-				runner.tests[testsLen] = method
-				testsLen += 1
+			if isWanted(conf.Benchmark, suiteName, method.Info.Name, filterRegexp) {
+				runner.tests = append(runner.tests, method)
 			}
 		}
 	}
-
-	runner.tests = runner.tests[0:testsLen]
 	return runner
 }
 
-// Return true if the given suite name and method name should be
-// considered as a test to be run.
-func isWantedTest(suiteName, testName string, filterRegexp *regexp.Regexp) bool {
-	if !strings.HasPrefix(testName, "Test") {
+// isWanted returns true if the given suite and method names should be run.
+// The bench result indicates whether the method is a benchmark rather than
+// a test.
+func isWanted(benchmark bool, suiteName, methodName string, filterRegexp *regexp.Regexp) bool {
+	prefix := "Test"
+	if benchmark {
+		prefix = "Benchmark"
+	}
+	if !strings.HasPrefix(methodName, prefix) {
 		return false
-	} else if filterRegexp == nil {
+	}
+	if filterRegexp == nil {
 		return true
 	}
-	return (filterRegexp.MatchString(testName) ||
+	return (filterRegexp.MatchString(methodName) ||
 		filterRegexp.MatchString(suiteName) ||
-		filterRegexp.MatchString(suiteName+"."+testName))
+		filterRegexp.MatchString(suiteName+"."+methodName))
 }
 
-
 // Run all methods in the given suite.
 func (runner *suiteRunner) run() *Result {
 	if runner.tracker.result.RunError == nil && len(runner.tests) > 0 {
@@ -546,7 +588,6 @@
 	return &runner.tracker.result
 }
 
-
 // Create a call object with the given suite method, and fork a
 // goroutine with the provided dispatcher for running it.
 func (runner *suiteRunner) forkCall(method *methodType, kind funcKind, logb *bytes.Buffer, dispatcher func(c *C)) *C {
@@ -554,7 +595,18 @@
 	if runner.output.Stream {
 		logw = runner.output
 	}
-	c := newC(method, kind, logb, logw, runner.tempDir)
+	if logb == nil {
+		logb = bytes.NewBuffer(nil)
+	}
+	c := &C{
+		method:  method,
+		kind:    kind,
+		logb:    logb,
+		logw:    logw,
+		tempDir: runner.tempDir,
+		done:    make(chan *C, 1),
+		timer:   timer{benchTime: runner.benchTime},
+	}
 	runner.tracker.expectCall(c)
 	go (func() {
 		runner.reportCallStarted(c)
@@ -611,6 +663,9 @@
 func (runner *suiteRunner) runFixture(method *methodType, logb *bytes.Buffer) *C {
 	if method != nil {
 		c := runner.runFunc(method, fixtureKd, logb, func(c *C) {
+			c.ResetTimer()
+			c.StartTimer()
+			defer c.StopTimer()
 			c.method.Call([]reflect.Value{reflect.ValueOf(c)})
 		})
 		return c
@@ -646,14 +701,25 @@
 		defer runner.runFixtureWithPanic(runner.tearDownTest, nil, &skipped)
 		runner.runFixtureWithPanic(runner.setUpTest, c.logb, &skipped)
 		mt := c.method.Type()
-		if mt.NumIn() == 1 && mt.In(0) == reflect.TypeOf(c) {
-			c.method.Call([]reflect.Value{reflect.ValueOf(c)})
-		} else {
+		if mt.NumIn() != 1 || mt.In(0) != reflect.TypeOf(c) {
 			// Rather than a plain panic, provide a more helpful message when
 			// the argument type is incorrect.
 			c.status = panickedSt
 			c.logArgPanic(c.method, "*gocheck.C")
+			return
 		}
+		if strings.HasPrefix(c.method.Info.Name, "Test") {
+			c.ResetTimer()
+			c.StartTimer()
+			defer c.StopTimer()
+			c.method.Call([]reflect.Value{reflect.ValueOf(c)})
+			return
+		}
+		if strings.HasPrefix(c.method.Info.Name, "Benchmark") {
+			benchmark(c)
+			return
+		}
+		panic("unexpected method prefix: " + c.method.Info.Name)
 	})
 }
 
@@ -725,7 +791,6 @@
 	}
 }
 
-
 // -----------------------------------------------------------------------
 // Output writer manages atomic output writing according to settings.
 
@@ -741,7 +806,7 @@
 	return &outputWriter{writer: writer, Stream: stream, Verbose: verbose}
 }
 
-func (ow *outputWriter) Write(content []byte) (n int, err os.Error) {
+func (ow *outputWriter) Write(content []byte) (n int, err error) {
 	ow.m.Lock()
 	n, err = ow.writer.Write(content)
 	ow.m.Unlock()
@@ -775,10 +840,14 @@
 
 func (ow *outputWriter) WriteCallSuccess(label string, c *C) {
 	if ow.Stream || (ow.Verbose && c.kind == testKd) {
+		// TODO Use a buffer here.
 		var suffix string
 		if c.reason != "" {
 			suffix = " (" + c.reason + ")"
 		}
+		if c.status == succeededSt {
+			suffix += "\t" + c.timerString()
+		}
 		suffix += "\n"
 		if ow.Stream {
 			suffix += "\n"
diff --git a/gocheck_test.go b/gocheck_test.go
index 479a835..e4bf4d4 100644
--- a/gocheck_test.go
+++ b/gocheck_test.go
@@ -3,7 +3,6 @@
 
 package gocheck_test
 
-
 import (
 	"launchpad.net/gocheck"
 	"testing"
@@ -12,13 +11,13 @@
 	"flag"
 	"fmt"
 	"os"
+	"time"
 )
 
-
 // We count the number of suites run at least to get a vague hint that the
 // test suite is behaving as it should.  Otherwise a bug introduced at the
 // very core of the system could go unperceived.
-const suitesRunExpected = 7
+const suitesRunExpected = 8
 
 var suitesRun int = 0
 
@@ -30,7 +29,6 @@
 	}
 }
 
-
 // -----------------------------------------------------------------------
 // Helper functions.
 
@@ -41,7 +39,6 @@
 	os.Exit(1)
 }
 
-
 // Return the file line where it's called.
 func getMyLine() int {
 	if _, _, line, ok := runtime.Caller(1); ok {
@@ -50,7 +47,6 @@
 	return -1
 }
 
-
 // -----------------------------------------------------------------------
 // Helper type implementing a basic io.Writer for testing output.
 
@@ -61,7 +57,7 @@
 
 // The only function required by the io.Writer interface.  Will append
 // written data to the String.value string.
-func (s *String) Write(p []byte) (n int, err os.Error) {
+func (s *String) Write(p []byte) (n int, err error) {
 	s.value += string(p)
 	return len(p), nil
 }
@@ -72,7 +68,6 @@
 	return c.Check(obtained, gocheck.Equals, expected), getMyLine()
 }
 
-
 // -----------------------------------------------------------------------
 // Helper suite for testing basic fail behavior.
 
@@ -86,7 +81,6 @@
 	c.Fail()
 }
 
-
 // -----------------------------------------------------------------------
 // Helper suite for testing basic success behavior.
 
@@ -96,16 +90,18 @@
 	c.Log("Expected success!")
 }
 
-
 // -----------------------------------------------------------------------
 // Helper suite for testing ordering and behavior of fixture.
 
 type FixtureHelper struct {
-	calls   [64]string
-	n       int
-	panicOn string
-	skip    bool
-	skipOnN int
+	calls    [64]string
+	n        int
+	panicOn  string
+	skip     bool
+	skipOnN  int
+	sleepOn  string
+	sleep    time.Duration
+	bytes    int64
 }
 
 func (s *FixtureHelper) trace(name string, c *gocheck.C) {
@@ -115,6 +111,9 @@
 	if name == s.panicOn {
 		panic(name)
 	}
+	if s.sleep > 0 && s.sleepOn == name {
+		time.Sleep(s.sleep)
+	}
 	if s.skip && s.skipOnN == n {
 		c.Skip("skipOnN == n")
 	}
@@ -144,6 +143,20 @@
 	s.trace("Test2", c)
 }
 
+func (s *FixtureHelper) Benchmark1(c *gocheck.C) {
+	s.trace("Benchmark1", c)
+	for i := 0; i < c.N; i++ {
+		time.Sleep(s.sleep)
+	}
+}
+
+func (s *FixtureHelper) Benchmark2(c *gocheck.C) {
+	s.trace("Benchmark2", c)
+	c.SetBytes(1024)
+	for i := 0; i < c.N; i++ {
+		time.Sleep(s.sleep)
+	}
+}
 
 // -----------------------------------------------------------------------
 // Helper which checks the state of the test and ensures that it matches
@@ -169,7 +182,7 @@
 		c.Errorf("Error in matching expression used in testing %s",
 			expected.name)
 	} else if !matched {
-		c.Errorf("%s logged %#v which doesn't match %#v",
+		c.Errorf("%s logged:\n----------\n%s----------\n\nExpected:\n----------\n%s\n----------",
 			expected.name, log, expected.log)
 	}
 	if result != expected.result {
diff --git a/helpers.go b/helpers.go
index d81b4a7..fe4ca51 100644
--- a/helpers.go
+++ b/helpers.go
@@ -1,12 +1,11 @@
 package gocheck
 
-
 import (
 	"fmt"
 	"strings"
+	"time"
 )
 
-
 // -----------------------------------------------------------------------
 // Basic succeeding/failing logic.
 
@@ -70,7 +69,6 @@
 	c.stopNow()
 }
 
-
 // -----------------------------------------------------------------------
 // Basic logging.
 
@@ -91,6 +89,15 @@
 	c.logf(format, args...)
 }
 
+// Output enables *C to be used as a logger in functions that require only
+// the minimum interface of *log.Logger.
+func (c *C) Output(calldepth int, s string) error {
+	ns := time.Now().Sub(time.Time{}).Nanoseconds()
+	t := float64(ns%100e9) / 1e9
+	c.Logf("[LOG] %.05f %s", t, s)
+	return nil
+}
+
 // Log an error into the test error output, and mark the test as failed.
 // The provided arguments will be assembled together into a string using
 // fmt.Sprint().
@@ -131,7 +138,6 @@
 	c.FailNow()
 }
 
-
 // -----------------------------------------------------------------------
 // Generic checks and assertions based on checkers.
 
@@ -170,10 +176,10 @@
 	}
 
 	// If the last argument is a bug info, extract it out.
-	var bug BugInfo
+	var comment CommentInterface
 	if len(args) > 0 {
-		if gotBug, hasBug := args[len(args)-1].(BugInfo); hasBug {
-			bug = gotBug
+		if c, ok := args[len(args)-1].(CommentInterface); ok {
+			comment = c
 			args = args[:len(args)-1]
 		}
 	}
@@ -201,8 +207,8 @@
 		for i := 0; i != len(params); i++ {
 			c.logValue(names[i], params[i])
 		}
-		if bug != nil {
-			c.logString(bug.GetBugInfo())
+		if comment != nil {
+			c.logString(comment.CheckCommentString())
 		}
 		if error != "" {
 			c.logString(error)
diff --git a/helpers_test.go b/helpers_test.go
index 7d4fe29..0469426 100644
--- a/helpers_test.go
+++ b/helpers_test.go
@@ -9,7 +9,6 @@
 	"reflect"
 )
 
-
 var helpersS = gocheck.Suite(&HelpersS{})
 
 type HelpersS struct{}
@@ -18,16 +17,15 @@
 	suitesRun += 1
 }
 
-
 // -----------------------------------------------------------------------
 // Fake checker and bug info to verify the behavior of Assert() and Check().
 
 type MyChecker struct {
-	info *gocheck.CheckerInfo
+	info   *gocheck.CheckerInfo
 	params []interface{}
-	names []string
+	names  []string
 	result bool
-	error string
+	error  string
 }
 
 func (checker *MyChecker) Info() *gocheck.CheckerInfo {
@@ -51,20 +49,16 @@
 	return checker.result, checker.error
 }
 
+type myCommentType string
 
-type myBugInfo struct {
-	info string
+func (c myCommentType) CheckCommentString() string {
+	return string(c)
 }
 
-func (bug *myBugInfo) GetBugInfo() string {
-	return bug.info
+func myComment(s string) myCommentType {
+	return myCommentType(s)
 }
 
-func myBug(info string) *myBugInfo {
-	return &myBugInfo{info}
-}
-
-
 // -----------------------------------------------------------------------
 // Ensure a real checker actually works fine.
 
@@ -74,7 +68,6 @@
 	})
 }
 
-
 // -----------------------------------------------------------------------
 // Tests for Check(), mostly the same as for Assert() following these.
 
@@ -100,7 +93,7 @@
 
 func (s *HelpersS) TestCheckFailWithExpected(c *gocheck.C) {
 	checker := &MyChecker{result: false}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    return c\\.Check\\(1, checker, 2\\)\n" +
 		"\\.+ myobtained int = 1\n" +
 		"\\.+ myexpected int = 2\n\n"
@@ -110,22 +103,36 @@
 		})
 }
 
-func (s *HelpersS) TestCheckFailWithExpectedAndBugInfo(c *gocheck.C) {
+func (s *HelpersS) TestCheckFailWithExpectedAndComment(c *gocheck.C) {
 	checker := &MyChecker{result: false}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
-		"    return c\\.Check\\(1, checker, 2, myBug\\(\"Hello world!\"\\)\\)\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+		"    return c\\.Check\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" +
 		"\\.+ myobtained int = 1\n" +
 		"\\.+ myexpected int = 2\n" +
 		"\\.+ Hello world!\n\n"
 	testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log,
 		func() interface{} {
-			return c.Check(1, checker, 2, myBug("Hello world!"))
+			return c.Check(1, checker, 2, myComment("Hello world!"))
+		})
+}
+
+func (s *HelpersS) TestCheckFailWithExpectedAndStaticComment(c *gocheck.C) {
+	checker := &MyChecker{result: false}
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+		"    // Nice leading comment\\.\n" +
+		"    return c\\.Check\\(1, checker, 2\\) // Hello there\n" +
+		"\\.+ myobtained int = 1\n" +
+		"\\.+ myexpected int = 2\n\n"
+	testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log,
+		func() interface{} {
+			// Nice leading comment.
+			return c.Check(1, checker, 2)  // Hello there
 		})
 }
 
 func (s *HelpersS) TestCheckFailWithoutExpected(c *gocheck.C) {
 	checker := &MyChecker{result: false, info: &gocheck.CheckerInfo{Params: []string{"myvalue"}}}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    return c\\.Check\\(1, checker\\)\n" +
 		"\\.+ myvalue int = 1\n\n"
 	testHelperFailure(c, "Check(1, checker)", false, false, log,
@@ -136,19 +143,19 @@
 
 func (s *HelpersS) TestCheckFailWithoutExpectedAndMessage(c *gocheck.C) {
 	checker := &MyChecker{result: false, info: &gocheck.CheckerInfo{Params: []string{"myvalue"}}}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
-		"    return c\\.Check\\(1, checker, myBug\\(\"Hello world!\"\\)\\)\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+		"    return c\\.Check\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" +
 		"\\.+ myvalue int = 1\n" +
 		"\\.+ Hello world!\n\n"
 	testHelperFailure(c, "Check(1, checker, msg)", false, false, log,
 		func() interface{} {
-			return c.Check(1, checker, myBug("Hello world!"))
+			return c.Check(1, checker, myComment("Hello world!"))
 		})
 }
 
 func (s *HelpersS) TestCheckWithMissingExpected(c *gocheck.C) {
 	checker := &MyChecker{result: true}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    return c\\.Check\\(1, checker\\)\n" +
 		"\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" +
 		"\\.+ Wrong number of parameters for MyChecker: " +
@@ -161,7 +168,7 @@
 
 func (s *HelpersS) TestCheckWithTooManyExpected(c *gocheck.C) {
 	checker := &MyChecker{result: true}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    return c\\.Check\\(1, checker, 2, 3\\)\n" +
 		"\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" +
 		"\\.+ Wrong number of parameters for MyChecker: " +
@@ -174,7 +181,7 @@
 
 func (s *HelpersS) TestCheckWithError(c *gocheck.C) {
 	checker := &MyChecker{result: false, error: "Some not so cool data provided!"}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    return c\\.Check\\(1, checker, 2\\)\n" +
 		"\\.+ myobtained int = 1\n" +
 		"\\.+ myexpected int = 2\n" +
@@ -186,7 +193,7 @@
 }
 
 func (s *HelpersS) TestCheckWithNilChecker(c *gocheck.C) {
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    return c\\.Check\\(1, nil\\)\n" +
 		"\\.+ Check\\(obtained, nil!\\?, \\.\\.\\.\\):\n" +
 		"\\.+ Oops\\.\\. you've provided a nil checker!\n\n"
@@ -198,7 +205,7 @@
 
 func (s *HelpersS) TestCheckWithParamsAndNamesMutation(c *gocheck.C) {
 	checker := &MyChecker{result: false, params: []interface{}{3, 4}, names: []string{"newobtained", "newexpected"}}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    return c\\.Check\\(1, checker, 2\\)\n" +
 		"\\.+ newobtained int = 3\n" +
 		"\\.+ newexpected int = 4\n\n"
@@ -208,7 +215,6 @@
 		})
 }
 
-
 // -----------------------------------------------------------------------
 // Tests for Assert(), mostly the same as for Check() above.
 
@@ -236,7 +242,7 @@
 
 func (s *HelpersS) TestAssertFailWithExpected(c *gocheck.C) {
 	checker := &MyChecker{result: false}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    c\\.Assert\\(1, checker, 2\\)\n" +
 		"\\.+ myobtained int = 1\n" +
 		"\\.+ myexpected int = 2\n\n"
@@ -249,21 +255,21 @@
 
 func (s *HelpersS) TestAssertFailWithExpectedAndMessage(c *gocheck.C) {
 	checker := &MyChecker{result: false}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
-		"    c\\.Assert\\(1, checker, 2, myBug\\(\"Hello world!\"\\)\\)\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+		"    c\\.Assert\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" +
 		"\\.+ myobtained int = 1\n" +
 		"\\.+ myexpected int = 2\n" +
 		"\\.+ Hello world!\n\n"
 	testHelperFailure(c, "Assert(1, checker, 2, msg)", nil, true, log,
 		func() interface{} {
-			c.Assert(1, checker, 2, myBug("Hello world!"))
+			c.Assert(1, checker, 2, myComment("Hello world!"))
 			return nil
 		})
 }
 
 func (s *HelpersS) TestAssertFailWithoutExpected(c *gocheck.C) {
 	checker := &MyChecker{result: false, info: &gocheck.CheckerInfo{Params: []string{"myvalue"}}}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    c\\.Assert\\(1, checker\\)\n" +
 		"\\.+ myvalue int = 1\n\n"
 	testHelperFailure(c, "Assert(1, checker)", nil, true, log,
@@ -275,20 +281,20 @@
 
 func (s *HelpersS) TestAssertFailWithoutExpectedAndMessage(c *gocheck.C) {
 	checker := &MyChecker{result: false, info: &gocheck.CheckerInfo{Params: []string{"myvalue"}}}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
-		"    c\\.Assert\\(1, checker, myBug\\(\"Hello world!\"\\)\\)\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+		"    c\\.Assert\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" +
 		"\\.+ myvalue int = 1\n" +
 		"\\.+ Hello world!\n\n"
 	testHelperFailure(c, "Assert(1, checker, msg)", nil, true, log,
 		func() interface{} {
-			c.Assert(1, checker, myBug("Hello world!"))
+			c.Assert(1, checker, myComment("Hello world!"))
 			return nil
 		})
 }
 
 func (s *HelpersS) TestAssertWithMissingExpected(c *gocheck.C) {
 	checker := &MyChecker{result: true}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    c\\.Assert\\(1, checker\\)\n" +
 		"\\.+ Assert\\(myobtained, MyChecker, myexpected\\):\n" +
 		"\\.+ Wrong number of parameters for MyChecker: " +
@@ -302,7 +308,7 @@
 
 func (s *HelpersS) TestAssertWithError(c *gocheck.C) {
 	checker := &MyChecker{result: false, error: "Some not so cool data provided!"}
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    c\\.Assert\\(1, checker, 2\\)\n" +
 		"\\.+ myobtained int = 1\n" +
 		"\\.+ myexpected int = 2\n" +
@@ -315,7 +321,7 @@
 }
 
 func (s *HelpersS) TestAssertWithNilChecker(c *gocheck.C) {
-	log := "helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
 		"    c\\.Assert\\(1, nil\\)\n" +
 		"\\.+ Assert\\(obtained, nil!\\?, \\.\\.\\.\\):\n" +
 		"\\.+ Oops\\.\\. you've provided a nil checker!\n\n"
@@ -326,13 +332,12 @@
 		})
 }
 
-
 // -----------------------------------------------------------------------
 // Ensure that values logged work properly in some interesting cases.
 
 func (s *HelpersS) TestValueLoggingWithArrays(c *gocheck.C) {
 	checker := &MyChecker{result: false}
-	log := "helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
+	log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
 		"    return c\\.Check\\(\\[\\]byte{1, 2}, checker, \\[\\]byte{1, 3}\\)\n" +
 		"\\.+ myobtained \\[\\]uint8 = \\[\\]byte{0x1, 0x2}\n" +
 		"\\.+ myexpected \\[\\]uint8 = \\[\\]byte{0x1, 0x3}\n\n"
@@ -342,6 +347,38 @@
 		})
 }
 
+func (s *HelpersS) TestValueLoggingWithMultiLine(c *gocheck.C) {
+	checker := &MyChecker{result: false}
+	log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
+		"    return c\\.Check\\(\"a\\\\nb\\\\n\", checker, \"a\\\\nb\\\\nc\"\\)\n" +
+		"\\.+ myobtained string = \"\" \\+\n" +
+		"\\.+     \"a\\\\n\" \\+\n" +
+		"\\.+     \"b\\\\n\"\n" +
+		"\\.+ myexpected string = \"\" \\+\n" +
+		"\\.+     \"a\\\\n\" \\+\n" +
+		"\\.+     \"b\\\\n\" \\+\n" +
+		"\\.+     \"c\"\n\n"
+	testHelperFailure(c, `Check("a\nb\n", chk, "a\nb\nc")`, false, false, log,
+		func() interface{} {
+			return c.Check("a\nb\n", checker, "a\nb\nc")
+		})
+}
+
+func (s *HelpersS) TestValueLoggingWithMultiLineException(c *gocheck.C) {
+	// If the newline is at the end of the string, don't log as multi-line.
+	checker := &MyChecker{result: false}
+	log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
+		"    return c\\.Check\\(\"a b\\\\n\", checker, \"a\\\\nb\"\\)\n" +
+		"\\.+ myobtained string = \"a b\\\\n\"\n" +
+		"\\.+ myexpected string = \"\" \\+\n" +
+		"\\.+     \"a\\\\n\" \\+\n" +
+		"\\.+     \"b\"\n\n"
+	testHelperFailure(c, `Check("a b\n", chk, "a\nb")`, false, false, log,
+		func() interface{} {
+			return c.Check("a b\n", checker, "a\nb")
+		})
+}
+
 
 // -----------------------------------------------------------------------
 // MakeDir() tests.
@@ -370,7 +407,6 @@
 	s.isDir4 = isDir(s.path2)
 }
 
-
 func (s *HelpersS) TestMkDir(c *gocheck.C) {
 	helper := MkDirHelper{}
 	output := String{}
@@ -388,12 +424,11 @@
 
 func isDir(path string) bool {
 	if stat, err := os.Stat(path); err == nil {
-		return stat.IsDirectory()
+		return stat.IsDir()
 	}
 	return false
 }
 
-
 // -----------------------------------------------------------------------
 // A couple of helper functions to test helper functions. :-)
 
diff --git a/printer.go b/printer.go
index e260494..103ab14 100644
--- a/printer.go
+++ b/printer.go
@@ -4,8 +4,8 @@
 	"bytes"
 	"go/ast"
 	"go/parser"
-	"go/token"
 	"go/printer"
+	"go/token"
 	"os"
 )
 
@@ -26,25 +26,32 @@
 	return s
 }
 
-func printLine(filename string, line int) (string, os.Error) {
+func printLine(filename string, line int) (string, error) {
 	fset := token.NewFileSet()
 	file, err := os.Open(filename)
 	if err != nil {
 		return "", err
 	}
-	fnode, err := parser.ParseFile(fset, filename, file, 0)
+	fnode, err := parser.ParseFile(fset, filename, file, parser.ParseComments)
 	if err != nil {
 		return "", err
 	}
 	config := &printer.Config{Mode: printer.UseSpaces, Tabwidth: 4}
-	lp := &linePrinter{fset: fset, line: line, config: config}
+	lp := &linePrinter{fset: fset, fnode: fnode, line: line, config: config}
 	ast.Walk(lp, fnode)
-	return lp.output.String(), nil
+	result := lp.output.Bytes()
+	// Comments leave \n at the end.
+	n := len(result)
+	for n > 0 && result[n-1] == '\n' {
+		n--
+	}
+	return string(result[:n]), nil
 }
 
 type linePrinter struct {
 	config *printer.Config
 	fset   *token.FileSet
+	fnode  *ast.File
 	line   int
 	output bytes.Buffer
 	stmt   ast.Stmt
@@ -53,13 +60,36 @@
 func (lp *linePrinter) emit() bool {
 	if lp.stmt != nil {
 		lp.trim(lp.stmt)
-		lp.config.Fprint(&lp.output, lp.fset, lp.stmt)
+		lp.printWithComments(lp.stmt)
 		lp.stmt = nil
 		return true
 	}
 	return false
 }
 
+func (lp *linePrinter) printWithComments(n ast.Node) {
+	nfirst := lp.fset.Position(n.Pos()).Line
+	nlast := lp.fset.Position(n.End()).Line
+	for _, g := range lp.fnode.Comments {
+		cfirst := lp.fset.Position(g.Pos()).Line
+		clast := lp.fset.Position(g.End()).Line
+		if clast == nfirst-1 && lp.fset.Position(n.Pos()).Column == lp.fset.Position(g.Pos()).Column {
+			for _, c := range g.List {
+				lp.output.WriteString(c.Text)
+				lp.output.WriteByte('\n')
+			}
+		}
+		if cfirst >= nfirst && cfirst <= nlast && n.End() <= g.List[0].Slash {
+			// The printer will not include the comment if it starts past
+			// the node itself. Trick it into printing by overlapping the
+			// slash with the end of the statement.
+			g.List[0].Slash = n.End() - 1
+		}
+	}
+	node := &printer.CommentedNode{n, lp.fnode.Comments}
+	lp.config.Fprint(&lp.output, lp.fset, node)
+}
+
 func (lp *linePrinter) Visit(n ast.Node) (w ast.Visitor) {
 	if n == nil {
 		if lp.output.Len() == 0 {
diff --git a/printer_test.go b/printer_test.go
index abd55ea..547a92d 100644
--- a/printer_test.go
+++ b/printer_test.go
@@ -19,15 +19,15 @@
 }
 
 func printTestFunc() {
-    println(1)
-    if 2 == 2 {
-        println(3)
+    println(1)           // Comment1
+    if 2 == 2 {          // Comment2
+        println(3)       // Comment3
     }
     switch 5 {
-    case 6: println(6)
+    case 6: println(6)   // Comment6
         println(7)
     }
-    switch interface{}(9).(type) {
+    switch interface{}(9).(type) {// Comment9
     case int: println(10)
         println(11)
     }
@@ -45,19 +45,22 @@
     println(24, func() {
         println(25)
     })
+    // Leading comment
+    // with multiple lines.
+    println(29)  // Comment29
 }
 
 var printLineTests = []struct {
     line   int
     output string
 }{
-    {1, "println(1)"},
-    {2, "if 2 == 2 {\n    ...\n}"},
-    {3, "println(3)"},
+    {1, "println(1) // Comment1"},
+    {2, "if 2 == 2 { // Comment2\n    ...\n}"},
+    {3, "println(3) // Comment3"},
     {5, "switch 5 {\n...\n}"},
-    {6, "case 6:\n    println(6)\n    ..."},
+    {6, "case 6:\n    println(6) // Comment6\n    ..."},
     {7, "println(7)"},
-    {9, "switch interface{}(9).(type) {\n...\n}"},
+    {9, "switch interface{}(9).(type) { // Comment9\n...\n}"},
     {10, "case int:\n    println(10)\n    ..."},
     {14, "case <-(chan bool)(nil):\n    println(14)\n    ..."},
     {15, "println(15)"},
@@ -70,6 +73,7 @@
     {24, "println(24, func() {\n    println(25)\n})"},
     {25, "println(25)"},
     {26, "println(24, func() {\n    println(25)\n})"},
+    {29, "// Leading comment\n// with multiple lines.\nprintln(29) // Comment29"},
 }
 
 func (s *PrinterS) TestPrintLine(c *C) {
diff --git a/run.go b/run.go
index 74a0fee..6d6393c 100644
--- a/run.go
+++ b/run.go
@@ -1,9 +1,10 @@
 package gocheck
 
 import (
-	"testing"
 	"flag"
 	"fmt"
+	"testing"
+	"time"
 )
 
 // -----------------------------------------------------------------------
@@ -19,23 +20,29 @@
 	return suite
 }
 
-
 // -----------------------------------------------------------------------
 // Public running interface.
 
-var filterFlag = flag.String("gocheck.f", "",
-	"Regular expression selecting what to run")
-var verboseFlag = flag.Bool("gocheck.v", false,
-	"Verbose mode")
-var streamFlag = flag.Bool("gocheck.vv", false,
-	"Super verbose mode (disables output caching)")
-
+var (
+	filterFlag  = flag.String("gocheck.f", "", "Regular expression selecting what to run")
+	verboseFlag = flag.Bool("gocheck.v", false, "Verbose mode")
+	streamFlag  = flag.Bool("gocheck.vv", false, "Super verbose mode (disables output caching)")
+	benchFlag   = flag.Bool("gocheck.b", false, "Run benchmarks")
+	benchTime   = flag.Duration("gocheck.btime", 1 * time.Second, "approximate run time for each benchmark")
+)
 
 // Run all test suites registered with the Suite() function, printing
 // results to stdout, and reporting any failures back to the 'testing'
 // module.
 func TestingT(testingT *testing.T) {
-	result := RunAll(&RunConf{Filter: *filterFlag, Verbose: *verboseFlag, Stream: *streamFlag})
+	conf := &RunConf{
+		Filter:    *filterFlag,
+		Verbose:   *verboseFlag,
+		Stream:    *streamFlag,
+		Benchmark: *benchFlag,
+		BenchmarkTime: *benchTime,
+	}
+	result := RunAll(conf)
 	println(result.String())
 	if !result.Passed() {
 		testingT.Fail()
@@ -58,7 +65,6 @@
 	return runner.run()
 }
 
-
 // -----------------------------------------------------------------------
 // Result methods.
 
@@ -68,6 +74,7 @@
 	r.Failed += other.Failed
 	r.Panicked += other.Panicked
 	r.FixturePanicked += other.FixturePanicked
+	r.ExpectedFailures += other.ExpectedFailures
 	r.Missed += other.Missed
 }
 
@@ -79,7 +86,7 @@
 
 func (r *Result) String() string {
 	if r.RunError != nil {
-		return "ERROR: " + r.RunError.String()
+		return "ERROR: " + r.RunError.Error()
 	}
 
 	var value string
diff --git a/run_test.go b/run_test.go
index 462e3df..081d3af 100644
--- a/run_test.go
+++ b/run_test.go
@@ -3,12 +3,11 @@
 package gocheck_test
 
 import (
+	"errors"
 	. "launchpad.net/gocheck"
 	"sync"
-	"os"
 )
 
-
 var runnerS = Suite(&RunS{})
 
 type RunS struct{}
@@ -17,7 +16,6 @@
 	suitesRun += 1
 }
 
-
 // -----------------------------------------------------------------------
 // Tests ensuring result counting works properly.
 
@@ -96,25 +94,38 @@
 	c.Check(result.RunError, IsNil)
 }
 
-
 // -----------------------------------------------------------------------
 // Check result aggregation.
 
 func (s *RunS) TestAdd(c *C) {
-	result := &Result{Succeeded: 1, Skipped: 2, Failed: 3, Panicked: 4,
-		FixturePanicked: 5, Missed: 6}
-	result.Add(&Result{Succeeded: 10, Skipped: 20, Failed: 30,
-		Panicked: 40, FixturePanicked: 50, Missed: 60})
+	result := &Result{
+		Succeeded: 1,
+		Skipped: 2,
+		Failed: 3,
+		Panicked: 4,
+		FixturePanicked: 5,
+		Missed: 6,
+		ExpectedFailures: 7,
+	}
+	result.Add(&Result{
+		Succeeded: 10,
+		Skipped: 20,
+		Failed: 30,
+		Panicked: 40,
+		FixturePanicked: 50,
+		Missed: 60,
+		ExpectedFailures: 70,
+	})
 	c.Check(result.Succeeded, Equals, 11)
 	c.Check(result.Skipped, Equals, 22)
 	c.Check(result.Failed, Equals, 33)
 	c.Check(result.Panicked, Equals, 44)
 	c.Check(result.FixturePanicked, Equals, 55)
 	c.Check(result.Missed, Equals, 66)
+	c.Check(result.ExpectedFailures, Equals, 77)
 	c.Check(result.RunError, IsNil)
 }
 
-
 // -----------------------------------------------------------------------
 // Check the Passed() method.
 
@@ -126,7 +137,7 @@
 	c.Assert((&Result{Panicked: 1}).Passed(), Equals, false)
 	c.Assert((&Result{FixturePanicked: 1}).Passed(), Equals, false)
 	c.Assert((&Result{Missed: 1}).Passed(), Equals, false)
-	c.Assert((&Result{RunError: os.NewError("!")}).Passed(), Equals, false)
+	c.Assert((&Result{RunError: errors.New("!")}).Passed(), Equals, false)
 }
 
 // -----------------------------------------------------------------------
@@ -177,11 +188,10 @@
 
 func (s *RunS) TestPrintRunError(c *C) {
 	result := &Result{Succeeded: 1, Failed: 1,
-		RunError: os.NewError("Kaboom!")}
+		RunError: errors.New("Kaboom!")}
 	c.Check(result.String(), Equals, "ERROR: Kaboom!")
 }
 
-
 // -----------------------------------------------------------------------
 // Verify that the method pattern flag works correctly.
 
@@ -265,11 +275,10 @@
 	runConf := RunConf{Output: &output, Filter: "]["}
 	result := Run(&helper, &runConf)
 	c.Check(result.String(), Equals,
-		"ERROR: Bad filter expression: regexp: unmatched ']'")
+		"ERROR: Bad filter expression: error parsing regexp: missing closing ]: `[`")
 	c.Check(helper.n, Equals, 0)
 }
 
-
 // -----------------------------------------------------------------------
 // Verify that verbose mode prints tests which pass as well. 
 
@@ -279,8 +288,8 @@
 	runConf := RunConf{Output: &output, Verbose: true}
 	Run(&helper, &runConf)
 
-	expected := "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test1\n" +
-		"PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test2\n"
+	expected := "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test1\t *[.0-9]+s\n" +
+		"PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n"
 
 	c.Assert(output.value, Matches, expected)
 }
@@ -291,13 +300,12 @@
 	runConf := RunConf{Output: &output, Verbose: true}
 	Run(&helper, &runConf)
 
-	expected := ".*PANIC.*\n-+\n" + // Should have an extra line.
-		"PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test2\n"
+	expected := "(?s).*PANIC.*\n-+\n" + // Should have an extra line.
+		"PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n"
 
 	c.Assert(output.value, Matches, expected)
 }
 
-
 // -----------------------------------------------------------------------
 // Verify the stream output mode.  In this mode there's no output caching.
 
@@ -329,7 +337,6 @@
 	c.Log("4")
 }
 
-
 func (s *RunS) TestStreamMode(c *C) {
 	helper := &StreamHelper{}
 	output := String{}
@@ -337,9 +344,9 @@
 	Run(helper, &runConf)
 
 	expected := "START: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\n0\n" +
-		"PASS: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\n\n" +
+		"PASS: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\t *[.0-9]+s\n\n" +
 		"START: run_test\\.go:[0-9]+: StreamHelper\\.Test1\n1\n" +
-		"PASS: run_test\\.go:[0-9]+: StreamHelper\\.Test1\n\n" +
+		"PASS: run_test\\.go:[0-9]+: StreamHelper\\.Test1\t *[.0-9]+s\n\n" +
 		"START: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n2\n3\n4\n" +
 		"FAIL: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n\n"