// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Test the device manager and related services and tools.
//
// By default, this script tests the device manager in a fashion amenable
// to automatic testing: the --single_user is passed to the device
// manager so that all device manager components run as the same user and
// no user input (such as an agent pass phrase) is needed.
//
// This script can exercise the device manager in two different modes. It
// can be executed like so:
//
//   jiri go test -v . --v23.tests
//
// This will exercise the device manager's single user mode where all
// processes run as the same invoking user.
//
// Alternatively, the device manager can be executed in multiple account
// mode by providing the --deviceuser <deviceuser> and --appuser
// <appuser> flags. In this case, the device manager will run as user
// <devicemgr> and the test will run applications as user <appuser>. If
// executed in this fashion, root permissions will be required to install
// and it may require configuring an agent passphrase. For example:
//
//   jiri go test -v . --v23.tests --deviceuser devicemanager --appuser  vana
//
// NB: the accounts provided as arguments to this test must already exist.
// Also, the --v23.tests.shell-on-fail flag is useful to enable debugging
// output. Note that this flag does not work for some shells. Set
// $SHELL in that case.

package device_test

import (
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"os"
	"os/user"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
	"sync"
	"testing"
	"time"

	"v.io/x/lib/gosh"
	"v.io/x/ref"
	"v.io/x/ref/lib/v23test"
	_ "v.io/x/ref/runtime/factories/generic"
	"v.io/x/ref/test/testutil"
)

var (
	appUserFlag    string
	deviceUserFlag string
	hostname       string
	errTimeout     = errors.New("timeout")
)

func init() {
	flag.StringVar(&appUserFlag, "appuser", "", "launch apps as the specified user")
	flag.StringVar(&deviceUserFlag, "deviceuser", "", "run the device manager as the specified user")
	name, err := os.Hostname()
	if err != nil {
		panic(fmt.Sprintf("Hostname() failed: %v", err))
	}
	hostname = name
}

func TestV23DeviceManagerSingleUser(t *testing.T) {
	v23test.SkipUnlessRunningIntegrationTests(t)
	sh := v23test.NewShell(t, v23test.Opts{})
	defer sh.Cleanup()

	u, err := user.Current()
	if err != nil {
		t.Fatalf("couldn't get the current user: %v", err)
	}
	testCore(t, sh, u.Username, "", false)
}

func TestV23DeviceManagerMultiUser(t *testing.T) {
	v23test.SkipUnlessRunningIntegrationTests(t)
	sh := v23test.NewShell(t, v23test.Opts{})
	defer sh.Cleanup()

	u, err := user.Current()
	if err != nil {
		t.Fatalf("couldn't get the current user: %v", err)
	}

	if u.Username == "veyron" && runTestOnThisPlatform {
		// We are running on the builder so run the multiuser
		// test with default user names. These will be created as
		// required.
		makeTestAccounts(t, sh)
		testCore(t, sh, "vana", "devicemanager", true)
		return
	}

	if len(deviceUserFlag) > 0 && len(appUserFlag) > 0 {
		testCore(t, sh, appUserFlag, deviceUserFlag, true)
	} else {
		t.Logf("Test skipped because running in multiuser mode requires --appuser and --deviceuser flags")
	}
}

