diff --git a/model/histogram/float_histogram_test.go b/model/histogram/float_histogram_test.go index 34988e9d39..3f0fcf13a8 100644 --- a/model/histogram/float_histogram_test.go +++ b/model/histogram/float_histogram_test.go @@ -2312,6 +2312,8 @@ func TestFloatHistogramAdd(t *testing.T) { t.Run(c.name, func(t *testing.T) { testHistogramAdd(t, c.in1, c.in2, c.expected, c.expErrMsg) testHistogramAdd(t, c.in2, c.in1, c.expected, c.expErrMsg) + testHistogramKahanAdd(t, c.in1, c.in2, c.expected, c.expErrMsg) + testHistogramKahanAdd(t, c.in2, c.in1, c.expected, c.expErrMsg) }) } } @@ -2348,6 +2350,51 @@ func testHistogramAdd(t *testing.T, a, b, expected *FloatHistogram, expErrMsg st } } +func testHistogramKahanAdd(t *testing.T, a, b, expected *FloatHistogram, expErrMsg string) { + var ( + aCopy = a.Copy() + bCopy = b.Copy() + expectedCopy *FloatHistogram + ) + + if expected != nil { + expectedCopy = expected.Copy() + } + + var res *FloatHistogram + comp := aCopy.NewCompensationHistogram() + var err error + + res, comp, err = aCopy.KahanAdd(bCopy, comp) + if expErrMsg != "" { + require.EqualError(t, err, expErrMsg) + } else { + require.NoError(t, err) + } + + if res != nil { + res, err = res.Add(comp) + if expErrMsg != "" { + require.EqualError(t, err, expErrMsg) + } else { + require.NoError(t, err) + } + } + + if expected != nil { + res.Compact(0) + expectedCopy.Compact(0) + + require.Equal(t, expectedCopy, res) + + // Has it also happened in-place? + require.Equal(t, expectedCopy, aCopy) + + // Check that the argument was not mutated. + require.Equal(t, b, bCopy) + } +} + func TestFloatHistogramSub(t *testing.T) { // This has fewer test cases than TestFloatHistogramAdd because Add and // Sub share most of the trickier code. @@ -2504,12 +2551,14 @@ func TestFloatHistogramSub(t *testing.T) { for _, c := range cases { t.Run(c.name, func(t *testing.T) { testFloatHistogramSub(t, c.in1, c.in2, c.expected, c.expErrMsg) + testHistogramKahanSub(t, c.in1, c.in2, c.expected, c.expErrMsg) var expectedNegative *FloatHistogram if c.expected != nil { expectedNegative = c.expected.Copy().Mul(-1) } testFloatHistogramSub(t, c.in2, c.in1, expectedNegative, c.expErrMsg) + testHistogramKahanSub(t, c.in2, c.in1, expectedNegative, c.expErrMsg) }) } } @@ -2546,6 +2595,51 @@ func testFloatHistogramSub(t *testing.T, a, b, expected *FloatHistogram, expErrM } } +func testHistogramKahanSub(t *testing.T, a, b, expected *FloatHistogram, expErrMsg string) { + var ( + aCopy = a.Copy() + bCopy = b.Copy() + expectedCopy *FloatHistogram + ) + + if expected != nil { + expectedCopy = expected.Copy() + } + + var res *FloatHistogram + comp := aCopy.NewCompensationHistogram() + var err error + + res, comp, err = aCopy.KahanSub(bCopy, comp) + if expErrMsg != "" { + require.EqualError(t, err, expErrMsg) + } else { + require.NoError(t, err) + } + + if res != nil { + res, err = res.Sub(comp) + if expErrMsg != "" { + require.EqualError(t, err, expErrMsg) + } else { + require.NoError(t, err) + } + } + + if expected != nil { + res.Compact(0) + expectedCopy.Compact(0) + + require.Equal(t, expectedCopy, res) + + // Has it also happened in-place? + require.Equal(t, expectedCopy, aCopy) + + // Check that the argument was not mutated. + require.Equal(t, b, bCopy) + } +} + func TestFloatHistogramCopyToSchema(t *testing.T) { cases := []struct { name string