veyron/tools/debug/testdata: add vtrace test

This CL ports the vtrace tests from test.sh to Go.

Change-Id: Ic317c826bfbfcbfae6775d6d3660844e90500d21
diff --git a/tools/debug/testdata/integration_test.go b/tools/debug/testdata/integration_test.go
index 86be0c9..7b8b579 100644
--- a/tools/debug/testdata/integration_test.go
+++ b/tools/debug/testdata/integration_test.go
@@ -4,6 +4,7 @@
 	"fmt"
 	"os"
 	"path/filepath"
+	"regexp"
 	"strconv"
 	"strings"
 	"testing"
@@ -65,17 +66,25 @@
 	}
 }
 
+func createTestLogFile(t *testing.T, env integration.TestEnvironment, content string) *os.File {
+	file := env.TempFile()
+	_, err := file.Write([]byte(content))
+	if err != nil {
+		t.Fatalf("Write failed: %v", err)
+	}
+	return file
+}
+
 func TestLogSize(t *testing.T) {
 	env := integration.NewTestEnvironment(t)
 	defer env.Cleanup()
 
 	binary := env.BuildGoPkg("veyron.io/veyron/veyron/tools/debug")
-	f := env.TempFile()
-	testLogData := []byte("This is a test log file")
-	f.Write(testLogData)
+	testLogData := "This is a test log file"
+	file := createTestLogFile(t, env, testLogData)
 
 	// Check to ensure the file size is accurate
-	str := strings.TrimSpace(binary.Start("logs", "size", env.RootMT()+"/__debug/logs/"+filepath.Base(f.Name())).Output())
+	str := strings.TrimSpace(binary.Start("logs", "size", env.RootMT()+"/__debug/logs/"+filepath.Base(file.Name())).Output())
 	got, err := strconv.Atoi(str)
 	if err != nil {
 		t.Fatalf("Atoi(\"%q\") failed", str)
@@ -91,9 +100,8 @@
 	defer env.Cleanup()
 
 	binary := env.BuildGoPkg("veyron.io/veyron/veyron/tools/debug")
-	file := env.TempFile()
-	testLogData := []byte("This is a test log file\n")
-	file.Write(testLogData)
+	testLogData := "This is a test log file\n"
+	file := createTestLogFile(t, env, testLogData)
 	logName := filepath.Base(file.Name())
 	runCount := 12
 	for i := 0; i < runCount; i++ {
@@ -105,3 +113,61 @@
 		t.Fatalf("expected output to contain %s, but did not\n", want, got)
 	}
 }
+
+func performTracedRead(debugBinary integration.TestBinary, path string) string {
+	return debugBinary.Start("--veyron.vtrace.sample_rate=1", "logs", "read", path).Output()
+}
+
+func TestVTrace(t *testing.T) {
+	env := integration.NewTestEnvironment(t)
+	defer env.Cleanup()
+
+	binary := env.BuildGoPkg("veyron.io/veyron/veyron/tools/debug")
+	logContent := "Hello, world!\n"
+	logPath := env.RootMT() + "/__debug/logs/" + filepath.Base(createTestLogFile(t, env, logContent).Name())
+	// Create a log file with tracing, read it and check that the resulting trace exists.
+	got := performTracedRead(binary, logPath)
+	if logContent != got {
+		t.Fatalf("unexpected output: want %s, got %s", logContent, got)
+	}
+
+	// Grab the ID of the first and only trace.
+	want, traceContent := 1, binary.Start("vtrace", env.RootMT()+"/__debug/vtrace").Output()
+	if count := strings.Count(traceContent, "Trace -"); count != want {
+		t.Fatalf("unexpected trace count, want %d, got %d\n%s", want, count, traceContent)
+	}
+	fields := strings.Split(traceContent, " ")
+	if len(fields) < 3 {
+		t.Fatalf("expected at least 3 space-delimited fields, got %d\n", len(fields), traceContent)
+	}
+	traceId := fields[2]
+
+	// Do a sanity check on the trace ID: it should be a 32-character hex ID.
+	if match, _ := regexp.MatchString("[0-9a-f]{32}", traceId); !match {
+		t.Fatalf("wanted a 32-character hex ID, got %s", traceId)
+	}
+
+	// Do another traced read, this will generate a new trace entry.
+	performTracedRead(binary, logPath)
+
+	// Read vtrace, we should have 2 traces now.
+	want, output := 2, binary.Start("vtrace", env.RootMT()+"/__debug/vtrace").Output()
+	if count := strings.Count(output, "Trace -"); count != want {
+		t.Fatalf("unexpected trace count, want %d, got %d\n%s", want, count, output)
+	}
+
+	// Now ask for a particular trace. The output should contain exactly
+	// one trace whose ID is equal to the one we asked for.
+	want, got = 1, binary.Start("vtrace", env.RootMT()+"/__debug/vtrace", traceId).Output()
+	if count := strings.Count(got, "Trace -"); count != want {
+		t.Fatalf("unexpected trace count, want %d, got %d\n%s", want, count, got)
+	}
+	fields = strings.Split(got, " ")
+	if len(fields) < 3 {
+		t.Fatalf("expected at least 3 space-delimited fields, got %d\n", len(fields), got)
+	}
+	got = fields[2]
+	if traceId != got {
+		t.Fatalf("unexpected traceId, want %s, got %s", traceId, got)
+	}
+}