116 lines
2.9 KiB
Go
116 lines
2.9 KiB
Go
|
// 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 (
|
||
|
"bufio"
|
||
|
"os"
|
||
|
"regexp"
|
||
|
"runtime/metrics"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
func TestDescriptionNameFormat(t *testing.T) {
|
||
|
r := regexp.MustCompile("^(?P<name>/[^:]+):(?P<unit>[^:*/]+(?:[*/][^:*/]+)*)$")
|
||
|
descriptions := metrics.All()
|
||
|
for _, desc := range descriptions {
|
||
|
if !r.MatchString(desc.Name) {
|
||
|
t.Errorf("metrics %q does not match regexp %s", desc.Name, r)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func extractMetricDocs(t *testing.T) map[string]string {
|
||
|
f, err := os.Open("doc.go")
|
||
|
if err != nil {
|
||
|
t.Fatalf("failed to open doc.go in runtime/metrics package: %v", err)
|
||
|
}
|
||
|
const (
|
||
|
stateSearch = iota // look for list of metrics
|
||
|
stateNextMetric // look for next metric
|
||
|
stateNextDescription // build description
|
||
|
)
|
||
|
state := stateSearch
|
||
|
s := bufio.NewScanner(f)
|
||
|
result := make(map[string]string)
|
||
|
var metric string
|
||
|
var prevMetric string
|
||
|
var desc strings.Builder
|
||
|
for s.Scan() {
|
||
|
line := strings.TrimSpace(s.Text())
|
||
|
switch state {
|
||
|
case stateSearch:
|
||
|
if line == "Below is the full list of supported metrics, ordered lexicographically." {
|
||
|
state = stateNextMetric
|
||
|
}
|
||
|
case stateNextMetric:
|
||
|
// Ignore empty lines until we find a non-empty
|
||
|
// one. This will be our metric name.
|
||
|
if len(line) != 0 {
|
||
|
prevMetric = metric
|
||
|
metric = line
|
||
|
if prevMetric > metric {
|
||
|
t.Errorf("metrics %s and %s are out of lexicographical order", prevMetric, metric)
|
||
|
}
|
||
|
state = stateNextDescription
|
||
|
}
|
||
|
case stateNextDescription:
|
||
|
if len(line) == 0 || line == `*/` {
|
||
|
// An empty line means we're done.
|
||
|
// Write down the description and look
|
||
|
// for a new metric.
|
||
|
result[metric] = desc.String()
|
||
|
desc.Reset()
|
||
|
state = stateNextMetric
|
||
|
} else {
|
||
|
// As long as we're seeing data, assume that's
|
||
|
// part of the description and append it.
|
||
|
if desc.Len() != 0 {
|
||
|
// Turn previous newlines into spaces.
|
||
|
desc.WriteString(" ")
|
||
|
}
|
||
|
desc.WriteString(line)
|
||
|
}
|
||
|
}
|
||
|
if line == `*/` {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if state == stateSearch {
|
||
|
t.Fatalf("failed to find supported metrics docs in %s", f.Name())
|
||
|
}
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
func TestDescriptionDocs(t *testing.T) {
|
||
|
docs := extractMetricDocs(t)
|
||
|
descriptions := metrics.All()
|
||
|
for _, d := range descriptions {
|
||
|
want := d.Description
|
||
|
got, ok := docs[d.Name]
|
||
|
if !ok {
|
||
|
t.Errorf("no docs found for metric %s", d.Name)
|
||
|
continue
|
||
|
}
|
||
|
if got != want {
|
||
|
t.Errorf("mismatched description and docs for metric %s", d.Name)
|
||
|
t.Errorf("want: %q, got %q", want, got)
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
if len(docs) > len(descriptions) {
|
||
|
docsLoop:
|
||
|
for name, _ := range docs {
|
||
|
for _, d := range descriptions {
|
||
|
if name == d.Name {
|
||
|
continue docsLoop
|
||
|
}
|
||
|
}
|
||
|
t.Errorf("stale documentation for non-existent metric: %s", name)
|
||
|
}
|
||
|
}
|
||
|
}
|