func testCore(t *testing.T, sh *v23test.Shell, appUser, deviceUser string, withSuid bool) {
	defer fmt.Fprintf(os.Stderr, "--------------- SHUTDOWN ---------------\n")

	// Call sh.StartRootMountTable() first, since it updates sh.Vars, which is
	// copied by various Cmds at Cmd creation time.
	sh.StartRootMountTable()

	// When running with --with_suid, TMPDIR must grant the invoking user rwx
	// permissions and world x permissions for all parent directories back to /.
	// Otherwise, the with_suid user will not be able to use absolute paths. On
	// Darwin, TMPDIR defaults to a directory hierararchy in /var that is 0700.
	// This is unworkable, so force TMPDIR to /tmp in this case.
	//
	// In addition, even when running without --with_suid, on Darwin the default
	// TMPDIR results in "socket path (...) exceeds maximum allowed socket path
	// length" errors, so we always set TMPDIR to /tmp.
	oldTmpdir := os.Getenv("TMPDIR")
	os.Setenv("TMPDIR", "/tmp")
	defer os.Setenv("TMPDIR", oldTmpdir)

	var (
		workDir       = sh.MakeTempDir()
		binStagingDir = mkSubdir(t, workDir, "bin")
		dmInstallDir  = filepath.Join(workDir, "dm")

		// Most vanadium command-line utilities will be run by a
		// principal that has "root:u:alice" as its blessing.
		// (Where "root" comes from i.Principal().BlessingStore().Default()).
		// Create those credentials and options to use to setup the
		// binaries with them.
		aliceCreds = sh.ForkCredentials("u:alice")

		// Build all the command-line tools and set them up to run as alice.
		// applicationd/binaryd servers will be run by alice too.
		// TODO: applicationd/binaryd should run as a separate "service" role, as
		// alice is just a user.
		namespaceBin    = sh.Cmd(sh.BuildGoPkg("v.io/x/ref/cmd/namespace")).WithCredentials(aliceCreds)
		deviceBin       = sh.Cmd(sh.BuildGoPkg("v.io/x/ref/services/device/device")).WithCredentials(aliceCreds)
		binarydBin      = sh.Cmd(sh.BuildGoPkg("v.io/x/ref/services/binary/binaryd")).WithCredentials(aliceCreds)
		applicationdBin = sh.Cmd(sh.BuildGoPkg("v.io/x/ref/services/application/applicationd")).WithCredentials(aliceCreds)

		// The devicex script is not provided with any credentials, it
		// will generate its own.  This means that on "devicex start"
		// the device will have no useful credentials and until "device
		// claim" is invoked (as alice), it will just sit around
		// waiting to be claimed.
		//
		// Other binaries, like applicationd and binaryd will be run by alice.
		deviceScript = sh.Cmd("./devicex")

		mtName = "devices/" + hostname // Name under which the device manager will publish itself.
	)
	deviceScript.Vars["V23_DEVICE_DIR"] = dmInstallDir
	delete(deviceScript.Vars, ref.EnvCredentials)

	// We also need some tools running with different sets of credentials...

	// Administration tasks will be performed with a blessing that represents a corporate
	// adminstrator (which is usually a role account)
	adminCreds := sh.ForkCredentials("r:admin")
	adminDeviceBin := deviceBin.WithCredentials(adminCreds)
	debugBin := sh.Cmd(sh.BuildGoPkg("v.io/x/ref/services/debug/debug")).WithCredentials(adminCreds)

	// A special set of credentials will be used to give two blessings to the device manager
	// when claiming it -- one blessing will be from the corporate administrator role who owns
	// the machine, and the other will be a manufacturer blessing. (This is a hack until
	// there's a way to separately supply a manufacturer blessing. Eventually, the claim
	// would really be done by the administator, and the adminstrator's blessing would get
	// added to the manufacturer's blessing, which would already be present.)
	claimCreds := sh.ForkCredentials("r:admin", "m:orange:zphone5:ime-i007")
	claimDeviceBin := deviceBin.WithCredentials(claimCreds)

	// Another set of credentials be used to represent the application publisher, who
	// signs and pushes binaries
	pubCreds := sh.ForkCredentials("a:rovio")
	pubDeviceBin := deviceBin.WithCredentials(pubCreds)
	applicationBin := sh.Cmd(sh.BuildGoPkg("v.io/x/ref/services/application/application")).WithCredentials(pubCreds)
	binaryBin := sh.Cmd(sh.BuildGoPkg("v.io/x/ref/services/binary/binary")).WithCredentials(pubCreds)

	if withSuid {
		// In multiuser mode, deviceUserFlag needs execute access to
		// tempDir.
		if err := os.Chmod(workDir, 0711); err != nil {
			t.Fatalf("os.Chmod() failed: %v", err)
		}
	}

	buildAndCopyBinaries(
		t, sh, binStagingDir,
		"v.io/x/ref/services/device/deviced",
		"v.io/x/ref/services/agent/agentd",
		"v.io/x/ref/services/device/suidhelper",
		"v.io/x/ref/services/device/inithelper")

	appDName := "applications"
	devicedAppName := filepath.Join(appDName, "deviced", "test")

	deviceScriptArguments := []string{
		"install",
		binStagingDir,
	}

	if withSuid {
		deviceScriptArguments = append(deviceScriptArguments, "--devuser="+deviceUser)
	} else {
		deviceScriptArguments = append(deviceScriptArguments, "--single_user")
	}

	deviceScriptArguments = append(deviceScriptArguments, []string{
		"--origin=" + devicedAppName,
		"--",
		"--v23.tcp.address=127.0.0.1:0",
		"--neighborhood-name=" + fmt.Sprintf("%s-%d-%d", hostname, os.Getpid(), rand.Int()),
	}...)

	withArgs(deviceScript, deviceScriptArguments...).Run()
	withArgs(deviceScript, "start").Run()
	dmLog := filepath.Join(dmInstallDir, "dmroot/device-manager/logs/deviced.INFO")
	stopDevMgr := func() {
		withArgs(deviceScript, "stop").Run()
		if dmLogF, err := os.Open(dmLog); err != nil {
			t.Errorf("Failed to read dm log: %v", err)
		} else {
			fmt.Fprintf(os.Stderr, "--------------- START DM LOG ---------------\n")
			defer dmLogF.Close()
			if _, err := io.Copy(os.Stderr, dmLogF); err != nil {
				t.Errorf("Error dumping dm log: %v", err)
			}
			fmt.Fprintf(os.Stderr, "--------------- END DM LOG ---------------\n")
		}
	}
	var stopDevMgrOnce sync.Once
	defer stopDevMgrOnce.Do(stopDevMgr)
	// Grab the endpoint for the claimable service from the device manager's
	// log.
	var claimableEP string
	expiry := time.Now().Add(30 * time.Second)
	for {
		if time.Now().After(expiry) {
			t.Fatalf("Timed out looking for claimable endpoint in %v", dmLog)
		}
		startLog, err := ioutil.ReadFile(dmLog)
		if err != nil {
			t.Logf("Couldn't read log %v: %v", dmLog, err)
			time.Sleep(time.Second)
			continue
		}
		re := regexp.MustCompile(`Unclaimed device manager endpoint: (.*)`)
		matches := re.FindSubmatch(startLog)
		if len(matches) == 0 {
			t.Logf("Couldn't find match in %v [%s]", dmLog, startLog)
			time.Sleep(time.Second)
			continue
		}
		if len(matches) < 2 {
			t.Fatalf("Wrong match in %v (%d) %v", dmLog, len(matches), string(matches[0]))
		}
		claimableEP = string(matches[len(matches)-1])
		break
	}
	// Claim the device as "root:u:alice:myworkstation".
	withArgs(claimDeviceBin, "claim", claimableEP, "myworkstation").Run()

	resolve := func(name string) string {
		res := ""
		if err := testutil.RetryFor(10*time.Second, func() error {
			// Set ExitErrorIsOk to true since we expect "namespace resolve" to fail
			// if the name doesn't exist.
			c := withArgs(namespaceBin, "resolve", name)
			c.ExitErrorIsOk = true
			c.AddStderrWriter(gosh.NopWriteCloser(os.Stderr))
			if res = tr(c.Stdout()); len(res) > 0 {
				return nil
			}
			return testutil.TryAgain(errors.New("resolve returned nothing"))
		}); err != nil {
			t.Fatal(err)
		}
		return res
	}

	// Wait for the device manager to publish its mount table entry.
	mtEP := resolve(mtName)
	withArgs(adminDeviceBin, "acl", "set", mtName+"/devmgr/device", "root:u:alice", "Read,Resolve,Write").Run()

	if withSuid {
		withArgs(adminDeviceBin, "associate", "add", mtName+"/devmgr/device", appUser, "root:u:alice").Run()
		associations := withArgs(adminDeviceBin, "associate", "list", mtName+"/devmgr/device").Stdout()
		if got, expected := strings.Trim(associations, "\n "), "root:u:alice "+appUser; got != expected {
			t.Fatalf("association test, got %v, expected %v", got, expected)
		}
	}

	// Verify the device's default blessing is as expected.
	mfrBlessing := "root:m:orange:zphone5:ime-i007:myworkstation"
	ownerBlessing := "root:r:admin:myworkstation"
	c := withArgs(debugBin, "stats", "read", mtName+"/devmgr/__debug/stats/security/principal/*/blessingstore/*")
	c.Run()
	c.S.ExpectSetEventuallyRE(".*Default Blessings[ ]+" + mfrBlessing + "," + ownerBlessing)

	// Get the device's profile, which should be set to non-empty string
	c = withArgs(adminDeviceBin, "describe", mtName+"/devmgr/device")
	c.Run()
	parts := c.S.ExpectRE(`{Profiles:map\[(.*):{}\]}`, 1)
	expectOneMatch := func(parts [][]string) string {
		if len(parts) != 1 || len(parts[0]) != 2 {
			t.Fatalf("%s: failed to match profile: %#v", caller(1), parts)
		}
		return parts[0][1]
	}
	deviceProfile := expectOneMatch(parts)
	if len(deviceProfile) == 0 {
		t.Fatalf("failed to get profile")
	}

	// Start a binaryd server that will serve the binary for the test
	// application to be installed on the device.
	binarydName := "binaries"
	withArgs(binarydBin,
		"--name="+binarydName,
		"--root-dir="+filepath.Join(workDir, "binstore"),
		"--v23.tcp.address=127.0.0.1:0",
		"--http=127.0.0.1:0").Start()
	// Allow publishers to update binaries
	withArgs(deviceBin, "acl", "set", binarydName, "root:a", "Write").Run()

	// We are also going to use the binaryd binary as our test app binary. Once our test app
	// binary is published to the binaryd server started above, this (augmented with a
	// timestamp) is the name the test app binary will have.
	sampleAppBinName := binarydName + "/binaryd"

	// Start an applicationd server that will serve the application
	// envelope for the test application to be installed on the device.
	withArgs(applicationdBin,
		"--name="+appDName,
		"--store="+mkSubdir(t, workDir, "appstore"),
		"--v23.tcp.address=127.0.0.1:0").Start()
	// Allow publishers to create and update envelopes
	withArgs(deviceBin, "acl", "set", appDName, "root:a", "Read,Write,Resolve").Run()

	sampleAppName := appDName + "/testapp"
	appPubName := "testbinaryd"
	appEnvelopeFilename := filepath.Join(workDir, "app.envelope")
	appEnvelope := fmt.Sprintf("{\"Title\":\"BINARYD\", \"Args\":[\"--name=%s\", \"--root-dir=./binstore\", \"--v23.tcp.address=127.0.0.1:0\", \"--http=127.0.0.1:0\"], \"Binary\":{\"File\":%q}, \"Env\":[]}", appPubName, sampleAppBinName)
	ioutil.WriteFile(appEnvelopeFilename, []byte(appEnvelope), 0666)
	defer os.Remove(appEnvelopeFilename)

	output := withArgs(applicationBin, "put", sampleAppName+"/0", deviceProfile, appEnvelopeFilename).Stdout()
	if got, want := tr(output), fmt.Sprintf("Application envelope added for profile %s.", deviceProfile); got != want {
		t.Fatalf("got %q, want %q", got, want)
	}

	// Verify that the envelope we uploaded shows up with glob.
	c = withArgs(applicationBin, "match", sampleAppName, deviceProfile)
	c.Run()
	parts = c.S.ExpectSetEventuallyRE(`"Title": "(.*)",`, `"File": "(.*)",`)
	if got, want := len(parts), 2; got != want {
		t.Fatalf("got %d, want %d", got, want)
	}
	for line, want := range []string{"BINARYD", sampleAppBinName} {
		if got := parts[line][1]; got != want {
			t.Fatalf("got %q, want %q", got, want)
		}
	}

	// Publish the app (This uses the binarydBin binary and the testapp envelope from above)
	withArgs(pubDeviceBin, "publish", "-from", filepath.Dir(binarydBin.Path), "-readers", "root:r:admin", filepath.Base(binarydBin.Path)+":testapp").Run()
	if got := withArgs(namespaceBin, "glob", sampleAppBinName).Stdout(); len(got) == 0 {
		t.Fatalf("glob failed for %q", sampleAppBinName)
	}

	// Install the app on the device.
	c = withArgs(deviceBin, "install", mtName+"/devmgr/apps", sampleAppName)
	c.Run()
	installationName := c.S.ReadLine()
	if installationName == "" {
		t.Fatalf("got empty installation name from install")
	}

	// Verify that the installation shows up when globbing the device manager.
	output = withArgs(namespaceBin, "glob", mtName+"/devmgr/apps/BINARYD/*").Stdout()
	if got, want := tr(output), installationName; got != want {
		t.Fatalf("got %q, want %q", got, want)
	}

	// Start an instance of the app, granting it blessing extension myapp.
	c = withArgs(deviceBin, "instantiate", installationName, "myapp")
	c.Run()
	instanceName := c.S.ReadLine()
	if instanceName == "" {
		t.Fatalf("got empty instance name from new")
	}
	withArgs(deviceBin, "run", instanceName).Run()

	resolve(mtName + "/" + appPubName)

	// Verify that the instance shows up when globbing the device manager.
	output = withArgs(namespaceBin, "glob", mtName+"/devmgr/apps/BINARYD/*/*").Stdout()
	if got, want := tr(output), instanceName; got != want {
		t.Fatalf("got %q, want %q", got, want)
	}

	c = withArgs(debugBin, "stats", "read", instanceName+"/stats/system/pid")
	c.Run()
	pid := c.S.ExpectRE("[0-9]+$", 1)[0][0]
	uname, err := getUserForPid(sh, pid)
	if err != nil {
		t.Errorf("getUserForPid could not determine the user running pid %v", pid)
	} else if uname != appUser {
		t.Errorf("app expected to be running as %v but is running as %v", appUser, uname)
	}

	// Verify the app's blessings. We check the default blessing, as well as the
	// "..." blessing, which should be the default blessing plus a publisher blessing.
	userBlessing := "root:u:alice:myapp"
	pubBlessing := "root:a:rovio:apps:published:binaryd"
	appBlessing := mfrBlessing + ":a:" + pubBlessing + "," + ownerBlessing + ":a:" + pubBlessing
	c = withArgs(debugBin, "stats", "read", instanceName+"/stats/security/principal/*/blessingstore/*")
	c.Run()
	c.S.ExpectSetEventuallyRE(".*Default Blessings[ ]+"+userBlessing+"$", "[.][.][.][ ]+"+userBlessing+","+appBlessing)

	// Kill and delete the instance.
	withArgs(deviceBin, "kill", instanceName).Run()
	withArgs(deviceBin, "delete", instanceName).Run()

	// Verify that logs, but not stats, show up when globbing the
	// not-running instance.
	if output = withArgs(namespaceBin, "glob", instanceName+"/stats/...").Stdout(); len(output) > 0 {
		t.Fatalf("no output expected for glob %s/stats/..., got %q", output, instanceName)
	}
	if output = withArgs(namespaceBin, "glob", instanceName+"/logs/...").Stdout(); len(output) == 0 {
		t.Fatalf("output expected for glob %s/logs/..., but got none", instanceName)
	}

	// TODO: The deviced binary should probably be published by someone other than rovio :-)
	// Maybe publishing the deviced binary should eventually use "device publish" too?
	// For now, it uses the "application" and "binary" tools directly to ensure that those work

	// Upload a deviced binary
	devicedAppBinName := binarydName + "/deviced"
	withArgs(binaryBin, "upload", devicedAppBinName, sh.BuildGoPkg("v.io/x/ref/services/device/deviced")).Run()
	// Allow root:r:admin and its devices to read the binary
	withArgs(deviceBin, "acl", "set", devicedAppBinName, "root:r:admin", "Read").Run()

	// Upload a device manager envelope.
	devicedEnvelopeFilename := filepath.Join(workDir, "deviced.envelope")
	devicedEnvelope := fmt.Sprintf("{\"Title\":\"device manager\", \"Binary\":{\"File\":%q}}", devicedAppBinName)
	ioutil.WriteFile(devicedEnvelopeFilename, []byte(devicedEnvelope), 0666)
	defer os.Remove(devicedEnvelopeFilename)
	withArgs(applicationBin, "put", devicedAppName, deviceProfile, devicedEnvelopeFilename).Run()
	// Allow root:r:admin and its devices to read the envelope
	withArgs(deviceBin, "acl", "set", devicedAppName, "root:r:admin", "Read").Run()

	// Update the device manager.
	withArgs(adminDeviceBin, "update", mtName+"/devmgr/device").Run()
	resolveChange := func(name, old string) string {
		res := ""
		if err := testutil.RetryFor(10*time.Second, func() error {
			// Set ExitErrorIsOk to true since we expect "namespace resolve" to fail
			// if the name doesn't exist.
			c := withArgs(namespaceBin, "resolve", name)
			c.ExitErrorIsOk = true
			c.AddStderrWriter(gosh.NopWriteCloser(os.Stderr))
			switch res = tr(c.Stdout()); {
			case res == "":
				return testutil.TryAgain(errors.New("resolve returned nothing"))
			case res == old:
				return testutil.TryAgain(errors.New("no change"))
			}
			return nil
		}); err != nil {
			t.Fatal(err)
		}
		return res
	}
	mtEP = resolveChange(mtName, mtEP)

	// Verify that device manager's mounttable is still published under the
	// expected name (hostname).
	if withArgs(namespaceBin, "glob", mtName).Stdout() == "" {
		t.Fatalf("failed to glob %s", mtName)
	}

	// Revert the device manager
	// The argument to "device revert" is a glob pattern. So we need to
	// wait for devmgr to be mounted before running the command.
	resolve(mtEP + "/devmgr")
	withArgs(adminDeviceBin, "revert", mtName+"/devmgr/device").Run()
	mtEP = resolveChange(mtName, mtEP)

	// Verify that device manager's mounttable is still published under the
	// expected name (hostname).
	if withArgs(namespaceBin, "glob", mtName).Stdout() == "" {
		t.Fatalf("failed to glob %s", mtName)
	}

	// Verify that the local mounttable exists, and that the device manager,
	// the global namespace, and the neighborhood are mounted on it.
	resolve(mtEP + "/devmgr")
	resolve(mtEP + "/nh")
	resolve(mtEP + "/global")

	namespaceRoot := sh.Vars[ref.EnvNamespacePrefix]
	output = withArgs(namespaceBin, "resolve", mtEP+"/global").Stdout()
	if got, want := tr(output), namespaceRoot; got != want {
		t.Fatalf("got %q, want %q", got, want)
	}

	// Kill the device manager (which causes it to be restarted), wait for
	// the endpoint to change.
	withArgs(deviceBin, "kill", mtName+"/devmgr/device").Run()
	mtEP = resolveChange(mtName, mtEP)

	// Shut down the device manager.
	stopDevMgrOnce.Do(stopDevMgr)

	// Wait for the mounttable entry to go away.
	resolveGone := func(name string) string {
		res := ""
		if err := testutil.RetryFor(10*time.Second, func() error {
			// Set ExitErrorIsOk to true since we expect "namespace resolve" to fail
			// if the name doesn't exist.
			c := withArgs(namespaceBin, "resolve", name)
			c.ExitErrorIsOk = true
			c.AddStderrWriter(gosh.NopWriteCloser(os.Stderr))
			if res = tr(c.Stdout()); len(res) == 0 {
				return nil
			}
			return testutil.TryAgain(errors.New("mount table entry still exists"))
		}); err != nil {
			t.Fatal(err)
		}
		return res
	}
	resolveGone(mtName)

	var fi []os.FileInfo

	// This doesn't work in multiuser mode because dmInstallDir is
	// owned by the device manager user and unreadable by the user
	// running this test.
	if !withSuid {
		fi, err = ioutil.ReadDir(dmInstallDir)
		if err != nil {
			t.Fatalf("failed to readdir for %q: %v", dmInstallDir, err)
		}
	}

	withArgs(deviceScript, "uninstall").Run()

	fi, err = ioutil.ReadDir(dmInstallDir)
	if err == nil || len(fi) > 0 {
		t.Fatalf("managed to read %d entries from %q", len(fi), dmInstallDir)
	}
	if err != nil && !strings.Contains(err.Error(), "no such file or directory") {
		t.Fatalf("wrong error: %v", err)
	}
}

