]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: make TestMemStats failure messages useful
authorAustin Clements <austin@google.com>
Fri, 24 Feb 2017 02:40:55 +0000 (21:40 -0500)
committerAustin Clements <austin@google.com>
Fri, 31 Mar 2017 00:46:14 +0000 (00:46 +0000)
Currently most TestMemStats failures dump the whole MemStats object if
anything is amiss without telling you what is amiss, or even which
field is wrong. This makes it hard to figure out what the actual
problem is.

Replace this with a reflection walk over MemStats and a map of
predicates to check. If one fails, we can construct a detailed and
descriptive error message. The predicates are a direct translation of
the current tests.

Change-Id: I5a7cafb8e6a1eeab653d2e18bb74e2245eaa5444
Reviewed-on: https://go-review.googlesource.com/37512
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
src/runtime/malloc_test.go

index 0cf9cfbf4279ca4974573b5ee2e26ca63ef8b112..596501f7d564569dbb0ae8a31c440bbf1fcaad5e 100644 (file)
@@ -6,6 +6,8 @@ package runtime_test
 
 import (
        "flag"
+       "fmt"
+       "reflect"
        . "runtime"
        "testing"
        "time"
@@ -20,24 +22,50 @@ func TestMemStats(t *testing.T) {
        st := new(MemStats)
        ReadMemStats(st)
 
-       // Everything except HeapReleased, HeapIdle, and NumGC,
-       // because they indeed can be 0.
-       if st.Alloc == 0 || st.TotalAlloc == 0 || st.Sys == 0 || st.Lookups == 0 ||
-               st.Mallocs == 0 || st.Frees == 0 || st.HeapAlloc == 0 || st.HeapSys == 0 ||
-               st.HeapInuse == 0 || st.HeapObjects == 0 || st.StackInuse == 0 ||
-               st.StackSys == 0 || st.MSpanInuse == 0 || st.MSpanSys == 0 || st.MCacheInuse == 0 ||
-               st.MCacheSys == 0 || st.BuckHashSys == 0 || st.GCSys == 0 || st.OtherSys == 0 ||
-               st.NextGC == 0 || st.NumForcedGC == 0 {
-               t.Fatalf("Zero value: %+v", *st)
+       nz := func(x interface{}) error {
+               if x != reflect.Zero(reflect.TypeOf(x)).Interface() {
+                       return nil
+               }
+               return fmt.Errorf("zero value")
+       }
+       le := func(thresh uint64) func(interface{}) error {
+               return func(x interface{}) error {
+                       if reflect.ValueOf(x).Uint() < thresh {
+                               return nil
+                       }
+                       return fmt.Errorf("insanely high value (overflow?); want <= %d", thresh)
+               }
+       }
+       // Of the uint fields, HeapReleased, HeapIdle, PauseTotalNs, and NumGC can be 0.
+       fields := map[string][]func(interface{}) error{
+               "Alloc": {nz, le(1e10)}, "TotalAlloc": {nz, le(1e11)}, "Sys": {nz, le(1e10)},
+               "Lookups": {nz, le(1e10)}, "Mallocs": {nz, le(1e10)}, "Frees": {nz, le(1e10)},
+               "HeapAlloc": {nz, le(1e10)}, "HeapSys": {nz, le(1e10)}, "HeapIdle": {le(1e10)},
+               "HeapInuse": {nz, le(1e10)}, "HeapReleased": nil, "HeapObjects": {nz, le(1e10)},
+               "StackInuse": {nz, le(1e10)}, "StackSys": {nz, le(1e10)},
+               "MSpanInuse": {nz, le(1e10)}, "MSpanSys": {nz, le(1e10)},
+               "MCacheInuse": {nz, le(1e10)}, "MCacheSys": {nz, le(1e10)},
+               "BuckHashSys": {nz, le(1e10)}, "GCSys": {nz, le(1e10)}, "OtherSys": {nz, le(1e10)},
+               "NextGC": {nz, le(1e10)}, "LastGC": nil,
+               "PauseTotalNs": {le(1e11)}, "PauseNs": nil, "PauseEnd": nil,
+               "NumGC": {le(1e9)}, "NumForcedGC": {nz, le(1e9)},
+               "GCCPUFraction": nil, "EnableGC": nil, "DebugGC": nil,
+               "BySize": nil,
        }
 
-       if st.Alloc > 1e10 || st.TotalAlloc > 1e11 || st.Sys > 1e10 || st.Lookups > 1e10 ||
-               st.Mallocs > 1e10 || st.Frees > 1e10 || st.HeapAlloc > 1e10 || st.HeapSys > 1e10 ||
-               st.HeapIdle > 1e10 || st.HeapInuse > 1e10 || st.HeapObjects > 1e10 || st.StackInuse > 1e10 ||
-               st.StackSys > 1e10 || st.MSpanInuse > 1e10 || st.MSpanSys > 1e10 || st.MCacheInuse > 1e10 ||
-               st.MCacheSys > 1e10 || st.BuckHashSys > 1e10 || st.GCSys > 1e10 || st.OtherSys > 1e10 ||
-               st.NextGC > 1e10 || st.NumGC > 1e9 || st.NumForcedGC > 1e9 || st.PauseTotalNs > 1e11 {
-               t.Fatalf("Insanely high value (overflow?): %+v", *st)
+       rst := reflect.ValueOf(st).Elem()
+       for i := 0; i < rst.Type().NumField(); i++ {
+               name, val := rst.Type().Field(i).Name, rst.Field(i).Interface()
+               checks, ok := fields[name]
+               if !ok {
+                       t.Errorf("unknown MemStats field %s", name)
+                       continue
+               }
+               for _, check := range checks {
+                       if err := check(val); err != nil {
+                               t.Errorf("%s = %v: %s", name, val, err)
+                       }
+               }
        }
 
        if st.Sys != st.HeapSys+st.StackSys+st.MSpanSys+st.MCacheSys+