Fix and tweak Go collector tests

Signed-off-by: beorn7 <bjoern@rabenste.in>
This commit is contained in:
beorn7 2019-05-05 23:44:22 +02:00
parent a325fb7566
commit 016273b1f9
1 changed files with 51 additions and 35 deletions

View File

@ -21,28 +21,40 @@ import (
dto "github.com/prometheus/client_model/go" dto "github.com/prometheus/client_model/go"
) )
func TestGoCollector(t *testing.T) { func TestGoCollectorGoroutines(t *testing.T) {
var ( var (
c = NewGoCollector() c = NewGoCollector()
ch = make(chan Metric) metricCh = make(chan Metric)
waitc = make(chan struct{}) waitCh = make(chan struct{})
closec = make(chan struct{}) endGoroutineCh = make(chan struct{})
endCollectionCh = make(chan struct{})
old = -1 old = -1
) )
defer close(closec) defer func() {
close(endGoroutineCh)
// Drain the collect channel to prevent goroutine leak.
for {
select {
case <-metricCh:
case <-endCollectionCh:
return
}
}
}()
go func() { go func() {
c.Collect(ch) c.Collect(metricCh)
go func(c <-chan struct{}) { go func(c <-chan struct{}) {
<-c <-c
}(closec) }(endGoroutineCh)
<-waitc <-waitCh
c.Collect(ch) c.Collect(metricCh)
close(endCollectionCh)
}() }()
for { for {
select { select {
case m := <-ch: case m := <-metricCh:
// m can be Gauge or Counter, // m can be Gauge or Counter,
// currently just test the go_goroutines Gauge // currently just test the go_goroutines Gauge
// and ignore others. // and ignore others.
@ -57,7 +69,7 @@ func TestGoCollector(t *testing.T) {
if old == -1 { if old == -1 {
old = int(pb.GetGauge().GetValue()) old = int(pb.GetGauge().GetValue())
close(waitc) close(waitCh)
continue continue
} }
@ -65,43 +77,47 @@ func TestGoCollector(t *testing.T) {
// TODO: This is flaky in highly concurrent situations. // TODO: This is flaky in highly concurrent situations.
t.Errorf("want 1 new goroutine, got %d", diff) t.Errorf("want 1 new goroutine, got %d", diff)
} }
// GoCollector performs three sends per call.
// On line 27 we need to receive three more sends
// to shut down cleanly.
<-ch
<-ch
<-ch
return
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
t.Fatalf("expected collect timed out") t.Fatalf("expected collect timed out")
} }
break
} }
} }
func TestGCCollector(t *testing.T) { func TestGoCollectorGC(t *testing.T) {
var ( var (
c = NewGoCollector() c = NewGoCollector()
ch = make(chan Metric) metricCh = make(chan Metric)
waitc = make(chan struct{}) waitCh = make(chan struct{})
closec = make(chan struct{}) endCollectionCh = make(chan struct{})
oldGC uint64 oldGC uint64
oldPause float64 oldPause float64
) )
defer close(closec)
go func() { go func() {
c.Collect(ch) c.Collect(metricCh)
// force GC // force GC
runtime.GC() runtime.GC()
<-waitc <-waitCh
c.Collect(ch) c.Collect(metricCh)
close(endCollectionCh)
}()
defer func() {
// Drain the collect channel to prevent goroutine leak.
for {
select {
case <-metricCh:
case <-endCollectionCh:
return
}
}
}() }()
first := true first := true
for { for {
select { select {
case metric := <-ch: case metric := <-metricCh:
pb := &dto.Metric{} pb := &dto.Metric{}
metric.Write(pb) metric.Write(pb)
if pb.GetSummary() == nil { if pb.GetSummary() == nil {
@ -119,7 +135,7 @@ func TestGCCollector(t *testing.T) {
first = false first = false
oldGC = *pb.GetSummary().SampleCount oldGC = *pb.GetSummary().SampleCount
oldPause = *pb.GetSummary().SampleSum oldPause = *pb.GetSummary().SampleSum
close(waitc) close(waitCh)
continue continue
} }
if diff := *pb.GetSummary().SampleCount - oldGC; diff != 1 { if diff := *pb.GetSummary().SampleCount - oldGC; diff != 1 {
@ -128,9 +144,9 @@ func TestGCCollector(t *testing.T) {
if diff := *pb.GetSummary().SampleSum - oldPause; diff <= 0 { if diff := *pb.GetSummary().SampleSum - oldPause; diff <= 0 {
t.Errorf("want moar pause, got %f", diff) t.Errorf("want moar pause, got %f", diff)
} }
return
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
t.Fatalf("expected collect timed out") t.Fatalf("expected collect timed out")
} }
break
} }
} }