github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/metrics/description_test.go (about) 1 // Copyright 2020 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 metrics_test 6 7 import ( 8 "bytes" 9 "flag" 10 "fmt" 11 "go/ast" 12 "go/doc" 13 "go/doc/comment" 14 "go/format" 15 "go/parser" 16 "go/token" 17 "internal/diff" 18 "os" 19 "regexp" 20 "runtime/metrics" 21 "sort" 22 "strings" 23 "testing" 24 _ "unsafe" 25 ) 26 27 // Implemented in the runtime. 28 // 29 //go:linkname runtime_readMetricNames 30 func runtime_readMetricNames() []string 31 32 func TestNames(t *testing.T) { 33 // Note that this regexp is promised in the package docs for Description. Do not change. 34 r := regexp.MustCompile("^(?P<name>/[^:]+):(?P<unit>[^:*/]+(?:[*/][^:*/]+)*)$") 35 all := metrics.All() 36 for i, d := range all { 37 if !r.MatchString(d.Name) { 38 t.Errorf("name %q does not match regexp %#q", d.Name, r) 39 } 40 if i > 0 && all[i-1].Name >= all[i].Name { 41 t.Fatalf("allDesc not sorted: %s ≥ %s", all[i-1].Name, all[i].Name) 42 } 43 } 44 45 names := runtime_readMetricNames() 46 sort.Strings(names) 47 samples := make([]metrics.Sample, len(names)) 48 for i, name := range names { 49 samples[i].Name = name 50 } 51 metrics.Read(samples) 52 53 for _, d := range all { 54 for len(samples) > 0 && samples[0].Name < d.Name { 55 t.Errorf("%s: reported by runtime but not listed in All", samples[0].Name) 56 samples = samples[1:] 57 } 58 if len(samples) == 0 || d.Name < samples[0].Name { 59 t.Errorf("%s: listed in All but not reported by runtime", d.Name) 60 continue 61 } 62 if samples[0].Value.Kind() != d.Kind { 63 t.Errorf("%s: runtime reports %v but All reports %v", d.Name, samples[0].Value.Kind(), d.Kind) 64 } 65 samples = samples[1:] 66 } 67 } 68 69 func wrap(prefix, text string, width int) string { 70 doc := &comment.Doc{Content: []comment.Block{&comment.Paragraph{Text: []comment.Text{comment.Plain(text)}}}} 71 pr := &comment.Printer{TextPrefix: prefix, TextWidth: width} 72 return string(pr.Text(doc)) 73 } 74 75 func formatDesc(t *testing.T) string { 76 var b strings.Builder 77 for i, d := range metrics.All() { 78 if i > 0 { 79 fmt.Fprintf(&b, "\n") 80 } 81 fmt.Fprintf(&b, "%s\n", d.Name) 82 fmt.Fprintf(&b, "%s", wrap("\t", d.Description, 80-2*8)) 83 } 84 return b.String() 85 } 86 87 var generate = flag.Bool("generate", false, "update doc.go for go generate") 88 89 func TestDocs(t *testing.T) { 90 want := formatDesc(t) 91 92 src, err := os.ReadFile("doc.go") 93 if err != nil { 94 t.Fatal(err) 95 } 96 fset := token.NewFileSet() 97 f, err := parser.ParseFile(fset, "doc.go", src, parser.ParseComments) 98 if err != nil { 99 t.Fatal(err) 100 } 101 fdoc := f.Doc 102 if fdoc == nil { 103 t.Fatal("no doc comment in doc.go") 104 } 105 pkg, err := doc.NewFromFiles(fset, []*ast.File{f}, "runtime/metrics") 106 if err != nil { 107 t.Fatal(err) 108 } 109 if pkg.Doc == "" { 110 t.Fatal("doc.NewFromFiles lost doc comment") 111 } 112 doc := new(comment.Parser).Parse(pkg.Doc) 113 expectCode := false 114 foundCode := false 115 updated := false 116 for _, block := range doc.Content { 117 switch b := block.(type) { 118 case *comment.Heading: 119 expectCode = false 120 if b.Text[0] == comment.Plain("Supported metrics") { 121 expectCode = true 122 } 123 case *comment.Code: 124 if expectCode { 125 foundCode = true 126 if b.Text != want { 127 if !*generate { 128 t.Fatalf("doc comment out of date; use go generate to rebuild\n%s", diff.Diff("old", []byte(b.Text), "want", []byte(want))) 129 } 130 b.Text = want 131 updated = true 132 } 133 } 134 } 135 } 136 137 if !foundCode { 138 t.Fatalf("did not find Supported metrics list in doc.go") 139 } 140 if updated { 141 fmt.Fprintf(os.Stderr, "go test -generate: writing new doc.go\n") 142 var buf bytes.Buffer 143 buf.Write(src[:fdoc.Pos()-f.FileStart]) 144 buf.WriteString("/*\n") 145 buf.Write(new(comment.Printer).Comment(doc)) 146 buf.WriteString("*/") 147 buf.Write(src[fdoc.End()-f.FileStart:]) 148 src, err := format.Source(buf.Bytes()) 149 if err != nil { 150 t.Fatal(err) 151 } 152 if err := os.WriteFile("doc.go", src, 0666); err != nil { 153 t.Fatal(err) 154 } 155 } else if *generate { 156 fmt.Fprintf(os.Stderr, "go test -generate: doc.go already up-to-date\n") 157 } 158 }