blob: de17dcaeae49f71df224886b6e0b9465ab989de9 [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 debuglib
import (
"io"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
"strings"
"testing"
"time"
"v.io/v23"
"v.io/v23/context"
"v.io/v23/naming"
"v.io/v23/services/logreader"
"v.io/v23/services/stats"
s_vtrace "v.io/v23/services/vtrace"
"v.io/v23/vdl"
"v.io/v23/verror"
"v.io/v23/vtrace"
"v.io/x/lib/vlog"
libstats "v.io/x/ref/lib/stats"
_ "v.io/x/ref/runtime/factories/generic"
"v.io/x/ref/test"
"v.io/x/ref/test/testutil"
)
func TestDebugServer(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
tracedContext := func(ctx *context.T) *context.T {
ctx, _ = vtrace.WithNewTrace(ctx)
vtrace.ForceCollect(ctx, 0)
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)
}
// Use logger configured with the directory that we want to use for this test.
testLogger := vlog.NewLogger("TestDebugServer")
testLogger.Configure(vlog.LogDir(workdir))
ctx = context.WithLogger(ctx, testLogger)
disp := NewDispatcher(nil)
ctx, server, err := v23.WithNewDispatchingServer(ctx, "", disp)
if err != nil {
t.Fatalf("failed to start debug server: %v", err)
}
endpoint := server.Status().Endpoints[0].String()
// Access a logs directory that exists.
{
results, _, err := testutil.GlobName(ctx, naming.JoinAddressName(endpoint, "debug/logs"), "*")
if err != nil {
t.Errorf("Glob failed: %v", err)
}
check(t, []string{"test.INFO"}, results)
}
// Access a logs directory that doesn't exist.
{
results, _, err := testutil.GlobName(ctx, 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(ctx))
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(ctx))
if expected := verror.ErrNoExist.ID; verror.ErrorID(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(ctx))
if err != nil {
t.Errorf("Value failed: %v", err)
}
vv := vdl.ValueOf(v)
if want := vdl.IntValue(vdl.Int64Type, 123); !vdl.EqualValue(vv, want) {
t.Errorf("unexpected result. got %v, want %v", vv, want)
}
}
// Access a stats object that doesn't exists.
{
st := stats.StatsClient(naming.JoinAddressName(endpoint, "debug/stats/testing/nobodyhome"))
_, err = st.Value(tracedContext(ctx))
if expected := verror.ErrNoExist.ID; verror.ErrorID(err) != expected {
t.Errorf("unexpected error value, got %v, want: %v", err, expected)
}
}
// Access vtrace.
{
vt := s_vtrace.StoreClient(naming.JoinAddressName(endpoint, "debug/vtrace"))
call, err := vt.AllTraces(ctx)
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(ctx, 10*time.Second)
defer cancel()
ns := v23.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 {
switch v := res.(type) {
case *naming.GlobReplyEntry:
results = append(results, v.Value.Name)
}
}
expected := []string{
"logs",
"logs/test.INFO",
}
check(t, expected, results)
c, err = ns.Glob(ctx, "stats/testing/*")
if err != nil {
t.Errorf("ns.Glob failed: %v", err)
}
results = []string{}
for res := range c {
t.Logf("got %v", res)
switch v := res.(type) {
case *naming.GlobReplyEntry:
results = append(results, v.Value.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 {
switch v := res.(type) {
case *naming.GlobReplyEntry:
results = append(results, v.Value.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 {
switch v := res.(type) {
case *naming.GlobReplyEntry:
if strings.HasPrefix(v.Value.Name, "stats/") && !strings.HasPrefix(v.Value.Name, "stats/testing/") {
// Skip any non-testing stats.
continue
}
results = append(results, v.Value.Name)
}
}
expected = []string{
"",
"logs",
"logs/test.INFO",
"pprof",
"stats",
"stats/testing/foo",
"vtrace",
}
check(t, expected, results)
}
}
func check(t *testing.T, expected, results []string) {
resultSet := map[string]bool{}
for _, result := range results {
resultSet[result] = true
}
var missing []string
for _, expected := range expected {
if !resultSet[expected] {
missing = append(missing, expected)
}
}
if len(missing) > 0 {
t.Errorf("Result %v missing expected results %v", results, missing)
}
}