Source file
src/cmd/go/counters_test.go
1
2
3
4
5 package main_test
6
7 import (
8 "cmd/go/internal/base"
9 "cmd/go/internal/cfg"
10 "flag"
11 "go/build"
12 "internal/diff"
13 "os"
14 "slices"
15 "strings"
16 "testing"
17 )
18
19 var update = flag.Bool("update", false, "if true update testdata/counternames.txt")
20
21 func TestCounterNamesUpToDate(t *testing.T) {
22 if !*update {
23 t.Parallel()
24 }
25
26 var counters []string
27
28
29
30
31 counters = append(counters, "go/flag:C", "go/subcommand:unknown")
32 counters = append(counters, flagscounters("go/flag:", *flag.CommandLine)...)
33
34
35
36 counters = append(counters, "go/subcommand:help")
37 for _, cmd := range base.Go.Commands {
38 cmdcounters, err := cmdcounters(nil, cmd)
39 if err != nil {
40 t.Fatal(err)
41 }
42 counters = append(counters, cmdcounters...)
43 }
44
45 counters = append(counters, base.RegisteredCounterNames()...)
46 for _, c := range counters {
47 const counterPrefix = "go/"
48 if !strings.HasPrefix(c, counterPrefix) {
49 t.Fatalf("registered counter %q does not start with %q", c, counterPrefix)
50 }
51 }
52
53 cstr := []byte(strings.Join(counters, "\n") + "\n")
54 const counterNamesFile = "testdata/counters.txt"
55 old, err := os.ReadFile(counterNamesFile)
56 if err != nil {
57 t.Fatalf("error reading %s: %v", counterNamesFile, err)
58 }
59 diff := diff.Diff(counterNamesFile, old, "generated counter names", cstr)
60 if diff == nil {
61 t.Logf("%s is up to date.", counterNamesFile)
62 return
63 }
64
65 if *update {
66 if err := os.WriteFile(counterNamesFile, cstr, 0666); err != nil {
67 t.Fatal(err)
68 }
69 t.Logf("wrote %d bytes to %s", len(cstr), counterNamesFile)
70 t.Logf("don't forget to file a proposal to update the list of collected counters")
71 } else {
72 t.Logf("\n%s", diff)
73 t.Errorf("%s is stale. To update, run 'go generate cmd/go'.", counterNamesFile)
74 }
75 }
76
77 func flagscounters(prefix string, flagSet flag.FlagSet) []string {
78 var counters []string
79 flagSet.VisitAll(func(f *flag.Flag) {
80 counters = append(counters, prefix+f.Name)
81 })
82 return counters
83 }
84
85 func cmdcounters(previous []string, cmd *base.Command) ([]string, error) {
86 const subcommandPrefix = "go/subcommand:"
87 const flagPrefix = "go/flag:"
88 var counters []string
89 previousComponent := strings.Join(previous, "-")
90 if len(previousComponent) > 0 {
91 previousComponent += "-"
92 }
93 if cmd.Runnable() {
94 if cmd.Name() == "tool" {
95
96
97
98 tools, err := toolNames()
99 if err != nil {
100 return nil, err
101 }
102 for _, t := range tools {
103 counters = append(counters, subcommandPrefix+previousComponent+cmd.Name()+"-"+t)
104 }
105 counters = append(counters, subcommandPrefix+previousComponent+cmd.Name()+"-unknown")
106 }
107 counters = append(counters, subcommandPrefix+previousComponent+cmd.Name())
108 }
109 counters = append(counters, flagscounters(flagPrefix+previousComponent+cmd.Name()+"-", cmd.Flag)...)
110 if len(previous) != 0 {
111 counters = append(counters, subcommandPrefix+previousComponent+"help-"+cmd.Name())
112 }
113 counters = append(counters, subcommandPrefix+"help-"+previousComponent+cmd.Name())
114
115 for _, subcmd := range cmd.Commands {
116 subcmdcounters, err := cmdcounters(append(slices.Clone(previous), cmd.Name()), subcmd)
117 if err != nil {
118 return nil, err
119 }
120 counters = append(counters, subcmdcounters...)
121 }
122 return counters, nil
123 }
124
125
126 func toolNames() ([]string, error) {
127 entries, err := os.ReadDir(build.ToolDir)
128 if err != nil {
129 return nil, err
130 }
131 var names []string
132 for _, e := range entries {
133 if e.IsDir() {
134 continue
135 }
136 name := strings.TrimSuffix(e.Name(), cfg.ToolExeSuffix())
137 names = append(names, name)
138 }
139 return names, nil
140 }
141
View as plain text