v23tests: use concrete rather than interface types.
MultiPart: 1/3

It's very convenient to be able to embed testing.T and
expect.Session in the v23tests.T type. We were doing this
using interfaces which was attractive because we envisaged being
able to substitute different implementations at some point in
the future. However, embedding in this way results in an autogenerated
stack frame which shows up as <autogenerated>:<some random line no>
when t.Logf, t.Errorf are called. The alternative of wrapping these
functions (i.e. have v23tests.T wrap testing.T.Errorf) can't be used
because the implementation of testing.T assumes a fixed call depth
of 3. This problem occurs if the concrete type (with the embedded
testing.T, expect.Session) that implements the interface type is
passed to a function that expects the interface as a parameter, hence
using structs instead of interfaces allows for embedding and correct
file, line number recording. We opt to lose the abstraction and
burden the v23tests.T implementor with having to deal with alternate
implementations in the future in order to give the test writer the
convenience of correct line number logging and embedded which leads
to a more concise API.

Change-Id: Icc3227434e61157e1b6208d643ab3535e71b86ae
diff --git a/lib/testutil/v23tests/internal/cached_test.go b/lib/testutil/v23tests/internal/cached_test.go
index 792a4c2..688ba64 100644
--- a/lib/testutil/v23tests/internal/cached_test.go
+++ b/lib/testutil/v23tests/internal/cached_test.go
@@ -30,7 +30,7 @@
 
 // build build's a binary and appends it's modtime to the
 // global slice modTimes
