blob: cdae9024c9d1c813ac9322120e3034f7f892697b [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rpc
import (
"io"
"reflect"
"sort"
"testing"
"v.io/v23"
"v.io/v23/context"
"v.io/v23/naming"
"v.io/v23/options"
"v.io/v23/rpc"
"v.io/x/lib/vlog"
"v.io/x/ref/lib/stats"
"v.io/x/ref/profiles/internal/rpc/stream/manager"
tnaming "v.io/x/ref/profiles/internal/testing/mocks/naming"
"v.io/x/ref/services/debug/debuglib"
"v.io/x/ref/test/testutil"
)
func TestDebugServer(t *testing.T) {
ctx, shutdown := initForTest()
defer shutdown()
// Setup the client and server principals, with the client willing to share its
// blessing with the server.
var (
pclient = testutil.NewPrincipal("client")
pserver = testutil.NewPrincipal("server")
bclient = bless(pserver, pclient, "client") // server/client blessing.
)
pclient.AddToRoots(bclient) // Client recognizes "server" as a root of blessings.
pclient.BlessingStore().Set(bclient, "server") // Client presents bclient to server
debugDisp := debuglib.NewDispatcher(vlog.Log.LogDir, nil)
sm := manager.InternalNew(naming.FixedRoutingID(0x555555555))
defer sm.Shutdown()
ns := tnaming.NewSimpleNamespace()
server, err := testInternalNewServer(ctx, sm, ns, pserver, ReservedNameDispatcher{debugDisp})
if err != nil {
t.Fatalf("InternalNewServer failed: %v", err)
}
defer server.Stop()
eps, err := server.Listen(listenSpec)
if err != nil {
t.Fatalf("server.Listen failed: %v", err)
}
if err := server.Serve("", &testObject{}, nil); err != nil {
t.Fatalf("server.Serve failed: %v", err)
}
ctx, _ = v23.WithPrincipal(ctx, pclient)
client, err := InternalNewClient(sm, ns)
if err != nil {
t.Fatalf("InternalNewClient failed: %v", err)
}
defer client.Close()
ep := eps[0]
// Call the Foo method on ""
{
var value string
if err := client.Call(ctx, ep.Name(), "Foo", nil, []interface{}{&value}); err != nil {
t.Fatalf("client.Call failed: %v", err)
}
if want := "BAR"; value != want {
t.Errorf("unexpected value: Got %v, want %v", value, want)
}
}
// Call Value on __debug/stats/testing/foo
{
foo := stats.NewString("testing/foo")
foo.Set("The quick brown fox jumps over the lazy dog")
addr := naming.JoinAddressName(ep.String(), "__debug/stats/testing/foo")
var value string
if err := client.Call(ctx, addr, "Value", nil, []interface{}{&value}, options.NoResolve{}); err != nil {
t.Fatalf("client.Call failed: %v", err)
}
if want := foo.Value(); value != want {
t.Errorf("unexpected result: Got %v, want %v", value, want)
}
}
// Call Glob
testcases := []struct {
name, pattern string
expected []string
}{
{"", "*", []string{}},
{"", "__*", []string{"__debug"}},
{"", "__*/*", []string{"__debug/logs", "__debug/pprof", "__debug/stats", "__debug/vtrace"}},
{"__debug", "*", []string{"logs", "pprof", "stats", "vtrace"}},
}
for _, tc := range testcases {
addr := naming.JoinAddressName(ep.String(), tc.name)
call, err := client.StartCall(ctx, addr, rpc.GlobMethod, []interface{}{tc.pattern}, options.NoResolve{})
if err != nil {
t.Fatalf("client.StartCall failed for %q: %v", tc.name, err)
}
results := []string{}
for {
var gr naming.GlobReply
if err := call.Recv(&gr); err != nil {
if err != io.EOF {
t.Fatalf("Recv failed for %q: %v. Results received thus far: %q", tc.name, err, results)
}
break
}
switch v := gr.(type) {
case naming.GlobReplyEntry:
results = append(results, v.Value.Name)
}
}
if err := call.Finish(); err != nil {
t.Fatalf("call.Finish failed for %q: %v", tc.name, err)
}
sort.Strings(results)
if !reflect.DeepEqual(tc.expected, results) {
t.Errorf("unexpected results for %q. Got %v, want %v", tc.name, results, tc.expected)
}
}
}
type testObject struct {
}
func (o testObject) Foo(*context.T, rpc.ServerCall) (string, error) {
return "BAR", nil
}