blob: 19ee38b28d5a357a2b47909c5f5dbefc0eb35174 [file] [log] [blame]
package core_test
import (
"fmt"
"os"
"reflect"
"sort"
"strconv"
"testing"
"time"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/vlog"
"veyron.io/veyron/veyron/lib/expect"
"veyron.io/veyron/veyron/lib/modules"
"veyron.io/veyron/veyron/lib/modules/core"
"veyron.io/veyron/veyron/lib/testutil"
_ "veyron.io/veyron/veyron/profiles"
)
func TestCommands(t *testing.T) {
sh := core.NewShell()
defer sh.Cleanup(nil, os.Stderr)
for _, c := range []string{core.RootMTCommand, core.MTCommand} {
if len(sh.Help(c)) == 0 {
t.Fatalf("missing command %q", c)
}
}
}
func init() {
testutil.Init()
rt.Init()
}
func newShell() (*modules.Shell, func()) {
sh := core.NewShell()
return sh, func() {
if testing.Verbose() {
vlog.Infof("------ cleanup ------")
sh.Cleanup(os.Stderr, os.Stderr)
} else {
sh.Cleanup(nil, nil)
}
}
}
func testArgs(args ...string) []string {
var targs = []string{"--", "--veyron.tcp.address=127.0.0.1:0"}
return append(targs, args...)
}
func TestRoot(t *testing.T) {
sh, fn := newShell()
defer fn()
root, err := sh.Start(core.RootMTCommand, nil, testArgs()...)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
s := expect.NewSession(t, root.Stdout(), time.Second)
s.ExpectVar("MT_NAME")
s.ExpectVar("MT_ADDR")
s.ExpectVar("PID")
root.CloseStdin()
}
func startMountTables(t *testing.T, sh *modules.Shell, mountPoints ...string) (map[string]string, func(), error) {
// Start root mount table
root, err := sh.Start(core.RootMTCommand, nil, testArgs()...)
if err != nil {
t.Fatalf("unexpected error for root mt: %s", err)
}
sh.Forget(root)
rootSession := expect.NewSession(t, root.Stdout(), time.Minute)
rootName := rootSession.ExpectVar("MT_NAME")
if t.Failed() {
return nil, nil, rootSession.Error()
}
sh.SetVar("NAMESPACE_ROOT", rootName)
mountAddrs := make(map[string]string)
mountAddrs["root"] = rootName
// Start the mount tables
for _, mp := range mountPoints {
h, err := sh.Start(core.MTCommand, nil, testArgs(mp)...)
if err != nil {
return nil, nil, fmt.Errorf("unexpected error for mt %q: %s", mp, err)
}
s := expect.NewSession(t, h.Stdout(), time.Minute)
// Wait until each mount table has at least called Serve to
// mount itself.
mountAddrs[mp] = s.ExpectVar("MT_NAME")
if s.Failed() {
return nil, nil, s.Error()
}
}
deferFn := func() {
if testing.Verbose() {
vlog.Infof("------ root shutdown ------")
root.Shutdown(os.Stderr, os.Stderr)
} else {
root.Shutdown(nil, nil)
}
}
return mountAddrs, deferFn, nil
}
func getMatchingMountpoint(r [][]string) string {
if len(r) != 1 {
return ""
}
shortest := ""
for _, p := range r[0][1:] {
if len(p) > 0 {
if len(shortest) == 0 {
shortest = p
}
if len(shortest) > 0 && len(p) < len(shortest) {
shortest = p
}
}
}
return shortest
}
func TestMountTableAndGlob(t *testing.T) {
sh, fn := newShell()
defer fn()
mountPoints := []string{"a", "b", "c", "d", "e"}
mountAddrs, fn, err := startMountTables(t, sh, mountPoints...)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
defer fn()
rootName := mountAddrs["root"]
ls, err := sh.Start(core.LSCommand, nil, rootName+"/...")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
lsSession := expect.NewSession(t, ls.Stdout(), time.Minute)
lsSession.SetVerbosity(testing.Verbose())
if got, want := lsSession.ExpectVar("RN"), strconv.Itoa(len(mountPoints)+1); got != want {
t.Fatalf("got %v, want %v", got, want)
}
lsSession.Expect("R0=" + rootName)
// Look for names that correspond to the mountpoints above (i.e, a, b or c)
pattern := ""
for _, n := range mountPoints {
pattern = pattern + "^R[\\d]+=(" + rootName + "/(" + n + ")$)|"
}
pattern = pattern[:len(pattern)-1]
found := []string{}
for i := 0; i < len(mountPoints); i++ {
found = append(found, getMatchingMountpoint(lsSession.ExpectRE(pattern, 1)))
}
sort.Strings(found)
sort.Strings(mountPoints)
if got, want := found, mountPoints; !reflect.DeepEqual(got, want) {
t.Errorf("got %v, want %v", got, want)
}
// Run the ls command in a subprocess, with NAMESPACE_ROOT as set above.
lse, err := sh.Start(core.LSExternalCommand, nil, "...")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
lseSession := expect.NewSession(t, lse.Stdout(), time.Minute)
lseSession.SetVerbosity(testing.Verbose())
if got, want := lseSession.ExpectVar("RN"), strconv.Itoa(len(mountPoints)); got != want {
t.Fatalf("got %v, want %v", got, want)
}
pattern = ""
for _, n := range mountPoints {
// Since the LSExternalCommand runs in a subprocess with NAMESPACE_ROOT
// set to the name of the root mount table it sees to the relative name
// format of the mounted mount tables.
pattern = pattern + "^R[\\d]+=(" + n + "$)|"
}
pattern = pattern[:len(pattern)-1]
found = []string{}
for i := 0; i < len(mountPoints); i++ {
found = append(found, getMatchingMountpoint(lseSession.ExpectRE(pattern, 1)))
}
sort.Strings(found)
sort.Strings(mountPoints)
if got, want := found, mountPoints; !reflect.DeepEqual(got, want) {
t.Errorf("got %v, want %v", got, want)
}
}
func TestEcho(t *testing.T) {
sh, fn := newShell()
defer fn()
srv, err := sh.Start(core.EchoServerCommand, nil, testArgs("test", "")...)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
srvSession := expect.NewSession(t, srv.Stdout(), time.Minute)
name := srvSession.ExpectVar("NAME")
if len(name) == 0 {
t.Fatalf("failed to get name")
}
clt, err := sh.Start(core.EchoClientCommand, nil, name, "a message")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
cltSession := expect.NewSession(t, clt.Stdout(), time.Minute)
cltSession.Expect("test: a message")
srv.Shutdown(nil, nil)
}
func TestResolve(t *testing.T) {
sh, fn := newShell()
defer fn()
mountPoints := []string{"a", "b"}
mountAddrs, fn, err := startMountTables(t, sh, mountPoints...)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
defer fn()
rootName := mountAddrs["root"]
mtName := "b"
echoName := naming.Join(mtName, "echo")
srv, err := sh.Start(core.EchoServerCommand, nil, testArgs("test", echoName)...)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
srvSession := expect.NewSession(t, srv.Stdout(), time.Minute)
srvSession.ExpectVar("NAME")
addr := srvSession.ExpectVar("ADDR")
addr = naming.JoinAddressName(addr, "//")
// Resolve an object
resolver, err := sh.Start(core.ResolveCommand, nil, rootName+"/"+echoName)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
resolverSession := expect.NewSession(t, resolver.Stdout(), time.Minute)
if got, want := resolverSession.ExpectVar("RN"), "1"; got != want {
t.Fatalf("got %v, want %v", got, want)
}
if got, want := resolverSession.ExpectVar("R0"), addr; got != want {
t.Errorf("got %v, want %v", got, want)
}
if err = resolver.Shutdown(nil, os.Stderr); err != nil {
t.Fatalf("unexpected error: %s", err)
}
// Resolve to a mount table using a rooted name.
addr = naming.JoinAddressName(mountAddrs[mtName], "//echo")
resolver, err = sh.Start(core.ResolveMTCommand, nil, rootName+"/"+echoName)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
resolverSession = expect.NewSession(t, resolver.Stdout(), time.Minute)
if got, want := resolverSession.ExpectVar("RN"), "1"; got != want {
t.Fatalf("got %v, want %v", got, want)
}
if got, want := resolverSession.ExpectVar("R0"), addr; got != want {
t.Fatalf("got %v, want %v", got, want)
}
if err := resolver.Shutdown(nil, os.Stderr); err != nil {
t.Fatalf("unexpected error: %s", err)
}
// Resolve to a mount table, but using a relative name.
nsroots, err := sh.Start(core.SetNamespaceRootsCommand, nil, rootName)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if err := nsroots.Shutdown(nil, os.Stderr); err != nil {
t.Fatalf("unexpected error: %s", err)
}
resolver, err = sh.Start(core.ResolveMTCommand, nil, echoName)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
resolverSession = expect.NewSession(t, resolver.Stdout(), time.Minute)
if got, want := resolverSession.ExpectVar("RN"), "1"; got != want {
t.Fatalf("got %v, want %v", got, want)
}
if got, want := resolverSession.ExpectVar("R0"), addr; got != want {
t.Fatalf("got %v, want %v", got, want)
}
if err := resolver.Shutdown(nil, os.Stderr); err != nil {
t.Fatalf("unexpected error: %s", err)
}
srv.Shutdown(nil, nil)
nsroots.Shutdown(nil, nil)
}
func TestHelperProcess(t *testing.T) {
modules.DispatchInTest()
}