runtime/metrics: ensure no stop-the-world in Read

Using the runtime/metrics package is meant to be cheap, and to not
affect performance of the application. In particular, all of the metrics
it exposes today are available without a stop-the-world pause.

Add a test to confirm, so we'll at least know if that changes.

Change-Id: I08110af5c84d76fc198aacdfaeca6dc8cd33a72c
Reviewed-on: https://go-review.googlesource.com/c/go/+/781420
Reviewed-by: Felix Geisendörfer <felix.geisendoerfer@datadoghq.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Rhys Hiltner <rhys.hiltner@gmail.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
diff --git a/src/runtime/metrics_test.go b/src/runtime/metrics_test.go
index 83f1f48..520452b 100644
--- a/src/runtime/metrics_test.go
+++ b/src/runtime/metrics_test.go
@@ -789,8 +789,9 @@
 }
 
 // Call f() and verify that the correct STW metrics increment. If isGC is true,
-// fn triggers a GC STW. Otherwise, fn triggers an other STW.
-func testSchedPauseMetrics(t *testing.T, fn func(t *testing.T), isGC bool) {
+// fn triggers a GC STW. If isOther is true, fn triggers an other STW. If both
+// are false, fn does not trigger any STW.
+func testSchedPauseMetrics(t *testing.T, fn func(t *testing.T), isGC, isOther bool) {
 	m := []metrics.Sample{
 		{Name: "/sched/pauses/stopping/gc:seconds"},
 		{Name: "/sched/pauses/stopping/other:seconds"},
@@ -832,13 +833,6 @@
 		if got := sampleCount(totalGC); got <= baselineTotalGC {
 			t.Errorf("/sched/pauses/total/gc:seconds sample count %d did not increase from baseline of %d", got, baselineTotalGC)
 		}
-
-		if got := sampleCount(stoppingOther); got != baselineStartOther {
-			t.Errorf("/sched/pauses/stopping/other:seconds sample count %d changed from baseline of %d", got, baselineStartOther)
-		}
-		if got := sampleCount(totalOther); got != baselineTotalOther {
-			t.Errorf("/sched/pauses/stopping/other:seconds sample count %d changed from baseline of %d", got, baselineTotalOther)
-		}
 	} else {
 		if got := sampleCount(stoppingGC); got != baselineStartGC {
 			t.Errorf("/sched/pauses/stopping/gc:seconds sample count %d changed from baseline of %d", got, baselineStartGC)
@@ -846,23 +840,45 @@
 		if got := sampleCount(totalGC); got != baselineTotalGC {
 			t.Errorf("/sched/pauses/total/gc:seconds sample count %d changed from baseline of %d", got, baselineTotalGC)
 		}
+	}
 
+	if isOther {
 		if got := sampleCount(stoppingOther); got <= baselineStartOther {
 			t.Errorf("/sched/pauses/stopping/other:seconds sample count %d did not increase from baseline of %d", got, baselineStartOther)
 		}
 		if got := sampleCount(totalOther); got <= baselineTotalOther {
-			t.Errorf("/sched/pauses/stopping/other:seconds sample count %d did not increase from baseline of %d", got, baselineTotalOther)
+			t.Errorf("/sched/pauses/total/other:seconds sample count %d did not increase from baseline of %d", got, baselineTotalOther)
+		}
+	} else {
+		if got := sampleCount(stoppingOther); got != baselineStartOther {
+			t.Errorf("/sched/pauses/stopping/other:seconds sample count %d changed from baseline of %d", got, baselineStartOther)
+		}
+		if got := sampleCount(totalOther); got != baselineTotalOther {
+			t.Errorf("/sched/pauses/total/other:seconds sample count %d changed from baseline of %d", got, baselineTotalOther)
 		}
 	}
 }
 
 func TestSchedPauseMetrics(t *testing.T) {
 	tests := []struct {
-		name string
-		isGC bool
-		fn   func(t *testing.T)
+		name   string
+		isGC   bool
+		isNone bool // no STW at all
+		fn     func(t *testing.T)
 	}{
 		{
+			name:   "runtime/metrics.Read",
+			isNone: true,
+			fn: func(t *testing.T) {
+				descs := metrics.All()
+				allSamples := make([]metrics.Sample, len(descs))
+				for i := range allSamples {
+					allSamples[i].Name = descs[i].Name
+				}
+				metrics.Read(allSamples)
+			},
+		},
+		{
 			name: "runtime.GC",
 			isGC: true,
 			fn: func(t *testing.T) {
@@ -946,7 +962,8 @@
 
 	for _, tc := range tests {
 		t.Run(tc.name, func(t *testing.T) {
-			testSchedPauseMetrics(t, tc.fn, tc.isGC)
+			isOther := !tc.isGC && !tc.isNone
+			testSchedPauseMetrics(t, tc.fn, tc.isGC, isOther)
 		})
 	}
 }