Merge "veyron/runtimes, veyron2/model: Share preferred protocols when client is changed with RuntimeX."
diff --git a/lib/modules/core/core_test.go b/lib/modules/core/core_test.go
index 09dc291..14ab572 100644
--- a/lib/modules/core/core_test.go
+++ b/lib/modules/core/core_test.go
@@ -200,7 +200,7 @@
func TestExec(t *testing.T) {
sh, cleanup := newShell(t)
defer cleanup()
- h, err := sh.Start(core.ExecCommand, nil, []string{"echo", "-n", "hello world"}...)
+ h, err := sh.Start(core.ExecCommand, nil, []string{"/bin/sh", "-c", "echo -n hello world"}...)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -216,7 +216,7 @@
func TestExecWithEnv(t *testing.T) {
sh, cleanup := newShell(t)
defer cleanup()
- h, err := sh.Start(core.ExecCommand, []string{"BLAH=hello world"}, "printenv", "BLAH")
+ h, err := sh.Start(core.ExecCommand, []string{"BLAH=hello world"}, "/bin/sh", "-c", "printenv BLAH")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
diff --git a/lib/modules/core/exec.go b/lib/modules/core/exec.go
index d0e5556..be41d0d 100644
--- a/lib/modules/core/exec.go
+++ b/lib/modules/core/exec.go
@@ -2,7 +2,7 @@
import (
"io"
- "os/exec"
+ "syscall"
"v.io/core/veyron/lib/modules"
)
@@ -12,15 +12,9 @@
}
func execCommand(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- cmd := exec.Command(args[1], args[2:]...)
envSlice := []string{}
for key, value := range env {
envSlice = append(envSlice, key+"="+value)
}
-
- cmd.Env = envSlice
- cmd.Stdin = stdin
- cmd.Stdout = stdout
- cmd.Stderr = stderr
- return cmd.Run()
+ return syscall.Exec(args[1], args[1:], envSlice)
}
diff --git a/lib/testutil/integration/util.go b/lib/testutil/integration/util.go
index 12d2dc6..4836fce 100644
--- a/lib/testutil/integration/util.go
+++ b/lib/testutil/integration/util.go
@@ -85,8 +85,16 @@
// Wait waits for this invocation to finish. If either stdout or stderr
// is non-nil, any remaining unread output from those sources will be
- // written to the corresponding writer.
- Wait(stdout, stderr io.Writer)
+ // written to the corresponding writer. The returned error represents
+ // the exit status of the underlying command.
+ Wait(stdout, stderr io.Writer) error
+
+ // Wait waits for this invocation to finish. If either stdout or stderr
+ // is non-nil, any remaining unread output from those sources will be
+ // written to the corresponding writer. If the underlying command
+ // exited with anything but success (exit status 0), this function will
+ // cause the current test to fail.
+ WaitOrDie(stdout, stderr io.Writer)
}
type integrationTestEnvironment struct {
@@ -163,9 +171,13 @@
return readerToString(i.env.t, i.Stderr())
}
-func (i *integrationTestBinaryInvocation) Wait(stdout, stderr io.Writer) {
- if err := (*i.handle).Shutdown(stdout, stderr); err != nil {
- i.env.t.Fatalf("Shutdown() failed: %v", err)
+func (i *integrationTestBinaryInvocation) Wait(stdout, stderr io.Writer) error {
+ return (*i.handle).Shutdown(stdout, stderr)
+}
+
+func (i *integrationTestBinaryInvocation) WaitOrDie(stdout, stderr io.Writer) {
+ if err := i.Wait(stdout, stderr); err != nil {
+ i.env.t.Fatalf("Wait() for pid %d failed: %v", (*i.handle).Pid(), err)
}
}
diff --git a/services/identity/identityd/main.go b/services/identity/identityd/main.go
index 4a9f96b..10af65a 100644
--- a/services/identity/identityd/main.go
+++ b/services/identity/identityd/main.go
@@ -78,7 +78,7 @@
fmt.Fprintf(os.Stderr, `%s starts an HTTP server that brokers blessings after authenticating through OAuth.
To generate TLS certificates so the HTTP server can use SSL:
-v23 go run $GOROOT/src/crypto/tls/generate_cert.go --host <IP address>
+go run $GOROOT/src/crypto/tls/generate_cert.go --host <IP address>
To use Google as an OAuth provider the --google_config_* flags must be set to point to
the a JSON file obtained after registering the application with the Google Developer Console
diff --git a/services/identity/identityd_test/main.go b/services/identity/identityd_test/main.go
index 6556f6e..4531b63 100644
--- a/services/identity/identityd_test/main.go
+++ b/services/identity/identityd_test/main.go
@@ -5,8 +5,11 @@
"flag"
"fmt"
"os"
+ "os/exec"
"time"
+ "v.io/core/veyron2/vlog"
+
"v.io/core/veyron/services/identity/auditor"
"v.io/core/veyron/services/identity/blesser"
"v.io/core/veyron/services/identity/caveats"
@@ -26,6 +29,14 @@
auditor, reader := auditor.NewMockBlessingAuditor()
revocationManager := revocation.NewMockRevocationManager()
+ // If no tlsconfig has been provided, write and use our own.
+ if flag.Lookup("tlsconfig").Value.String() == "" {
+ writeCertAndKey()
+ if err := flag.Set("tlsconfig", "./cert.pem,./key.pem"); err != nil {
+ vlog.Fatal(err)
+ }
+ }
+
server.NewIdentityServer(
oauth.NewMockOAuth(),
auditor,
@@ -36,17 +47,30 @@
}
func usage() {
- fmt.Fprintf(os.Stderr, `%s starts an test version of the identityd server that
+ fmt.Fprintf(os.Stderr, `%s starts a test version of the identityd server that
mocks out oauth, auditing, and revocation.
To generate TLS certificates so the HTTP server can use SSL:
-v23 go run $GOROOT/src/crypto/tls/generate_cert.go --host <IP address>
+go run $GOROOT/src/crypto/tls/generate_cert.go --host <IP address>
Flags:
`, os.Args[0])
flag.PrintDefaults()
}
+func writeCertAndKey() {
+ goroot := os.Getenv("GOROOT")
+ if goroot == "" {
+ vlog.Fatal("GOROOT not set")
+ }
+ generateCertFile := goroot + "/src/crypto/tls/generate_cert.go"
+ host := flag.Lookup("host").Value.String()
+ duration := 1 * time.Hour
+ if err := exec.Command("go", "run", generateCertFile, "--host", host, "--duration", duration.String()).Run(); err != nil {
+ vlog.Fatalf("Could not generate key and cert: %v", err)
+ }
+}
+
func oauthBlesserGoogleParams(revocationManager revocation.RevocationManager) blesser.GoogleParams {
googleParams := blesser.GoogleParams{
BlessingDuration: 365 * 24 * time.Hour,
diff --git a/services/identity/test.sh b/services/identity/test.sh
index 67ccffa..5b30587 100755
--- a/services/identity/test.sh
+++ b/services/identity/test.sh
@@ -11,24 +11,6 @@
PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/tools/principal')"
}
-# These certificatese were created with "generate_cert.go --host=localhost --duration=87600h --ecdsa-curve=P256"
-CERT="-----BEGIN CERTIFICATE-----
-MIIBbTCCARSgAwIBAgIRANKYmC0v3pK+VohyJOdD1hgwCgYIKoZIzj0EAwIwEjEQ
-MA4GA1UEChMHQWNtZSBDbzAeFw0xNDExMjEyMjEwNTJaFw0yNDExMTgyMjEwNTJa
-MBIxEDAOBgNVBAoTB0FjbWUgQ28wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASv
-heWcWcZT7d5Sm/uoWhBUJJPBSREN4qGzBV7yFYUFvHJ9mNaEcopo/6BopJRbvUmj
-CQMVDZVMm5Er/f8HgCngo0swSTAOBgNVHQ8BAf8EBAMCAKAwEwYDVR0lBAwwCgYI
-KwYBBQUHAwEwDAYDVR0TAQH/BAIwADAUBgNVHREEDTALgglsb2NhbGhvc3QwCgYI
-KoZIzj0EAwIDRwAwRAIgAkwh+mi5YlIxYzxzT7bQj/ZYU5pufxHt+F+a75gbm7AC
-IAI9+axCPawySY+UYvjO14hklsyy3LnSf1mNHyeGydMM
------END CERTIFICATE-----"
-
-KEY="-----BEGIN EC PRIVATE KEY-----
-MHcCAQEEIHxiR6vjOn1jF1KS0V//pXrulxss9PwUgV/7/QVeV2zCoAoGCCqGSM49
-AwEHoUQDQgAEr4XlnFnGU+3eUpv7qFoQVCSTwUkRDeKhswVe8hWFBbxyfZjWhHKK
-aP+gaKSUW71JowkDFQ2VTJuRK/3/B4Ap4A==
------END EC PRIVATE KEY-----"
-
# runprincipal starts the principal tool, extracts the url and curls it, to avoid the
# dependence the principal tool has on a browser.
runprincipal() {
@@ -51,15 +33,11 @@
cd "${WORKDIR}"
build
- # Setup the certificate files.
- echo "${CERT}" > "${WORKDIR}/cert.pem"
- echo "${KEY}" > "${WORKDIR}/key.pem"
-
shell_test::setup_server_test || shell_test::fail "line ${LINENO} failed to setup server test"
unset VEYRON_CREDENTIALS
# Start the identityd server in test identity server.
- shell_test::start_server "${IDENTITYD_BIN}" --host=localhost --tlsconfig="${WORKDIR}/cert.pem,${WORKDIR}/key.pem" -veyron.tcp.address=127.0.0.1:0
+ shell_test::start_server "${IDENTITYD_BIN}" --host=localhost -veyron.tcp.address=127.0.0.1:0
echo Identityd Log File: $START_SERVER_LOG_FILE
export VEYRON_CREDENTIALS="$(shell::tmp_dir)"
diff --git a/services/mgmt/binary/binaryd/testdata/integration_test.go b/services/mgmt/binary/binaryd/testdata/integration_test.go
index a70b1b0..87ff0f4 100644
--- a/services/mgmt/binary/binaryd/testdata/integration_test.go
+++ b/services/mgmt/binary/binaryd/testdata/integration_test.go
@@ -4,10 +4,11 @@
"bytes"
"fmt"
"io/ioutil"
+ "net/http"
"os"
"os/exec"
- "path/filepath"
"strings"
+ "syscall"
"testing"
"v.io/core/veyron/lib/modules"
@@ -22,11 +23,6 @@
testutil.Init()
}
-var binPkgs = []string{
- "v.io/core/veyron/services/mgmt/binary/binaryd",
- "v.io/core/veyron/tools/binary",
-}
-
func checkFileType(t *testing.T, file, typeString string) {
var catOut bytes.Buffer
catCmd := exec.Command("cat", file+".__info")
@@ -40,89 +36,76 @@
}
}
+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) {
- var cmpOut bytes.Buffer
- cmpCmd := exec.Command("cmp", f1, f2)
- cmpCmd.Stdout = &cmpOut
- cmpCmd.Stderr = &cmpOut
- if err := cmpCmd.Run(); err != nil {
- t.Fatalf("%q failed: %v\n%v", strings.Join(cmpCmd.Args, " "), err, cmpOut.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(t *testing.T, binDir, credentials, mt, name, suffix string) {
- var deleteOut bytes.Buffer
+func deleteFile(env integration.TestEnvironment, clientBin integration.TestBinary, credentials, name, suffix string) {
deleteArgs := []string{
"-veyron.credentials=" + credentials,
- "-veyron.namespace.root=" + mt,
+ "-veyron.namespace.root=" + env.RootMT(),
"delete", naming.Join(name, suffix),
}
- deleteCmd := exec.Command(filepath.Join(binDir, "binary"), deleteArgs...)
- deleteCmd.Stdout = &deleteOut
- deleteCmd.Stderr = &deleteOut
- if err := deleteCmd.Run(); err != nil {
- t.Fatalf("%q failed: %v\n%v", strings.Join(deleteCmd.Args, " "), err, deleteOut.String())
- }
+ clientBin.Start(deleteArgs...).WaitOrDie(nil, nil)
}
-func downloadFile(t *testing.T, expectError bool, binDir, credentials, mt, name, path, suffix string) {
- var downloadOut bytes.Buffer
+func downloadFile(t *testing.T, env integration.TestEnvironment, clientBin integration.TestBinary, expectError bool, credentials, name, path, suffix string) {
downloadArgs := []string{
"-veyron.credentials=" + credentials,
- "-veyron.namespace.root=" + mt,
+ "-veyron.namespace.root=" + env.RootMT(),
"download", naming.Join(name, suffix), path,
}
- downloadCmd := exec.Command(filepath.Join(binDir, "binary"), downloadArgs...)
- downloadCmd.Stdout = &downloadOut
- downloadCmd.Stderr = &downloadOut
- err := downloadCmd.Run()
- if err != nil && !expectError {
- t.Fatalf("%q failed: %v\n%v", strings.Join(downloadCmd.Args, " "), err, downloadOut.String())
+ 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 err == nil && expectError {
- t.Fatalf("%q did not fail when it should", strings.Join(downloadCmd.Args, " "))
+ 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) {
- var curlOut bytes.Buffer
- curlCmd := exec.Command("curl", "-f", "-o", path, fmt.Sprintf("%v/%v", rootURL, suffix))
- curlCmd.Stdout = &curlOut
- curlCmd.Stderr = &curlOut
- if err := curlCmd.Run(); err != nil {
- t.Fatalf("%q failed: %v\n%v", strings.Join(curlCmd.Args, " "), err, curlOut.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, binDir, credentials, mt, name string) string {
- var rootOut bytes.Buffer
+func rootURL(t *testing.T, env integration.TestEnvironment, clientBin integration.TestBinary, credentials, name string) string {
rootArgs := []string{
"-veyron.credentials=" + credentials,
- "-veyron.namespace.root=" + mt,
+ "-veyron.namespace.root=" + env.RootMT(),
"url", name,
}
- rootCmd := exec.Command(filepath.Join(binDir, "binary"), rootArgs...)
- rootCmd.Stdout = &rootOut
- rootCmd.Stderr = &rootOut
- if err := rootCmd.Run(); err != nil {
- t.Fatalf("%q failed: %v\n%v", strings.Join(rootCmd.Args, " "), err, rootOut.String())
- }
- return strings.TrimSpace(rootOut.String())
+ return strings.TrimSpace(clientBin.Start(rootArgs...).Output())
}
-func uploadFile(t *testing.T, binDir, credentials, mt, name, path, suffix string) {
- var uploadOut bytes.Buffer
+func uploadFile(t *testing.T, env integration.TestEnvironment, clientBin integration.TestBinary, credentials, name, path, suffix string) {
uploadArgs := []string{
"-veyron.credentials=" + credentials,
- "-veyron.namespace.root=" + mt,
+ "-veyron.namespace.root=" + env.RootMT(),
"upload", naming.Join(name, suffix), path,
}
- uploadCmd := exec.Command(filepath.Join(binDir, "binary"), uploadArgs...)
- uploadCmd.Stdout = &uploadOut
- uploadCmd.Stderr = &uploadOut
- if err := uploadCmd.Run(); err != nil {
- t.Fatalf("%q failed: %v\n%v", strings.Join(uploadCmd.Args, " "), err, uploadOut.String())
- }
+ clientBin.Start(uploadArgs...).WaitOrDie(os.Stdout, os.Stderr)
}
func TestHelperProcess(t *testing.T) {
@@ -130,24 +113,12 @@
}
func TestBinaryRepositoryIntegration(t *testing.T) {
- // Build the required binaries.
- binDir, cleanup, err := integration.BuildPkgs(binPkgs)
- if err != nil {
- t.Fatalf("%v", err)
- }
- defer cleanup()
+ env := integration.NewTestEnvironment(t)
+ defer env.Cleanup()
- // Start a root mount table.
- shell, err := modules.NewShell(nil)
- if err != nil {
- t.Fatalf("NewShell() failed: %v", err)
- }
- defer shell.Cleanup(os.Stdin, os.Stderr)
- handle, mt, err := integration.StartRootMT(shell)
- if err != nil {
- t.Fatalf("%v", err)
- }
- defer handle.CloseStdin()
+ // 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")
@@ -156,33 +127,25 @@
defer os.RemoveAll(clientCred)
// Start the build server.
- binaryRepoBin := filepath.Join(binDir, "binaryd")
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,
- "-veyron.namespace.root=" + mt,
+ "-veyron.namespace.root=" + env.RootMT(),
}
- serverProcess, err := integration.StartServer(binaryRepoBin, args)
- if err != nil {
- t.Fatalf("%v", err)
- }
- defer serverProcess.Kill()
+
+ server := binaryRepoBin.Start(args...)
+ defer server.Kill(syscall.SIGTERM)
// Upload a random binary file.
- binFile, err := ioutil.TempFile("", "")
- if err != nil {
- t.Fatalf("TempFile() failed: %v", err)
- }
- defer binFile.Close()
- defer os.Remove(binFile.Name())
+ 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, binDir, clientCred, mt, binaryRepoName, binFile.Name(), binSuffix)
+ uploadFile(t, env, clientBin, clientCred, binaryRepoName, binFile.Name(), binSuffix)
// Upload a compressed version of the binary file.
tarFile := binFile.Name() + ".tar.gz"
@@ -195,13 +158,13 @@
}
defer os.Remove(tarFile)
tarSuffix := "test-compressed-file"
- uploadFile(t, binDir, clientCred, mt, binaryRepoName, tarFile, tarSuffix)
+ 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, false, binDir, clientCred, mt, binaryRepoName, downloadedBinFile, binSuffix)
+ downloadFile(t, env, clientBin, false, clientCred, binaryRepoName, downloadedBinFile, binSuffix)
compareFiles(t, binFile.Name(), downloadedBinFile)
checkFileType(t, downloadedBinFile, `{"Type":"application/octet-stream","Encoding":""}`)
@@ -210,13 +173,13 @@
// right file type.
downloadedTarFile := binFile.Name() + "-downloaded.tar.gz"
defer os.Remove(downloadedTarFile)
- downloadFile(t, false, binDir, clientCred, mt, binaryRepoName, downloadedTarFile, tarSuffix)
+ 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, binDir, clientCred, mt, binaryRepoName)
+ root := rootURL(t, env, clientBin, clientCred, binaryRepoName)
// Download the binary file using the HTTP protocol and check
// that it matches the original one.
@@ -234,10 +197,10 @@
compareFiles(t, downloadedTarFile, downloadedTarFileURL)
// Delete the files.
- deleteFile(t, binDir, clientCred, mt, binaryRepoName, binSuffix)
- deleteFile(t, binDir, clientCred, mt, binaryRepoName, tarSuffix)
+ deleteFile(env, clientBin, clientCred, binaryRepoName, binSuffix)
+ deleteFile(env, clientBin, clientCred, binaryRepoName, tarSuffix)
// Check the files no longer exist.
- downloadFile(t, true, binDir, clientCred, mt, binaryRepoName, downloadedBinFile, binSuffix)
- downloadFile(t, true, binDir, clientCred, mt, binaryRepoName, downloadedTarFile, tarSuffix)
+ downloadFile(t, env, clientBin, true, clientCred, binaryRepoName, downloadedBinFile, binSuffix)
+ downloadFile(t, env, clientBin, true, clientCred, binaryRepoName, downloadedTarFile, tarSuffix)
}
diff --git a/tools/debug/testdata/integration_test.go b/tools/debug/testdata/integration_test.go
index 46c4c1b..8216925 100644
--- a/tools/debug/testdata/integration_test.go
+++ b/tools/debug/testdata/integration_test.go
@@ -108,7 +108,7 @@
logName := filepath.Base(file.Name())
runCount := 12
for i := 0; i < runCount; i++ {
- binary.Start("logs", "read", env.RootMT()+"/__debug/logs/"+logName).Wait(nil, nil)
+ binary.Start("logs", "read", env.RootMT()+"/__debug/logs/"+logName).WaitOrDie(nil, nil)
}
got := binary.Start("stats", "read", env.RootMT()+"/__debug/stats/ipc/server/routing-id/*/methods/ReadLog/latency-ms").Output()
want := fmt.Sprintf("Count: %d", runCount)
@@ -125,7 +125,7 @@
testLogData := "This is a test log file\n"
file := createTestLogFile(t, env, testLogData)
logName := filepath.Base(file.Name())
- binary.Start("logs", "read", env.RootMT()+"/__debug/logs/"+logName).Wait(nil, nil)
+ binary.Start("logs", "read", env.RootMT()+"/__debug/logs/"+logName).WaitOrDie(nil, nil)
inv := binary.Start("stats", "watch", "-raw", env.RootMT()+"/__debug/stats/ipc/server/routing-id/*/methods/ReadLog/latency-ms")