Home | History | Annotate | Download | only in trace
      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package trace
      6 
      7 import (
      8 	"bytes"
      9 	"io/ioutil"
     10 	"path/filepath"
     11 	"strings"
     12 	"testing"
     13 )
     14 
     15 func TestCorruptedInputs(t *testing.T) {
     16 	// These inputs crashed parser previously.
     17 	tests := []string{
     18 		"gotrace\x00\x020",
     19 		"gotrace\x00Q00\x020",
     20 		"gotrace\x00T00\x020",
     21 		"gotrace\x00\xc3\x0200",
     22 		"go 1.5 trace\x00\x00\x00\x00\x020",
     23 		"go 1.5 trace\x00\x00\x00\x00Q00\x020",
     24 		"go 1.5 trace\x00\x00\x00\x00T00\x020",
     25 		"go 1.5 trace\x00\x00\x00\x00\xc3\x0200",
     26 	}
     27 	for _, data := range tests {
     28 		res, err := Parse(strings.NewReader(data), "")
     29 		if err == nil || res.Events != nil || res.Stacks != nil {
     30 			t.Fatalf("no error on input: %q", data)
     31 		}
     32 	}
     33 }
     34 
     35 func TestParseCanned(t *testing.T) {
     36 	files, err := ioutil.ReadDir("./testdata")
     37 	if err != nil {
     38 		t.Fatalf("failed to read ./testdata: %v", err)
     39 	}
     40 	for _, f := range files {
     41 		data, err := ioutil.ReadFile(filepath.Join("./testdata", f.Name()))
     42 		if err != nil {
     43 			t.Fatalf("failed to read input file: %v", err)
     44 		}
     45 		// Instead of Parse that requires a proper binary name for old traces,
     46 		// we use 'parse' that omits symbol lookup if an empty string is given.
     47 		_, _, err = parse(bytes.NewReader(data), "")
     48 		switch {
     49 		case strings.HasSuffix(f.Name(), "_good"):
     50 			if err != nil {
     51 				t.Errorf("failed to parse good trace %v: %v", f.Name(), err)
     52 			}
     53 		case strings.HasSuffix(f.Name(), "_unordered"):
     54 			if err != ErrTimeOrder {
     55 				t.Errorf("unordered trace is not detected %v: %v", f.Name(), err)
     56 			}
     57 		default:
     58 			t.Errorf("unknown input file suffix: %v", f.Name())
     59 		}
     60 	}
     61 }
     62 
     63 func TestParseVersion(t *testing.T) {
     64 	tests := map[string]int{
     65 		"go 1.5 trace\x00\x00\x00\x00": 1005,
     66 		"go 1.7 trace\x00\x00\x00\x00": 1007,
     67 		"go 1.10 trace\x00\x00\x00":    1010,
     68 		"go 1.25 trace\x00\x00\x00":    1025,
     69 		"go 1.234 trace\x00\x00":       1234,
     70 		"go 1.2345 trace\x00":          -1,
     71 		"go 0.0 trace\x00\x00\x00\x00": -1,
     72 		"go a.b trace\x00\x00\x00\x00": -1,
     73 	}
     74 	for header, ver := range tests {
     75 		ver1, err := parseHeader([]byte(header))
     76 		if ver == -1 {
     77 			if err == nil {
     78 				t.Fatalf("no error on input: %q, version %v", header, ver1)
     79 			}
     80 		} else {
     81 			if err != nil {
     82 				t.Fatalf("failed to parse: %q (%v)", header, err)
     83 			}
     84 			if ver != ver1 {
     85 				t.Fatalf("wrong version: %v, want %v, input: %q", ver1, ver, header)
     86 			}
     87 		}
     88 	}
     89 }
     90 
     91 func TestTimestampOverflow(t *testing.T) {
     92 	// Test that parser correctly handles large timestamps (long tracing).
     93 	w := NewWriter()
     94 	w.Emit(EvBatch, 0, 0)
     95 	w.Emit(EvFrequency, 1e9)
     96 	for ts := uint64(1); ts < 1e16; ts *= 2 {
     97 		w.Emit(EvGoCreate, ts, ts, 0, 0)
     98 	}
     99 	if _, err := Parse(w, ""); err != nil {
    100 		t.Fatalf("failed to parse: %v", err)
    101 	}
    102 }
    103