services/device/mgmt_v23_test et al.: support for multiuser tests
Update the device manager's Go integration tests with support to run
the device manager in multiuser mode.
Change-Id: I0c81ae428fcf61d2414b1f84c7460d50d1bf9f59
diff --git a/cmd/principal/principal_v23_test.go b/cmd/principal/principal_v23_test.go
index 04f9fa3..ad0d319 100644
--- a/cmd/principal/principal_v23_test.go
+++ b/cmd/principal/principal_v23_test.go
@@ -43,7 +43,7 @@
func V23TestBlessSelf(t *v23tests.T) {
var (
- outputDir = t.NewTempDir()
+ outputDir = t.NewTempDir("")
aliceDir = filepath.Join(outputDir, "alice")
aliceBlessingFile = filepath.Join(outputDir, "aliceself")
)
@@ -67,7 +67,7 @@
func V23TestStore(t *v23tests.T) {
var (
- outputDir = t.NewTempDir()
+ outputDir = t.NewTempDir("")
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal")
aliceDir = filepath.Join(outputDir, "alice")
aliceFriend = filepath.Join(outputDir, "alice.bless")
@@ -128,7 +128,7 @@
func V23TestDump(t *v23tests.T) {
var (
- outputDir = t.NewTempDir()
+ outputDir = t.NewTempDir("")
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal")
aliceDir = filepath.Join(outputDir, "alice")
)
@@ -153,7 +153,7 @@
func V23TestGetRecognizedRoots(t *v23tests.T) {
var (
- outputDir = t.NewTempDir()
+ outputDir = t.NewTempDir("")
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal")
aliceDir = filepath.Join(outputDir, "alice")
)
@@ -172,7 +172,7 @@
func V23TestGetPeermap(t *v23tests.T) {
var (
- outputDir = t.NewTempDir()
+ outputDir = t.NewTempDir("")
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal")
aliceDir = filepath.Join(outputDir, "alice")
)
@@ -209,7 +209,7 @@
func V23TestRecvBlessings(t *v23tests.T) {
var (
- outputDir = t.NewTempDir()
+ outputDir = t.NewTempDir("")
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal")
aliceDir = filepath.Join(outputDir, "alice")
bobDir = filepath.Join(outputDir, "bob")
@@ -305,7 +305,7 @@
func V23TestFork(t *v23tests.T) {
var (
- outputDir = t.NewTempDir()
+ outputDir = t.NewTempDir("")
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal")
aliceDir = filepath.Join(outputDir, "alice")
alicePhoneDir = filepath.Join(outputDir, "alice-phone")
@@ -392,7 +392,7 @@
func V23TestCreate(t *v23tests.T) {
var (
- outputDir = t.NewTempDir()
+ outputDir = t.NewTempDir("")
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal")
aliceDir = filepath.Join(outputDir, "alice")
)
@@ -411,7 +411,7 @@
func V23TestCaveats(t *v23tests.T) {
var (
- outputDir = t.NewTempDir()
+ outputDir = t.NewTempDir("")
aliceDir = filepath.Join(outputDir, "alice")
aliceBlessingFile = filepath.Join(outputDir, "aliceself")
)
@@ -443,21 +443,21 @@
func V23TestForkWithoutVDLPATH(t *v23tests.T) {
var (
- parent = t.NewTempDir()
+ parent = t.NewTempDir("")
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal").WithEnv("V23_ROOT=''", "VDLPATH=''")
)
if err := bin.Start("create", parent, "parent").Wait(os.Stdout, os.Stderr); err != nil {
t.Fatalf("create %q failed: %v", parent, err)
}
- if err := bin.Start("--v23.credentials="+parent, "fork", "--for=1s", t.NewTempDir(), "child").Wait(os.Stdout, os.Stderr); err != nil {
+ if err := bin.Start("--v23.credentials="+parent, "fork", "--for=1s", t.NewTempDir(""), "child").Wait(os.Stdout, os.Stderr); err != nil {
t.Errorf("fork failed: %v", err)
}
}
func V23TestForkWithoutCaveats(t *v23tests.T) {
var (
- parent = t.NewTempDir()
- child = t.NewTempDir()
+ parent = t.NewTempDir("")
+ child = t.NewTempDir("")
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal")
buf bytes.Buffer
)
@@ -482,7 +482,7 @@
func V23TestBless(t *v23tests.T) {
var (
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal")
- dir = t.NewTempDir()
+ dir = t.NewTempDir("")
aliceDir = filepath.Join(dir, "alice")
bobDir = filepath.Join(dir, "bob")
tmpfile = filepath.Join(dir, "tmpfile")
@@ -549,9 +549,9 @@
func V23TestAddBlessingsToRoots(t *v23tests.T) {
var (
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal")
- aliceDir = t.NewTempDir()
- bobDir = t.NewTempDir()
- blessingFile = filepath.Join(t.NewTempDir(), "bobfile")
+ aliceDir = t.NewTempDir("")
+ bobDir = t.NewTempDir("")
+ blessingFile = filepath.Join(t.NewTempDir(""), "bobfile")
// Extract the public key from the first line of output from
// "principal dump", which is formatted as:
@@ -585,7 +585,7 @@
func V23TestAddKeyToRoots(t *v23tests.T) {
var (
bin = t.BuildGoPkg("v.io/x/ref/cmd/principal")
- aliceDir = t.NewTempDir()
+ aliceDir = t.NewTempDir("")
)
bin.Start("create", aliceDir, "alice").WaitOrDie(os.Stdout, os.Stderr)
// The second argument and the "want" line below were generated by:
diff --git a/cmd/vrun/vrun_v23_test.go b/cmd/vrun/vrun_v23_test.go
index b064186..cb43c0a 100644
--- a/cmd/vrun/vrun_v23_test.go
+++ b/cmd/vrun/vrun_v23_test.go
@@ -19,7 +19,7 @@
func V23TestAgentd(t *v23tests.T) {
var (
clientAgent, serverAgent = createClientAndServerAgents(t)
- tmpdir = t.NewTempDir()
+ tmpdir = t.NewTempDir("")
vrun = t.BuildGoPkg("v.io/x/ref/cmd/vrun").Path()
pingpong = t.BuildGoPkg("v.io/x/ref/services/agent/internal/pingpong").Path()
serverName = serverAgent.Start(pingpong).ExpectVar("NAME")
@@ -62,8 +62,8 @@
func createClientAndServerAgents(i *v23tests.T) (client, server *v23tests.Binary) {
var (
agentd = i.BuildGoPkg("v.io/x/ref/services/agent/agentd")
- clientDir = i.NewTempDir()
- serverDir = i.NewTempDir()
+ clientDir = i.NewTempDir("")
+ serverDir = i.NewTempDir("")
)
pserver, err := vsecurity.CreatePersistentPrincipal(serverDir, nil)
if err != nil {
diff --git a/examples/tunnel/tunneld/tunneld_v23_test.go b/examples/tunnel/tunneld/tunneld_v23_test.go
index e153e8a..cf8ef05 100644
--- a/examples/tunnel/tunneld/tunneld_v23_test.go
+++ b/examples/tunnel/tunneld/tunneld_v23_test.go
@@ -41,7 +41,7 @@
}
// And again with a file redirection this time.
- outDir := t.NewTempDir()
+ outDir := t.NewTempDir("")
outPath := filepath.Join(outDir, "hello.txt")
// TODO(sjr): instead of using Output() here, we'd really rather do
diff --git a/services/agent/agentlib/agent_v23_test.go b/services/agent/agentlib/agent_v23_test.go
index daa9185..cecdcc0 100644
--- a/services/agent/agentlib/agent_v23_test.go
+++ b/services/agent/agentlib/agent_v23_test.go
@@ -22,7 +22,7 @@
//go:generate v23 test generate
func V23TestTestPassPhraseUse(i *v23tests.T) {
- bin := i.BuildGoPkg("v.io/x/ref/services/agent/agentd").WithEnv(envvar.Credentials + "=" + i.NewTempDir())
+ bin := i.BuildGoPkg("v.io/x/ref/services/agent/agentd").WithEnv(envvar.Credentials + "=" + i.NewTempDir(""))
// Create the passphrase
agent := bin.Start("echo", "Hello")
@@ -65,7 +65,7 @@
// (Errors are printed to STDERR)
testbin := i.BuildGoPkg("v.io/x/ref/services/agent/internal/test_principal").Path()
i.BuildGoPkg("v.io/x/ref/services/agent/agentd").
- WithEnv(envvar.Credentials+"="+i.NewTempDir()).
+ WithEnv(envvar.Credentials+"="+i.NewTempDir("")).
Start(testbin).
WaitOrDie(nil, os.Stderr)
}
@@ -95,7 +95,7 @@
// This only works with shells that propagate open file descriptors to
// children. POSIX-compliant shells do this as to many other commonly
// used ones like bash.
- script := filepath.Join(i.NewTempDir(), "test.sh")
+ script := filepath.Join(i.NewTempDir(""), "test.sh")
if err := writeScript(
script,
`#!/bin/bash
@@ -126,7 +126,7 @@
pingpong = i.BuildGoPkg("v.io/x/ref/services/agent/internal/pingpong").Path()
serverName = serverAgent.Start(pingpong).ExpectVar("NAME")
- scriptDir = i.NewTempDir()
+ scriptDir = i.NewTempDir("")
counter = filepath.Join(scriptDir, "counter")
script = filepath.Join(scriptDir, "test.sh")
)
@@ -224,8 +224,8 @@
func createClientAndServerAgents(i *v23tests.T) (client, server *v23tests.Binary) {
var (
agentd = i.BuildGoPkg("v.io/x/ref/services/agent/agentd")
- clientDir = i.NewTempDir()
- serverDir = i.NewTempDir()
+ clientDir = i.NewTempDir("")
+ serverDir = i.NewTempDir("")
)
pserver, err := vsecurity.CreatePersistentPrincipal(serverDir, nil)
if err != nil {
diff --git a/services/application/applicationd/applicationd_v23_test.go b/services/application/applicationd/applicationd_v23_test.go
index 9c9e0fd..b76a389 100644
--- a/services/application/applicationd/applicationd_v23_test.go
+++ b/services/application/applicationd/applicationd_v23_test.go
@@ -59,7 +59,7 @@
appRepoName := "test-app-repo"
binaryWithCredentials(i, "applicationd", "v.io/x/ref/services/application/applicationd").Start(
"-name="+appRepoName,
- "-store="+i.NewTempDir(),
+ "-store="+i.NewTempDir(""),
"-v=2",
"-v23.tcp.address=127.0.0.1:0")
diff --git a/services/build/buildd/buildd_v23_test.go b/services/build/buildd/buildd_v23_test.go
index 68381bb..e42767e 100644
--- a/services/build/buildd/buildd_v23_test.go
+++ b/services/build/buildd/buildd_v23_test.go
@@ -51,7 +51,7 @@
"-v23.tcp.address=127.0.0.1:0")
// Create and build a test source file.
- testGoPath := i.NewTempDir()
+ testGoPath := i.NewTempDir("")
testBinDir := filepath.Join(testGoPath, "bin")
if err := os.MkdirAll(testBinDir, os.FileMode(0700)); err != nil {
i.Fatalf("MkdirAll(%v) failed: %v", testBinDir, err)
diff --git a/services/device/mgmt_v23_test.go b/services/device/mgmt_v23_test.go
index 742439c..1b09af6 100644
--- a/services/device/mgmt_v23_test.go
+++ b/services/device/mgmt_v23_test.go
@@ -9,20 +9,27 @@
// manager so that all device manager components run as the same user and
// no user input (such as an agent pass phrase) is needed.
//
-// When this script is invoked with the --with_suid <user> flag, it
-// installs the device manager in its more secure multi-account
-// configuration where the device manager runs under the account of the
-// invoker and test apps will be executed as <user>. This mode will
-// require root permisisons to install and may require configuring an
-// agent passphrase.
+// This script can exercise the device manager in two different modes. It
+// can be executed like so:
//
-// For exanple:
+// v23 go test -v . --v23.tests
//
-// v23 go test -v . --v23.tests --with_suid vanaguest
+// This will exercise the device manager's single user mode where all
+// processes run as the same invoking user.
//
-// to test a device manager with multi-account support enabled for app
-// account vanaguest.
+// 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:
//
+// v23 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.
+
package device_test
//go:generate v23 test generate .
@@ -34,7 +41,9 @@
"io/ioutil"
"math/rand"
"os"
+ "os/user"
"path/filepath"
+ "regexp"
"strings"
"time"
@@ -44,13 +53,15 @@
)
var (
- suidUserFlag string
- hostname string
- errTimeout = errors.New("timeout")
+ appUserFlag string
+ deviceUserFlag string
+ hostname string
+ errTimeout = errors.New("timeout")
)
func init() {
- flag.StringVar(&suidUserFlag, "with_suid", "", "run the device manager as the specified user")
+ 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))
@@ -62,14 +73,30 @@
defer fmt.Fprintf(os.Stderr, "--------------- SHUTDOWN ---------------\n")
userFlag := "--single_user"
withSuid := false
- if len(suidUserFlag) > 0 {
- userFlag = "--with_suid=" + suidUserFlag
+ tempDir := ""
+ if len(deviceUserFlag) > 0 && len(appUserFlag) > 0 {
withSuid = true
+ i.Logf("device user %s, app user %s", deviceUserFlag, appUserFlag)
+ // When running --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 hieararchy
+ // in /var that is 0700. This is unworkable so force
+ // TMPDIR to /tmp in this case.
+ tempDir = "/tmp"
+ } else if len(deviceUserFlag) > 0 || len(appUserFlag) > 0 {
+ i.Fatalf("Running in multiuser mode requires --appuser and --deviceuser")
+ } else {
+ u, err := user.Current()
+ if err != nil {
+ i.Fatalf("couldn't get the current user: %v", err)
+ }
+ appUserFlag = u.Username
}
- i.Logf("user flag: %q", userFlag)
var (
- workDir = i.NewTempDir()
+ workDir = i.NewTempDir(tempDir)
binStagingDir = mkSubdir(i, workDir, "bin")
dmInstallDir = filepath.Join(workDir, "dm")
@@ -103,6 +130,14 @@
mtName = "devices/" + hostname // Name under which the device manager will publish itself.
)
+ if withSuid {
+ // In multiuser mode, deviceUserFlag needs execute access to
+ // tempDir.
+ if err := os.Chmod(workDir, 0711); err != nil {
+ i.Fatalf("os.Chmod() failed: %v", err)
+ }
+ }
+
v23tests.RunRootMT(i, "--v23.tcp.address=127.0.0.1:0")
buildAndCopyBinaries(
i,
@@ -115,15 +150,25 @@
appDName := "applicationd"
devicedAppName := filepath.Join(appDName, "deviced", "test")
- deviceScript.Start(
+ deviceScriptArguments := []string{
"install",
binStagingDir,
- userFlag,
- "--origin="+devicedAppName,
+ }
+
+ if withSuid {
+ deviceScriptArguments = append(deviceScriptArguments, "--devuser="+deviceUserFlag)
+ } else {
+ deviceScriptArguments = append(deviceScriptArguments, userFlag)
+ }
+
+ 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())).
- WaitOrDie(os.Stdout, os.Stderr)
+ "--neighborhood-name=" + fmt.Sprintf("%s-%d-%d", hostname, os.Getpid(), rand.Int()),
+ }...)
+
+ deviceScript.Start(deviceScriptArguments...).WaitOrDie(os.Stdout, os.Stderr)
deviceScript.Start("start").WaitOrDie(os.Stdout, os.Stderr)
resolve := func(name string) string {
@@ -168,11 +213,12 @@
mtEP = resolveChange(mtName, mtEP)
if withSuid {
- /*
- "${DEVICE_BIN}" associate add "${MT_NAME}/devmgr/device" "${SUID_USER}" "alice"
- shell_test::assert_eq "$("${DEVICE_BIN}" associate list "${MT_NAME}/devmgr/device")" \
- "alice ${SUID_USER}" "${LINENO}"
- */
+ deviceBin.Start("associate", "add", mtName+"/devmgr/device", appUserFlag, "root/alice")
+
+ aai := deviceBin.Start("associate", "list", mtName+"/devmgr/device")
+ if got, expected := strings.Trim(aai.Output(), "\n "), "root/alice "+appUserFlag; got != expected {
+ i.Fatalf("association test, got %v, expected %v", got, expected)
+ }
}
// Verify the device's default blessing is as expected.
@@ -269,7 +315,15 @@
i.Fatalf("got %q, want %q", got, want)
}
- // TODO(rjkroege): Verify that the app is actually running as ${SUID_USER}
+ inv = debugBin.Start("stats", "read", instanceName+"/stats/system/pid")
+ pid := inv.ExpectRE("[0-9]+$", 1)[0][0]
+ uname, err := getUserForPid(i, pid)
+ if err != nil {
+ i.Errorf("getUserForPid could not determine the user running pid %v", pid)
+ }
+ if uname != appUserFlag {
+ i.Errorf("app expected to be running as %v but is running as %v", appUserFlag, uname)
+ }
// Verify the app's default blessing.
inv = debugBin.Start("stats", "read", instanceName+"/stats/security/principal/*/blessingstore")
@@ -357,9 +411,16 @@
}
resolveGone(mtName)
- fi, err := ioutil.ReadDir(dmInstallDir)
- if err != nil {
- i.Fatalf("failed to readdir for %q: %v", dmInstallDir, err)
+ 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 {
+ i.Fatalf("failed to readdir for %q: %v", dmInstallDir, err)
+ }
}
deviceScript.Run("uninstall")
@@ -389,3 +450,17 @@
}
return dir
}
+
+var re = regexp.MustCompile("[ \t]+")
+
+// getUserForPid determines the username running process pid.
+func getUserForPid(i *v23tests.T, pid string) (string, error) {
+ pidString := i.BinaryFromPath("/bin/ps").Start(psFlags).Output()
+ 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)
+}
diff --git a/services/device/shell.sh b/services/device/shell.sh
deleted file mode 100755
index d55c678..0000000
--- a/services/device/shell.sh
+++ /dev/null
@@ -1,217 +0,0 @@
-#!/bin/bash
-# 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.
-
-# The shell library is used to execute vanadium shell scripts.
-
-# IMPORTANT: If your script registers its own "trap" handler, that handler must
-# call shell::at_exit to clean up all temporary files and directories created by
-# this library.
-
-set -e
-set -u
-
-TMPDIR="${TMPDIR-/tmp}"
-V23_SHELL_TMP_DIRS=${V23_SHELL_TMP_DIRS-$(mktemp "${TMPDIR}/XXXXXXXX")}
-V23_SHELL_TMP_FILES=${V23_SHELL_TMP_FILES-$(mktemp "${TMPDIR}/XXXXXXXX")}
-V23_SHELL_TMP_PIDS=${V23_SHELL_TMP_PIDS-$(mktemp "${TMPDIR}/XXXXXXXX")}
-
-trap shell::at_exit INT TERM EXIT
-
-# When a user of this library needs cleanup to be performed by root
-# because different processes are running with different system
-# identities, it should set this variable to root to escalate
-# privilege appropriately.
-SUDO_USER="$(whoami)"
-
-# shell::at_exit is executed when the shell script exits. It is used,
-# for example, to garbage collect any temporary files and directories
-# created by invocations of shell::tmp_file and shell:tmp_dir.
-shell::at_exit() {
- # If the variable V23_SHELL_CMD_LOOP_AT_EXIT is non-empty, accept commands
- # from the user in a command loop. This can preserve the state in the logs
- # directories while the user examines them.
- case "${V23_SHELL_CMD_LOOP_AT_EXIT-}" in
- ?*)
- local cmdline
- set +u
- echo 'Entering debug shell. Type control-D or "exit" to exit.' >&2
- while echo -n "test> " >&2; read cmdline; do
- eval "$cmdline"
- done
- set -u
- ;;
- esac
- # Unset the trap so that it doesn't run again on exit.
- trap - INT TERM EXIT
- for pid in $(cat "${V23_SHELL_TMP_PIDS}"); do
- sudo -u "${SUDO_USER}" kill "${pid}" &> /dev/null || true
- done
- for tmp_dir in $(cat "${V23_SHELL_TMP_DIRS}"); do
- sudo -u "${SUDO_USER}" rm -rf "${tmp_dir}" &>/dev/null
- done
- for tmp_file in $(cat "${V23_SHELL_TMP_FILES}"); do
- sudo -u "${SUDO_USER}" rm -f "${tmp_file}" &>/dev/null
- done
- sudo -u "${SUDO_USER}" rm -f "${V23_SHELL_TMP_DIRS}" "${V23_SHELL_TMP_FILES}" "${V23_SHELL_TMP_PIDS}" &>/dev/null
-}
-
-# shell::kill_child_processes kills all child processes.
-# Note, child processes must set their own "at_exit: kill_child_processes"
-# signal handlers in order for this to kill their descendants.
-shell::kill_child_processes() {
- # Attempt to shutdown child processes by sending the TERM signal.
- if [[ -n "$(jobs -p -r)" ]]; then
- shell::silence pkill -P $$
- sleep 1
- # Force shutdown of any remaining child processes using the KILL signal.
- # Note, we only "sleep 1" and "kill -9" if there were child processes.
- if [[ -n "$(jobs -p -r)" ]]; then
- shell::silence sudo -u "${SUDO_USER}" pkill -9 -P $$
- fi
- fi
-}
-
-# shell::check_deps can be used to check which dependencies are
-# missing on the host.
-#
-# Example:
-# local -r DEPS=$(shell::check_deps git golang-go)
-# if [[ -n "${DEPS} ]]; then
-# sudo apt-get install $DEPS
-# fi
-shell::check_deps() {
- local RESULT=""
- case $(uname -s) in
- "Linux")
- set +e
- for pkg in "$@"; do
- dpkg -s "${pkg}" &> /dev/null
- if [[ "$?" -ne 0 ]]; then
- RESULT+=" ${pkg}"
- fi
- done
- set -e
- ;;
- "Darwin")
- set +e
- for pkg in "$@"; do
- if [[ -z "$(brew ls --versions ${pkg})" ]]; then
- RESULT+=" ${pkg}"
- fi
- done
- set -e
- ;;
- *)
- echo "Operating system $(uname -s) is not supported."
- exit 1
- esac
- echo "${RESULT}"
-}
-
-# shell::check_result can be used to obtain the exit status of a bash
-# command. By the semantics of "set -e", a script exits immediately
-# upon encountering a command that fails. This function should be used
-# if instead, a script wants to take an action depending on the exit
-# status.
-#
-# Example:
-# local -r RESULT=$(shell::check_result <command>)
-# if [[ "${RESULT}" -ne 0 ]]; then
-# <handle failure>
-# else
-# <handle success>
-# fi
-shell::check_result() {
- set +e
- "$@" &> /dev/null
- echo "$?"
- set -e
-}
-
-# shell::tmp_dir can be used to create a temporary directory.
-#
-# Example:
-# local -R TMP_DIR=$(shell::tmp_dir)
-shell::tmp_dir() {
- local -r RESULT=$(mktemp -d "${TMPDIR}/XXXXXXXX")
- echo "${RESULT}" >> "${V23_SHELL_TMP_DIRS}"
- echo "${RESULT}"
-}
-
-# shell::tmp_file can be used to create a temporary file.
-#
-# Example:
-# local -R TMP_FILE=$(shell::tmp_file)
-shell::tmp_file() {
- local -r RESULT=$(mktemp "${TMPDIR}/XXXXXXXX")
- echo "${RESULT}" >> "${V23_SHELL_TMP_FILES}"
- echo "${RESULT}"
-}
-
-# shell::run_server is used to start a long running server process and
-# to verify that it is still running after a set timeout period. This
-# is useful for catching cases where the server either fails to start or
-# fails soon after it has started.
-# The script will return 0 if the command is running at that point in time
-# and a non-zero value otherwise. It echos the server's pid.
-#
-# Example:
-# shell::run_server 5 stdout stderr command arg1 arg2 || exit 1
-shell::run_server() {
- local -r TIMEOUT="$1"
- local -r STDOUT="$2"
- local -r STDERR="$3"
- shift; shift; shift
- if [[ "${STDOUT}" = "${STDERR}" ]]; then
- "$@" > "${STDOUT}" 2>&1 &
- else
- "$@" > "${STDOUT}" 2> "${STDERR}" &
- fi
- local -r SERVER_PID=$!
- echo "${SERVER_PID}" >> "${V23_SHELL_TMP_PIDS}"
- echo "${SERVER_PID}"
-
- for i in $(seq 1 "${TIMEOUT}"); do
- sleep 1
- local RESULT=$(shell::check_result kill -0 "${SERVER_PID}")
- if [[ "${RESULT}" = "0" ]]; then
- # server's up, can return early
- return 0
- fi
- done
- return "${RESULT}"
-}
-
-# shell::timed_wait_for is used to wait until the given pattern appears
-# in the given file within a set timeout. It returns 0 if the pattern
-# was successfully matched and 1 if the timeout expires before the pattern
-# is found.
-#
-# Example:
-# local -r LOG_FILE=$(shell::tmp_file)
-# shell::run_server 1 "${LOG_FILE}" "${LOG_FILE}" <server> <args>...
-# shell::timed_wait_for 1 "${LOG_FILE}" "server started"
-shell::timed_wait_for() {
- local -r TIMEOUT="$1"
- local -r FILE="$2"
- local -r PATTERN="$3"
- for i in $(seq 1 "${TIMEOUT}"); do
- sleep 1
- grep -m 1 "${PATTERN}" "${FILE}" > /dev/null && return 0 || true
- done
- # grep has timed out.
- echo "Timed out. Here's the file:"
- echo "====BEGIN FILE==="
- cat "${FILE}"
- echo "====END FILE==="
- return 1
-}
-
-# shell::silence runs the given command with the supplied arguments,
-# redirecting all of its output to /dev/null and ignoring its exit
-# code.
-shell::silence() {
- "$@" &> /dev/null || true
-}
diff --git a/services/device/shell_test.sh b/services/device/shell_test.sh
deleted file mode 100755
index 9d66678..0000000
--- a/services/device/shell_test.sh
+++ /dev/null
@@ -1,276 +0,0 @@
-#!/bin/bash
-# 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.
-
-# The shell_test library is used to execute shell tests.
-
-# IMPORTANT: If your script registers its own "trap" handler, that
-# handler must call shell_test::at_exit to clean up all temporary
-# files and directories created by this library.
-
-source "$(go list -f {{.Dir}} v.io/x/ref/cmd/mgmt)/shell.sh"
-
-trap shell_test::at_exit INT TERM EXIT
-
-# ensure that we print a 'FAIL' message unless shell_test::pass is
-# explicitly called.
-shell_test_EXIT_MESSAGE="FAIL_UNEXPECTED_EXIT"
-
-# default timeout values.
-shell_test_DEFAULT_SERVER_TIMEOUT="10"
-shell_test_DEFAULT_MESSAGE_TIMEOUT="30"
-
-# default binary dir and working dir.
-shell_test_BIN_DIR="${shell_test_BIN_DIR:-$(shell::tmp_dir)}"
-shell_test_WORK_DIR="$(shell::tmp_dir)"
-
-# shell_test::assert_eq GOT WANT LINENO checks that GOT == WANT and if
-# not, fails the test, outputting the offending line number.
-shell_test::assert_eq() {
- local -r GOT="$1"
- local -r WANT="$2"
- local -r LINENO="$3"
- if [[ "${GOT}" != "${WANT}" ]]; then
- shell_test::fail "line ${LINENO}: expected '${GOT}' == '${WANT}'"
- fi
-}
-
-# shell_test::assert_ge GOT WANT LINENO checks that GOT >= WANT and if
-# not, fails the test, outputting the given line number and error
-# message.
-shell_test::assert_ge() {
- local -r GOT="$1"
- local -r WANT="$2"
- local -r LINENO="$3"
- if [[ "${GOT}" -lt "${WANT}" ]]; then
- shell_test::fail "line ${LINENO}: expected ${GOT} >= ${WANT}"
- fi
-}
-
-# shell_test::assert_gt GOT WANT LINENO checks that GOT > WANT and if
-# not, fails the test, outputting the given line number and error
-# message.
-shell_test::assert_gt() {
- local -r GOT="$1"
- local -r WANT="$2"
- local -r LINENO="$3"
- if [[ "${GOT}" -le "${WANT}" ]]; then
- shell_test::fail "line ${LINENO}: expected ${GOT} > ${WANT}"
- fi
-}
-
-# shell_test::assert_le GOT WANT LINENO checks that GOT <= WANT and if
-# not, fails the test, outputting the given line number and error
-# message.
-shell_test::assert_le() {
- local -r GOT="$1"
- local -r WANT="$2"
- local -r LINENO="$3"
- if [[ "${GOT}" -gt "${WANT}" ]]; then
- shell_test::fail "line ${LINENO}: expected ${GOT} <= ${WANT}"
- fi
-}
-
-# shell_test::assert_lt GOT WANT LINENO checks that GOT < WANT and if
-# not, fails the test, outputting the given line number and error
-# message.
-shell_test::assert_lt() {
- local -r GOT="$1"
- local -r WANT="$2"
- local -r LINENO="$3"
- if [[ "${GOT}" -ge "${WANT}" ]]; then
- shell_test::fail "line ${LINENO}: expected ${GOT} < ${WANT}"
- fi
-}
-
-# shell_test::assert_ne GOT WANT LINENO checks that GOT != WANT and if
-# not, fails the test, outputting the offending line number.
-shell_test::assert_ne() {
- local -r GOT="$1"
- local -r WANT="$2"
- local -r LINENO="$3"
- if [[ "${GOT}" == "${WANT}" ]]; then
- shell_test::fail "line ${LINENO}: expected '${GOT}' != '${WANT}'"
- fi
-}
-
-# shell_test::assert_contains GOT WANT LINENO checks that GOT contains WANT and
-# if not, fails the test, outputting the offending line number.
-shell_test::assert_contains() {
- local -r GOT="$1"
- local -r WANT="$2"
- local -r LINENO="$3"
- if [[ ! "${GOT}" =~ "${WANT}" ]]; then
- shell_test::fail "line ${LINENO}: expected '${GOT}' contains '${WANT}'"
- fi
-}
-
-# shell_test::at_exit is executed when the shell script exits.
-shell_test::at_exit() {
- echo "${shell_test_EXIT_MESSAGE}"
- # Note: shell::at_exit unsets our trap, so it won't run again on exit.
- shell::at_exit
- shell::kill_child_processes
-}
-
-# shell_test::fail is used to identify a failing test.
-#
-# Example:
-# <command> || shell_test::fail "line ${LINENO}: <error message>"
-shell_test::fail() {
- [[ "$#" -gt 0 ]] && echo "$0 $*"
- shell_test_EXIT_MESSAGE="FAIL"
- exit 1
-}
-
-# shell_test::pass is used to identify a passing test.
-shell_test::pass() {
- shell_test_EXIT_MESSAGE="PASS"
- exit 0
-}
-
-# shell_test::build_go_binary builds the binary for the given go package ($1) with
-# the given output ($2) in $shell_test_BIN_DIR. Before building a binary, it will
-# check whether it already exists. If so, it will skip it.
-shell_test::build_go_binary() {
- pushd "${shell_test_BIN_DIR}" > /dev/null
- local -r PACKAGE="$1"
- local OUTPUT="${2:-$(basename ${PACKAGE})}"
- if [[ -f "${OUTPUT}" ]]; then
- echo "${shell_test_BIN_DIR}/${OUTPUT}"
- return
- fi
-
- go build -o "${OUTPUT}" "${PACKAGE}" 2>/dev/null || shell_test::fail "line ${LINENO}: failed to build ${OUTPUT}"
- echo "${shell_test_BIN_DIR}/${OUTPUT}"
- popd > /dev/null
-}
-
-# shell_test::setup_server_test is common boilerplate used for testing vanadium
-# servers. In particular, this function sets up an instance of the mount table
-# daemon, and sets the V23_NAMESPACE environment variable accordingly. It also
-# sets up credentials as needed.
-shell_test::setup_server_test() {
- if [[ -n ${shell_test_RUNNING_UNDER_AGENT+1} ]]; then
- shell_test::setup_server_test_agent
- else
- shell_test::setup_server_test_no_agent
- fi
-}
-
-# shell_test::setup_mounttable brings up a mounttable and sets the
-# V23_NAMESPACE to point to it.
-shell_test::setup_mounttable() {
- # Build the mount table daemon and related tools.
- MOUNTTABLED_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/mounttable/mounttabled')"
-
- # Start the mounttable daemon.
- local -r MT_LOG=$(shell::tmp_file)
- if [[ -n ${shell_test_RUNNING_UNDER_AGENT+1} ]]; then
- shell::run_server "${shell_test_DEFAULT_SERVER_TIMEOUT}" "${MT_LOG}" "${MT_LOG}" "${VRUN}" "${MOUNTTABLED_BIN}" --v23="127.0.0.1:0" &> /dev/null || (cat "${MT_LOG}" && shell_test::fail "line ${LINENO}: failed to start mounttabled")
- else
- shell::run_server "${shell_test_DEFAULT_SERVER_TIMEOUT}" "${MT_LOG}" "${MT_LOG}" "${MOUNTTABLED_BIN}" --v23.tcp.address="127.0.0.1:0" &> /dev/null || (cat "${MT_LOG}" && shell_test::fail "line ${LINENO}: failed to start mounttabled")
- fi
- shell::timed_wait_for "${shell_test_DEFAULT_MESSAGE_TIMEOUT}" "${MT_LOG}" "Mount table service" || shell_test::fail "line ${LINENO}: failed to find expected output"
-
- export V23_NAMESPACE=$(grep "Mount table service at:" "${MT_LOG}" | sed -e 's/^.*endpoint: //')
- [[ -n "${V23_NAMESPACE}" ]] || shell_test::fail "line ${LINENO}: failed to read endpoint from logfile"
-}
-
-# shell_test::setup_server_test_no_agent does the work of setup_server_test when
-# not running under enable_agent (using credentials directories).
-shell_test::setup_server_test_no_agent() {
- [[ ! -n ${shell_test_RUNNING_UNDER_AGENT+1} ]] \
- || shell_test::fail "setup_server_test_no_agent called when running under enable_agent"
- shell_test::setup_mounttable
-
- # Create and use a new credentials directory /after/ the mount table is
- # started so that servers or clients started after this point start with different
- # credentials.
- local -r TMP=${V23_CREDENTIALS:-}
- if [[ -z "${TMP}" ]]; then
- export V23_CREDENTIALS=$(shell::tmp_dir)
- fi
-}
-
-# shell_test::setup_server_test_agent does the work of setup_server_test when
-# running under enable_agent.
-shell_test::setup_server_test_agent() {
- [[ -n ${shell_test_RUNNING_UNDER_AGENT+1} ]] \
- || shell_test::fail "setup_server_test_agent called when not running under enable_agent"
- shell_test::setup_mounttable
-}
-
-# shell_test::start_server is used to start a server. The server is
-# considered started when it successfully mounts itself into a mount
-# table; an event that is detected using the shell::wait_for
-# function.
-#
-# Example:
-# shell_test::start_server <server> <args>
-shell_test::start_server() {
- START_SERVER_LOG_FILE=$(shell::tmp_file)
- START_SERVER_PID=$(shell::run_server "${shell_test_DEFAULT_SERVER_TIMEOUT}" "${START_SERVER_LOG_FILE}" "${START_SERVER_LOG_FILE}" "$@" -logtostderr -vmodule=publisher=2)
- shell::timed_wait_for "${shell_test_DEFAULT_MESSAGE_TIMEOUT}" "${START_SERVER_LOG_FILE}" "ipc pub: mount"
-}
-
-# shell_test::credentials is used to create a new VeyronCredentials directory.
-# The directory is initialized with a new principal that has a self-signed
-# blessing of the specified name set as default and shareable with all peers.
-#
-# Example:
-# shell_test::credentials <self blessing name>
-shell_test::credentials() {
- [[ ! -n ${shell_test_RUNNING_UNDER_AGENT+1} ]] \
- || shell_test::fail "credentials called when running under enable_agent"
- local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/principal')"
- local -r CRED=$(shell::tmp_dir)
- "${PRINCIPAL_BIN}" create --overwrite=true "${CRED}" "$1" >/dev/null || shell_test::fail "line ${LINENO}: create failed"
- echo "${CRED}"
-}
-
-# shell_test::forkcredentials is used to create a new VeyronCredentials directory
-# that is initialized with a principal blessed by the provided principal under the
-# provided extension.
-#
-# Example:
-# shell_test::forkcredentials <blesser principal's VeyronCredentials> <extension>
-shell_test::forkcredentials() {
- [[ ! -n ${shell_test_RUNNING_UNDER_AGENT+1} ]] \
- || shell_test::fail "forkcredentials called when running under enable_agent"
-
- local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/principal')"
- local -r FORKCRED=$(shell::tmp_dir)
- "${PRINCIPAL_BIN}" create --overwrite=true "${FORKCRED}" self >/dev/null || shell_test::fail "line ${LINENO}: create failed"
- "${PRINCIPAL_BIN}" --v23.credentials="$1" bless --require-caveats=false "${FORKCRED}" "$2" >blessing || shell_test::fail "line ${LINENO}: bless failed"
- "${PRINCIPAL_BIN}" --v23.credentials="${FORKCRED}" store setdefault blessing || shell_test::fail "line ${LINENO}: store setdefault failed"
- "${PRINCIPAL_BIN}" --v23.credentials="${FORKCRED}" store set blessing ... || shell_test::fail "line ${LINENO}: store set failed"
- echo "${FORKCRED}"
-}
-
-# shell_test::enable_agent causes the test to be executed under the security
-# agent. It sets up the agent and then runs itself under that agent.
-#
-# Example:
-# shell_test::enable_agent "$@"
-# build() {
-# ...
-# }
-# main() {
-# build
-# ...
-# shell_test::pass
-# }
-# main "$@"
-shell_test::enable_agent() {
- if [[ ! -n ${shell_test_RUNNING_UNDER_AGENT+1} ]]; then
- local -r AGENTD="$(shell_test::build_go_binary 'v.io/x/ref/services/agent/agentd')"
- local -r WORKDIR="${shell_test_WORK_DIR}"
- export shell_test_RUNNING_UNDER_AGENT=1
- V23_CREDENTIALS="${WORKDIR}/credentials" exec ${AGENTD} --no-passphrase --additional-principals="${WORKDIR}/childcredentials" bash -"$-" "$0" "$@"
- shell_test::fail "failed to run test under agent"
- else
- VRUN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/vrun')"
- fi
-}
diff --git a/services/device/suid_test.sh b/services/device/suid_test.sh
deleted file mode 100755
index 2c09107..0000000
--- a/services/device/suid_test.sh
+++ /dev/null
@@ -1,348 +0,0 @@
-#!/bin/bash
-# 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.
-#
-# When this script is invoked with the --with_suid <user1> <user2> flag, it
-# installs the device manager in its more secure multi-account
-# configuration where the device manager runs under the account of <user1>
-# while test apps will be executed as <user2>. This mode will
-# require root permissions to install and may require configuring an
-# agent passphrase.
-#
-# For exanple:
-#
-# ./suid_test.sh --with_suid devicemanager vana
-#
-# to test a device manager with multi-account support enabled for app
-# account vana.
-#
-
-# When running --with_suid, TMPDIR must grant the invoking user rwx
-# permissions and x permissions for all directories back to / for world.
-# Otherwise, the with_suid user will not be able to use absolute paths.
-# On Darwin, TMPDIR defaults to a directory hieararchy in /var that is
-# 0700. This is unworkable so force TMPDIR to /tmp in this case.
-WITH_SUID="${1:-no}"
-# TODO(caprita,rjkroege): Add logic to the integration test that verifies
-# installing and accessing packages from apps. This would add coverage to the
-# package-related code in suid mode.
-if [[ "${WITH_SUID}" == "--with_suid" ]]; then
- DEVMGR_USER="${2:?--with_suid requires a devicemgr user}"
- SUID_USER="${3:?--with_suid requires a app user}"
- SUDO_USER="root"
- TMPDIR=/tmp
- umask 066
-fi
-
- source "$(go list -f {{.Dir}} v.io/x/ref/cmd/mgmt)/shell_test.sh"
-
-# Run the test under the security agent.
-shell_test::enable_agent "$@"
-
-readonly WORKDIR="${shell_test_WORK_DIR}"
-
-build() {
- echo ">> Building binaries"
- BINARYD_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/binary/binaryd')"
- BINARY_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/binary/binary')"
- APPLICATIOND_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/application/applicationd')"
- APPLICATION_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/application/application')"
- AGENTD_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/agent/agentd')"
- SUIDHELPER_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/device/suidhelper')"
- INITHELPER_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/device/inithelper')"
- DEVICEMANAGER_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/device/deviced')"
- DEVICE_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/device/device')"
- NAMESPACE_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/namespace')"
- PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/principal')"
- DEBUG_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/debug/debug')"
- DEVICE_SCRIPT="$(go list -f {{.Dir}} v.io/x/ref/services/device)/devicex"
-}
-
-# TODO(caprita): Move to shell_tesh.sh
-
-###############################################################################
-# Waits until the given name appears in the mounttable, within a set timeout.
-# Arguments:
-# path to namespace command-line tool
-# timeout in seconds
-# name to look up
-# old mount entry value (if specified, waits until a different value appears)
-# Returns:
-# 0 if the name was successfully found, and 1 if the timeout expires before
-# the name appears.
-# Prints the new value of the mount entry.
-###############################################################################
-wait_for_mountentry() {
- local -r NAMESPACE_BIN="$1"
- local -r TIMEOUT="$2"
- local -r NAME="$3"
- local -r OLD_ENTRY="${4:+}"
- for i in $(seq 1 "${TIMEOUT}"); do
- local ENTRY=$("${NAMESPACE_BIN}" resolve "${NAME}" 2>/dev/null)
- if [[ -n "${ENTRY}" && "${ENTRY}" != "${OLD_ENTRY}" ]]; then
- echo ${ENTRY}
- return 0
- fi
- sleep 1
- done
- echo "Timed out waiting for ${NAME} to have a mounttable entry different from ${OLD_ENTRY}."
- return 1
-}
-
-###############################################################################
-# Waits until the given name disappears from the mounttable, within a set
-# timeout.
-# Arguments:
-# path to namespace command-line tool
-# timeout in seconds
-# name to look up
-# Returns:
-# 0 if the name was gone from the mounttable, and 1 if the timeout expires
-# while the name is still in the mounttable.
-###############################################################################
-wait_for_no_mountentry() {
- local -r NAMESPACE_BIN="$1"
- local -r TIMEOUT="$2"
- local -r NAME="$3"
- for i in $(seq 1 "${TIMEOUT}"); do
- local ENTRY=$("${NAMESPACE_BIN}" resolve "${NAME}" 2>/dev/null)
- if [[ -z "${ENTRY}" ]]; then
- return 0
- fi
- sleep 1
- done
- echo "Timed out waiting for ${NAME} to disappear from the mounttable."
- return 1
-}
-
-main() {
- cd "${WORKDIR}"
- build
-
- local -r APPLICATIOND_NAME="applicationd"
- local -r DEVICED_APP_NAME="${APPLICATIOND_NAME}/deviced/test"
-
- BIN_STAGING_DIR="${WORKDIR}/bin"
- mkdir -p "${BIN_STAGING_DIR}"
- cp "${AGENTD_BIN}" "${SUIDHELPER_BIN}" "${INITHELPER_BIN}" "${DEVICEMANAGER_BIN}" "${BIN_STAGING_DIR}"
- shell_test::setup_server_test
-
- if [[ "${WITH_SUID}" == "--with_suid" ]]; then
- chmod go+x "${WORKDIR}"
- fi
-
- echo ">> Installing and starting the device manager"
- DM_INSTALL_DIR="${WORKDIR}/dm"
-
- export V23_DEVICE_DIR="${DM_INSTALL_DIR}"
-
- if [[ "${WITH_SUID}" != "--with_suid" ]]; then
- local -r extra_arg="--single_user"
- else
- local -r extra_arg="--devuser=${DEVMGR_USER}"
- fi
-
- local -r NEIGHBORHOODNAME="$(hostname)-$$-${RANDOM}"
- "${DEVICE_SCRIPT}" install "${BIN_STAGING_DIR}" \
- ${extra_arg} \
- --origin="${DEVICED_APP_NAME}" \
- -- \
- --v23.tcp.address=127.0.0.1:0 \
- --neighborhood-name="${NEIGHBORHOODNAME}"
-
- "${VRUN}" "${DEVICE_SCRIPT}" start
- local -r MT_NAME=devices/$(hostname)
- MT_EP=$(wait_for_mountentry "${NAMESPACE_BIN}" 5 "${MT_NAME}")
-
- # Verify that device manager's mounttable is published under the expected name
- # (hostname).
- shell_test::assert_ne "$("${NAMESPACE_BIN}" glob "${MT_NAME}")" "" "${LINENO}"
-
- # Create a self-signed blessing with name "alice" and set it as default and
- # shareable with all peers on the principal that this process is running
- # as. This blessing will be used by all commands except those running under
- # "vrun" which gets a principal forked from the process principal.
- "${PRINCIPAL_BIN}" blessself alice > alice.bless || \
- shell_test::fail "line ${LINENO}: blessself alice failed"
- "${PRINCIPAL_BIN}" store setdefault alice.bless || \
- shell_test::fail "line ${LINENO}: store setdefault failed"
- "${PRINCIPAL_BIN}" store set alice.bless ... || \
- shell_test::fail "line ${LINENO}: store set failed"
-
- # Claim the device as "alice/myworkstation".
- echo ">> Claiming the device manager"
- "${DEVICE_BIN}" claim "${MT_NAME}/devmgr/device" myworkstation
- # Wait for the device manager to re-mount after being claimed
- MT_EP=$(wait_for_mountentry "${NAMESPACE_BIN}" 5 "${MT_NAME}" "${MT_EP}")
-
- if [[ "${WITH_SUID}" == "--with_suid" ]]; then
- echo ">> Verify that devicemanager has valid association for alice"
- "${DEVICE_BIN}" associate add "${MT_NAME}/devmgr/device" "${SUID_USER}" "alice"
- shell_test::assert_eq "$("${DEVICE_BIN}" associate list "${MT_NAME}/devmgr/device")" \
- "alice ${SUID_USER}" "${LINENO}"
- echo ">> Verify that devicemanager runs as ${DEVMGR_USER}"
- local -r DPID=$("${DEBUG_BIN}" stats read \
- "${MT_NAME}/devmgr/__debug/stats/system/pid" \
- | awk '{print $2}')
- # ps flags need to be different on linux
- case "$(uname)" in
- "Darwin")
- local -r COMPUTED_DEVMGR_USER=$(ps -ej | \
- awk '$2 ~'"${DPID}"' { print $1 }')
- ;;
- "Linux")
- local -r COMPUTED_DEVMGR_USER=$(awk '/^Uid:/{print $2}' /proc/${DPID}/status | \
- xargs getent passwd | awk -F: '{print $1}')
- ;;
- esac
- shell_test::assert_eq "${COMPUTED_DEVMGR_USER}" \
- "${DEVMGR_USER}" \
- "${LINENO}"
- fi
-
- # Verify the device's default blessing is as expected.
- shell_test::assert_contains "$("${DEBUG_BIN}" stats read "${MT_NAME}/devmgr/__debug/stats/security/principal/*/blessingstore" | head -1)" \
- "Default blessings: alice/myworkstation" "${LINENO}"
-
- # Get the device's profile.
- local -r DEVICE_PROFILE=$("${DEVICE_BIN}" describe "${MT_NAME}/devmgr/device" | sed -e 's/{Profiles:map\[\(.*\):{}]}/\1/')
-
- # Start a binary server under the blessing "alice/myworkstation/binaryd" so that
- # the device ("alice/myworkstation") can talk to it.
- local -r BINARYD_NAME="binaryd"
- shell_test::start_server "${VRUN}" --name=myworkstation/binaryd "${BINARYD_BIN}" --name="${BINARYD_NAME}" \
- --root-dir="${WORKDIR}/binstore" --v23.tcp.address=127.0.0.1:0 --http=127.0.0.1:0 \
- || shell_test::fail "line ${LINENO} failed to start binaryd"
-
- # Upload a binary to the binary server. The binary we upload is binaryd
- # itself.
- local -r SAMPLE_APP_BIN_NAME="${BINARYD_NAME}/testapp"
- echo ">> Uploading ${SAMPLE_APP_BIN_NAME}"
- "${BINARY_BIN}" upload "${SAMPLE_APP_BIN_NAME}" "${BINARYD_BIN}"
-
- # Verify that the binary we uploaded is shown by glob.
- shell_test::assert_eq "$("${NAMESPACE_BIN}" glob "${SAMPLE_APP_BIN_NAME}")" \
- "${SAMPLE_APP_BIN_NAME}" "${LINENO}"
-
- # Start an application server under the blessing "alice/myworkstation/applicationd" so that
- # the device ("alice/myworkstation") can talk to it.
- mkdir -p "${WORKDIR}/appstore"
- shell_test::start_server "${VRUN}" --name=myworkstation/applicationd "${APPLICATIOND_BIN}" --name="${APPLICATIOND_NAME}" \
- --store="${WORKDIR}/appstore" --v23.tcp.address=127.0.0.1:0 \
- || shell_test::fail "line ${LINENO} failed to start applicationd"
-
- # Upload an envelope for our test app.
- local -r SAMPLE_APP_NAME="${APPLICATIOND_NAME}/testapp/v0"
- local -r APP_PUBLISH_NAME="testbinaryd"
- echo ">> Uploading ${SAMPLE_APP_NAME}"
- echo "{\"Title\":\"BINARYD\", \"Args\":[\"--name=${APP_PUBLISH_NAME}\", \"--root-dir=./binstore\", \"--v23.tcp.address=127.0.0.1:0\"], \"Binary\":{\"File\":\"${SAMPLE_APP_BIN_NAME}\"}, \"Env\":[]}" > ./app.envelope
- "${APPLICATION_BIN}" put "${SAMPLE_APP_NAME}" "${DEVICE_PROFILE}" ./app.envelope
- rm ./app.envelope
-
- # Verify that the envelope we uploaded shows up with glob.
- shell_test::assert_eq "$("${APPLICATION_BIN}" match "${SAMPLE_APP_NAME}" "${DEVICE_PROFILE}" | grep Title | sed -e 's/^.*"Title": "'// | sed -e 's/",//')" \
- "BINARYD" "${LINENO}"
-
- # Install the app on the device.
- echo ">> Installing ${SAMPLE_APP_NAME}"
- local -r INSTALLATION_NAME=$("${DEVICE_BIN}" install "${MT_NAME}/devmgr/apps" "${SAMPLE_APP_NAME}" | sed -e 's/Successfully installed: "//' | sed -e 's/"//')
-
- # Verify that the installation shows up when globbing the device manager.
- shell_test::assert_eq "$("${NAMESPACE_BIN}" glob "${MT_NAME}/devmgr/apps/BINARYD/*")" \
- "${INSTALLATION_NAME}" "${LINENO}"
-
- # Start an instance of the app, granting it blessing extension myapp.
- echo ">> Starting ${INSTALLATION_NAME}"
- local -r INSTANCE_NAME=$("${DEVICE_BIN}" start "${INSTALLATION_NAME}" myapp | sed -e 's/Successfully started: "//' | sed -e 's/"//')
- wait_for_mountentry "${NAMESPACE_BIN}" "5" "${MT_NAME}/${APP_PUBLISH_NAME}"
-
- # Verify that the instance shows up when globbing the device manager.
- shell_test::assert_eq "$("${NAMESPACE_BIN}" glob "${MT_NAME}/devmgr/apps/BINARYD/*/*")" "${INSTANCE_NAME}" "${LINENO}"
-
- if [[ "${WITH_SUID}" == "--with_suid" ]]; then
- echo ">> Verifying that the app is actually running as the associated user"
- local -r PID=$("${DEBUG_BIN}" stats read "${MT_NAME}/devmgr/apps/BINARYD/*/*/stats/system/pid" | awk '{print $2}')
- # ps flags need to be different on linux
- case "$(uname)" in
- "Darwin")
- local -r COMPUTED_SUID_USER=$(ps -ej | awk '$2 ~'"${PID}"' { print $1 }')
- ;;
- "Linux")
- local -r COMPUTED_SUID_USER=$(awk '/^Uid:/{print $2}' /proc/${PID}/status | \
- xargs getent passwd | awk -F: '{print $1}')
- ;;
- esac
- shell_test::assert_eq "${COMPUTED_SUID_USER}" "${SUID_USER}" "${LINENO}"
- fi
-
- # Verify the app's default blessing.
- shell_test::assert_contains "$("${DEBUG_BIN}" stats read "${INSTANCE_NAME}/stats/security/principal/*/blessingstore" | head -1)" \
- "Default blessings: alice/myapp/BINARYD" "${LINENO}"
-
- # Stop the instance.
- echo ">> Stopping ${INSTANCE_NAME}"
- "${DEVICE_BIN}" stop "${INSTANCE_NAME}"
-
- # Verify that logs, but not stats, show up when globbing the stopped instance.
- shell_test::assert_eq "$("${NAMESPACE_BIN}" glob "${INSTANCE_NAME}/stats/...")" "" "${LINENO}"
- shell_test::assert_ne "$("${NAMESPACE_BIN}" glob "${INSTANCE_NAME}/logs/...")" "" "${LINENO}"
-
- # Upload a deviced binary.
- local -r DEVICED_APP_BIN_NAME="${BINARYD_NAME}/deviced"
- echo ">> Uploading ${DEVICEMANAGER_BIN}"
- "${BINARY_BIN}" upload "${DEVICED_APP_BIN_NAME}" "${DEVICEMANAGER_BIN}"
-
- # Upload a device manager envelope.
- echo ">> Uploading ${DEVICED_APP_NAME}"
- echo "{\"Title\":\"device manager\", \"Binary\":{\"File\":\"${DEVICED_APP_BIN_NAME}\"}}" > ./deviced.envelope
- "${APPLICATION_BIN}" put "${DEVICED_APP_NAME}" "${DEVICE_PROFILE}" ./deviced.envelope
- rm ./deviced.envelope
- # Update the device manager.
- echo ">> Updating device manager"
- "${DEVICE_BIN}" update "${MT_NAME}/devmgr/device"
- MT_EP=$(wait_for_mountentry "${NAMESPACE_BIN}" 5 "${MT_NAME}" "${MT_EP}")
-
- # Verify that device manager's mounttable is still published under the
- # expected name (hostname).
- shell_test::assert_ne "$("${NAMESPACE_BIN}" glob "${MT_NAME}")" "" "${LINENO}"
-
- # Revert the device manager.
- echo ">> Reverting device manager"
- "${DEVICE_BIN}" revert "${MT_NAME}/devmgr/device"
- MT_EP=$(wait_for_mountentry "${NAMESPACE_BIN}" 5 "${MT_NAME}" "${MT_EP}")
-
- # Verify that device manager's mounttable is still published under the
- # expected name (hostname).
- shell_test::assert_ne "$("${NAMESPACE_BIN}" glob "${MT_NAME}")" "" "${LINENO}"
-
- # Verify that the local mounttable exists, and that the device manager, the
- # global namespace, and the neighborhood are mounted on it.
- shell_test::assert_ne $("${NAMESPACE_BIN}" resolve "${MT_EP}/devmgr") "" "${LINENO}"
- shell_test::assert_eq $("${NAMESPACE_BIN}" resolve "${MT_EP}/global") "[alice/myworkstation]${V23_NAMESPACE}" "${LINENO}"
- shell_test::assert_ne $("${NAMESPACE_BIN}" resolve "${MT_EP}/nh") "" "${LINENO}"
-
- # Suspend the device manager.
- "${DEVICE_BIN}" suspend "${MT_NAME}/devmgr/device"
- wait_for_mountentry "${NAMESPACE_BIN}" "5" "${MT_NAME}" "${MT_EP}"
-
- # Stop the device manager.
- "${DEVICE_SCRIPT}" stop
- wait_for_no_mountentry "${NAMESPACE_BIN}" "5" "${MT_NAME}"
-
- "${DEVICE_SCRIPT}" uninstall
- if [[ -n "$(ls -A "${V23_DEVICE_DIR}" 2>/dev/null)" ]]; then
- shell_test::fail "${V23_DEVICE_DIR} is not empty"
- fi
- shell_test::pass
-}
-
-main "$@"
diff --git a/services/device/test.sh b/services/device/test.sh
deleted file mode 100755
index 5bca914..0000000
--- a/services/device/test.sh
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/bin/bash
-# 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.
-
-#
-# Unit tests for the shell functions in this directory
-#
-
-source "$(go list -f {{.Dir}} v.io/x/ref/cmd/mgmt)/shell_test.sh"
-
-test_assert() {
- shell_test::assert_eq "foo" "foo" "${LINENO}"
- shell_test::assert_eq "42" "42" "${LINENO}"
- shell_test::assert_ge "1" "1" "${LINENO}"
- shell_test::assert_ge "42" "1" "${LINENO}"
- shell_test::assert_gt "42" "1" "${LINENO}"
- shell_test::assert_le "1" "1" "${LINENO}"
- shell_test::assert_le "1" "42" "${LINENO}"
- shell_test::assert_lt "1" "42" "${LINENO}"
- shell_test::assert_ne "1" "42" "${LINENO}"
- shell_test::assert_ne "foo" "bar" "${LINENO}"
-}
-
-test_run_server() {
- shell::run_server 1 /dev/null /dev/null foobar > /dev/null 2>&1
- shell_test::assert_eq "$?" "1" "${LINENO}"
-
- shell::run_server 1 /dev/null /dev/null sleep 10 > /dev/null 2>&1
- shell_test::assert_eq "$?" "0" "${LINENO}"
-}
-
-test_timed_wait_for() {
- local GOT WANT
- local -r TMPFILE=$(shell::tmp_file)
- touch "${TMPFILE}"
-
- shell::timed_wait_for 2 "${TMPFILE}" "doesn't matter, it's all zeros anyway"
- shell_test::assert_eq "$?" "1" "${LINENO}"
-
- echo "foo" > "${TMPFILE}"
- shell::timed_wait_for 2 "${TMPFILE}" "bar"
- shell_test::assert_eq "$?" "1" "${LINENO}"
-
- echo "bar" >> "${TMPFILE}"
- echo "baz" >> "${TMPFILE}"
- shell::timed_wait_for 2 "${TMPFILE}" "bar"
- shell_test::assert_eq "$?" "0" "${LINENO}"
-}
-
-# rmpublickey replaces public keys (16 hex bytes, :-separated) with XX:....
-# This substitution enables comparison with golden output even when keys are freshly
-# minted by the "principal create" command.
-rmpublickey() {
- sed -e "s/\([0-9a-f]\{2\}:\)\{15\}[0-9a-f]\{2\}/XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX/g"
-}
-
-test_credentials() {
- local -r CRED=$(shell_test::credentials alice)
-
- local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/principal')"
-
- "${PRINCIPAL_BIN}" --v23.credentials="${CRED}" dump >alice.dump || shell_test::fail "line ${LINENO}: ${PRINCIPAL_BIN} dump ${CRED} failed"
- cat alice.dump | rmpublickey >got || shell_test::fail "line ${LINENO}: cat alice.dump | rmpublickey failed"
- cat >want <<EOF
-Public key : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
----------------- BlessingStore ----------------
-Default blessings: alice
-Peer pattern : Blessings
-... : alice
----------------- BlessingRoots ----------------
-Public key : Pattern
-XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : [alice]
-EOF
- if ! diff got want; then
- shell_test::fail "line ${LINENO}"
- fi
-}
-
-test_forkcredentials() {
- local -r CRED=$(shell_test::credentials alice)
- local -r FORKCRED=$(shell_test::forkcredentials "${CRED}" fork)
-
- local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/principal')"
-
- "${PRINCIPAL_BIN}" --v23.credentials="${FORKCRED}" dump >alice.dump || shell_test::fail "line ${LINENO}: ${PRINCIPAL_BIN} dump ${CRED} failed"
- cat alice.dump | rmpublickey >got || shell_test::fail "line ${LINENO}: cat alice.dump | rmpublickey failed"
- cat >want <<EOF
-Public key : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
----------------- BlessingStore ----------------
-Default blessings: alice/fork
-Peer pattern : Blessings
-... : alice/fork
----------------- BlessingRoots ----------------
-Public key : Pattern
-XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : [alice]
-XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : [self]
-EOF
- if ! diff got want; then
- shell_test::fail "line ${LINENO}"
- fi
-}
-
-main() {
- test_assert || shell_test::fail "assert"
- test_run_server || shell_test::fail "test_run_server"
- test_timed_wait_for || shell_test::fail "test_run_server"
- test_credentials || shell_test::fail "test_credentials"
- test_forkcredentials || shell_test::fail "test_forkcredentials"
-
- shell_test::pass
-}
-
-main "$@"
diff --git a/services/device/util_darwin_test.go b/services/device/util_darwin_test.go
new file mode 100644
index 0000000..2a91405
--- /dev/null
+++ b/services/device/util_darwin_test.go
@@ -0,0 +1,7 @@
+// 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.
+
+package device_test
+
+const psFlags = "-ej"
diff --git a/services/device/util_linux_test.go b/services/device/util_linux_test.go
new file mode 100644
index 0000000..bb96666
--- /dev/null
+++ b/services/device/util_linux_test.go
@@ -0,0 +1,7 @@
+// 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.
+
+package device_test
+
+const psFlags = "-ef"
diff --git a/services/profile/profiled/profiled_v23_test.go b/services/profile/profiled/profiled_v23_test.go
index 527ba7f..a91cfbe 100644
--- a/services/profile/profiled/profiled_v23_test.go
+++ b/services/profile/profiled/profiled_v23_test.go
@@ -51,7 +51,7 @@
// Start the profile repository.
profileRepoName := "test-profile-repo"
- profileRepoStore := i.NewTempDir()
+ profileRepoStore := i.NewTempDir("")
args := []string{
"-name=" + profileRepoName, "-store=" + profileRepoStore,
"-v23.tcp.address=127.0.0.1:0",
diff --git a/test/v23tests/v23tests.go b/test/v23tests/v23tests.go
index 8945296..b2122e7 100644
--- a/test/v23tests/v23tests.go
+++ b/test/v23tests/v23tests.go
@@ -475,9 +475,9 @@
// NewTempDir creates a temporary directory. Temporary directories and
// their contents will be deleted by Cleanup.
-func (t *T) NewTempDir() string {
+func (t *T) NewTempDir(dir string) string {
loc := Caller(1)
- f, err := ioutil.TempDir("", "")
+ f, err := ioutil.TempDir(dir, "")
if err != nil {
t.Fatalf("%s: TempDir() failed: %v", loc, err)
}
@@ -538,7 +538,7 @@
shutdown: shutdown,
}
if len(e.cachedBinDir) == 0 {
- e.binDir = e.NewTempDir()
+ e.binDir = e.NewTempDir("")
}
return e
}