(t *testing.T)
| 259 | } |
| 260 | |
| 261 | func TestMemStatsEquivalence(t *testing.T) { |
| 262 | var msReal, msFake runtime.MemStats |
| 263 | descs := bestEffortLookupRM(rmNamesForMemStatsMetrics) |
| 264 | |
| 265 | samples := make([]metrics.Sample, len(descs)) |
| 266 | samplesMap := make(map[string]*metrics.Sample) |
| 267 | for i := range descs { |
| 268 | samples[i].Name = descs[i].Name |
| 269 | samplesMap[descs[i].Name] = &samples[i] |
| 270 | } |
| 271 | |
| 272 | // Force a GC cycle to try to reach a clean slate. |
| 273 | runtime.GC() |
| 274 | |
| 275 | // Populate msReal. |
| 276 | runtime.ReadMemStats(&msReal) |
| 277 | // Populate msFake and hope that no GC happened in between (: |
| 278 | metrics.Read(samples) |
| 279 | |
| 280 | memStatsFromRM(&msFake, samplesMap) |
| 281 | |
| 282 | // Iterate over them and make sure they're somewhat close. |
| 283 | msRealValue := reflect.ValueOf(msReal) |
| 284 | msFakeValue := reflect.ValueOf(msFake) |
| 285 | |
| 286 | typ := msRealValue.Type() |
| 287 | for i := 0; i < msRealValue.NumField(); i++ { |
| 288 | fr := msRealValue.Field(i) |
| 289 | ff := msFakeValue.Field(i) |
| 290 | |
| 291 | if typ.Field(i).Name == "PauseTotalNs" || typ.Field(i).Name == "LastGC" { |
| 292 | // We don't use those fields for metrics, |
| 293 | // thus we are not interested in having this filled. |
| 294 | continue |
| 295 | } |
| 296 | switch fr.Kind() { |
| 297 | // Fields which we are interested in are all uint64s. |
| 298 | // The only float64 field GCCPUFraction is by design omitted. |
| 299 | case reflect.Uint64: |
| 300 | vr := fr.Interface().(uint64) |
| 301 | vf := ff.Interface().(uint64) |
| 302 | if float64(vr-vf)/float64(vf) > 0.05 { |
| 303 | t.Errorf("wrong value for %s: got %d, want %d", typ.Field(i).Name, vf, vr) |
| 304 | } |
| 305 | } |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | func TestExpectedRuntimeMetrics(t *testing.T) { |
| 310 | goMetrics := collectGoMetrics(t, internal.GoCollectorOptions{ |
nothing calls this directly
no test coverage detected