github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/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 "bufio" 9 "os" 10 "regexp" 11 "runtime/metrics" 12 "strings" 13 "testing" 14 ) 15 16 func TestDescriptionNameFormat(t *testing.T) { 17 r := regexp.MustCompile("^(?P<name>/[^:]+):(?P<unit>[^:*/]+(?:[*/][^:*/]+)*)$") 18 descriptions := metrics.All() 19 for _, desc := range descriptions { 20 if !r.MatchString(desc.Name) { 21 t.Errorf("metrics %q does not match regexp %s", desc.Name, r) 22 } 23 } 24 } 25 26 func extractMetricDocs(t *testing.T) map[string]string { 27 f, err := os.Open("doc.go") 28 if err != nil { 29 t.Fatalf("failed to open doc.go in runtime/metrics package: %v", err) 30 } 31 const ( 32 stateSearch = iota // look for list of metrics 33 stateNextMetric // look for next metric 34 stateNextDescription // build description 35 ) 36 state := stateSearch 37 s := bufio.NewScanner(f) 38 result := make(map[string]string) 39 var metric string 40 var prevMetric string 41 var desc strings.Builder 42 for s.Scan() { 43 line := strings.TrimSpace(s.Text()) 44 switch state { 45 case stateSearch: 46 if line == "Below is the full list of supported metrics, ordered lexicographically." { 47 state = stateNextMetric 48 } 49 case stateNextMetric: 50 // Ignore empty lines until we find a non-empty 51 // one. This will be our metric name. 52 if len(line) != 0 { 53 prevMetric = metric 54 metric = line 55 if prevMetric > metric { 56 t.Errorf("metrics %s and %s are out of lexicographical order", prevMetric, metric) 57 } 58 state = stateNextDescription 59 } 60 case stateNextDescription: 61 if len(line) == 0 || line == `*/` { 62 // An empty line means we're done. 63 // Write down the description and look 64 // for a new metric. 65 result[metric] = desc.String() 66 desc.Reset() 67 state = stateNextMetric 68 } else { 69 // As long as we're seeing data, assume that's 70 // part of the description and append it. 71 if desc.Len() != 0 { 72 // Turn previous newlines into spaces. 73 desc.WriteString(" ") 74 } 75 desc.WriteString(line) 76 } 77 } 78 if line == `*/` { 79 break 80 } 81 } 82 if state == stateSearch { 83 t.Fatalf("failed to find supported metrics docs in %s", f.Name()) 84 } 85 return result 86 } 87 88 func TestDescriptionDocs(t *testing.T) { 89 docs := extractMetricDocs(t) 90 descriptions := metrics.All() 91 for _, d := range descriptions { 92 want := d.Description 93 got, ok := docs[d.Name] 94 if !ok { 95 t.Errorf("no docs found for metric %s", d.Name) 96 continue 97 } 98 if got != want { 99 t.Errorf("mismatched description and docs for metric %s", d.Name) 100 t.Errorf("want: %q, got %q", want, got) 101 continue 102 } 103 } 104 if len(docs) > len(descriptions) { 105 docsLoop: 106 for name, _ := range docs { 107 for _, d := range descriptions { 108 if name == d.Name { 109 continue docsLoop 110 } 111 } 112 t.Errorf("stale documentation for non-existent metric: %s", name) 113 } 114 } 115 }