func withArgs(cmd *v23test.Cmd, args ...string) *v23test.Cmd {
	res := cmd.Clone()
	res.Args = append(res.Args, args...)
	return res
}

func buildAndCopyBinaries(t *testing.T, sh *v23test.Shell, destinationDir string, packages ...string) {
	var args []string
	for _, pkg := range packages {
		args = append(args, sh.BuildGoPkg(pkg))
	}
	args = append(args, destinationDir)
	sh.Cmd("/bin/cp", args...).Run()
}

func mkSubdir(t *testing.T, parent, child string) string {
	dir := filepath.Join(parent, child)
	if err := os.Mkdir(dir, 0755); err != nil {
		t.Fatalf("failed to create %q: %v", dir, err)
	}
	return dir
}

var re = regexp.MustCompile("[ \t]+")

// getUserForPid determines the username running process pid.
func getUserForPid(sh *v23test.Shell, pid string) (string, error) {
	pidString := sh.Cmd("/bin/ps", psFlags).Stdout()
	for _, line := range strings.Split(pidString, "\n") {
		fields := re.Split(line, -1)
		if len(fields) > 1 && pid == fields[1] {
			return fields[0], nil
		}
	}
	return "", fmt.Errorf("Couldn't determine the user for pid %s", pid)
}

// tr trims off trailing newline characters.
func tr(s string) string {
	return strings.TrimRight(s, "\n")
}

// caller returns a string of the form <filename>:<lineno>.
func caller(skip int) string {
	_, file, line, _ := runtime.Caller(skip + 1)
	return fmt.Sprintf("%s:%d", filepath.Base(file), line)
}

func TestMain(m *testing.M) {
	os.Exit(v23test.Run(m.Run))
}
