blob: 09d877c54431404e11519e9280ecc5f5fe59a129 [file] [log] [blame]
package unresolve
import (
"fmt"
"testing"
"veyron2"
"veyron2/ipc"
"veyron2/naming"
"veyron2/rt"
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...).Shutdown
}
func newServer(opts ...ipc.ServerOpt) ipc.Server {
server, err := rt.R().NewServer(opts...)
if err != nil {
panic(fmt.Sprintf("r.NewServer failed with %v", err))
}
return server
}
func createServer(server ipc.Server, prefix string, dispatcher ipc.Dispatcher) string {
if err := server.Register(prefix, dispatcher); err != nil {
panic(fmt.Sprintf("server.Register 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))
}
return naming.JoinAddressName(ep.String(), prefix)
}
func serverMain(servesMT bool, serviceCreator func(ipc.Server) string, args []string) {
defer initRT()()
server := newServer(veyron2.ServesMountTableOpt(servesMT))
defer server.Stop()
service := serviceCreator(server)
vlog.Infof("created %v", service)
for _, arg := range args {
if err := server.Publish(arg); err != nil {
panic(fmt.Sprintf("server.Publish(%q) failed with %v", arg, err))
}
}
fmt.Println("ready")
blackbox.WaitForEOFOnStdin()
}
func createMT(server ipc.Server) string {
mt, err := mounttable.NewMountTable("")
if err != nil {
panic(fmt.Sprintf("NewMountTable failed with %v", err))
}
return createServer(server, "mt", mt)
}
func childMT(args []string) {
serverMain(true, createMT, args)
}
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 createFortune(server ipc.Server) string {
return createServer(server, "fortune", ipc.SoloDispatcher(fortuneidl.NewServerFortune(new(fortune)), nil))
}
func childFortune(args []string) {
serverMain(false, createFortune, args)
}
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().MountTable().ResolveToMountTable("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
}
func createFortuneCustomUnresolve(server ipc.Server) string {
oa := createServer(server, "tell/me/the/future", ipc.SoloDispatcher(fortuneidl.NewServerFortune(new(fortuneCustomUnresolve)), nil))
ep, _ := naming.SplitAddressName(oa)
oa = naming.MakeTerminal(naming.JoinAddressName(ep, "tell/me"))
// Doesn't get unmounted. Fine for a test.
oa = naming.MakeTerminal(oa)
rt.R().MountTable().Mount("I/want/to/know", oa, 0)
return oa
}
func childFortuneCustomUnresolve(args []string) {
serverMain(false, createFortuneCustomUnresolve, args)
}
func createFortuneClient(rt veyron2.Runtime, name string) fortuneidl.Fortune {
client, err := fortuneidl.BindFortune(name, veyron2.RuntimeOpt{rt})
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().MountTable().ResolveToMountTable("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 createFortuneNoIDL(server ipc.Server) string {
return createServer(server, "fortune", ipc.SoloDispatcher(new(fortuneNoIDL), nil))
}
func childFortuneNoIDL(args []string) {
serverMain(false, createFortuneNoIDL, args)
}
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, mt naming.MountTable, name string) string {
results, err := mt.Resolve(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(ipc.Context, ...ipc.CallOpt) ([]string, error)
}
func unresolveStep(t *testing.T, ctx ipc.Context, 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, mt naming.MountTable, name string) string {
results, err := mt.Unresolve(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]
}