v23tests: port tools/debug to v23tests + v23tests improvements/fixes

Improvements to v23tests:
- invocations should be shut down in LIFO order - they were not!
- adopt the convention of naming v23 integration tests as:
	<pkg>_v23_test.go
- export NewChildCredentials from the shell and use it in
  v23tests to give DebugShell's access to the security agent.
- remove an annoying .VI(1) in vif.go
- make sure that all V23Tests in a single package share binaries, it's
  up to v23 to arrange for sharing binaries across multiple packages.
- transition a bunch of testdata tests to <pkg>_v23_tests.

MultiPart: 1/2

Change-Id: Iee6db154a6908c0f4c817f7cb9d56f8982c188a5
diff --git a/lib/modules/shell.go b/lib/modules/shell.go
index cfdfc73..df14af9 100644
--- a/lib/modules/shell.go
+++ b/lib/modules/shell.go
@@ -136,7 +136,12 @@
 	return sh, nil
 }
 
-func (sh *Shell) getChildCredentials() (c *os.File, err error) {
+// NewChildCredentials creates a new set of credentials, stored in the
+// security agent, that have a blessing from this shell's principal.
+// All processes started by this shell will have access to these credentials
+// and this method can be used to create other processes that can communicate
+// with these.
+func (sh *Shell) NewChildCredentials() (c *os.File, err error) {
 	if sh.ctx == nil {
 		return nil, nil
 	}
@@ -273,7 +278,7 @@
 	if err != nil {
 		return nil, err
 	}
-	p, err := sh.getChildCredentials()
+	p, err := sh.NewChildCredentials()
 	if err != nil {
 		return nil, err
 	}
diff --git a/lib/testutil/v23tests/v23tests.go b/lib/testutil/v23tests/v23tests.go
index 00fe66f..b1d392b 100644
--- a/lib/testutil/v23tests/v23tests.go
+++ b/lib/testutil/v23tests/v23tests.go
@@ -93,16 +93,12 @@
 	"v.io/core/veyron/lib/modules"
 	"v.io/core/veyron/lib/testutil"
 	tsecurity "v.io/core/veyron/lib/testutil/security"
+	"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,cnicolaou): caching of binaries is per test environment -
-// it should be in a file system somewhere and should handle all tests run
-// from a single invocation of v23.
-//
 // TODO(sjr): make this thread safe.
 //
 // TODO(sjr): document all of the methods.
@@ -499,10 +495,11 @@
 	}
 
 	vlog.VI(1).Infof("V23Test.Cleanup")
-	// Shut down all processes before attempting to delete any
+	// Shut down all processes in LIFO order before attempting to delete any
 	// files/directories to avoid potential 'file system busy' problems
 	// on non-unix systems.
-	for _, inv := range e.invocations {
+	for i := len(e.invocations); i > 0; i-- {
+		inv := e.invocations[i-1]
 		if inv.hasShutdown {
 			vlog.VI(1).Infof("V23Test.Cleanup: %q has been shutdown", inv.Path())
 			continue
@@ -578,22 +575,24 @@
 		vlog.Errorf("WARNING: Open(%v) failed, was asked to create a debug shell but cannot: %v", dev, err)
 		return
 	}
+
+	agentFile, err := e.shell.NewChildCredentials()
+	if err != nil {
+		vlog.Errorf("WARNING: failed to obtain credentials for the debug shell: %v", err)
+	}
+
 	file := os.NewFile(uintptr(fd), dev)
 	attr := os.ProcAttr{
 		Files: []*os.File{file, file, file},
 		Dir:   cwd,
 	}
+	attr.Files = append(attr.Files, agentFile)
+	attr.Env = append(attr.Env, fmt.Sprintf("%s=%d", agent.FdVarName, len(attr.Files)-1))
 
 	// Set up environment for Child.
 	if ns, ok := e.GetVar("NAMESPACE_ROOT"); ok {
 		attr.Env = append(attr.Env, "NAMESPACE_ROOT="+ns)
 	}
-	// TODO(sjr): talk to Ankur about how to do this properly/safely
-	// using either the agent, or a file descriptor inherited by the shell
-	// and its children. This is preferable since it avoids compiling and
-	// running the agent which can be an overhead in tests.
-	dir, _ := tsecurity.ForkCredentials(e.principal, "debugShell")
-	attr.Env = append(attr.Env, "VEYRON_CREDENTIALS="+dir)
 
 	// Start up a new shell.
 	writeStringOrDie(e, file, ">> Starting a new interactive shell\n")
@@ -638,25 +637,24 @@
 }
 
 func (e *testEnvironment) BuildGoPkg(binary_path string) TestBinary {
-	vlog.Infof("building %s...", binary_path)
-	if cached_binary := e.builtBinaries[binary_path]; cached_binary != nil {
-		vlog.Infof("using cached binary for %s at %s.", binary_path, cached_binary.Path())
-		return cached_binary
-	}
-	built_path, cleanup, err := buildPkg(e.cachedBinDir, binary_path)
+	then := time.Now()
+	cached, built_path, cleanup, err := buildPkg(e.cachedBinDir, binary_path)
 	if err != nil {
-		e.Fatalf("buildPkg() failed: %v", err)
+		e.Fatalf("buildPkg(%s) failed: %v", binary_path, err)
 		return nil
 	}
 	output_path := path.Join(built_path, path.Base(binary_path))
 
-	if fi, err := os.Stat(output_path); err != nil {
-		e.Fatalf("failed to stat %q", output_path)
+	if _, err := os.Stat(output_path); err != nil {
+		e.Fatalf("buildPkg(%s) failed to stat %q", binary_path, output_path)
+	}
+	taken := time.Now().Sub(then)
+	if cached {
+		vlog.Infof("using %s, from %s in %s.", binary_path, output_path, taken)
 	} else {
-		vlog.VI(1).Info("using %q: built at %s", output_path, fi.ModTime())
+		vlog.Infof("built %s, written to %s in %s.", binary_path, output_path, taken)
 	}
 
-	vlog.Infof("done building %s, written to %s.", binary_path, output_path)
 	binary := &testBinary{
 		env:         e,
 		envVars:     nil,
@@ -720,12 +718,12 @@
 	shell.SetStartTimeout(1 * time.Minute)
 	shell.SetWaitTimeout(5 * time.Minute)
 
+	// The V23_BIN_DIR environment variable can be
+	// used to identify a directory that multiple integration
+	// tests can use to share binaries. Whoever sets this
+	// environment variable is responsible for cleaning up the
+	// directory it points to.
 	cachedBinDir := os.Getenv("V23_BIN_DIR")
-	if len(cachedBinDir) == 0 {
-		vlog.Infof("WARNING: not using a cached binary")
-	} else {
-		vlog.Infof("Caching binaries in %q", cachedBinDir)
-	}
 	return &testEnvironment{
 		Test:          t,
 		principal:     principal,
@@ -743,12 +741,7 @@
 // build artifacts. Note that the clients of this function should not modify
 // the contents of this directory directly and instead defer to the cleanup
 // function.
-func buildPkg(binDir, pkg string) (string, func(), error) {
-	// The V23_BIN_DIR environment variable can be
-	// used to identify a directory that multiple integration
-	// tests can use to share binaries. Whoever sets this
-	// environment variable is responsible for cleaning up the
-	// directory it points to.
+func buildPkg(binDir, pkg string) (bool, string, func(), error) {
 	cleanupFn := func() {}
 	if len(binDir) == 0 {
 		// If the aforementioned environment variable is not
@@ -756,21 +749,23 @@
 		// directory, which the cleanup function removes.
 		tmpDir, err := ioutil.TempDir("", "")
 		if err != nil {
-			return "", nil, fmt.Errorf("TempDir() failed: %v", err)
+			return false, "", nil, fmt.Errorf("TempDir() failed: %v", err)
 		}
 		binDir, cleanupFn = tmpDir, func() { os.RemoveAll(tmpDir) }
 	}
 	binFile := filepath.Join(binDir, path.Base(pkg))
+	cached := true
 	if _, err := os.Stat(binFile); err != nil {
 		if !os.IsNotExist(err) {
-			return "", nil, err
+			return false, "", nil, err
 		}
 		cmd := exec.Command("v23", "go", "build", "-o", filepath.Join(binDir, path.Base(pkg)), pkg)
 		if err := cmd.Run(); err != nil {
-			return "", nil, err
+			return false, "", nil, err
 		}
+		cached = false
 	}
-	return binDir, cleanupFn, nil
+	return cached, binDir, cleanupFn, nil
 }
 
 // RunTest runs a single Vanadium 'v23 style' integration test.
@@ -794,8 +789,29 @@
 	s := expect.NewSession(t, i.Stdout(), time.Minute)
 	name := s.ExpectVar("NAME")
 	i.Environment().SetVar("NAMESPACE_ROOT", name)
+	vlog.Infof("Running root mount table: %q", name)
 	return b, i
 }
 
+// UseShardBinDir ensures that a shared directory is used for binaries
+// across multiple instances of the test environment. This is achieved
+// by setting the V23_BIN_DIR environment variable if it is not already
+// set in the test processes environment (as will typically be the case when
+// these tests are run from the v23 tool). It is intended to be called
+// from TestMain.
+func UseSharedBinDir() func() {
+	if v23BinDir := os.Getenv("V23_BIN_DIR"); len(v23BinDir) == 0 {
+		v23BinDir, err := ioutil.TempDir("", "bin-")
+		if err == nil {
+			vlog.Infof("Setting V23_BIN_DIR to %q", v23BinDir)
+			os.Setenv("V23_BIN_DIR", v23BinDir)
+			return func() { os.RemoveAll(v23BinDir) }
+		}
+	} else {
+		vlog.Infof("Using V23_BIN_DIR %q", v23BinDir)
+	}
+	return func() {}
+}
+
 // TODO(sjr): provided convenience wrapper for dealing with credentials if
 // necessary.
diff --git a/runtimes/google/ipc/stream/vif/vif.go b/runtimes/google/ipc/stream/vif/vif.go
index 21122db..133c72f 100644
--- a/runtimes/google/ipc/stream/vif/vif.go
+++ b/runtimes/google/ipc/stream/vif/vif.go
@@ -632,7 +632,7 @@
 
 // sendOnExpressQ adds 'msg' to the expressQ (highest priority queue) of messages to write on the wire.
 func (vif *VIF) sendOnExpressQ(msg message.T) error {
-	vlog.VI(1).Infof("sendOnExpressQ(%T = %+v) on VIF %s", msg, msg, vif)
+	vlog.VI(2).Infof("sendOnExpressQ(%T = %+v) on VIF %s", msg, msg, vif)
 	var buf bytes.Buffer
 	// Don't encrypt yet, because the message ordering isn't yet determined.
 	// Encryption is performed by vif.writeSerializedMessage() when the
diff --git a/services/mgmt/application/applicationd/applicationd_v23_test.go b/services/mgmt/application/applicationd/applicationd_v23_test.go
new file mode 100644
index 0000000..7544fb3
--- /dev/null
+++ b/services/mgmt/application/applicationd/applicationd_v23_test.go
@@ -0,0 +1,124 @@
+package main_test
+
+import (
+	"encoding/json"
+	"os"
+	"strings"
+
+	libsecurity "v.io/core/veyron/lib/testutil/security"
+	"v.io/core/veyron/lib/testutil/v23tests"
+	vsecurity "v.io/core/veyron/security"
+	"v.io/core/veyron2/naming"
+	"v.io/core/veyron2/security"
+)
+
+var binPkgs = []string{
+	"v.io/core/veyron/services/mgmt/application/applicationd",
+	"v.io/core/veyron/tools/application",
+}
+
+//go:generate v23 test generate
+
+func helper(i v23tests.T, clientBin v23tests.TestBinary, expectError bool, credentials, cmd string, args ...string) string {
+	args = append([]string{"-veyron.credentials=" + credentials, cmd}, args...)
+	inv := clientBin.Start(args...)
+	out := inv.Output()
+	err := inv.Wait(os.Stdout, os.Stderr)
+	if err != nil && !expectError {
+		i.Fatalf("%s %q failed: %v\n%v", clientBin.Path(), strings.Join(args, " "), err, out)
+	}
+	if err == nil && expectError {
+		i.Fatalf("%s %q did not fail when it should", clientBin.Path(), strings.Join(args, " "))
+	}
+	return strings.TrimSpace(out)
+
+}
+
+func matchEnvelope(i v23tests.T, clientBin v23tests.TestBinary, 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 {
+	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 {
+	return helper(i, clientBin, false, credentials, "remove", naming.Join(name, suffix), "test-profile")
+}
+
+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.
+	// Generate credentials.
+	serverCred, serverPrin := libsecurity.NewCredentials("server")
+	defer os.RemoveAll(serverCred)
+	clientCred, _ := libsecurity.ForkCredentials(serverPrin, "client")
+	defer os.RemoveAll(clientCred)
+
+	// Start the application repository.
+	appRepoName := "test-app-repo"
+	appRepoStore := i.TempDir()
+	args := []string{
+		"-name=" + appRepoName,
+		"-store=" + appRepoStore,
+		"-v=2",
+		"-veyron.tcp.address=127.0.0.1:0",
+		"-veyron.credentials=" + serverCred,
+	}
+	i.BuildGoPkg("v.io/core/veyron/services/mgmt/application/applicationd").Start(args...)
+
+	// Build the client binary.
+	clientBin := i.BuildGoPkg("v.io/core/veyron/tools/application")
+
+	// Generate publisher blessings
+	principal, err := vsecurity.NewPrincipal()
+	if err != nil {
+		i.Fatal(err)
+	}
+	blessings, err := principal.BlessSelf("self")
+	if err != nil {
+		i.Fatal(err)
+	}
+	sig, err := principal.Sign([]byte("binarycontents"))
+	if err != nil {
+		i.Fatal(err)
+	}
+	sigJSON, err := json.MarshalIndent(sig, "  ", "  ")
+	if err != nil {
+		i.Fatal(err)
+	}
+	pubJSON, err := json.MarshalIndent(security.MarshalBlessings(blessings), "  ", "  ")
+	if err != nil {
+		i.Fatal(err)
+	}
+
+	// Create an application envelope.
+	appRepoSuffix := "test-application/v1"
+	appEnvelopeFile := i.TempFile()
+	wantEnvelope := `{
+  "Title": "title",
+  "Args": null,
+  "Binary": "foo",
+  "Signature": ` + string(sigJSON) + `,
+  "Publisher": ` + string(pubJSON) + `,
+  "Env": null,
+  "Packages": null
+}`
+	if _, err := appEnvelopeFile.Write([]byte(wantEnvelope)); err != nil {
+		i.Fatalf("Write() failed: %v", err)
+	}
+	putEnvelope(i, clientBin, clientCred, appRepoName, appRepoSuffix, appEnvelopeFile.Name())
+
+	// Match the application envelope.
+	gotEnvelope := matchEnvelope(i, clientBin, false, clientCred, appRepoName, appRepoSuffix)
+	if gotEnvelope != wantEnvelope {
+		i.Fatalf("unexpected output: got %v, want %v", gotEnvelope, wantEnvelope)
+	}
+
+	// Remove the application envelope.
+	removeEnvelope(i, clientBin, clientCred, appRepoName, appRepoSuffix)
+
+	// Check that the application envelope no longer exists.
+	matchEnvelope(i, clientBin, true, clientCred, appRepoName, appRepoSuffix)
+}
diff --git a/services/mgmt/application/applicationd/testdata/integration_test.go b/services/mgmt/application/applicationd/testdata/integration_test.go
deleted file mode 100644
index 697b482..0000000
--- a/services/mgmt/application/applicationd/testdata/integration_test.go
+++ /dev/null
@@ -1,126 +0,0 @@
-package integration_test
-
-import (
-	"encoding/json"
-	"os"
-	"strings"
-	"testing"
-
-	libsecurity "v.io/core/veyron/lib/testutil/security"
-	"v.io/core/veyron/lib/testutil/v23tests"
-	_ "v.io/core/veyron/profiles"
-	vsecurity "v.io/core/veyron/security"
-	"v.io/core/veyron2/naming"
-	"v.io/core/veyron2/security"
-)
-
-var binPkgs = []string{
-	"v.io/core/veyron/services/mgmt/application/applicationd",
-	"v.io/core/veyron/tools/application",
-}
-
-func helper(t *testing.T, env v23tests.T, clientBin v23tests.TestBinary, expectError bool, credentials, cmd string, args ...string) string {
-	args = append([]string{"-veyron.credentials=" + credentials, cmd}, args...)
-	inv := clientBin.Start(args...)
-	out := inv.Output()
-	err := inv.Wait(os.Stdout, os.Stderr)
-	if err != nil && !expectError {
-		t.Fatalf("%s %q failed: %v\n%v", clientBin.Path(), strings.Join(args, " "), err, out)
-	}
-	if err == nil && expectError {
-		t.Fatalf("%s %q did not fail when it should", clientBin.Path(), strings.Join(args, " "))
-	}
-	return strings.TrimSpace(out)
-
-}
-
-func matchEnvelope(t *testing.T, env v23tests.T, clientBin v23tests.TestBinary, expectError bool, credentials, name, suffix string) string {
-	return helper(t, env, clientBin, expectError, credentials, "match", naming.Join(name, suffix), "test-profile")
-}
-
-func putEnvelope(t *testing.T, env v23tests.T, clientBin v23tests.TestBinary, credentials, name, suffix, envelope string) string {
-	return helper(t, env, clientBin, false, credentials, "put", naming.Join(name, suffix), "test-profile", envelope)
-}
-
-func removeEnvelope(t *testing.T, env v23tests.T, clientBin v23tests.TestBinary, credentials, name, suffix string) string {
-	return helper(t, env, clientBin, false, credentials, "remove", naming.Join(name, suffix), "test-profile")
-}
-
-func TestApplicationRepository(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
-
-	// TODO(sjr): talk to caprita about the necessity/correctness of these.
-	// Generate credentials.
-	serverCred, serverPrin := libsecurity.NewCredentials("server")
-	defer os.RemoveAll(serverCred)
-	clientCred, _ := libsecurity.ForkCredentials(serverPrin, "client")
-	defer os.RemoveAll(clientCred)
-
-	// Start the application repository.
-	appRepoName := "test-app-repo"
-	appRepoStore := env.TempDir()
-	args := []string{
-		"-name=" + appRepoName,
-		"-store=" + appRepoStore,
-		"-v=2",
-		"-veyron.tcp.address=127.0.0.1:0",
-		"-veyron.credentials=" + serverCred,
-	}
-	env.BuildGoPkg("v.io/core/veyron/services/mgmt/application/applicationd").Start(args...)
-
-	// Build the client binary.
-	clientBin := env.BuildGoPkg("v.io/core/veyron/tools/application")
-
-	// Generate publisher blessings
-	principal, err := vsecurity.NewPrincipal()
-	if err != nil {
-		t.Fatal(err)
-	}
-	blessings, err := principal.BlessSelf("self")
-	if err != nil {
-		t.Fatal(err)
-	}
-	sig, err := principal.Sign([]byte("binarycontents"))
-	if err != nil {
-		t.Fatal(err)
-	}
-	sigJSON, err := json.MarshalIndent(sig, "  ", "  ")
-	if err != nil {
-		t.Fatal(err)
-	}
-	pubJSON, err := json.MarshalIndent(security.MarshalBlessings(blessings), "  ", "  ")
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	// Create an application envelope.
-	appRepoSuffix := "test-application/v1"
-	appEnvelopeFile := env.TempFile()
-	wantEnvelope := `{
-  "Title": "title",
-  "Args": null,
-  "Binary": "foo",
-  "Signature": ` + string(sigJSON) + `,
-  "Publisher": ` + string(pubJSON) + `,
-  "Env": null,
-  "Packages": null
-}`
-	if _, err := appEnvelopeFile.Write([]byte(wantEnvelope)); err != nil {
-		t.Fatalf("Write() failed: %v", err)
-	}
-	putEnvelope(t, env, clientBin, clientCred, appRepoName, appRepoSuffix, appEnvelopeFile.Name())
-
-	// Match the application envelope.
-	gotEnvelope := matchEnvelope(t, env, clientBin, false, clientCred, appRepoName, appRepoSuffix)
-	if gotEnvelope != wantEnvelope {
-		t.Fatalf("unexpected output: got %v, want %v", gotEnvelope, wantEnvelope)
-	}
-
-	// Remove the application envelope.
-	removeEnvelope(t, env, clientBin, clientCred, appRepoName, appRepoSuffix)
-
-	// Check that the application envelope no longer exists.
-	matchEnvelope(t, env, clientBin, true, clientCred, appRepoName, appRepoSuffix)
-}
diff --git a/services/mgmt/application/applicationd/v23_test.go b/services/mgmt/application/applicationd/v23_test.go
new file mode 100644
index 0000000..9e43b89
--- /dev/null
+++ b/services/mgmt/application/applicationd/v23_test.go
@@ -0,0 +1,22 @@
+// This file was auto-generated via go generate.
+// DO NOT UPDATE MANUALLY
+package main_test
+
+import "testing"
+import "os"
+
+import "v.io/core/veyron/lib/testutil"
+import "v.io/core/veyron/lib/testutil/v23tests"
+
+func TestMain(m *testing.M) {
+	testutil.Init()
+	cleanup := v23tests.UseSharedBinDir()
+	r := m.Run()
+	cleanup()
+	// TODO(cnicolaou): call modules.Dispatch and remove the need for TestHelperProcess
+	os.Exit(r)
+}
+
+func TestV23ApplicationRepository(t *testing.T) {
+	v23tests.RunTest(t, V23TestApplicationRepository)
+}
diff --git a/services/mgmt/binary/binaryd/binaryd_v23_test.go b/services/mgmt/binary/binaryd/binaryd_v23_test.go
new file mode 100644
index 0000000..bb58d2d
--- /dev/null
+++ b/services/mgmt/binary/binaryd/binaryd_v23_test.go
@@ -0,0 +1,189 @@
+package main_test
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"os/exec"
+	"strings"
+
+	"v.io/core/veyron/lib/testutil"
+	"v.io/core/veyron/lib/testutil/security"
+	"v.io/core/veyron/lib/testutil/v23tests"
+	"v.io/core/veyron2/naming"
+)
+
+//go:generate v23 test generate
+
+func checkFileType(i v23tests.T, file, typeString string) {
+	var catOut bytes.Buffer
+	catCmd := exec.Command("cat", file+".__info")
+	catCmd.Stdout = &catOut
+	catCmd.Stderr = &catOut
+	if err := catCmd.Run(); err != nil {
+		i.Fatalf("%q failed: %v\n%v", strings.Join(catCmd.Args, " "), err, catOut.String())
+	}
+	if got, want := strings.TrimSpace(catOut.String()), typeString; got != want {
+		i.Fatalf("unexpect file type: got %v, want %v", got, want)
+	}
+}
+
+func readFileOrDie(i v23tests.T, path string) []byte {
+	result, err := ioutil.ReadFile(path)
+	if err != nil {
+		i.Fatalf("ReadFile(%q) failed: %v", path, err)
+	}
+	return result
+}
+
+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) {
+	deleteArgs := []string{
+		"-veyron.credentials=" + credentials,
+		"delete", naming.Join(name, suffix),
+	}
+	clientBin.Start(deleteArgs...).WaitOrDie(nil, nil)
+}
+
+func downloadFile(i v23tests.T, clientBin v23tests.TestBinary, expectError bool, credentials, name, path, suffix string) {
+	downloadArgs := []string{
+		"-veyron.credentials=" + credentials,
+		"download", naming.Join(name, suffix), path,
+	}
+	err := clientBin.Start(downloadArgs...).Wait(os.Stdout, os.Stderr)
+	if expectError && err == nil {
+		i.Fatalf("%s %q did not fail when it should", clientBin.Path(), strings.Join(downloadArgs, " "))
+	}
+	if !expectError && err != nil {
+		i.Fatalf("%s %q failed: %v", clientBin.Path(), strings.Join(downloadArgs, " "), err)
+	}
+}
+
+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 {
+		i.Fatalf("Get(%q) failed: %v", url, err)
+	}
+	output, err := ioutil.ReadAll(resp.Body)
+	resp.Body.Close()
+	if err != nil {
+		i.Fatalf("ReadAll() failed: %v", err)
+	}
+	if err = ioutil.WriteFile(path, output, 0600); err != nil {
+		i.Fatalf("WriteFile() failed: %v", err)
+	}
+}
+
+func rootURL(i v23tests.T, clientBin v23tests.TestBinary, credentials, name string) string {
+	rootArgs := []string{
+		"-veyron.credentials=" + credentials,
+		"url", name,
+	}
+	return strings.TrimSpace(clientBin.Start(rootArgs...).Output())
+}
+
+func uploadFile(i v23tests.T, clientBin v23tests.TestBinary, credentials, name, path, suffix string) {
+	uploadArgs := []string{
+		"-veyron.credentials=" + credentials,
+		"upload", naming.Join(name, suffix), path,
+	}
+	clientBin.Start(uploadArgs...).WaitOrDie(os.Stdout, os.Stderr)
+}
+
+func V23TestBinaryRepositoryIntegration(i v23tests.T) {
+	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
+
+	// Build the required binaries.
+	binaryRepoBin := i.BuildGoPkg("v.io/core/veyron/services/mgmt/binary/binaryd")
+	clientBin := i.BuildGoPkg("v.io/core/veyron/tools/binary")
+
+	// Generate credentials.
+	serverCred, serverPrin := security.NewCredentials("server")
+	defer os.RemoveAll(serverCred)
+	clientCred, _ := security.ForkCredentials(serverPrin, "client")
+	defer os.RemoveAll(clientCred)
+
+	// Start the build server.
+	binaryRepoName := "test-binary-repository"
+	args := []string{
+		"-name=" + binaryRepoName,
+		"-http=127.0.0.1:0",
+		"-veyron.tcp.address=127.0.0.1:0",
+		"-veyron.credentials=" + serverCred,
+	}
+
+	binaryRepoBin.Start(args...)
+
+	// Upload a random binary file.
+	binFile := i.TempFile()
+	if _, err := binFile.Write(testutil.RandomBytes(16 * 1000 * 1000)); err != nil {
+		i.Fatalf("Write() failed: %v", err)
+	}
+	binSuffix := "test-binary"
+	uploadFile(i, clientBin, clientCred, binaryRepoName, binFile.Name(), binSuffix)
+
+	// Upload a compressed version of the binary file.
+	tarFile := binFile.Name() + ".tar.gz"
+	var tarOut bytes.Buffer
+	tarCmd := exec.Command("tar", "zcvf", tarFile, binFile.Name())
+	tarCmd.Stdout = &tarOut
+	tarCmd.Stderr = &tarOut
+	if err := tarCmd.Run(); err != nil {
+		i.Fatalf("%q failed: %v\n%v", strings.Join(tarCmd.Args, " "), err, tarOut.String())
+	}
+	defer os.Remove(tarFile)
+	tarSuffix := "test-compressed-file"
+	uploadFile(i, clientBin, clientCred, binaryRepoName, tarFile, tarSuffix)
+
+	// Download the binary file and check that it matches the
+	// original one and that it has the right file type.
+	downloadedBinFile := binFile.Name() + "-downloaded"
+	defer os.Remove(downloadedBinFile)
+	downloadFile(i, clientBin, false, clientCred, binaryRepoName, downloadedBinFile, binSuffix)
+	compareFiles(i, binFile.Name(), downloadedBinFile)
+	checkFileType(i, downloadedBinFile, `{"Type":"application/octet-stream","Encoding":""}`)
+
+	// Download the compressed version of the binary file and
+	// check that it matches the original one and that it has the
+	// right file type.
+	downloadedTarFile := binFile.Name() + "-downloaded.tar.gz"
+	defer os.Remove(downloadedTarFile)
+	downloadFile(i, clientBin, false, clientCred, binaryRepoName, downloadedTarFile, tarSuffix)
+	compareFiles(i, tarFile, downloadedTarFile)
+	checkFileType(i, downloadedTarFile, `{"Type":"application/x-tar","Encoding":"gzip"}`)
+
+	// Fetch the root URL of the HTTP server used by the binary
+	// repository to serve URLs.
+	root := rootURL(i, clientBin, clientCred, binaryRepoName)
+
+	// Download the binary file using the HTTP protocol and check
+	// that it matches the original one.
+	downloadedBinFileURL := binFile.Name() + "-downloaded-url"
+	defer os.Remove(downloadedBinFileURL)
+	downloadURL(i, downloadedBinFileURL, root, binSuffix)
+	compareFiles(i, downloadedBinFile, downloadedBinFileURL)
+
+	// Download the compressed version of the binary file using
+	// the HTTP protocol and check that it matches the original
+	// one.
+	downloadedTarFileURL := binFile.Name() + "-downloaded-url.tar.gz"
+	defer os.Remove(downloadedTarFileURL)
+	downloadURL(i, downloadedTarFileURL, root, tarSuffix)
+	compareFiles(i, downloadedTarFile, downloadedTarFileURL)
+
+	// Delete the files.
+	deleteFile(i, clientBin, clientCred, binaryRepoName, binSuffix)
+	deleteFile(i, clientBin, clientCred, binaryRepoName, tarSuffix)
+
+	// Check the files no longer exist.
+	downloadFile(i, clientBin, true, clientCred, binaryRepoName, downloadedBinFile, binSuffix)
+	downloadFile(i, clientBin, true, clientCred, binaryRepoName, downloadedTarFile, tarSuffix)
+}
diff --git a/services/mgmt/binary/binaryd/testdata/integration_test.go b/services/mgmt/binary/binaryd/testdata/integration_test.go
deleted file mode 100644
index 80e39c1..0000000
--- a/services/mgmt/binary/binaryd/testdata/integration_test.go
+++ /dev/null
@@ -1,195 +0,0 @@
-package integration_test
-
-import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"os"
-	"os/exec"
-	"strings"
-	"testing"
-
-	"v.io/core/veyron/lib/testutil"
-	"v.io/core/veyron/lib/testutil/security"
-	"v.io/core/veyron/lib/testutil/v23tests"
-	_ "v.io/core/veyron/profiles"
-	"v.io/core/veyron2/naming"
-)
-
-func init() {
-	testutil.Init()
-}
-
-func checkFileType(t *testing.T, file, typeString string) {
-	var catOut bytes.Buffer
-	catCmd := exec.Command("cat", file+".__info")
-	catCmd.Stdout = &catOut
-	catCmd.Stderr = &catOut
-	if err := catCmd.Run(); err != nil {
-		t.Fatalf("%q failed: %v\n%v", strings.Join(catCmd.Args, " "), err, catOut.String())
-	}
-	if got, want := strings.TrimSpace(catOut.String()), typeString; got != want {
-		t.Fatalf("unexpect file type: got %v, want %v", got, want)
-	}
-}
-
-func readFileOrDie(t *testing.T, path string) []byte {
-	result, err := ioutil.ReadFile(path)
-	if err != nil {
-		t.Fatalf("ReadFile(%q) failed: %v", path, err)
-	}
-	return result
-}
-
-func compareFiles(t *testing.T, f1, f2 string) {
-	if !bytes.Equal(readFileOrDie(t, f1), readFileOrDie(t, f2)) {
-		t.Fatalf("the contents of %s and %s differ when they should not", f1, f2)
-	}
-}
-
-func deleteFile(env v23tests.T, clientBin v23tests.TestBinary, credentials, name, suffix string) {
-	deleteArgs := []string{
-		"-veyron.credentials=" + credentials,
-		"delete", naming.Join(name, suffix),
-	}
-	clientBin.Start(deleteArgs...).WaitOrDie(nil, nil)
-}
-
-func downloadFile(t *testing.T, env v23tests.T, clientBin v23tests.TestBinary, expectError bool, credentials, name, path, suffix string) {
-	downloadArgs := []string{
-		"-veyron.credentials=" + credentials,
-		"download", naming.Join(name, suffix), path,
-	}
-	err := clientBin.Start(downloadArgs...).Wait(os.Stdout, os.Stderr)
-	if expectError && err == nil {
-		t.Fatalf("%s %q did not fail when it should", clientBin.Path(), strings.Join(downloadArgs, " "))
-	}
-	if !expectError && err != nil {
-		t.Fatalf("%s %q failed: %v", clientBin.Path(), strings.Join(downloadArgs, " "), err)
-	}
-}
-
-func downloadURL(t *testing.T, path, rootURL, suffix string) {
-	url := fmt.Sprintf("http://%v/%v", rootURL, suffix)
-	resp, err := http.Get(url)
-	if err != nil {
-		t.Fatalf("Get(%q) failed: %v", url, err)
-	}
-	output, err := ioutil.ReadAll(resp.Body)
-	resp.Body.Close()
-	if err != nil {
-		t.Fatalf("ReadAll() failed: %v", err)
-	}
-	if err = ioutil.WriteFile(path, output, 0600); err != nil {
-		t.Fatalf("WriteFile() failed: %v", err)
-	}
-}
-
-func rootURL(t *testing.T, env v23tests.T, clientBin v23tests.TestBinary, credentials, name string) string {
-	rootArgs := []string{
-		"-veyron.credentials=" + credentials,
-		"url", name,
-	}
-	return strings.TrimSpace(clientBin.Start(rootArgs...).Output())
-}
-
-func uploadFile(t *testing.T, env v23tests.T, clientBin v23tests.TestBinary, credentials, name, path, suffix string) {
-	uploadArgs := []string{
-		"-veyron.credentials=" + credentials,
-		"upload", naming.Join(name, suffix), path,
-	}
-	clientBin.Start(uploadArgs...).WaitOrDie(os.Stdout, os.Stderr)
-}
-
-func TestBinaryRepositoryIntegration(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
-
-	// Build the required binaries.
-	binaryRepoBin := env.BuildGoPkg("v.io/core/veyron/services/mgmt/binary/binaryd")
-	clientBin := env.BuildGoPkg("v.io/core/veyron/tools/binary")
-
-	// Generate credentials.
-	serverCred, serverPrin := security.NewCredentials("server")
-	defer os.RemoveAll(serverCred)
-	clientCred, _ := security.ForkCredentials(serverPrin, "client")
-	defer os.RemoveAll(clientCred)
-
-	// Start the build server.
-	binaryRepoName := "test-binary-repository"
-	args := []string{
-		"-name=" + binaryRepoName,
-		"-http=127.0.0.1:0",
-		"-veyron.tcp.address=127.0.0.1:0",
-		"-veyron.credentials=" + serverCred,
-	}
-
-	binaryRepoBin.Start(args...)
-
-	// Upload a random binary file.
-	binFile := env.TempFile()
-	if _, err := binFile.Write(testutil.RandomBytes(16 * 1000 * 1000)); err != nil {
-		t.Fatalf("Write() failed: %v", err)
-	}
-	binSuffix := "test-binary"
-	uploadFile(t, env, clientBin, clientCred, binaryRepoName, binFile.Name(), binSuffix)
-
-	// Upload a compressed version of the binary file.
-	tarFile := binFile.Name() + ".tar.gz"
-	var tarOut bytes.Buffer
-	tarCmd := exec.Command("tar", "zcvf", tarFile, binFile.Name())
-	tarCmd.Stdout = &tarOut
-	tarCmd.Stderr = &tarOut
-	if err := tarCmd.Run(); err != nil {
-		t.Fatalf("%q failed: %v\n%v", strings.Join(tarCmd.Args, " "), err, tarOut.String())
-	}
-	defer os.Remove(tarFile)
-	tarSuffix := "test-compressed-file"
-	uploadFile(t, env, clientBin, clientCred, binaryRepoName, tarFile, tarSuffix)
-
-	// Download the binary file and check that it matches the
-	// original one and that it has the right file type.
-	downloadedBinFile := binFile.Name() + "-downloaded"
-	defer os.Remove(downloadedBinFile)
-	downloadFile(t, env, clientBin, false, clientCred, binaryRepoName, downloadedBinFile, binSuffix)
-	compareFiles(t, binFile.Name(), downloadedBinFile)
-	checkFileType(t, downloadedBinFile, `{"Type":"application/octet-stream","Encoding":""}`)
-
-	// Download the compressed version of the binary file and
-	// check that it matches the original one and that it has the
-	// right file type.
-	downloadedTarFile := binFile.Name() + "-downloaded.tar.gz"
-	defer os.Remove(downloadedTarFile)
-	downloadFile(t, env, clientBin, false, clientCred, binaryRepoName, downloadedTarFile, tarSuffix)
-	compareFiles(t, tarFile, downloadedTarFile)
-	checkFileType(t, downloadedTarFile, `{"Type":"application/x-tar","Encoding":"gzip"}`)
-
-	// Fetch the root URL of the HTTP server used by the binary
-	// repository to serve URLs.
-	root := rootURL(t, env, clientBin, clientCred, binaryRepoName)
-
-	// Download the binary file using the HTTP protocol and check
-	// that it matches the original one.
-	downloadedBinFileURL := binFile.Name() + "-downloaded-url"
-	defer os.Remove(downloadedBinFileURL)
-	downloadURL(t, downloadedBinFileURL, root, binSuffix)
-	compareFiles(t, downloadedBinFile, downloadedBinFileURL)
-
-	// Download the compressed version of the binary file using
-	// the HTTP protocol and check that it matches the original
-	// one.
-	downloadedTarFileURL := binFile.Name() + "-downloaded-url.tar.gz"
-	defer os.Remove(downloadedTarFileURL)
-	downloadURL(t, downloadedTarFileURL, root, tarSuffix)
-	compareFiles(t, downloadedTarFile, downloadedTarFileURL)
-
-	// Delete the files.
-	deleteFile(env, clientBin, clientCred, binaryRepoName, binSuffix)
-	deleteFile(env, clientBin, clientCred, binaryRepoName, tarSuffix)
-
-	// Check the files no longer exist.
-	downloadFile(t, env, clientBin, true, clientCred, binaryRepoName, downloadedBinFile, binSuffix)
-	downloadFile(t, env, clientBin, true, clientCred, binaryRepoName, downloadedTarFile, tarSuffix)
-}
diff --git a/services/mgmt/binary/binaryd/v23_test.go b/services/mgmt/binary/binaryd/v23_test.go
new file mode 100644
index 0000000..a74c88b
--- /dev/null
+++ b/services/mgmt/binary/binaryd/v23_test.go
@@ -0,0 +1,22 @@
+// This file was auto-generated via go generate.
+// DO NOT UPDATE MANUALLY
+package main_test
+
+import "testing"
+import "os"
+
+import "v.io/core/veyron/lib/testutil"
+import "v.io/core/veyron/lib/testutil/v23tests"
+
+func TestMain(m *testing.M) {
+	testutil.Init()
+	cleanup := v23tests.UseSharedBinDir()
+	r := m.Run()
+	cleanup()
+	// TODO(cnicolaou): call modules.Dispatch and remove the need for TestHelperProcess
+	os.Exit(r)
+}
+
+func TestV23BinaryRepositoryIntegration(t *testing.T) {
+	v23tests.RunTest(t, V23TestBinaryRepositoryIntegration)
+}
diff --git a/services/mgmt/build/buildd/testdata/integration_test.go b/services/mgmt/build/buildd/buildd_v23_test.go
similarity index 69%
rename from services/mgmt/build/buildd/testdata/integration_test.go
rename to services/mgmt/build/buildd/buildd_v23_test.go
index 6a8f0e1..a3391cd 100644
--- a/services/mgmt/build/buildd/testdata/integration_test.go
+++ b/services/mgmt/build/buildd/buildd_v23_test.go
@@ -1,4 +1,4 @@
-package integration_test
+package main_test
 
 import (
 	"bytes"
@@ -8,14 +8,13 @@
 	"path/filepath"
 	"runtime"
 	"strings"
-	"testing"
 
-	"v.io/core/veyron/lib/modules"
 	"v.io/core/veyron/lib/testutil/security"
 	"v.io/core/veyron/lib/testutil/v23tests"
-	_ "v.io/core/veyron/profiles"
 )
 
+//go:generate v23 test generate
+
 var testProgram = `package main
 
 import "fmt"
@@ -23,14 +22,8 @@
 func main() { fmt.Println("Hello World!") }
 `
 
-func TestHelperProcess(t *testing.T) {
-	modules.DispatchInTest()
-}
-
-func TestBuildServerIntegration(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
+func V23TestBuildServerIntegration(i v23tests.T) {
+	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	// Generate credentials.
 	serverCred, serverPrin := security.NewCredentials("server")
@@ -39,11 +32,11 @@
 	defer os.RemoveAll(clientCred)
 
 	// Start the build server.
-	buildServerBin := env.BuildGoPkg("v.io/core/veyron/services/mgmt/build/buildd")
+	buildServerBin := i.BuildGoPkg("v.io/core/veyron/services/mgmt/build/buildd")
 	buildServerName := "test-build-server"
 	goBin, err := exec.LookPath("go")
 	if err != nil {
-		t.Fatalf("%v", err)
+		i.Fatalf("%v", err)
 	}
 	goRoot := runtime.GOROOT()
 	args := []string{
@@ -54,35 +47,35 @@
 	buildServerBin.Start(args...)
 
 	// Create and build a test source file.
-	testGoPath := env.TempDir()
+	testGoPath := i.TempDir()
 	testBinDir := filepath.Join(testGoPath, "bin")
 	if err := os.MkdirAll(testBinDir, os.FileMode(0700)); err != nil {
-		t.Fatalf("MkdirAll(%v) failed: %v", testBinDir, err)
+		i.Fatalf("MkdirAll(%v) failed: %v", testBinDir, err)
 	}
 	testBinFile := filepath.Join(testBinDir, "test")
 	testSrcDir := filepath.Join(testGoPath, "src", "test")
 	if err := os.MkdirAll(testSrcDir, os.FileMode(0700)); err != nil {
-		t.Fatalf("MkdirAll(%v) failed: %v", testSrcDir, err)
+		i.Fatalf("MkdirAll(%v) failed: %v", testSrcDir, err)
 	}
 	testSrcFile := filepath.Join(testSrcDir, "test.go")
 	if err := ioutil.WriteFile(testSrcFile, []byte(testProgram), os.FileMode(0600)); err != nil {
-		t.Fatalf("WriteFile(%v) failed: %v", testSrcFile, err)
+		i.Fatalf("WriteFile(%v) failed: %v", testSrcFile, err)
 	}
 	buildArgs := []string{
 		"-veyron.credentials=" + clientCred,
 		"build", buildServerName, "test",
 	}
 	buildEnv := []string{"GOPATH=" + testGoPath, "GOROOT=" + goRoot, "TMPDIR=" + testBinDir}
-	buildBin := env.BuildGoPkg("v.io/core/veyron/tools/build")
+	buildBin := i.BuildGoPkg("v.io/core/veyron/tools/build")
 	buildBin.WithEnv(buildEnv...).Start(buildArgs...).WaitOrDie(os.Stdout, os.Stderr)
 	var testOut bytes.Buffer
 	testCmd := exec.Command(testBinFile)
 	testCmd.Stdout = &testOut
 	testCmd.Stderr = &testOut
 	if err := testCmd.Run(); err != nil {
-		t.Fatalf("%q failed: %v\n%v", strings.Join(testCmd.Args, " "), err, testOut.String())
+		i.Fatalf("%q failed: %v\n%v", strings.Join(testCmd.Args, " "), err, testOut.String())
 	}
 	if got, want := strings.TrimSpace(testOut.String()), "Hello World!"; got != want {
-		t.Fatalf("unexpected output: got %v, want %v", got, want)
+		i.Fatalf("unexpected output: got %v, want %v", got, want)
 	}
 }
diff --git a/services/mgmt/build/buildd/v23_test.go b/services/mgmt/build/buildd/v23_test.go
new file mode 100644
index 0000000..6c1a4c8
--- /dev/null
+++ b/services/mgmt/build/buildd/v23_test.go
@@ -0,0 +1,22 @@
+// This file was auto-generated via go generate.
+// DO NOT UPDATE MANUALLY
+package main_test
+
+import "testing"
+import "os"
+
+import "v.io/core/veyron/lib/testutil"
+import "v.io/core/veyron/lib/testutil/v23tests"
+
+func TestMain(m *testing.M) {
+	testutil.Init()
+	cleanup := v23tests.UseSharedBinDir()
+	r := m.Run()
+	cleanup()
+	// TODO(cnicolaou): call modules.Dispatch and remove the need for TestHelperProcess
+	os.Exit(r)
+}
+
+func TestV23BuildServerIntegration(t *testing.T) {
+	v23tests.RunTest(t, V23TestBuildServerIntegration)
+}
diff --git a/services/mgmt/profile/profiled/profiled_v23_test.go b/services/mgmt/profile/profiled/profiled_v23_test.go
new file mode 100644
index 0000000..4e862b7
--- /dev/null
+++ b/services/mgmt/profile/profiled/profiled_v23_test.go
@@ -0,0 +1,89 @@
+package main_test
+
+import (
+	"os"
+	"strings"
+
+	"v.io/core/veyron/lib/testutil/v23tests"
+	"v.io/core/veyron2/naming"
+)
+
+//go:generate v23 test generate
+
+func profileCommandOutput(i v23tests.T, profileBin v23tests.TestBinary, expectError bool, command, name, suffix string) string {
+	labelArgs := []string{
+		command, naming.Join(name, suffix),
+	}
+	labelCmd := profileBin.Start(labelArgs...)
+	out := labelCmd.Output()
+	err := labelCmd.Wait(os.Stdout, os.Stderr)
+	if err != nil && !expectError {
+		i.Fatalf("%s %q failed: %v\n%v", profileBin.Path(), strings.Join(labelArgs, " "), err, out)
+	}
+	if err == nil && expectError {
+		i.Fatalf("%s %q did not fail when it should", profileBin.Path(), strings.Join(labelArgs, " "))
+	}
+	return strings.TrimSpace(out)
+}
+
+func putProfile(i v23tests.T, profileBin v23tests.TestBinary, 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) {
+	removeArgs := []string{
+		"remove", naming.Join(name, suffix),
+	}
+	profileBin.Start(removeArgs...).WaitOrDie(os.Stdout, os.Stderr)
+}
+
+func V23TestProfileRepository(i v23tests.T) {
+	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
+
+	// Start the profile repository.
+	profileRepoName := "test-profile-repo"
+	profileRepoStore := i.TempDir()
+	args := []string{
+		"-name=" + profileRepoName, "-store=" + profileRepoStore,
+		"-veyron.tcp.address=127.0.0.1:0",
+	}
+	i.BuildGoPkg("v.io/core/veyron/services/mgmt/profile/profiled").Start(args...)
+
+	clientBin := i.BuildGoPkg("v.io/core/veyron/tools/profile")
+
+	// Create a profile.
+	const profile = "test-profile"
+	putProfile(i, clientBin, profileRepoName, profile)
+
+	// Retrieve the profile label and check it matches the
+	// expected label.
+	profileLabel := profileCommandOutput(i, clientBin, false, "label", profileRepoName, profile)
+	if got, want := profileLabel, "example"; got != want {
+		i.Fatalf("unexpected output: got %v, want %v", got, want)
+	}
+
+	// Retrieve the profile description and check it matches the
+	// expected description.
+	profileDesc := profileCommandOutput(i, clientBin, false, "description", profileRepoName, profile)
+	if got, want := profileDesc, "Example profile to test the profile manager implementation."; got != want {
+		i.Fatalf("unexpected output: got %v, want %v", got, want)
+	}
+
+	// Retrieve the profile specification and check it matches the
+	// expected specification.
+	profileSpec := profileCommandOutput(i, clientBin, false, "specification", profileRepoName, profile)
+	if got, want := profileSpec, `profile.Specification{Label:"example", Description:"Example profile to test the profile manager implementation.", Arch:"amd64", OS:"linux", Format:"ELF", Libraries:map[profile.Library]struct {}{profile.Library{Name:"foo", MajorVersion:"1", MinorVersion:"0"}:struct {}{}}}`; got != want {
+		i.Fatalf("unexpected output: got %v, want %v", got, want)
+	}
+
+	// Remove the profile.
+	removeProfile(i, clientBin, profileRepoName, profile)
+
+	// Check that the profile no longer exists.
+	profileCommandOutput(i, clientBin, true, "label", profileRepoName, profile)
+	profileCommandOutput(i, clientBin, true, "description", profileRepoName, profile)
+	profileCommandOutput(i, clientBin, true, "specification", profileRepoName, profile)
+}
diff --git a/services/mgmt/profile/profiled/testdata/integration_test.go b/services/mgmt/profile/profiled/testdata/integration_test.go
deleted file mode 100644
index 1d76a11..0000000
--- a/services/mgmt/profile/profiled/testdata/integration_test.go
+++ /dev/null
@@ -1,91 +0,0 @@
-package integration_test
-
-import (
-	"os"
-	"strings"
-	"testing"
-
-	"v.io/core/veyron/lib/testutil/v23tests"
-	_ "v.io/core/veyron/profiles"
-	"v.io/core/veyron2/naming"
-)
-
-func profileCommandOutput(t *testing.T, env v23tests.T, profileBin v23tests.TestBinary, expectError bool, command, name, suffix string) string {
-	labelArgs := []string{
-		command, naming.Join(name, suffix),
-	}
-	labelCmd := profileBin.Start(labelArgs...)
-	out := labelCmd.Output()
-	err := labelCmd.Wait(os.Stdout, os.Stderr)
-	if err != nil && !expectError {
-		t.Fatalf("%s %q failed: %v\n%v", profileBin.Path(), strings.Join(labelArgs, " "), err, out)
-	}
-	if err == nil && expectError {
-		t.Fatalf("%s %q did not fail when it should", profileBin.Path(), strings.Join(labelArgs, " "))
-	}
-	return strings.TrimSpace(out)
-}
-
-func putProfile(t *testing.T, env v23tests.T, profileBin v23tests.TestBinary, name, suffix string) {
-	putArgs := []string{
-		"put", naming.Join(name, suffix),
-	}
-	profileBin.Start(putArgs...).WaitOrDie(os.Stdout, os.Stderr)
-}
-
-func removeProfile(t *testing.T, env v23tests.T, profileBin v23tests.TestBinary, name, suffix string) {
-	removeArgs := []string{
-		"remove", naming.Join(name, suffix),
-	}
-	profileBin.Start(removeArgs...).WaitOrDie(os.Stdout, os.Stderr)
-}
-
-func TestProfileRepository(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
-
-	// Start the profile repository.
-	profileRepoName := "test-profile-repo"
-	profileRepoStore := env.TempDir()
-	args := []string{
-		"-name=" + profileRepoName, "-store=" + profileRepoStore,
-		"-veyron.tcp.address=127.0.0.1:0",
-	}
-	env.BuildGoPkg("v.io/core/veyron/services/mgmt/profile/profiled").Start(args...)
-
-	clientBin := env.BuildGoPkg("v.io/core/veyron/tools/profile")
-
-	// Create a profile.
-	const profile = "test-profile"
-	putProfile(t, env, clientBin, profileRepoName, profile)
-
-	// Retrieve the profile label and check it matches the
-	// expected label.
-	profileLabel := profileCommandOutput(t, env, clientBin, false, "label", profileRepoName, profile)
-	if got, want := profileLabel, "example"; got != want {
-		t.Fatalf("unexpected output: got %v, want %v", got, want)
-	}
-
-	// Retrieve the profile description and check it matches the
-	// expected description.
-	profileDesc := profileCommandOutput(t, env, clientBin, false, "description", profileRepoName, profile)
-	if got, want := profileDesc, "Example profile to test the profile manager implementation."; got != want {
-		t.Fatalf("unexpected output: got %v, want %v", got, want)
-	}
-
-	// Retrieve the profile specification and check it matches the
-	// expected specification.
-	profileSpec := profileCommandOutput(t, env, clientBin, false, "specification", profileRepoName, profile)
-	if got, want := profileSpec, `profile.Specification{Label:"example", Description:"Example profile to test the profile manager implementation.", Arch:"amd64", OS:"linux", Format:"ELF", Libraries:map[profile.Library]struct {}{profile.Library{Name:"foo", MajorVersion:"1", MinorVersion:"0"}:struct {}{}}}`; got != want {
-		t.Fatalf("unexpected output: got %v, want %v", got, want)
-	}
-
-	// Remove the profile.
-	removeProfile(t, env, clientBin, profileRepoName, profile)
-
-	// Check that the profile no longer exists.
-	profileCommandOutput(t, env, clientBin, true, "label", profileRepoName, profile)
-	profileCommandOutput(t, env, clientBin, true, "description", profileRepoName, profile)
-	profileCommandOutput(t, env, clientBin, true, "specification", profileRepoName, profile)
-}
diff --git a/services/mgmt/profile/profiled/v23_test.go b/services/mgmt/profile/profiled/v23_test.go
new file mode 100644
index 0000000..2917072
--- /dev/null
+++ b/services/mgmt/profile/profiled/v23_test.go
@@ -0,0 +1,22 @@
+// This file was auto-generated via go generate.
+// DO NOT UPDATE MANUALLY
+package main_test
+
+import "testing"
+import "os"
+
+import "v.io/core/veyron/lib/testutil"
+import "v.io/core/veyron/lib/testutil/v23tests"
+
+func TestMain(m *testing.M) {
+	testutil.Init()
+	cleanup := v23tests.UseSharedBinDir()
+	r := m.Run()
+	cleanup()
+	// TODO(cnicolaou): call modules.Dispatch and remove the need for TestHelperProcess
+	os.Exit(r)
+}
+
+func TestV23ProfileRepository(t *testing.T) {
+	v23tests.RunTest(t, V23TestProfileRepository)
+}
diff --git a/services/mounttable/mounttabled/testdata/integration_test.go b/services/mounttable/mounttabled/mounttabled_v23_test.go
similarity index 64%
rename from services/mounttable/mounttabled/testdata/integration_test.go
rename to services/mounttable/mounttabled/mounttabled_v23_test.go
index 4c9dd9d..5db9f1d 100644
--- a/services/mounttable/mounttabled/testdata/integration_test.go
+++ b/services/mounttable/mounttabled/mounttabled_v23_test.go
@@ -1,43 +1,40 @@
-package testdata
+package main_test
 
 import (
 	"fmt"
 	"os"
 	"regexp"
-	"testing"
 
 	"v.io/core/veyron/lib/testutil/v23tests"
-	_ "v.io/core/veyron/profiles/static"
 )
 
-func getHostname(t *testing.T) string {
+//go:generate v23 test generate
+
+func getHostname(i v23tests.T) string {
 	if hostname, err := os.Hostname(); err != nil {
-		t.Fatalf("Hostname() failed: %v", err)
+		i.Fatalf("Hostname() failed: %v", err)
 		return ""
 	} else {
 		return hostname
 	}
 }
 
-func TestMount(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
+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)
 
-	neighborhood := fmt.Sprintf("test-%s-%d", getHostname(t), os.Getpid())
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0", "--neighborhood_name="+neighborhood)
+	name, _ := i.GetVar("NAMESPACE_ROOT")
 
-	name, _ := env.GetVar("NAMESPACE_ROOT")
-
-	clientBin := env.BuildGoPkg("v.io/core/veyron/tools/mounttable")
+	clientBin := i.BuildGoPkg("v.io/core/veyron/tools/mounttable")
 
 	// Get the neighborhood endpoint from the mounttable.
 	neighborhoodEndpoint := clientBin.Start("glob", name, "nh").ExpectSetEventuallyRE(`^nh (.*) \(TTL .*\)$`)[0][1]
 
 	if clientBin.Start("mount", name+"/myself", name, "5m").Wait(os.Stdout, os.Stderr) != nil {
-		t.Fatalf("failed to mount the mounttable on itself")
+		i.Fatalf("failed to mount the mounttable on itself")
 	}
 	if clientBin.Start("mount", name+"/google", "/www.google.com:80", "5m").Wait(os.Stdout, os.Stderr) != nil {
-		t.Fatalf("failed to mount www.google.com")
+		i.Fatalf("failed to mount www.google.com")
 	}
 
 	// Test glob output. We expect three entries (two we mounted plus the
@@ -49,7 +46,7 @@
 		`^myself (.*) \(TTL .*\)$`,
 		`^nh `+regexp.QuoteMeta(neighborhoodEndpoint)+` \(TTL .*\)$`)
 	if matches[1][1] != name {
-		t.Fatalf("expected 'myself' entry to be %q, but was %q", name, matches[1][1])
+		i.Fatalf("expected 'myself' entry to be %q, but was %q", name, matches[1][1])
 	}
 
 	// Test globbing on the neighborhood name. Its endpoint should be the
@@ -57,6 +54,6 @@
 	glob = clientBin.Start("glob", "/"+neighborhoodEndpoint, neighborhood)
 	matches = glob.ExpectSetEventuallyRE("^" + regexp.QuoteMeta(neighborhood) + ` (.*) \(TTL .*\)$`)
 	if matches[0][1] != name {
-		t.Fatalf("expected endpoint of mount table for name %s", neighborhood)
+		i.Fatalf("expected endpoint of mount table for name %s", neighborhood)
 	}
 }
diff --git a/services/mounttable/mounttabled/v23_test.go b/services/mounttable/mounttabled/v23_test.go
new file mode 100644
index 0000000..7cfad44
--- /dev/null
+++ b/services/mounttable/mounttabled/v23_test.go
@@ -0,0 +1,22 @@
+// This file was auto-generated via go generate.
+// DO NOT UPDATE MANUALLY
+package main_test
+
+import "testing"
+import "os"
+
+import "v.io/core/veyron/lib/testutil"
+import "v.io/core/veyron/lib/testutil/v23tests"
+
+func TestMain(m *testing.M) {
+	testutil.Init()
+	cleanup := v23tests.UseSharedBinDir()
+	r := m.Run()
+	cleanup()
+	// TODO(cnicolaou): call modules.Dispatch and remove the need for TestHelperProcess
+	os.Exit(r)
+}
+
+func TestV23Mount(t *testing.T) {
+	v23tests.RunTest(t, V23TestMount)
+}
diff --git a/tools/debug/debug_v23_test.go b/tools/debug/debug_v23_test.go
new file mode 100644
index 0000000..7f66e0f
--- /dev/null
+++ b/tools/debug/debug_v23_test.go
@@ -0,0 +1,216 @@
+package main_test
+
+import (
+	"bufio"
+	"fmt"
+	"os"
+	"path/filepath"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+
+	"v.io/core/veyron/lib/testutil/v23tests"
+)
+
+//go:generate v23 test generate
+
+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")
+	inv := binary.Start("glob", "__debug/*")
+
+	var want string
+	for _, entry := range []string{"logs", "pprof", "stats", "vtrace"} {
+		want += "__debug/" + entry + "\n"
+	}
+	if got := inv.Output(); got != want {
+		i.Fatalf("unexpected output, want %s, got %s", want, got)
+	}
+}
+
+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.
+	fileName := filepath.Base(i.TempFile().Name())
+	binary := i.BuildGoPkg("v.io/core/veyron/tools/debug")
+	output := binary.Start("glob", "__debug/logs/*").Output()
+
+	// The output should contain the filename.
+	want := "/logs/" + fileName
+	if !strings.Contains(output, want) {
+		i.Fatalf("output should contain %s but did not\n%s", want, output)
+	}
+}
+
+func V23TestReadHostname(i v23tests.T) {
+	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
+
+	path := "__debug/stats/system/hostname"
+	binary := i.BuildGoPkg("v.io/core/veyron/tools/debug")
+	got := binary.Start("stats", "read", path).Output()
+	hostname, err := os.Hostname()
+	if err != nil {
+		i.Fatalf("Hostname() failed: %v", err)
+	}
+	if want := path + ": " + hostname + "\n"; got != want {
+		i.Fatalf("unexpected output, want %q, got %q", want, got)
+	}
+}
+
+func createTestLogFile(i v23tests.T, content string) *os.File {
+	file := i.TempFile()
+	_, err := file.Write([]byte(content))
+	if err != nil {
+		i.Fatalf("Write failed: %v", err)
+	}
+	return file
+}
+
+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")
+	testLogData := "This is a test log file"
+	file := createTestLogFile(i, testLogData)
+
+	// Check to ensure the file size is accurate
+	str := strings.TrimSpace(binary.Start("logs", "size", "__debug/logs/"+filepath.Base(file.Name())).Output())
+	got, err := strconv.Atoi(str)
+	if err != nil {
+		i.Fatalf("Atoi(\"%q\") failed", str)
+	}
+	want := len(testLogData)
+	if got != want {
+		i.Fatalf("unexpected output, want %d, got %d", got, want)
+	}
+}
+
+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")
+	testLogData := "This is a test log file\n"
+	file := createTestLogFile(i, testLogData)
+	logName := filepath.Base(file.Name())
+	runCount := 12
+	for i := 0; i < runCount; i++ {
+		binary.Start("logs", "read", "__debug/logs/"+logName).WaitOrDie(nil, nil)
+	}
+
+	got := binary.Start("stats", "read", "__debug/stats/ipc/server/routing-id/*/methods/ReadLog/latency-ms").Output()
+
+	want := fmt.Sprintf("Count: %d", runCount)
+	if !strings.Contains(got, want) {
+		i.Fatalf("expected output to contain %s, but did not\n", want, got)
+	}
+}
+
+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")
+	testLogData := "This is a test log file\n"
+	file := createTestLogFile(i, testLogData)
+	logName := filepath.Base(file.Name())
+	binary.Start("logs", "read", "__debug/logs/"+logName).WaitOrDie(nil, nil)
+
+	inv := binary.Start("stats", "watch", "-raw", "__debug/stats/ipc/server/routing-id/*/methods/ReadLog/latency-ms")
+
+	lineChan := make(chan string)
+	// Go off and read the invocation's stdout.
+	go func() {
+		line, err := bufio.NewReader(inv.Stdout()).ReadString('\n')
+		if err != nil {
+			i.Fatalf("Could not read line from invocation")
+		}
+		lineChan <- line
+	}()
+
+	// Wait up to 10 seconds for some stats output. Either some output
+	// occurs or the timeout expires without any output.
+	select {
+	case <-time.After(10 * time.Second):
+		i.Errorf("Timed out waiting for output")
+	case got := <-lineChan:
+		// Expect one ReadLog call to have occurred.
+		want := "latency-ms: {Count:1"
+		if !strings.Contains(got, want) {
+			i.Errorf("wanted but could not find %q in output\n%s", want, got)
+		}
+	}
+}
+
+func performTracedRead(debugBinary v23tests.TestBinary, path string) string {
+	return debugBinary.Start("--veyron.vtrace.sample_rate=1", "logs", "read", path).Output()
+}
+
+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")
+	logContent := "Hello, world!\n"
+	logPath := "__debug/logs/" + filepath.Base(createTestLogFile(i, logContent).Name())
+	// Create a log file with tracing, read it and check that the resulting trace exists.
+	got := performTracedRead(binary, logPath)
+	if logContent != got {
+		i.Fatalf("unexpected output: want %s, got %s", logContent, got)
+	}
+
+	// Grab the ID of the first and only trace.
+	want, traceContent := 1, binary.Start("vtrace", "__debug/vtrace").Output()
+	if count := strings.Count(traceContent, "Trace -"); count != want {
+		i.Fatalf("unexpected trace count, want %d, got %d\n%s", want, count, traceContent)
+	}
+	fields := strings.Split(traceContent, " ")
+	if len(fields) < 3 {
+		i.Fatalf("expected at least 3 space-delimited fields, got %d\n", len(fields), traceContent)
+	}
+	traceId := fields[2]
+
+	// Do a sanity check on the trace ID: it should be a 32-character hex ID prefixed with 0x
+	if match, _ := regexp.MatchString("0x[0-9a-f]{32}", traceId); !match {
+		i.Fatalf("wanted a 32-character hex ID prefixed with 0x, got %s", traceId)
+	}
+
+	// Do another traced read, this will generate a new trace entry.
+	performTracedRead(binary, logPath)
+
+	// Read vtrace, we should have 2 traces now.
+	want, output := 2, binary.Start("vtrace", "__debug/vtrace").Output()
+	if count := strings.Count(output, "Trace -"); count != want {
+		i.Fatalf("unexpected trace count, want %d, got %d\n%s", want, count, output)
+	}
+
+	// Now ask for a particular trace. The output should contain exactly
+	// one trace whose ID is equal to the one we asked for.
+	want, got = 1, binary.Start("vtrace", "__debug/vtrace", traceId).Output()
+	if count := strings.Count(got, "Trace -"); count != want {
+		i.Fatalf("unexpected trace count, want %d, got %d\n%s", want, count, got)
+	}
+	fields = strings.Split(got, " ")
+	if len(fields) < 3 {
+		i.Fatalf("expected at least 3 space-delimited fields, got %d\n", len(fields), got)
+	}
+	got = fields[2]
+	if traceId != got {
+		i.Fatalf("unexpected traceId, want %s, got %s", traceId, got)
+	}
+}
+
+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")
+	inv := binary.Start("pprof", "run", "__debug/pprof", "heap", "--text")
+
+	// Assert that a profile indicating the heap size was written out.
+	want, got := "(.*) of (.*) total", inv.Output()
+	var groups []string
+	if groups = regexp.MustCompile(want).FindStringSubmatch(got); len(groups) < 3 {
+		i.Fatalf("could not find regexp %q in output\n%s", want, got)
+	}
+	i.Logf("got a heap profile showing a heap size of %s", groups[2])
+}
diff --git a/tools/debug/testdata/integration_test.go b/tools/debug/testdata/integration_test.go
deleted file mode 100644
index 0a09142..0000000
--- a/tools/debug/testdata/integration_test.go
+++ /dev/null
@@ -1,237 +0,0 @@
-package testdata
-
-import (
-	"bufio"
-	"fmt"
-	"os"
-	"path/filepath"
-	"regexp"
-	"strconv"
-	"strings"
-	"testing"
-	"time"
-
-	"v.io/core/veyron/lib/testutil/v23tests"
-	_ "v.io/core/veyron/profiles/static"
-)
-
-// TODO(sjr): consolidate some of these tests to amortize the cost
-// of the build/setup times.
-
-// TODO(sjr): caching of binaries is limited to a single instance of
-// of the integration environment which makes this test very slow.
-func TestDebugGlob(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
-
-	binary := env.BuildGoPkg("v.io/core/veyron/tools/debug")
-	inv := binary.Start("glob", "__debug/*")
-
-	var want string
-	for _, entry := range []string{"logs", "pprof", "stats", "vtrace"} {
-		want += "__debug/" + entry + "\n"
-	}
-	if got := inv.Output(); got != want {
-		t.Fatalf("unexpected output, want %s, got %s", want, got)
-	}
-}
-
-func TestDebugGlobLogs(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
-
-	fileName := filepath.Base(env.TempFile().Name())
-	binary := env.BuildGoPkg("v.io/core/veyron/tools/debug")
-	output := binary.Start("glob", "__debug/logs/*").Output()
-
-	// The output should contain the filename.
-	want := "/logs/" + fileName
-	if !strings.Contains(output, want) {
-		t.Fatalf("output should contain %s but did not\n%s", want, output)
-	}
-}
-
-func TestReadHostname(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
-
-	path := "__debug/stats/system/hostname"
-	binary := env.BuildGoPkg("v.io/core/veyron/tools/debug")
-	got := binary.Start("stats", "read", path).Output()
-	hostname, err := os.Hostname()
-	if err != nil {
-		t.Fatalf("Hostname() failed: %v", err)
-	}
-	if want := path + ": " + hostname + "\n"; got != want {
-		t.Fatalf("unexpected output, want %s, got %s", want, got)
-	}
-}
-
-func createTestLogFile(t *testing.T, env v23tests.T, content string) *os.File {
-	file := env.TempFile()
-	_, err := file.Write([]byte(content))
-	if err != nil {
-		t.Fatalf("Write failed: %v", err)
-	}
-	return file
-}
-
-func TestLogSize(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
-
-	binary := env.BuildGoPkg("v.io/core/veyron/tools/debug")
-	testLogData := "This is a test log file"
-	file := createTestLogFile(t, env, testLogData)
-
-	// Check to ensure the file size is accurate
-	str := strings.TrimSpace(binary.Start("logs", "size", "__debug/logs/"+filepath.Base(file.Name())).Output())
-	got, err := strconv.Atoi(str)
-	if err != nil {
-		t.Fatalf("Atoi(\"%q\") failed", str)
-	}
-	want := len(testLogData)
-	if got != want {
-		t.Fatalf("unexpected output, want %d, got %d", got, want)
-	}
-}
-
-func TestStatsRead(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
-
-	binary := env.BuildGoPkg("v.io/core/veyron/tools/debug")
-	testLogData := "This is a test log file\n"
-	file := createTestLogFile(t, env, testLogData)
-	logName := filepath.Base(file.Name())
-	runCount := 12
-	for i := 0; i < runCount; i++ {
-		binary.Start("logs", "read", "__debug/logs/"+logName).WaitOrDie(nil, nil)
-	}
-
-	got := binary.Start("stats", "read", "__debug/stats/ipc/server/routing-id/*/methods/ReadLog/latency-ms").Output()
-
-	want := fmt.Sprintf("Count: %d", runCount)
-	if !strings.Contains(got, want) {
-		t.Fatalf("expected output to contain %s, but did not\n", want, got)
-	}
-}
-
-func TestStatsWatch(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
-
-	binary := env.BuildGoPkg("v.io/core/veyron/tools/debug")
-	testLogData := "This is a test log file\n"
-	file := createTestLogFile(t, env, testLogData)
-	logName := filepath.Base(file.Name())
-	binary.Start("logs", "read", "__debug/logs/"+logName).WaitOrDie(nil, nil)
-
-	inv := binary.Start("stats", "watch", "-raw", "__debug/stats/ipc/server/routing-id/*/methods/ReadLog/latency-ms")
-
-	lineChan := make(chan string)
-	// Go off and read the invocation's stdout.
-	go func() {
-		line, err := bufio.NewReader(inv.Stdout()).ReadString('\n')
-		if err != nil {
-			t.Fatalf("Could not read line from invocation")
-		}
-		lineChan <- line
-	}()
-
-	// Wait up to 10 seconds for some stats output. Either some output
-	// occurs or the timeout expires without any output.
-	select {
-	case <-time.After(10 * time.Second):
-		t.Errorf("Timed out waiting for output")
-	case got := <-lineChan:
-		// Expect one ReadLog call to have occurred.
-		want := "latency-ms: {Count:1"
-		if !strings.Contains(got, want) {
-			t.Errorf("wanted but could not find %q in output\n%s", want, got)
-		}
-	}
-}
-
-func performTracedRead(debugBinary v23tests.TestBinary, path string) string {
-	return debugBinary.Start("--veyron.vtrace.sample_rate=1", "logs", "read", path).Output()
-}
-
-func TestVTrace(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
-
-	binary := env.BuildGoPkg("v.io/core/veyron/tools/debug")
-	logContent := "Hello, world!\n"
-	logPath := "__debug/logs/" + filepath.Base(createTestLogFile(t, env, logContent).Name())
-	// Create a log file with tracing, read it and check that the resulting trace exists.
-	got := performTracedRead(binary, logPath)
-	if logContent != got {
-		t.Fatalf("unexpected output: want %s, got %s", logContent, got)
-	}
-
-	// Grab the ID of the first and only trace.
-	want, traceContent := 1, binary.Start("vtrace", "__debug/vtrace").Output()
-	if count := strings.Count(traceContent, "Trace -"); count != want {
-		t.Fatalf("unexpected trace count, want %d, got %d\n%s", want, count, traceContent)
-	}
-	fields := strings.Split(traceContent, " ")
-	if len(fields) < 3 {
-		t.Fatalf("expected at least 3 space-delimited fields, got %d\n", len(fields), traceContent)
-	}
-	traceId := fields[2]
-
-	// Do a sanity check on the trace ID: it should be a 32-character hex ID prefixed with 0x
-	if match, _ := regexp.MatchString("0x[0-9a-f]{32}", traceId); !match {
-		t.Fatalf("wanted a 32-character hex ID prefixed with 0x, got %s", traceId)
-	}
-
-	// Do another traced read, this will generate a new trace entry.
-	performTracedRead(binary, logPath)
-
-	// Read vtrace, we should have 2 traces now.
-	want, output := 2, binary.Start("vtrace", "__debug/vtrace").Output()
-	if count := strings.Count(output, "Trace -"); count != want {
-		t.Fatalf("unexpected trace count, want %d, got %d\n%s", want, count, output)
-	}
-
-	// Now ask for a particular trace. The output should contain exactly
-	// one trace whose ID is equal to the one we asked for.
-	want, got = 1, binary.Start("vtrace", "__debug/vtrace", traceId).Output()
-	if count := strings.Count(got, "Trace -"); count != want {
-		t.Fatalf("unexpected trace count, want %d, got %d\n%s", want, count, got)
-	}
-	fields = strings.Split(got, " ")
-	if len(fields) < 3 {
-		t.Fatalf("expected at least 3 space-delimited fields, got %d\n", len(fields), got)
-	}
-	got = fields[2]
-	if traceId != got {
-		t.Fatalf("unexpected traceId, want %s, got %s", traceId, got)
-	}
-}
-
-func TestPprof(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
-
-	binary := env.BuildGoPkg("v.io/core/veyron/tools/debug")
-	inv := binary.Start("pprof", "run", "__debug/pprof", "heap", "--text")
-
-	// Assert that a profile indicating the heap size was written out.
-	want, got := "(.*) of (.*) total", inv.Output()
-	var groups []string
-	if groups = regexp.MustCompile(want).FindStringSubmatch(got); len(groups) < 3 {
-		t.Fatalf("could not find regexp %q in output\n%s", want, got)
-	}
-
-	t.Logf("got a heap profile showing a heap size of %s", groups[2])
-}
diff --git a/tools/debug/v23_test.go b/tools/debug/v23_test.go
new file mode 100644
index 0000000..0dc059b
--- /dev/null
+++ b/tools/debug/v23_test.go
@@ -0,0 +1,50 @@
+// This file was auto-generated via go generate.
+// DO NOT UPDATE MANUALLY
+package main_test
+
+import "testing"
+import "os"
+
+import "v.io/core/veyron/lib/testutil"
+import "v.io/core/veyron/lib/testutil/v23tests"
+
+func TestMain(m *testing.M) {
+	testutil.Init()
+	cleanup := v23tests.UseSharedBinDir()
+	r := m.Run()
+	cleanup()
+	// TODO(cnicolaou): call modules.Dispatch and remove the need for TestHelperProcess
+	os.Exit(r)
+}
+
+func TestV23DebugGlob(t *testing.T) {
+	v23tests.RunTest(t, V23TestDebugGlob)
+}
+
+func TestV23DebugGlobLogs(t *testing.T) {
+	v23tests.RunTest(t, V23TestDebugGlobLogs)
+}
+
+func TestV23ReadHostname(t *testing.T) {
+	v23tests.RunTest(t, V23TestReadHostname)
+}
+
+func TestV23LogSize(t *testing.T) {
+	v23tests.RunTest(t, V23TestLogSize)
+}
+
+func TestV23StatsRead(t *testing.T) {
+	v23tests.RunTest(t, V23TestStatsRead)
+}
+
+func TestV23StatsWatch(t *testing.T) {
+	v23tests.RunTest(t, V23TestStatsWatch)
+}
+
+func TestV23VTrace(t *testing.T) {
+	v23tests.RunTest(t, V23TestVTrace)
+}
+
+func TestV23Pprof(t *testing.T) {
+	v23tests.RunTest(t, V23TestPprof)
+}
diff --git a/tools/naming/simulator/simulator_test.go b/tools/naming/simulator/simulator_v23_test.go
similarity index 100%
rename from tools/naming/simulator/simulator_test.go
rename to tools/naming/simulator/simulator_v23_test.go
diff --git a/tools/naming/simulator/testdata/integration_test.go b/tools/naming/simulator/testdata/integration_test.go
deleted file mode 100644
index 12c8576..0000000
--- a/tools/naming/simulator/testdata/integration_test.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package testdata
-
-import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"regexp"
-	"testing"
-
-	"v.io/core/veyron/lib/modules"
-	"v.io/core/veyron/lib/testutil/v23tests"
-	_ "v.io/core/veyron/profiles/static"
-)
-
-func TestHelperProcess(t *testing.T) {
-	modules.DispatchInTest()
-}
-
-func TestSimulator(t *testing.T) {
-	env := v23tests.New(t)
-	defer env.Cleanup()
-	binary := env.BuildGoPkg("v.io/core/veyron/tools/naming/simulator")
-	files, err := ioutil.ReadDir(".")
-	if err != nil {
-		t.Fatal(err)
-	}
-	scripts := []string{}
-	re := regexp.MustCompile(`.*\.scr`)
-	for _, f := range files {
-		if !f.IsDir() && re.MatchString(f.Name()) {
-			scripts = append(scripts, f.Name())
-		}
-	}
-	for _, script := range scripts {
-		invocation := binary.Start("--file", script)
-		var stdout, stderr bytes.Buffer
-		if err := invocation.Wait(&stdout, &stderr); err != nil {
-			fmt.Fprintf(os.Stderr, "Script %v failed\n", script)
-			fmt.Fprintln(os.Stderr, stdout.String())
-			fmt.Fprintln(os.Stderr, stderr.String())
-			t.Error(err)
-		}
-	}
-}
diff --git a/tools/naming/simulator/v23_test.go b/tools/naming/simulator/v23_test.go
index be63305..9c42af4 100644
--- a/tools/naming/simulator/v23_test.go
+++ b/tools/naming/simulator/v23_test.go
@@ -10,8 +10,11 @@
 
 func TestMain(m *testing.M) {
 	testutil.Init()
+	cleanup := v23tests.UseSharedBinDir()
+	r := m.Run()
+	cleanup()
 	// TODO(cnicolaou): call modules.Dispatch and remove the need for TestHelperProcess
-	os.Exit(m.Run())
+	os.Exit(r)
 }
 
 func TestV23Simulator(t *testing.T) {
diff --git a/tools/principal/v23_test.go b/tools/principal/v23_test.go
index 4e12189..613e3c3 100644
--- a/tools/principal/v23_test.go
+++ b/tools/principal/v23_test.go
@@ -10,8 +10,11 @@
 
 func TestMain(m *testing.M) {
 	testutil.Init()
+	cleanup := v23tests.UseSharedBinDir()
+	r := m.Run()
+	cleanup()
 	// TODO(cnicolaou): call modules.Dispatch and remove the need for TestHelperProcess
-	os.Exit(m.Run())
+	os.Exit(r)
 }
 
 func TestV23BlessSelf(t *testing.T) {