...

Source file src/runtime/metrics/description_test.go

Documentation: runtime/metrics

		 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  }
	 116  

View as plain text