summaryrefslogtreecommitdiffstats
path: root/src/runtime/metrics/description_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/metrics/description_test.go')
-rw-r--r--src/runtime/metrics/description_test.go158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/runtime/metrics/description_test.go b/src/runtime/metrics/description_test.go
new file mode 100644
index 0000000..4fc6523
--- /dev/null
+++ b/src/runtime/metrics/description_test.go
@@ -0,0 +1,158 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package metrics_test
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/doc"
+ "go/doc/comment"
+ "go/format"
+ "go/parser"
+ "go/token"
+ "internal/diff"
+ "os"
+ "regexp"
+ "runtime/metrics"
+ "sort"
+ "strings"
+ "testing"
+ _ "unsafe"
+)
+
+// Implemented in the runtime.
+//
+//go:linkname runtime_readMetricNames
+func runtime_readMetricNames() []string
+
+func TestNames(t *testing.T) {
+ // Note that this regexp is promised in the package docs for Description. Do not change.
+ r := regexp.MustCompile("^(?P<name>/[^:]+):(?P<unit>[^:*/]+(?:[*/][^:*/]+)*)$")
+ all := metrics.All()
+ for i, d := range all {
+ if !r.MatchString(d.Name) {
+ t.Errorf("name %q does not match regexp %#q", d.Name, r)
+ }
+ if i > 0 && all[i-1].Name >= all[i].Name {
+ t.Fatalf("allDesc not sorted: %s ≥ %s", all[i-1].Name, all[i].Name)
+ }
+ }
+
+ names := runtime_readMetricNames()
+ sort.Strings(names)
+ samples := make([]metrics.Sample, len(names))
+ for i, name := range names {
+ samples[i].Name = name
+ }
+ metrics.Read(samples)
+
+ for _, d := range all {
+ for len(samples) > 0 && samples[0].Name < d.Name {
+ t.Errorf("%s: reported by runtime but not listed in All", samples[0].Name)
+ samples = samples[1:]
+ }
+ if len(samples) == 0 || d.Name < samples[0].Name {
+ t.Errorf("%s: listed in All but not reported by runtime", d.Name)
+ continue
+ }
+ if samples[0].Value.Kind() != d.Kind {
+ t.Errorf("%s: runtime reports %v but All reports %v", d.Name, samples[0].Value.Kind(), d.Kind)
+ }
+ samples = samples[1:]
+ }
+}
+
+func wrap(prefix, text string, width int) string {
+ doc := &comment.Doc{Content: []comment.Block{&comment.Paragraph{Text: []comment.Text{comment.Plain(text)}}}}
+ pr := &comment.Printer{TextPrefix: prefix, TextWidth: width}
+ return string(pr.Text(doc))
+}
+
+func formatDesc(t *testing.T) string {
+ var b strings.Builder
+ for i, d := range metrics.All() {
+ if i > 0 {
+ fmt.Fprintf(&b, "\n")
+ }
+ fmt.Fprintf(&b, "%s\n", d.Name)
+ fmt.Fprintf(&b, "%s", wrap("\t", d.Description, 80-2*8))
+ }
+ return b.String()
+}
+
+var generate = flag.Bool("generate", false, "update doc.go for go generate")
+
+func TestDocs(t *testing.T) {
+ want := formatDesc(t)
+
+ src, err := os.ReadFile("doc.go")
+ if err != nil {
+ t.Fatal(err)
+ }
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, "doc.go", src, parser.ParseComments)
+ if err != nil {
+ t.Fatal(err)
+ }
+ fdoc := f.Doc
+ if fdoc == nil {
+ t.Fatal("no doc comment in doc.go")
+ }
+ pkg, err := doc.NewFromFiles(fset, []*ast.File{f}, "runtime/metrics")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if pkg.Doc == "" {
+ t.Fatal("doc.NewFromFiles lost doc comment")
+ }
+ doc := new(comment.Parser).Parse(pkg.Doc)
+ expectCode := false
+ foundCode := false
+ updated := false
+ for _, block := range doc.Content {
+ switch b := block.(type) {
+ case *comment.Heading:
+ expectCode = false
+ if b.Text[0] == comment.Plain("Supported metrics") {
+ expectCode = true
+ }
+ case *comment.Code:
+ if expectCode {
+ foundCode = true
+ if b.Text != want {
+ if !*generate {
+ t.Fatalf("doc comment out of date; use go generate to rebuild\n%s", diff.Diff("old", []byte(b.Text), "want", []byte(want)))
+ }
+ b.Text = want
+ updated = true
+ }
+ }
+ }
+ }
+
+ if !foundCode {
+ t.Fatalf("did not find Supported metrics list in doc.go")
+ }
+ if updated {
+ fmt.Fprintf(os.Stderr, "go test -generate: writing new doc.go\n")
+ var buf bytes.Buffer
+ buf.Write(src[:fdoc.Pos()-f.FileStart])
+ buf.WriteString("/*\n")
+ buf.Write(new(comment.Printer).Comment(doc))
+ buf.WriteString("*/")
+ buf.Write(src[fdoc.End()-f.FileStart:])
+ src, err := format.Source(buf.Bytes())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := os.WriteFile("doc.go", src, 0666); err != nil {
+ t.Fatal(err)
+ }
+ } else if *generate {
+ fmt.Fprintf(os.Stderr, "go test -generate: doc.go already up-to-date\n")
+ }
+}