blob: c107d420d9d9b44e0bf754d5c51a87cdaf81eb33 [file] [log] [blame]
package impl_test
import (
"fmt"
"os"
"testing"
"veyron.io/veyron/veyron2"
"veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/services/mgmt/node"
"veyron.io/veyron/veyron2/verror"
"veyron.io/veyron/veyron2/vlog"
"veyron.io/veyron/veyron/lib/exec"
"veyron.io/veyron/veyron/lib/testutil/blackbox"
"veyron.io/veyron/veyron/lib/testutil/security"
"veyron.io/veyron/veyron/profiles"
mtlib "veyron.io/veyron/veyron/services/mounttable/lib"
)
// TODO(caprita): I've had to write one too many of these, let's move it to some
// central utility library.
// setupLocalNamespace sets up a mounttable and sets the local namespace root
// to point to it. Returns a cleanup function.
func setupLocalNamespace(t *testing.T) func() {
server, err := rt.R().NewServer(veyron2.ServesMountTableOpt(true))
if err != nil {
t.Fatalf("NewServer() failed: %v", err)
}
dispatcher, err := mtlib.NewMountTable("")
if err != nil {
t.Fatalf("NewMountTable() failed: %v", err)
}
endpoint, err := server.ListenX(profiles.LocalListenSpec)
if err != nil {
t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
}
if err := server.Serve("", dispatcher); err != nil {
t.Fatalf("Serve(%v) failed: %v", dispatcher, err)
}
name := naming.JoinAddressName(endpoint.String(), "")
vlog.VI(1).Infof("Mount table object name: %v", name)
ns := rt.R().Namespace()
// Make the runtime's namespace rooted at the MountTable server started
// above.
ns.SetRoots(name)
return func() {
if err := server.Stop(); err != nil {
t.Fatalf("Stop() failed: %v", err)
}
// The runtime outlives the particular test case that invokes
// setupLocalNamespace. It's good practice to reset the
// runtime's state before the next test uses it.
ns.SetRoots()
}
}
// TODO(caprita): Move this setup into the blackbox lib.
// setupChildCommand configures the child to use the right mounttable root
// and identity. It returns a cleanup function.
func setupChildCommand(child *blackbox.Child) func() {
cmd := child.Cmd
for i, root := range rt.R().Namespace().Roots() {
cmd.Env = exec.Setenv(cmd.Env, fmt.Sprintf("NAMESPACE_ROOT%d", i), root)
}
idFile := security.SaveIdentityToFile(security.NewBlessedIdentity(rt.R().Identity(), "test"))
cmd.Env = exec.Setenv(cmd.Env, "VEYRON_IDENTITY", idFile)
return func() {
os.Remove(idFile)
}
}
func newServer() (ipc.Server, string) {
server, err := rt.R().NewServer()
if err != nil {
vlog.Fatalf("NewServer() failed: %v", err)
}
protocol, hostname := "tcp", "127.0.0.1:0"
endpoint, err := server.Listen(protocol, hostname)
if err != nil {
vlog.Fatalf("Listen(%v, %v) failed: %v", protocol, hostname, err)
}
return server, endpoint.String()
}
// resolveExpectError verifies that the given name is not in the mounttable.
func resolveExpectNotFound(t *testing.T, name string) {
if results, err := rt.R().Namespace().Resolve(rt.R().NewContext(), name); err == nil {
t.Fatalf("Resolve(%v) succeeded with results %v when it was expected to fail", name, results)
} else if expectErr := verror.NoExist; !verror.Is(err, expectErr) {
t.Fatalf("Resolve(%v) failed with error %v, expected error ID %v", name, err, expectErr)
}
}
// resolve looks up the given name in the mounttable.
func resolve(t *testing.T, name string, replicas int) []string {
results, err := rt.R().Namespace().Resolve(rt.R().NewContext(), name)
if err != nil {
t.Fatalf("Resolve(%v) failed: %v", name, err)
}
if want, got := replicas, len(results); want != got {
t.Fatalf("Resolve(%v) expected %d result(s), got %d instead", name, want, got)
}
return results
}
// The following set of functions are convenience wrappers around Update and
// Revert for node manager.
func nodeStub(t *testing.T, name string) node.Node {
nodeName := naming.Join(name, "nm")
stub, err := node.BindNode(nodeName)
if err != nil {
t.Fatalf("BindNode(%v) failed: %v", nodeName, err)
}
return stub
}
func updateNodeExpectError(t *testing.T, name string, errID verror.ID) {
if err := nodeStub(t, name).Update(rt.R().NewContext()); !verror.Is(err, errID) {
t.Fatalf("Update(%v) expected to fail with %v, got %v instead", name, errID, err)
}
}
func updateNode(t *testing.T, name string) {
if err := nodeStub(t, name).Update(rt.R().NewContext()); err != nil {
t.Fatalf("Update(%v) failed: %v", name, err)
}
}
func revertNodeExpectError(t *testing.T, name string, errID verror.ID) {
if err := nodeStub(t, name).Revert(rt.R().NewContext()); !verror.Is(err, errID) {
t.Fatalf("Revert(%v) expected to fail with %v, got %v instead", name, errID, err)
}
}
func revertNode(t *testing.T, name string) {
if err := nodeStub(t, name).Revert(rt.R().NewContext()); err != nil {
t.Fatalf("Revert(%v) failed: %v", name, err)
}
}
// The following set of functions are convenience wrappers around various app
// management methods.
func appStub(t *testing.T, nameComponents ...string) node.Application {
appsName := "nm//apps"
appName := naming.Join(append([]string{appsName}, nameComponents...)...)
stub, err := node.BindApplication(appName)
if err != nil {
t.Fatalf("BindApplication(%v) failed: %v", appName, err)
}
return stub
}
func installApp(t *testing.T) string {
appID, err := appStub(t).Install(rt.R().NewContext(), "ar")
if err != nil {
t.Fatalf("Install failed: %v", err)
}
return appID
}
func startAppImpl(t *testing.T, appID string) (string, error) {
if instanceIDs, err := appStub(t, appID).Start(rt.R().NewContext()); err != nil {
return "", err
} else {
if want, got := 1, len(instanceIDs); want != got {
t.Fatalf("Start(%v): expected %v instance ids, got %v instead", appID, want, got)
}
return instanceIDs[0], nil
}
}
func startApp(t *testing.T, appID string) string {
instanceID, err := startAppImpl(t, appID)
if err != nil {
t.Fatalf("Start(%v) failed: %v", appID, err)
}
return instanceID
}
func startAppExpectError(t *testing.T, appID string, expectedError verror.ID) {
if _, err := startAppImpl(t, appID); err == nil || !verror.Is(err, expectedError) {
t.Fatalf("Start(%v) expected to fail with %v, got %v instead", appID, expectedError, err)
}
}
func stopApp(t *testing.T, appID, instanceID string) {
if err := appStub(t, appID, instanceID).Stop(rt.R().NewContext(), 5); err != nil {
t.Fatalf("Stop(%v/%v) failed: %v", appID, instanceID, err)
}
}
func suspendApp(t *testing.T, appID, instanceID string) {
if err := appStub(t, appID, instanceID).Suspend(rt.R().NewContext()); err != nil {
t.Fatalf("Suspend(%v/%v) failed: %v", appID, instanceID, err)
}
}
func resumeApp(t *testing.T, appID, instanceID string) {
if err := appStub(t, appID, instanceID).Resume(rt.R().NewContext()); err != nil {
t.Fatalf("Resume(%v/%v) failed: %v", appID, instanceID, err)
}
}
func updateApp(t *testing.T, appID string) {
if err := appStub(t, appID).Update(rt.R().NewContext()); err != nil {
t.Fatalf("Update(%v) failed: %v", appID, err)
}
}
func updateAppExpectError(t *testing.T, appID string, expectedError verror.ID) {
if err := appStub(t, appID).Update(rt.R().NewContext()); err == nil || !verror.Is(err, expectedError) {
t.Fatalf("Update(%v) expected to fail with %v, got %v instead", appID, expectedError, err)
}
}
func revertApp(t *testing.T, appID string) {
if err := appStub(t, appID).Revert(rt.R().NewContext()); err != nil {
t.Fatalf("Revert(%v) failed: %v", appID, err)
}
}
func revertAppExpectError(t *testing.T, appID string, expectedError verror.ID) {
if err := appStub(t, appID).Revert(rt.R().NewContext()); err == nil || !verror.Is(err, expectedError) {
t.Fatalf("Revert(%v) expected to fail with %v, got %v instead", appID, expectedError, err)
}
}
func uninstallApp(t *testing.T, appID string) {
if err := appStub(t, appID).Uninstall(rt.R().NewContext()); err != nil {
t.Fatalf("Uninstall(%v) failed: %v", appID, err)
}
}