Source file src/internal/trace/tracev2/events_test.go

     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  package tracev2_test
     6  
     7  import (
     8  	"internal/trace/tracev2"
     9  	"iter"
    10  	"regexp"
    11  	"slices"
    12  	"strings"
    13  	"testing"
    14  )
    15  
    16  var argNameRegexp = regexp.MustCompile(`((?P<name>[A-Za-z]+)_)?(?P<type>[A-Za-z]+)`)
    17  
    18  func TestSpecs(t *testing.T) {
    19  	if tracev2.NumEvents <= 0 {
    20  		t.Fatalf("no trace events?")
    21  	}
    22  	if tracev2.MaxExperimentalEvent < tracev2.MaxEvent {
    23  		t.Fatalf("max experimental event (%d) is < max event (%d)", tracev2.MaxExperimentalEvent, tracev2.MaxEvent)
    24  	}
    25  	specs := tracev2.Specs()
    26  	for ev := range allEvents() {
    27  		spec := &specs[ev]
    28  		if spec.Name == "" {
    29  			t.Errorf("expected event %d to be defined in specs", ev)
    30  			continue
    31  		}
    32  		if spec.IsTimedEvent && spec.Args[0] != "dt" {
    33  			t.Errorf("%s is a timed event, but its first argument is not 'dt'", spec.Name)
    34  		}
    35  		if spec.HasData && spec.Name != "String" && spec.Name != "ExperimentalBatch" {
    36  			t.Errorf("%s has data, but is not a special kind of event (unsupported, but could be)", spec.Name)
    37  		}
    38  		if spec.IsStack && spec.Name != "Stack" {
    39  			t.Errorf("%s listed as being a stack, but is not the Stack event (unsupported)", spec.Name)
    40  		}
    41  		if spec.IsTimedEvent && len(spec.Args) > tracev2.MaxTimedEventArgs {
    42  			t.Errorf("%s has too many timed event args: have %d, want %d at most", spec.Name, len(spec.Args), tracev2.MaxTimedEventArgs)
    43  		}
    44  		if ev.Experimental() && spec.Experiment == tracev2.NoExperiment {
    45  			t.Errorf("experimental event %s must have an experiment", spec.Name)
    46  		}
    47  
    48  		// Check arg types.
    49  		for _, arg := range spec.Args {
    50  			matches := argNameRegexp.FindStringSubmatch(arg)
    51  			if len(matches) == 0 {
    52  				t.Errorf("malformed argument %s for event %s", arg, spec.Name)
    53  			}
    54  		}
    55  
    56  		// Check stacks.
    57  		for _, i := range spec.StackIDs {
    58  			if !strings.HasSuffix(spec.Args[i], "stack") {
    59  				t.Errorf("stack argument listed at %d in %s, but argument name %s does not imply stack type", i, spec.Name, spec.Args[i])
    60  			}
    61  		}
    62  		for i, arg := range spec.Args {
    63  			if !strings.HasSuffix(spec.Args[i], "stack") {
    64  				continue
    65  			}
    66  			if !slices.Contains(spec.StackIDs, i) {
    67  				t.Errorf("found stack argument %s in %s at index %d not listed in StackIDs", arg, spec.Name, i)
    68  			}
    69  		}
    70  
    71  		// Check strings.
    72  		for _, i := range spec.StringIDs {
    73  			if !strings.HasSuffix(spec.Args[i], "string") {
    74  				t.Errorf("string argument listed at %d in %s, but argument name %s does not imply string type", i, spec.Name, spec.Args[i])
    75  			}
    76  		}
    77  		for i, arg := range spec.Args {
    78  			if !strings.HasSuffix(spec.Args[i], "string") {
    79  				continue
    80  			}
    81  			if !slices.Contains(spec.StringIDs, i) {
    82  				t.Errorf("found string argument %s in %s at index %d not listed in StringIDs", arg, spec.Name, i)
    83  			}
    84  		}
    85  	}
    86  }
    87  
    88  func allEvents() iter.Seq[tracev2.EventType] {
    89  	return func(yield func(tracev2.EventType) bool) {
    90  		for ev := tracev2.EvNone + 1; ev < tracev2.NumEvents; ev++ {
    91  			if !yield(ev) {
    92  				return
    93  			}
    94  		}
    95  		for ev := tracev2.MaxEvent + 1; ev < tracev2.NumExperimentalEvents; ev++ {
    96  			if !yield(ev) {
    97  				return
    98  			}
    99  		}
   100  	}
   101  }
   102  

View as plain text