forked from mirror/client_golang
Implements review commentary
Specifically @beorn7 pointed out that the previous implementation had some shortcomings around large numbers. I've changed the code to match the suggestion in review, as well as added a few test cases.
This commit is contained in:
parent
ae6939214c
commit
35559538c7
|
@ -126,3 +126,87 @@ func expectPanic(t *testing.T, op func(), errorMsg string) {
|
||||||
|
|
||||||
op()
|
op()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCounterAddInf(t *testing.T) {
|
||||||
|
counter := NewCounter(CounterOpts{
|
||||||
|
Name: "test",
|
||||||
|
Help: "test help",
|
||||||
|
}).(*counter)
|
||||||
|
|
||||||
|
counter.Inc()
|
||||||
|
if expected, got := 0.0, math.Float64frombits(counter.valBits); expected != got {
|
||||||
|
t.Errorf("Expected %f, got %f.", expected, got)
|
||||||
|
}
|
||||||
|
if expected, got := int64(1), counter.valInt; expected != got {
|
||||||
|
t.Errorf("Expected %f, got %f.", expected, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
counter.Add(math.Inf(1))
|
||||||
|
if expected, got := math.Inf(1), math.Float64frombits(counter.valBits); expected != got {
|
||||||
|
t.Errorf("valBits expected %f, got %f.", expected, got)
|
||||||
|
}
|
||||||
|
if expected, got := int64(1), counter.valInt; expected != got {
|
||||||
|
t.Errorf("valInts expected %d, got %d.", expected, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
counter.Inc()
|
||||||
|
if expected, got := math.Inf(1), math.Float64frombits(counter.valBits); expected != got {
|
||||||
|
t.Errorf("Expected %f, got %f.", expected, got)
|
||||||
|
}
|
||||||
|
if expected, got := int64(2), counter.valInt; expected != got {
|
||||||
|
t.Errorf("Expected %d, got %d.", expected, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
m := &dto.Metric{}
|
||||||
|
counter.Write(m)
|
||||||
|
|
||||||
|
if expected, got := `counter:<value:inf > `, m.String(); expected != got {
|
||||||
|
t.Errorf("expected %q, got %q", expected, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCounterAddLarge(t *testing.T) {
|
||||||
|
counter := NewCounter(CounterOpts{
|
||||||
|
Name: "test",
|
||||||
|
Help: "test help",
|
||||||
|
}).(*counter)
|
||||||
|
|
||||||
|
// large overflows the underlying type and should therefore be stored in valBits
|
||||||
|
large := float64(math.MaxInt64 + 1)
|
||||||
|
counter.Add(large)
|
||||||
|
if expected, got := large, math.Float64frombits(counter.valBits); expected != got {
|
||||||
|
t.Errorf("valBits expected %f, got %f.", expected, got)
|
||||||
|
}
|
||||||
|
if expected, got := int64(0), counter.valInt; expected != got {
|
||||||
|
t.Errorf("valInts expected %d, got %d.", expected, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
m := &dto.Metric{}
|
||||||
|
counter.Write(m)
|
||||||
|
|
||||||
|
if expected, got := fmt.Sprintf("counter:<value:%0.15e > ", large), m.String(); expected != got {
|
||||||
|
t.Errorf("expected %q, got %q", expected, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCounterAddSmall(t *testing.T) {
|
||||||
|
counter := NewCounter(CounterOpts{
|
||||||
|
Name: "test",
|
||||||
|
Help: "test help",
|
||||||
|
}).(*counter)
|
||||||
|
small := 0.000000000001
|
||||||
|
counter.Add(small)
|
||||||
|
if expected, got := small, math.Float64frombits(counter.valBits); expected != got {
|
||||||
|
t.Errorf("valBits expected %f, got %f.", expected, got)
|
||||||
|
}
|
||||||
|
if expected, got := int64(0), counter.valInt; expected != got {
|
||||||
|
t.Errorf("valInts expected %d, got %d.", expected, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
m := &dto.Metric{}
|
||||||
|
counter.Write(m)
|
||||||
|
|
||||||
|
if expected, got := fmt.Sprintf("counter:<value:%0.0e > ", small), m.String(); expected != got {
|
||||||
|
t.Errorf("expected %q, got %q", expected, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -45,7 +45,6 @@ type value struct {
|
||||||
// to go first in the struct to guarantee alignment for atomic
|
// to go first in the struct to guarantee alignment for atomic
|
||||||
// operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG
|
// operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG
|
||||||
valBits uint64
|
valBits uint64
|
||||||
|
|
||||||
// valInt is used to store values that are exact integers
|
// valInt is used to store values that are exact integers
|
||||||
valInt int64
|
valInt int64
|
||||||
|
|
||||||
|
@ -99,8 +98,9 @@ func (v *value) Dec() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *value) Add(val float64) {
|
func (v *value) Add(val float64) {
|
||||||
if math.Trunc(val) == val {
|
ival := int64(val)
|
||||||
atomic.AddInt64(&v.valInt, int64(val))
|
if float64(ival) == val {
|
||||||
|
v.add(ival)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue