golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/trace/reader_test.go (about)

     1  // Copyright 2023 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  // Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT.
     6  
     7  //go:build go1.21
     8  
     9  package trace_test
    10  
    11  import (
    12  	"bytes"
    13  	"flag"
    14  	"fmt"
    15  	"io"
    16  	"os"
    17  	"path/filepath"
    18  	"strings"
    19  	"testing"
    20  
    21  	"golang.org/x/exp/trace"
    22  	"golang.org/x/exp/trace/internal/raw"
    23  	"golang.org/x/exp/trace/internal/testtrace"
    24  	"golang.org/x/exp/trace/internal/version"
    25  )
    26  
    27  var (
    28  	logEvents  = flag.Bool("log-events", false, "whether to log high-level events; significantly slows down tests")
    29  	dumpTraces = flag.Bool("dump-traces", false, "dump traces even on success")
    30  )
    31  
    32  func TestReaderGolden(t *testing.T) {
    33  	matches, err := filepath.Glob("./testdata/tests/*.test")
    34  	if err != nil {
    35  		t.Fatalf("failed to glob for tests: %v", err)
    36  	}
    37  	for _, testPath := range matches {
    38  		testPath := testPath
    39  		testName, err := filepath.Rel("./testdata", testPath)
    40  		if err != nil {
    41  			t.Fatalf("failed to relativize testdata path: %v", err)
    42  		}
    43  		t.Run(testName, func(t *testing.T) {
    44  			tr, exp, err := testtrace.ParseFile(testPath)
    45  			if err != nil {
    46  				t.Fatalf("failed to parse test file at %s: %v", testPath, err)
    47  			}
    48  			testReader(t, tr, exp)
    49  		})
    50  	}
    51  }
    52  
    53  func FuzzReader(f *testing.F) {
    54  	// Currently disabled because the parser doesn't do much validation and most
    55  	// getters can be made to panic. Turn this on once the parser is meant to
    56  	// reject invalid traces.
    57  	const testGetters = false
    58  
    59  	f.Fuzz(func(t *testing.T, b []byte) {
    60  		r, err := trace.NewReader(bytes.NewReader(b))
    61  		if err != nil {
    62  			return
    63  		}
    64  		for {
    65  			ev, err := r.ReadEvent()
    66  			if err != nil {
    67  				break
    68  			}
    69  
    70  			if !testGetters {
    71  				continue
    72  			}
    73  			// Make sure getters don't do anything that panics
    74  			switch ev.Kind() {
    75  			case trace.EventLabel:
    76  				ev.Label()
    77  			case trace.EventLog:
    78  				ev.Log()
    79  			case trace.EventMetric:
    80  				ev.Metric()
    81  			case trace.EventRangeActive, trace.EventRangeBegin:
    82  				ev.Range()
    83  			case trace.EventRangeEnd:
    84  				ev.Range()
    85  				ev.RangeAttributes()
    86  			case trace.EventStateTransition:
    87  				ev.StateTransition()
    88  			case trace.EventRegionBegin, trace.EventRegionEnd:
    89  				ev.Region()
    90  			case trace.EventTaskBegin, trace.EventTaskEnd:
    91  				ev.Task()
    92  			case trace.EventSync:
    93  			case trace.EventStackSample:
    94  			case trace.EventBad:
    95  			}
    96  		}
    97  	})
    98  }
    99  
   100  func testReader(t *testing.T, tr io.Reader, exp *testtrace.Expectation) {
   101  	r, err := trace.NewReader(tr)
   102  	if err != nil {
   103  		if err := exp.Check(err); err != nil {
   104  			t.Error(err)
   105  		}
   106  		return
   107  	}
   108  	v := testtrace.NewValidator()
   109  	for {
   110  		ev, err := r.ReadEvent()
   111  		if err == io.EOF {
   112  			break
   113  		}
   114  		if err != nil {
   115  			if err := exp.Check(err); err != nil {
   116  				t.Error(err)
   117  			}
   118  			return
   119  		}
   120  		if *logEvents {
   121  			t.Log(ev.String())
   122  		}
   123  		if err := v.Event(ev); err != nil {
   124  			t.Error(err)
   125  		}
   126  	}
   127  	if err := exp.Check(nil); err != nil {
   128  		t.Error(err)
   129  	}
   130  }
   131  
   132  func dumpTraceToText(t *testing.T, b []byte) string {
   133  	t.Helper()
   134  
   135  	br, err := raw.NewReader(bytes.NewReader(b))
   136  	if err != nil {
   137  		t.Fatalf("dumping trace: %v", err)
   138  	}
   139  	var sb strings.Builder
   140  	tw, err := raw.NewTextWriter(&sb, version.Current)
   141  	if err != nil {
   142  		t.Fatalf("dumping trace: %v", err)
   143  	}
   144  	for {
   145  		ev, err := br.ReadEvent()
   146  		if err == io.EOF {
   147  			break
   148  		}
   149  		if err != nil {
   150  			t.Fatalf("dumping trace: %v", err)
   151  		}
   152  		if err := tw.WriteEvent(ev); err != nil {
   153  			t.Fatalf("dumping trace: %v", err)
   154  		}
   155  	}
   156  	return sb.String()
   157  }
   158  
   159  func dumpTraceToFile(t *testing.T, testName string, stress bool, b []byte) string {
   160  	t.Helper()
   161  
   162  	desc := "default"
   163  	if stress {
   164  		desc = "stress"
   165  	}
   166  	name := fmt.Sprintf("%s.%s.trace.", testName, desc)
   167  	f, err := os.CreateTemp("", name)
   168  	if err != nil {
   169  		t.Fatalf("creating temp file: %v", err)
   170  	}
   171  	defer f.Close()
   172  	if _, err := io.Copy(f, bytes.NewReader(b)); err != nil {
   173  		t.Fatalf("writing trace dump to %q: %v", f.Name(), err)
   174  	}
   175  	return f.Name()
   176  }