blob: 2036d94e914d9cfe04995d832a50fcdbe2ee4ac4 [file] [log] [blame]
package debug
import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
"strings"
"testing"
"time"
"v.io/core/veyron2"
"v.io/core/veyron2/context"
"v.io/core/veyron2/ipc"
"v.io/core/veyron2/naming"
"v.io/core/veyron2/rt"
"v.io/core/veyron2/services/mgmt/logreader"
"v.io/core/veyron2/services/mgmt/stats"
vtracesvc "v.io/core/veyron2/services/mgmt/vtrace"
verror "v.io/core/veyron2/verror2"
"v.io/core/veyron2/vtrace"
libstats "v.io/core/veyron/lib/stats"
"v.io/core/veyron/lib/testutil"
"v.io/core/veyron/profiles"
)
// startDebugServer starts a debug server.
func startDebugServer(rt veyron2.Runtime, listenSpec ipc.ListenSpec, logsDir string) (string, func(), error) {
if len(logsDir) == 0 {
return "", nil, fmt.Errorf("logs directory missing")
}
disp := NewDispatcher(logsDir, nil)
server, err := rt.NewServer()
if err != nil {
return "", nil, fmt.Errorf("failed to start debug server: %v", err)
}
endpoints, err := server.Listen(listenSpec)
if err != nil {
return "", nil, fmt.Errorf("failed to listen on %s: %v", listenSpec, err)
}
if err := server.ServeDispatcher("", disp); err != nil {
return "", nil, err
}
ep := endpoints[0].String()
return ep, func() { server.Stop() }, nil
}
func TestDebugServer(t *testing.T) {
runtime, err := rt.New()
if err != nil {
t.Fatalf("Could not initialize runtime: %v", err)
}
defer runtime.Cleanup()
tracedContext := func() *context.T {
ctx := runtime.NewContext()
vtrace.ForceCollect(ctx)
return ctx
}
rootName = "debug"
workdir, err := ioutil.TempDir("", "logreadertest")
if err != nil {
t.Fatalf("ioutil.TempDir: %v", err)
}
defer os.RemoveAll(workdir)
if err = ioutil.WriteFile(filepath.Join(workdir, "test.INFO"), []byte("test"), os.FileMode(0644)); err != nil {
t.Fatalf("ioutil.WriteFile failed: %v", err)
}
endpoint, stop, err := startDebugServer(runtime, profiles.LocalListenSpec, workdir)
if err != nil {
t.Fatalf("StartDebugServer failed: %v", err)
}
defer stop()
// Access a logs directory that exists.
{
results, err := testutil.GlobName(runtime.NewContext(), naming.JoinAddressName(endpoint, "debug/logs"), "*")
if err != nil {
t.Errorf("Glob failed: %v", err)
}
if len(results) != 1 || results[0] != "test.INFO" {
t.Errorf("unexpected result. Got %v, want 'test.INFO'", results)
}
}
// Access a logs directory that doesn't exist.
{
results, err := testutil.GlobName(runtime.NewContext(), naming.JoinAddressName(endpoint, "debug/logs/nowheretobefound"), "*")
if len(results) != 0 {
t.Errorf("unexpected result. Got %v, want ''", results)
}
if err != nil {
t.Errorf("unexpected error value: %v", err)
}
}
// Access a log file that exists.
{
lf := logreader.LogFileClient(naming.JoinAddressName(endpoint, "debug/logs/test.INFO"))
size, err := lf.Size(tracedContext())
if err != nil {
t.Errorf("Size failed: %v", err)
}
if expected := int64(len("test")); size != expected {
t.Errorf("unexpected result. Got %v, want %v", size, expected)
}
}
// Access a log file that doesn't exist.
{
lf := logreader.LogFileClient(naming.JoinAddressName(endpoint, "debug/logs/nosuchfile.INFO"))
_, err = lf.Size(tracedContext())
if expected := verror.NoExist.ID; !verror.Is(err, expected) {
t.Errorf("unexpected error value, got %v, want: %v", err, expected)
}
}
// Access a stats object that exists.
{
foo := libstats.NewInteger("testing/foo")
foo.Set(123)
st := stats.StatsClient(naming.JoinAddressName(endpoint, "debug/stats/testing/foo"))
v, err := st.Value(tracedContext())
if err != nil {
t.Errorf("Value failed: %v", err)
}
if expected := int64(123); v != expected {
t.Errorf("unexpected result. Got %v, want %v", v, expected)
}
}
// Access a stats object that doesn't exists.
{
st := stats.StatsClient(naming.JoinAddressName(endpoint, "debug/stats/testing/nobodyhome"))
_, err = st.Value(tracedContext())
if expected := verror.NoExist.ID; !verror.Is(err, expected) {
t.Errorf("unexpected error value, got %v, want: %v", err, expected)
}
}
// Access vtrace.
{
vt := vtracesvc.StoreClient(naming.JoinAddressName(endpoint, "debug/vtrace"))
call, err := vt.AllTraces(runtime.NewContext())
if err != nil {
t.Errorf("AllTraces failed: %v", err)
}
ntraces := 0
stream := call.RecvStream()
for stream.Advance() {
stream.Value()
ntraces++
}
if err = stream.Err(); err != nil && err != io.EOF {
t.Fatalf("Unexpected error reading trace stream: %s", err)
}
if ntraces != 4 {
t.Errorf("We expected 4 traces, got: %d", ntraces)
}
}
// Glob from the root.
{
ctx, cancel := context.WithTimeout(runtime.NewContext(), 10*time.Second)
defer cancel()
ns := veyron2.GetNamespace(ctx)
ns.SetRoots(naming.JoinAddressName(endpoint, "debug"))
c, err := ns.Glob(ctx, "logs/...")
if err != nil {
t.Errorf("ns.Glob failed: %v", err)
}
results := []string{}
for res := range c {
results = append(results, res.Name)
}
sort.Strings(results)
expected := []string{
"logs",
"logs/test.INFO",
}
if !reflect.DeepEqual(expected, results) {
t.Errorf("unexpected result. Got %v, want %v", results, expected)
}
c, err = ns.Glob(ctx, "stats/testing/*")
if err != nil {
t.Errorf("ns.Glob failed: %v", err)
}
results = []string{}
for res := range c {
results = append(results, res.Name)
}
sort.Strings(results)
expected = []string{
"stats/testing/foo",
}
if !reflect.DeepEqual(expected, results) {
t.Errorf("unexpected result. Got %v, want %v", results, expected)
}
c, err = ns.Glob(ctx, "*")
if err != nil {
t.Errorf("ns.Glob failed: %v", err)
}
results = []string{}
for res := range c {
results = append(results, res.Name)
}
sort.Strings(results)
expected = []string{
"logs",
"pprof",
"stats",
"vtrace",
}
if !reflect.DeepEqual(expected, results) {
t.Errorf("unexpected result. Got %v, want %v", results, expected)
}
c, err = ns.Glob(ctx, "...")
if err != nil {
t.Errorf("ns.Glob failed: %v", err)
}
results = []string{}
for res := range c {
if strings.HasPrefix(res.Name, "stats/") && !strings.HasPrefix(res.Name, "stats/testing/") {
// Skip any non-testing stats.
continue
}
results = append(results, res.Name)
}
sort.Strings(results)
expected = []string{
"",
"logs",
"logs/test.INFO",
"pprof",
"stats",
"stats/testing/foo",
"vtrace",
}
if !reflect.DeepEqual(expected, results) {
t.Errorf("unexpected result. Got %v, want %v", results, expected)
}
}
}