-func build(i v23tests.T) {
+func build(i *v23tests.T) {
 	nsBin := i.BuildGoPkg("v.io/core/veyron/tools/namespace")
 	fi, err := os.Stat(nsBin.Path())
 	if err != nil {
@@ -49,7 +49,7 @@
 
 // checkTimes returns true if modTimes has at least one value
 // and the values are all the same.
-func checkTimes(i v23tests.T) bool {
+func checkTimes(i *v23tests.T) bool {
 	_, file, line, _ := runtime.Caller(1)
 	loc := fmt.Sprintf("%s:%d", filepath.Dir(file), line)
 	if len(modTimes) == 0 {
@@ -65,22 +65,22 @@
 	return true
 }
 
-func V23TestOne(i v23tests.T) {
+func V23TestOne(i *v23tests.T) {
 	build(i)
 	checkTimes(i)
 }
 
-func V23TestTwo(i v23tests.T) {
+func V23TestTwo(i *v23tests.T) {
 	build(i)
 	checkTimes(i)
 }
 
-func V23TestThree(i v23tests.T) {
+func V23TestThree(i *v23tests.T) {
 	build(i)
 	checkTimes(i)
 }
 
-func V23TestFour(i v23tests.T) {
+func V23TestFour(i *v23tests.T) {
 	build(i)
 	checkTimes(i)
 }
diff --git a/lib/testutil/v23tests/v23tests.go b/lib/testutil/v23tests/v23tests.go
index b1d392b..137d4b2 100644
--- a/lib/testutil/v23tests/v23tests.go
+++ b/lib/testutil/v23tests/v23tests.go
@@ -30,7 +30,7 @@
 // details and options. In short, any function in an external
 // (i.e. <pgk>_test) test package of the following form:
 //
-// V23Test<x>(t integration.T)
+// V23Test<x>(t *v23tests.T)
 //
 // will be invoked as integration test if the --v23.tests flag is used.
 //
@@ -83,6 +83,7 @@
 	"path/filepath"
 	"strings"
 	"syscall"
+	"testing"
 	"time"
 
 	"v.io/core/veyron2"
@@ -96,9 +97,6 @@
 	"v.io/core/veyron/security/agent"
 )
 
-// TODO(cnicolaou): need to enable running under the agent as per the old shell tests,
-// via the shell_test::enable_agent "$@" mechanism.
-//
 // TODO(sjr): make this thread safe.
 //
 // TODO(sjr): document all of the methods.
@@ -109,174 +107,11 @@
 // TODO(sjr): provide a utility function to retry an operation for a specific
 // time before failing. Useful for synchronising across process startups etc.
 //
-// Test represents the currently running test. In a local end-to-end test
-// environment obtained though New, this interface will be
-// typically be implemented by Go's standard testing.T.
-type Test interface {
-	Error(args ...interface{})
-	Errorf(format string, args ...interface{})
-	Fail()
-	FailNow()
-	Failed() bool
-	Fatal(args ...interface{})
-	Fatalf(format string, args ...interface{})
-	Log(args ...interface{})
-	Logf(format string, args ...interface{})
-	Skip(args ...interface{})
-	SkipNow()
-	Skipf(format string, args ...interface{})
-	Skipped() bool
-}
 
 // T represents an integration test environment.
-type T interface {
-	Test
-
-	// Cleanup cleans up the environment, deletes all its artifacts and
-	// kills all subprocesses. It will kill subprocesses in LIFO order.
-	// Cleanup checks to see if the test has failed and logs information
-	// as to the state of the processes it was asked to invoke up to that
-	// point and optionally, if the --v23.tests.shell-on-fail flag is set
-	// then it will run a debug shell before cleaning up its state.
-	Cleanup()
-
-	// BinaryFromPath returns a new TestBinary that, when started, will
-	// execute the executable or script at the given path.
-	//
-	// E.g. env.BinaryFromPath("/bin/bash").Start("-c", "echo hello world").Output() -> "hello world"
-	BinaryFromPath(path string) TestBinary
-
-	// BuildGoPkg expects a Go package path that identifies a "main"
-	// package and returns a TestBinary representing the newly built
-	// binary.
-	BuildGoPkg(path string) TestBinary
-
-	// Principal returns the security principal of this environment.
-	Principal() security.Principal
-
-	// DebugShell drops the user into a debug shell. If there is no
-	// controlling TTY, DebugShell will emit a warning message and take no
-	// futher action.
-	DebugShell()
-
-	// TempFile creates a temporary file. Temporary files will be deleted
-	// by Cleanup.
-	TempFile() *os.File
-
-	// TempDir creates a temporary directory. Temporary directories and
-	// their contents will be deleted by Cleanup.
-	TempDir() string
-
-	// SetVar sets the value to be associated with key.
-	SetVar(key, value string)
-
-	// GetVar returns the variable associated with the specified key
-	// and an indication of whether it is defined or not.
-	GetVar(key string) (string, bool)
-
-	// ClearVar removes the speficied variable from the Shell's environment
-	ClearVar(key string)
-}
-
-// TestBinary represents an executable program that will be executed during a
-// test. A binary may be invoked multiple times by calling Start, each call
-// will return a new Invocation.
-//
-// TestBinary instances are typically obtained from a T by calling BuildGoPkg
-// (for Vanadium and other Go binaries) or BinaryFromPath (to start binaries
-// that are already present on the system).
-type TestBinary interface {
-	// Start starts the given binary with the given arguments.
-	Start(args ...string) Invocation
-
-	// Path returns the path to the binary.
-	Path() string
-
-	// Returns a copy of this binary that, when Start is called, will use
-	// the given environment variables. Each environment variable should be
-	// in "key=value" form. For example:
-	//
-	// bin.WithEnv("EXAMPLE_ENV=/tmp/something").Start(...)
-	WithEnv(env ...string) TestBinary
-
-	// WithStdin returns a copy of this binary that, when Start is called,
-	// will read its input from the given reader. Once the reader returns
-	// EOF, the returned invocation's standard input will be closed (see
-	// Invocation.CloseStdin).
-	WithStdin(r io.Reader) TestBinary
-}
-
-// Session mirrors veyron/lib/expect is used to allow us to embed all of
-// expect.Session's methods in Invocation below.
-type Session interface {
-	Expect(expected string)
-	Expectf(format string, args ...interface{})
-	ExpectRE(pattern string, n int) [][]string
-	ExpectVar(name string) string
-	ExpectSetRE(expected ...string) [][]string
-	ExpectSetEventuallyRE(expected ...string) [][]string
-	ReadLine() string
-	ExpectEOF() error
-}
-
-// Invocation represents a single invocation of a TestBinary.
-//
-// Any bytes written by the invocation to its standard error may be recovered
-// using the Wait or WaitOrDie functions.
-//
-// For example:
-//   bin := env.BinaryFromPath("/bin/bash")
-//   inv := bin.Start("-c", "echo hello world 1>&2")
-//   var stderr bytes.Buffer
-//   inv.WaitOrDie(nil, &stderr)
-//   // stderr.Bytes() now contains 'hello world\n'
-type Invocation interface {
-	Session
-
-	Stdin() io.Writer
-
-	// CloseStdin closes the write-side of the pipe to the invocation's
-	// standard input.
-	CloseStdin()
-
-	Stdout() io.Reader
-
-	// Output reads the invocation's stdout until EOF and then returns what
-	// was read as a string.
-	Output() string
-
-	// Sends the given signal to this invocation. It is up to the test
-	// author to decide whether failure to deliver the signal is fatal to
-	// the test.
-	Kill(syscall.Signal) error
-
-	// Exists returns true if the invocation still exists.
-	Exists() bool
-
-	// Wait waits for this invocation to finish. If either stdout or stderr
-	// is non-nil, any remaining unread output from those sources will be
-	// written to the corresponding writer. The returned error represents
-	// the exit status of the underlying command.
-	Wait(stdout, stderr io.Writer) error
-
-	// Wait waits for this invocation to finish. If either stdout or stderr
-	// is non-nil, any remaining unread output from those sources will be
-	// written to the corresponding writer. If the underlying command
-	// exited with anything but success (exit status 0), this function will
-	// cause the current test to fail.
-	WaitOrDie(stdout, stderr io.Writer)
-
-	// Environment returns the instance of the test environment that this
-	// invocation was from.
-	Environment() T
-
-	// Path returns the path to the binary that was used for this invocation.
-	Path() string
-}
-
-type testEnvironment struct {
-	// The testing framework.
-	Test
+type T struct {
+	// The embedded testing.T
+	*testing.T
 
 	// The function to shutdown the context used to create the environment.
 	shutdown veyron2.Shutdown
@@ -287,19 +122,26 @@
 	// The environment's root security principal.
 	principal security.Principal
 
-	// Maps path to TestBinary.
-	builtBinaries map[string]*testBinary
+	// Maps path to Binary.
+	builtBinaries map[string]*Binary
 
 	tempFiles    []*os.File
 	tempDirs     []string
 	cachedBinDir string
 
-	invocations []*testBinaryInvocation
+	invocations []*Invocation
 }
 
-type testBinary struct {
+// Binary represents an executable program that will be executed during a
+// test. A binary may be invoked multiple times by calling Start, each call
+// will return a new Invocation.
+//
+// Binary instances are typically obtained from a T by calling BuildGoPkg
+// (for Vanadium and other Go binaries) or BinaryFromPath (to start binaries
+// that are already present on the system).
+type Binary struct {
 	// The environment to which this binary belongs.
-	env *testEnvironment
+	env *T
 
 	// The path to the binary.
 	path string
@@ -315,12 +157,22 @@
 	inputReader io.Reader
 }
 
-type testBinaryInvocation struct {
-	// The embedded Session
-	Session
+// Invocation represents a single invocation of a Binary.
+//
+// Any bytes written by the invocation to its standard error may be recovered
+// using the Wait or WaitOrDie functions.
+//
+// For example:
+//   bin := env.BinaryFromPath("/bin/bash")
+//   inv := bin.Start("-c", "echo hello world 1>&2")
+//   var stderr bytes.Buffer
+//   inv.WaitOrDie(nil, &stderr)
+//   // stderr.Bytes() now contains 'hello world\n'
+type Invocation struct {
+	*expect.Session
 
 	// The environment to which this invocation belongs.
-	env *testEnvironment
+	env *T
 
 	// The handle to the process that was run when this invocation was started.
 	handle modules.Handle
@@ -347,27 +199,36 @@
 
 var errNotShutdown = errors.New("has not been shutdown")
 
-func (i *testBinaryInvocation) Stdin() io.Writer {
+// Stdin returns this invocations Stdin stream.
+func (i *Invocation) Stdin() io.Writer {
 	return i.handle.Stdin()
 }
 
-func (i *testBinaryInvocation) CloseStdin() {
+// CloseStdin closes the write-side of the pipe to the invocation's
+// standard input.
+func (i *Invocation) CloseStdin() {
 	i.handle.CloseStdin()
 }
 
-func (i *testBinaryInvocation) Stdout() io.Reader {
+// Stdout returns this invocations Stdout stream.
+func (i *Invocation) Stdout() io.Reader {
 	return i.handle.Stdout()
 }
 
-func (i *testBinaryInvocation) Path() string {
+// Path returns the path to the binary that was used for this invocation.
+func (i *Invocation) Path() string {
 	return i.path
 }
 
-func (i *testBinaryInvocation) Exists() bool {
+// Exists returns true if the invocation still exists.
+func (i *Invocation) Exists() bool {
 	return syscall.Kill(i.handle.Pid(), 0) == nil
 }
 
-func (i *testBinaryInvocation) Kill(sig syscall.Signal) error {
+// Sends the given signal to this invocation. It is up to the test
+// author to decide whether failure to deliver the signal is fatal to
+// the test.
+func (i *Invocation) Kill(sig syscall.Signal) error {
 	// TODO(sjr): consider using vexec to manage subprocesses.
 	// TODO(sjr): if we use vexec, will want to tee stderr reliably to a file
 	// as well as a stderr stream, maintain an 'enviroment' here.
@@ -377,7 +238,7 @@
 	return syscall.Kill(pid, sig)
 }
 
-func readerToString(t Test, r io.Reader) string {
+func readerToString(t *T, r io.Reader) string {
 	buf := bytes.Buffer{}
 	_, err := buf.ReadFrom(r)
 	if err != nil {
@@ -386,28 +247,41 @@
 	return buf.String()
 }
 
-func (i *testBinaryInvocation) Output() string {
+// Output reads the invocation's stdout until EOF and then returns what
+// was read as a string.
+func (i *Invocation) Output() string {
 	return readerToString(i.env, i.Stdout())
 }
 
-func (i *testBinaryInvocation) Wait(stdout, stderr io.Writer) error {
+// Wait waits for this invocation to finish. If either stdout or stderr
+// is non-nil, any remaining unread output from those sources will be
+// written to the corresponding writer. The returned error represents
+// the exit status of the underlying command.
+func (i *Invocation) Wait(stdout, stderr io.Writer) error {
 	err := i.handle.Shutdown(stdout, stderr)
 	i.hasShutdown = true
 	i.shutdownErr = err
 	return err
 }
 
-func (i *testBinaryInvocation) WaitOrDie(stdout, stderr io.Writer) {
+// Wait waits for this invocation to finish. If either stdout or stderr
+// is non-nil, any remaining unread output from those sources will be
+// written to the corresponding writer. If the underlying command
+// exited with anything but success (exit status 0), this function will
+// cause the current test to fail.
+func (i *Invocation) WaitOrDie(stdout, stderr io.Writer) {
 	if err := i.Wait(stdout, stderr); err != nil {
 		i.env.Fatalf("FATAL: Wait() for pid %d failed: %v", i.handle.Pid(), err)
 	}
 }
 
-func (i *testBinaryInvocation) Environment() T {
+// Environment returns the instance of the test environment that this
+// invocation was from.
+func (i *Invocation) Environment() *T {
 	return i.env
 }
 
-func (b *testBinary) cleanup() {
+func (b *Binary) cleanup() {
 	binaryDir := path.Dir(b.path)
 	vlog.Infof("cleaning up %s", binaryDir)
 	if err := os.RemoveAll(binaryDir); err != nil {
@@ -415,11 +289,13 @@
 	}
 }
 
-func (b *testBinary) Path() string {
+// Path returns the path to the binary.
+func (b *Binary) Path() string {
 	return b.path
 }
 
-func (b *testBinary) Start(args ...string) Invocation {
+// Start starts the given binary with the given arguments.
+func (b *Binary) Start(args ...string) *Invocation {
 	depth := testutil.DepthToExternalCaller()
 	vlog.Infof(testutil.FormatLogLine(depth, "starting %s %s", b.Path(), strings.Join(args, " ")))
 	handle, err := b.env.shell.StartExternalCommand(b.envVars, append([]string{b.Path()}, args...)...)
@@ -427,7 +303,7 @@
 		b.env.Fatalf("StartExternalCommand(%v, %v) failed: %v", b.Path(), strings.Join(args, ", "), err)
 	}
 	vlog.Infof("started PID %d\n", handle.Pid())
-	inv := &testBinaryInvocation{
+	inv := &Invocation{
 		env:         b.env,
 		handle:      handle,
 		path:        b.path,
@@ -457,23 +333,39 @@
 	return inv
 }
 
-func (b *testBinary) WithStdin(r io.Reader) TestBinary {
+// WithStdin returns a copy of this binary that, when Start is called,
+// will read its input from the given reader. Once the reader returns
+// EOF, the returned invocation's standard input will be closed (see
+// Invocation.CloseStdin).
+func (b *Binary) WithStdin(r io.Reader) *Binary {
 	newBin := *b
 	newBin.inputReader = r
 	return &newBin
 }
 
-func (b *testBinary) WithEnv(env ...string) TestBinary {
+// Returns a copy of this binary that, when Start is called, will use
+// the given environment variables. Each environment variable should be
+// in "key=value" form. For example:
+//
+// bin.WithEnv("EXAMPLE_ENV=/tmp/something").Start(...)
+func (b *Binary) WithEnv(env ...string) *Binary {
 	newBin := *b
 	newBin.envVars = env
 	return &newBin
 }
 
-func (e *testEnvironment) Principal() security.Principal {
+// Principal returns the security principal of this environment.
+func (e *T) Principal() security.Principal {
 	return e.principal
 }
 
-func (e *testEnvironment) Cleanup() {
+// Cleanup cleans up the environment, deletes all its artifacts and
+// kills all subprocesses. It will kill subprocesses in LIFO order.
+// Cleanup checks to see if the test has failed and logs information
+// as to the state of the processes it was asked to invoke up to that
+// point and optionally, if the --v23.tests.shell-on-fail flag is set
+// then it will run a debug shell before cleaning up its state.
+func (e *T) Cleanup() {
 	if e.Failed() {
 		if testutil.IntegrationTestsDebugShellOnError {
 			e.DebugShell()
@@ -542,25 +434,32 @@
 	e.shutdown()
 }
 
-func (e *testEnvironment) GetVar(key string) (string, bool) {
+// GetVar returns the variable associated with the specified key
+// and an indication of whether it is defined or not.
+func (e *T) GetVar(key string) (string, bool) {
 	return e.shell.GetVar(key)
 }
 
-func (e *testEnvironment) SetVar(key, value string) {
+// SetVar sets the value to be associated with key.
+func (e *T) SetVar(key, value string) {
 	e.shell.SetVar(key, value)
 }
 
-func (e *testEnvironment) ClearVar(key string) {
+// ClearVar removes the speficied variable from the Shell's environment
+func (e *T) ClearVar(key string) {
 	e.shell.ClearVar(key)
 }
 
-func writeStringOrDie(t Test, f *os.File, s string) {
+func writeStringOrDie(t *T, f *os.File, s string) {
 	if _, err := f.WriteString(s); err != nil {
 		t.Fatalf("Write() failed: %v", err)
 	}
 }
 
-func (e *testEnvironment) DebugShell() {
+// DebugShell drops the user into a debug shell. If there is no
+// controlling TTY, DebugShell will emit a warning message and take no
+// futher action.
+func (e *T) DebugShell() {
 	// Get the current working directory.
 	cwd, err := os.Getwd()
 	if err != nil {
@@ -627,8 +526,12 @@
 	writeStringOrDie(e, file, fmt.Sprintf("<< Exited shell: %s\n", state.String()))
 }
 
-func (e *testEnvironment) BinaryFromPath(path string) TestBinary {
-	return &testBinary{
+// BinaryFromPath returns a new Binary that, when started, will
+// execute the executable or script at the given path.
+//
+// E.g. env.BinaryFromPath("/bin/bash").Start("-c", "echo hello world").Output() -> "hello world"
+func (e *T) BinaryFromPath(path string) *Binary {
+	return &Binary{
 		env:         e,
 		envVars:     nil,
 		path:        path,
@@ -636,7 +539,10 @@
 	}
 }
 
-func (e *testEnvironment) BuildGoPkg(binary_path string) TestBinary {
+// BuildGoPkg expects a Go package path that identifies a "main"
+// package and returns a Binary representing the newly built
+// binary.
+func (e *T) BuildGoPkg(binary_path string) *Binary {
 	then := time.Now()
 	cached, built_path, cleanup, err := buildPkg(e.cachedBinDir, binary_path)
 	if err != nil {
@@ -655,7 +561,7 @@
 		vlog.Infof("built %s, written to %s in %s.", binary_path, output_path, taken)
 	}
 
-	binary := &testBinary{
+	binary := &Binary{
 		env:         e,
 		envVars:     nil,
 		path:        output_path,
@@ -665,7 +571,9 @@
 	return binary
 }
 
-func (e *testEnvironment) TempFile() *os.File {
+// TempFile creates a temporary file. Temporary files will be deleted
+// by Cleanup.
+func (e *T) TempFile() *os.File {
 	f, err := ioutil.TempFile("", "")
 	if err != nil {
 		e.Fatalf("TempFile() failed: %v", err)
@@ -675,7 +583,9 @@
 	return f
 }
 
-func (e *testEnvironment) TempDir() string {
+// TempDir creates a temporary directory. Temporary directories and
+// their contents will be deleted by Cleanup.
+func (e *T) TempDir() string {
 	f, err := ioutil.TempDir("", "")
 	if err != nil {
 		e.Fatalf("TempDir() failed: %v", err)
@@ -685,7 +595,7 @@
 	return f
 }
 
-func (e *testEnvironment) appendInvocation(inv *testBinaryInvocation) {
+func (e *T) appendInvocation(inv *Invocation) {
 	e.invocations = append(e.invocations, inv)
 }
 
@@ -696,12 +606,12 @@
 // A typical end-to-end test will begin like:
 //
 //   func TestFoo(t *testing.T) {
-//     env := integration.NewTestEnvironment(t)
+//     env := integration.NewT(t)
 //     defer env.Cleanup()
 //
 //     ...
 //   }
-func New(t Test) T {
+func New(t *testing.T) *T {
 	ctx, shutdown := veyron2.Init()
 
 	vlog.Infof("creating root principal")
@@ -724,10 +634,10 @@
 	// environment variable is responsible for cleaning up the
 	// directory it points to.
 	cachedBinDir := os.Getenv("V23_BIN_DIR")
-	return &testEnvironment{
-		Test:          t,
+	return &T{
+		T:             t,
 		principal:     principal,
-		builtBinaries: make(map[string]*testBinary),
+		builtBinaries: make(map[string]*Binary),
 		shell:         shell,
 		tempFiles:     []*os.File{},
 		tempDirs:      []string{},
@@ -769,7 +679,7 @@
 }
 
 // RunTest runs a single Vanadium 'v23 style' integration test.
-func RunTest(t Test, fn func(i T)) {
+func RunTest(t *testing.T, fn func(i *T)) {
 	if !testutil.IntegrationTestsEnabled {
 		t.Skip()
 	}
@@ -783,14 +693,13 @@
 // RunRootMT builds and runs a root mount table instance. It populates
 // the NAMESPACE_ROOT variable in the test environment so that all subsequent
 // invocations will access this root mount table.
-func RunRootMT(t T, args ...string) (TestBinary, Invocation) {
-	b := t.BuildGoPkg("v.io/core/veyron/services/mounttable/mounttabled")
-	i := b.Start(args...)
-	s := expect.NewSession(t, i.Stdout(), time.Minute)
-	name := s.ExpectVar("NAME")
-	i.Environment().SetVar("NAMESPACE_ROOT", name)
+func RunRootMT(i *T, args ...string) (*Binary, *Invocation) {
+	b := i.BuildGoPkg("v.io/core/veyron/services/mounttable/mounttabled")
+	inv := b.Start(args...)
+	name := inv.ExpectVar("NAME")
+	inv.Environment().SetVar("NAMESPACE_ROOT", name)
 	vlog.Infof("Running root mount table: %q", name)
-	return b, i
+	return b, inv
 }
 
 // UseShardBinDir ensures that a shared directory is used for binaries
diff --git a/lib/testutil/v23tests/v23tests_test.go b/lib/testutil/v23tests/v23tests_test.go
index 8b58360..9546c05 100644
--- a/lib/testutil/v23tests/v23tests_test.go
+++ b/lib/testutil/v23tests/v23tests_test.go
@@ -84,7 +84,7 @@
 // to an instance of testing.T which we obtain via a global variable.
 // TODO(cnicolaou): this will need to change once we switch to using
 // TestMain.
-func IntegrationTestInChild(i v23tests.T) {
+func IntegrationTestInChild(i *v23tests.T) {
 	fmt.Println("Hello")
 	sleep := i.BinaryFromPath("/bin/sleep")
 	sleep.Start("3600")
diff --git a/services/mgmt/application/applicationd/applicationd_v23_test.go b/services/mgmt/application/applicationd/applicationd_v23_test.go
index 7544fb3..2f521bd 100644
--- a/services/mgmt/application/applicationd/applicationd_v23_test.go
+++ b/services/mgmt/application/applicationd/applicationd_v23_test.go
@@ -19,7 +19,7 @@
 
 //go:generate v23 test generate
 
-func helper(i v23tests.T, clientBin v23tests.TestBinary, expectError bool, credentials, cmd string, args ...string) string {
+func helper(i *v23tests.T, clientBin *v23tests.Binary, expectError bool, credentials, cmd string, args ...string) string {
 	args = append([]string{"-veyron.credentials=" + credentials, cmd}, args...)
 	inv := clientBin.Start(args...)
 	out := inv.Output()
@@ -34,19 +34,19 @@
 
 }
 
-func matchEnvelope(i v23tests.T, clientBin v23tests.TestBinary, expectError bool, credentials, name, suffix string) string {
+func matchEnvelope(i *v23tests.T, clientBin *v23tests.Binary, expectError bool, credentials, name, suffix string) string {
 	return helper(i, clientBin, expectError, credentials, "match", naming.Join(name, suffix), "test-profile")
 }
 
-func putEnvelope(i v23tests.T, clientBin v23tests.TestBinary, credentials, name, suffix, envelope string) string {
+func putEnvelope(i *v23tests.T, clientBin *v23tests.Binary, credentials, name, suffix, envelope string) string {
 	return helper(i, clientBin, false, credentials, "put", naming.Join(name, suffix), "test-profile", envelope)
 }
 
-func removeEnvelope(i v23tests.T, clientBin v23tests.TestBinary, credentials, name, suffix string) string {
+func removeEnvelope(i *v23tests.T, clientBin *v23tests.Binary, credentials, name, suffix string) string {
 	return helper(i, clientBin, false, credentials, "remove", naming.Join(name, suffix), "test-profile")
 }
 
-func V23TestApplicationRepository(i v23tests.T) {
+func V23TestApplicationRepository(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	// TODO(sjr): talk to caprita about the necessity/correctness of these.
diff --git a/services/mgmt/binary/binaryd/binaryd_v23_test.go b/services/mgmt/binary/binaryd/binaryd_v23_test.go
index bb58d2d..9646991 100644
--- a/services/mgmt/binary/binaryd/binaryd_v23_test.go
+++ b/services/mgmt/binary/binaryd/binaryd_v23_test.go
@@ -17,7 +17,7 @@
 
 //go:generate v23 test generate
 
-func checkFileType(i v23tests.T, file, typeString string) {
+func checkFileType(i *v23tests.T, file, typeString string) {
 	var catOut bytes.Buffer
 	catCmd := exec.Command("cat", file+".__info")
 	catCmd.Stdout = &catOut
@@ -30,7 +30,7 @@
 	}
 }
 
-func readFileOrDie(i v23tests.T, path string) []byte {
+func readFileOrDie(i *v23tests.T, path string) []byte {
 	result, err := ioutil.ReadFile(path)
 	if err != nil {
 		i.Fatalf("ReadFile(%q) failed: %v", path, err)
@@ -38,13 +38,13 @@
 	return result
 }
 
-func compareFiles(i v23tests.T, f1, f2 string) {
+func compareFiles(i *v23tests.T, f1, f2 string) {
 	if !bytes.Equal(readFileOrDie(i, f1), readFileOrDie(i, f2)) {
 		i.Fatalf("the contents of %s and %s differ when they should not", f1, f2)
 	}
 }
 
-func deleteFile(i v23tests.T, clientBin v23tests.TestBinary, credentials, name, suffix string) {
+func deleteFile(i *v23tests.T, clientBin *v23tests.Binary, credentials, name, suffix string) {
 	deleteArgs := []string{
 		"-veyron.credentials=" + credentials,
 		"delete", naming.Join(name, suffix),
@@ -52,7 +52,7 @@
 	clientBin.Start(deleteArgs...).WaitOrDie(nil, nil)
 }
 
-func downloadFile(i v23tests.T, clientBin v23tests.TestBinary, expectError bool, credentials, name, path, suffix string) {
+func downloadFile(i *v23tests.T, clientBin *v23tests.Binary, expectError bool, credentials, name, path, suffix string) {
 	downloadArgs := []string{
 		"-veyron.credentials=" + credentials,
 		"download", naming.Join(name, suffix), path,
@@ -66,7 +66,7 @@
 	}
 }
 
-func downloadURL(i v23tests.T, path, rootURL, suffix string) {
+func downloadURL(i *v23tests.T, path, rootURL, suffix string) {
 	url := fmt.Sprintf("http://%v/%v", rootURL, suffix)
 	resp, err := http.Get(url)
 	if err != nil {
@@ -82,7 +82,7 @@
 	}
 }
 
-func rootURL(i v23tests.T, clientBin v23tests.TestBinary, credentials, name string) string {
+func rootURL(i *v23tests.T, clientBin *v23tests.Binary, credentials, name string) string {
 	rootArgs := []string{
 		"-veyron.credentials=" + credentials,
 		"url", name,
@@ -90,7 +90,7 @@
 	return strings.TrimSpace(clientBin.Start(rootArgs...).Output())
 }
 
-func uploadFile(i v23tests.T, clientBin v23tests.TestBinary, credentials, name, path, suffix string) {
+func uploadFile(i *v23tests.T, clientBin *v23tests.Binary, credentials, name, path, suffix string) {
 	uploadArgs := []string{
 		"-veyron.credentials=" + credentials,
 		"upload", naming.Join(name, suffix), path,
@@ -98,7 +98,7 @@
 	clientBin.Start(uploadArgs...).WaitOrDie(os.Stdout, os.Stderr)
 }
 
-func V23TestBinaryRepositoryIntegration(i v23tests.T) {
+func V23TestBinaryRepositoryIntegration(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	// Build the required binaries.
diff --git a/services/mgmt/build/buildd/buildd_v23_test.go b/services/mgmt/build/buildd/buildd_v23_test.go
index a3391cd..99b28d0 100644
--- a/services/mgmt/build/buildd/buildd_v23_test.go
+++ b/services/mgmt/build/buildd/buildd_v23_test.go
@@ -22,7 +22,7 @@
 func main() { fmt.Println("Hello World!") }
 `
 
-func V23TestBuildServerIntegration(i v23tests.T) {
+func V23TestBuildServerIntegration(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	// Generate credentials.
diff --git a/services/mgmt/profile/profiled/profiled_v23_test.go b/services/mgmt/profile/profiled/profiled_v23_test.go
index 4e862b7..4180ebe 100644
--- a/services/mgmt/profile/profiled/profiled_v23_test.go
+++ b/services/mgmt/profile/profiled/profiled_v23_test.go
@@ -10,7 +10,7 @@
 
 //go:generate v23 test generate
 
-func profileCommandOutput(i v23tests.T, profileBin v23tests.TestBinary, expectError bool, command, name, suffix string) string {
+func profileCommandOutput(i *v23tests.T, profileBin *v23tests.Binary, expectError bool, command, name, suffix string) string {
 	labelArgs := []string{
 		command, naming.Join(name, suffix),
 	}
@@ -26,21 +26,21 @@
 	return strings.TrimSpace(out)
 }
 
-func putProfile(i v23tests.T, profileBin v23tests.TestBinary, name, suffix string) {
+func putProfile(i *v23tests.T, profileBin *v23tests.Binary, name, suffix string) {
 	putArgs := []string{
 		"put", naming.Join(name, suffix),
 	}
 	profileBin.Start(putArgs...).WaitOrDie(os.Stdout, os.Stderr)
 }
 
-func removeProfile(i v23tests.T, profileBin v23tests.TestBinary, name, suffix string) {
+func removeProfile(i *v23tests.T, profileBin *v23tests.Binary, name, suffix string) {
 	removeArgs := []string{
 		"remove", naming.Join(name, suffix),
 	}
 	profileBin.Start(removeArgs...).WaitOrDie(os.Stdout, os.Stderr)
 }
 
-func V23TestProfileRepository(i v23tests.T) {
+func V23TestProfileRepository(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	// Start the profile repository.
diff --git a/services/mounttable/mounttabled/mounttabled_v23_test.go b/services/mounttable/mounttabled/mounttabled_v23_test.go
index 5db9f1d..6faaa8a 100644
--- a/services/mounttable/mounttabled/mounttabled_v23_test.go
+++ b/services/mounttable/mounttabled/mounttabled_v23_test.go
@@ -10,7 +10,7 @@
 
 //go:generate v23 test generate
 
-func getHostname(i v23tests.T) string {
+func getHostname(i *v23tests.T) string {
 	if hostname, err := os.Hostname(); err != nil {
 		i.Fatalf("Hostname() failed: %v", err)
 		return ""
@@ -19,7 +19,7 @@
 	}
 }
 
-func V23TestMount(i v23tests.T) {
+func V23TestMount(i *v23tests.T) {
 	neighborhood := fmt.Sprintf("test-%s-%d", getHostname(i), os.Getpid())
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0", "--neighborhood_name="+neighborhood)
 
diff --git a/tools/debug/debug_v23_test.go b/tools/debug/debug_v23_test.go
index 7f66e0f..4cb0ccd 100644
--- a/tools/debug/debug_v23_test.go
+++ b/tools/debug/debug_v23_test.go
@@ -15,7 +15,7 @@
 
 //go:generate v23 test generate
 
-func V23TestDebugGlob(i v23tests.T) {
+func V23TestDebugGlob(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	binary := i.BuildGoPkg("v.io/core/veyron/tools/debug")
@@ -30,7 +30,7 @@
 	}
 }
 
-func V23TestDebugGlobLogs(i v23tests.T) {
+func V23TestDebugGlobLogs(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	// Create a temp file before we list the logs.
@@ -45,7 +45,7 @@
 	}
 }
 
-func V23TestReadHostname(i v23tests.T) {
+func V23TestReadHostname(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	path := "__debug/stats/system/hostname"
@@ -60,7 +60,7 @@
 	}
 }
 
-func createTestLogFile(i v23tests.T, content string) *os.File {
+func createTestLogFile(i *v23tests.T, content string) *os.File {
 	file := i.TempFile()
 	_, err := file.Write([]byte(content))
 	if err != nil {
@@ -69,7 +69,7 @@
 	return file
 }
 
-func V23TestLogSize(i v23tests.T) {
+func V23TestLogSize(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	binary := i.BuildGoPkg("v.io/core/veyron/tools/debug")
@@ -88,7 +88,7 @@
 	}
 }
 
-func V23TestStatsRead(i v23tests.T) {
+func V23TestStatsRead(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	binary := i.BuildGoPkg("v.io/core/veyron/tools/debug")
@@ -108,7 +108,7 @@
 	}
 }
 
-func V23TestStatsWatch(i v23tests.T) {
+func V23TestStatsWatch(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	binary := i.BuildGoPkg("v.io/core/veyron/tools/debug")
@@ -143,11 +143,11 @@
 	}
 }
 
-func performTracedRead(debugBinary v23tests.TestBinary, path string) string {
+func performTracedRead(debugBinary *v23tests.Binary, path string) string {
 	return debugBinary.Start("--veyron.vtrace.sample_rate=1", "logs", "read", path).Output()
 }
 
-func V23TestVTrace(i v23tests.T) {
+func V23TestVTrace(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	binary := i.BuildGoPkg("v.io/core/veyron/tools/debug")
@@ -200,7 +200,7 @@
 	}
 }
 
-func V23TestPprof(i v23tests.T) {
+func V23TestPprof(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	binary := i.BuildGoPkg("v.io/core/veyron/tools/debug")
diff --git a/tools/naming/simulator/simulator_v23_test.go b/tools/naming/simulator/simulator_v23_test.go
index b998f00..71b762b 100644
--- a/tools/naming/simulator/simulator_v23_test.go
+++ b/tools/naming/simulator/simulator_v23_test.go
@@ -18,7 +18,7 @@
 	modules.DispatchInTest()
 }
 
-func V23TestSimulator(t v23tests.T) {
+func V23TestSimulator(t *v23tests.T) {
 	binary := t.BuildGoPkg("v.io/core/veyron/tools/naming/simulator")
 	files, err := ioutil.ReadDir("./testdata")
 	if err != nil {
diff --git a/tools/principal/principal_test.go b/tools/principal/principal_v23_test.go
similarity index 92%
rename from tools/principal/principal_test.go
rename to tools/principal/principal_v23_test.go
index f0d393b..47b92b9 100644
--- a/tools/principal/principal_test.go
+++ b/tools/principal/principal_v23_test.go
@@ -18,13 +18,13 @@
 
 // redirect redirects the stdout of the given invocation to the file at the
 // given path.
-func redirect(t v23tests.T, inv v23tests.Invocation, path string) {
+func redirect(t *v23tests.T, inv *v23tests.Invocation, path string) {
 	if err := ioutil.WriteFile(path, []byte(inv.Output()), 0600); err != nil {
 		t.Fatalf("WriteFile(%q) failed: %v\n", path, err)
 	}
 }
 
-func V23TestBlessSelf(t v23tests.T) {
+func V23TestBlessSelf(t *v23tests.T) {
 	var (
 		outputDir         = t.TempDir()
 		aliceDir          = filepath.Join(outputDir, "alice")
diff --git a/tools/vrun/test/vrun_test.go b/tools/vrun/test/vrun_v23_test.go
similarity index 95%
rename from tools/vrun/test/vrun_test.go
rename to tools/vrun/test/vrun_v23_test.go
index 6086292..e13f09f 100644
--- a/tools/vrun/test/vrun_test.go
+++ b/tools/vrun/test/vrun_v23_test.go
@@ -9,7 +9,7 @@
 	_ "v.io/core/veyron/profiles/static"
 )
 
-func V23TestAgentd(t v23tests.T) {
+func V23TestAgentd(t *v23tests.T) {
 	vrunBin := t.BuildGoPkg("v.io/core/veyron/tools/vrun")
 	pingpongBin := t.BuildGoPkg("v.io/core/veyron/security/agent/pingpong")
 	agentdBin := t.BuildGoPkg("v.io/core/veyron/security/agent/agentd")