blob: b4cfc18e3333711ca0b32fe636368cdf0ae96cf9 [file] [log] [blame]
package unresolve
import (
"fmt"
"testing"
"veyron2"
"veyron2/context"
"veyron2/ipc"
"veyron2/naming"
"veyron2/rt"
"veyron2/security"
mtidl "veyron2/services/mounttable"
"veyron2/vlog"
_ "veyron/lib/testutil"
"veyron/lib/testutil/blackbox"
mounttable "veyron/services/mounttable/lib"
fortuneidl "veyron/examples/fortune"
)
func initRT(opts ...veyron2.ROpt) func() {
return rt.Init(opts...).Cleanup
}
func createServer(name string, dispatcher ipc.Dispatcher, opts ...ipc.ServerOpt) (ipc.Server, string) {
server, err := rt.R().NewServer(opts...)
if err != nil {
panic(fmt.Sprintf("r.NewServer failed with %v", err))
}
ep, err := server.Listen("tcp", "127.0.0.1:0")
if err != nil {
panic(fmt.Sprintf("server.Listen failed with %v", err))
}
if err := server.Serve(name, dispatcher); err != nil {
panic(fmt.Sprintf("server.Serve failed with %v", err))
}
oa := naming.JoinAddressName(ep.String(), "")
vlog.Infof("created %s -> %s", name, oa)
return server, oa
}
func childMT(args []string) {
defer initRT()()
for _, arg := range args {
server, _ := createMTServer(arg)
defer server.Stop()
}
fmt.Println("ready")
blackbox.WaitForEOFOnStdin()
}
func createMTServer(mp string) (ipc.Server, string) {
mt, err := mounttable.NewMountTable("")
if err != nil {
panic(fmt.Sprintf("NewMountTable failed with %v", err))
}
return createServer(mp, mt, veyron2.ServesMountTableOpt(true))
}
func createMTClient(name string) mtidl.MountTable {
client, err := mtidl.BindMountTable(name)
if err != nil {
panic(fmt.Sprintf("BindMountTable failed with %v", err))
}
return client
}
const fixedFortuneMessage = "Sooner than you think, you will be deeply dissatisfied with a fortune."
type fortune struct{}
func (*fortune) Get(ipc.ServerContext) (string, error) {
return fixedFortuneMessage, nil
}
func (*fortune) Add(ipc.ServerContext, string) error {
return nil
}
func childFortune(args []string) {
defer initRT()()
server, _ := createServer(args[0], ipc.LeafDispatcher(fortuneidl.NewServerFortune(new(fortune)), nil))
defer server.Stop()
for _, arg := range args[1:] {
server.Serve(arg, nil)
}
fmt.Println("ready")
blackbox.WaitForEOFOnStdin()
}
type fortuneCustomUnresolve struct {
custom string
}
func (*fortuneCustomUnresolve) Get(ipc.ServerContext) (string, error) {
return fixedFortuneMessage, nil
}
func (*fortuneCustomUnresolve) Add(ipc.ServerContext, string) error {
return nil
}
func (*fortuneCustomUnresolve) UnresolveStep(context ipc.ServerContext) ([]string, error) {
servers, err := rt.R().Namespace().ResolveToMountTable(rt.R().NewContext(), "I/want/to/know")
if err != nil {
return nil, err
}
var reply []string
for _, s := range servers {
r := naming.MakeResolvable(s)
reply = append(reply, naming.Join(r, "the/future"))
}
return reply, nil
}
// Can't use the LeafDispatcher since it doesn't allow name suffixes.
type fortuned struct{ obj interface{} }
func (f *fortuned) Lookup(suffix, method string) (ipc.Invoker, security.Authorizer, error) {
return ipc.ReflectInvoker(f.obj), nil, nil
}
func createFortuneCustomUnresolve(mp string) (ipc.Server, string) {
server, oa := createServer(mp, &fortuned{fortuneidl.NewServerFortune(new(fortuneCustomUnresolve))})
rt.R().Namespace().Mount(rt.R().NewContext(), "I/want/to/know", oa+"//", 0)
rt.R().Namespace().Mount(rt.R().NewContext(), "tell/me", oa+"//", 0)
return server, oa
}
func childFortuneCustomUnresolve(args []string) {
defer initRT()()
for _, arg := range args {
server, _ := createFortuneCustomUnresolve(arg)
defer server.Stop()
}
fmt.Println("ready")
blackbox.WaitForEOFOnStdin()
}
func childFortuneNoIDL(args []string) {
defer initRT()()
for _, arg := range args {
server, _ := createServer(arg, ipc.LeafDispatcher(new(fortuneNoIDL), nil))
defer server.Stop()
}
fmt.Println("ready")
blackbox.WaitForEOFOnStdin()
}
func createFortuneClient(rt veyron2.Runtime, name string) fortuneidl.Fortune {
client, err := fortuneidl.BindFortune(name, rt.Client())
if err != nil {
panic(fmt.Sprintf("BindFortune failed with %v", err))
}
return client
}
type fortuneNoIDL struct{}
func (*fortuneNoIDL) Get(ipc.ServerCall) (string, error) {
return fixedFortuneMessage, nil
}
func (*fortuneNoIDL) UnresolveStep(ipc.ServerCall) ([]string, error) {
servers, err := rt.R().Namespace().ResolveToMountTable(rt.R().NewContext(), "g")
if err != nil {
return nil, err
}
var reply []string
for _, s := range servers {
r := naming.MakeResolvable(s)
reply = append(reply, naming.Join(r, "fortune"))
}
return reply, nil
}
func resolveStep(t *testing.T, name string) string {
client := createMTClient(name)
results, suffix, err := client.ResolveStep(rt.R().NewContext())
if err != nil {
t.Errorf("ResolveStep on %q failed with %v", name, err)
return ""
}
if len(results) != 1 {
t.Errorf("Expected one result when resolving %q, got %q", name, results)
return ""
}
return naming.Join(results[0].Server, suffix)
}
func resolve(t *testing.T, ns naming.Namespace, name string) string {
results, err := ns.Resolve(rt.R().NewContext(), name)
if err != nil {
t.Errorf("Resolve failed with %v", err)
return ""
}
if len(results) != 1 {
t.Errorf("Expected one result when resolving %q, got %q", name, results)
return ""
}
return results[0]
}
type unresolver interface {
UnresolveStep(context.T, ...ipc.CallOpt) ([]string, error)
}
func unresolveStep(t *testing.T, ctx context.T, c unresolver) string {
unres, err := c.UnresolveStep(ctx)
if err != nil {
t.Errorf("UnresolveStep failed with %v", err)
return ""
}
if len(unres) != 1 {
t.Errorf("c.UnresolveStep wanted 1 result, got: %q", unres)
return ""
}
return unres[0]
}
func unresolve(t *testing.T, ns naming.Namespace, name string) string {
results, err := ns.Unresolve(rt.R().NewContext(), name)
if err != nil {
t.Errorf("Unresolve failed with %v", err)
return ""
}
if len(results) != 1 {
t.Errorf("Expected one result when unresolving %q, got %q", name, results)
return ""
}
return results[0]
}
func glob(t *testing.T, pattern string) []string {
var replies []string
rc, err := rt.R().Namespace().Glob(rt.R().NewContext(), pattern)
if err != nil {
t.Errorf("Glob(%s): err %v", pattern, err)
return nil
}
for s := range rc {
replies = append(replies, s.Name)
}
return replies
}