@@ -1554,20 +1554,6 @@ func TestProcessTopK(t *testing.T) {
1554
1554
"b" : {2 , 6 , 2 },
1555
1555
}),
1556
1556
},
1557
- // FIXME: this test case is flaky, needs to be handled better
1558
- // {
1559
- // name: "test ties at a timestamp",
1560
- // input: createSeriesSet(map[string][]float64{
1561
- // "a": {10, 5, 3},
1562
- // "b": {10, 4, 2},
1563
- // "c": {10, 3, 1},
1564
- // }),
1565
- // limit: 2,
1566
- // expected: createSeriesSet(map[string][]float64{
1567
- // "a": {10, 5, 3}, // tie at timestamp 0, top 2 at timestamp 1, 2
1568
- // "b": {10, 4, 2}, // tie at timestamp 0, top 2 at timestamp 1, 2
1569
- // }),
1570
- // },
1571
1557
{
1572
1558
name : "negative and infinity values" ,
1573
1559
input : createSeriesSet (map [string ][]float64 {
@@ -1659,21 +1645,6 @@ func TestProcessBottomK(t *testing.T) {
1659
1645
"c" : {math .NaN (), 1 , 1 }, // Bottom-2 at timestamps 1, 2
1660
1646
}),
1661
1647
},
1662
- // FIXME: this case is flaky, need to handle it better
1663
- // {
1664
- // name: "test ties at a timestamp",
1665
- // input: createSeriesSet(map[string][]float64{
1666
- // "a": {10, 5, 3},
1667
- // "b": {10, 4, 2},
1668
- // "c": {10, 3, 1},
1669
- // }),
1670
- // limit: 2,
1671
- // expected: createSeriesSet(map[string][]float64{
1672
- // "a": {10, math.NaN(), math.NaN()},
1673
- // "b": {10, 4, 2},
1674
- // "c": {math.NaN(), 3, 1},
1675
- // }),
1676
- // },
1677
1648
{
1678
1649
name : "all series with NaN values" ,
1679
1650
input : createSeriesSet (map [string ][]float64 {
@@ -1720,12 +1691,49 @@ func TestProcessBottomK(t *testing.T) {
1720
1691
1721
1692
for _ , tt := range tests {
1722
1693
t .Run (tt .name , func (t * testing.T ) {
1694
+ fmt .Printf ("input: %v\n " , tt .input )
1723
1695
result := processBottomK (tt .input , 3 , tt .limit )
1696
+ fmt .Printf ("result: %v\n " , result )
1724
1697
expectSeriesSet (t , tt .expected , result )
1725
1698
})
1726
1699
}
1727
1700
}
1728
1701
1702
+ func TestTiesInTopK (t * testing.T ) {
1703
+ input := createSeriesSet (map [string ][]float64 {
1704
+ "a" : {10 , 5 , 1 },
1705
+ "b" : {10 , 4 , 2 },
1706
+ "c" : {10 , 3 , 3 },
1707
+ })
1708
+ result := processTopK (input , 3 , 2 )
1709
+ fmt .Printf ("result: %v\n " , result )
1710
+
1711
+ // because of ties, we can have different result at index 0
1712
+ // "a" can be [10, 5, NaN] OR [NaN, 5, NaN]
1713
+ // "b" can be [10, 4, 2] OR [NaN, 4, 2]
1714
+ // "c" can be [10, NaN, 3] OR [NaN, NaN, 3]
1715
+ checkEqualForTies (t , result [`{label="a"}` ].Values , []float64 {10 , 5 , math .NaN ()})
1716
+ checkEqualForTies (t , result [`{label="b"}` ].Values , []float64 {10 , 4 , 2 })
1717
+ checkEqualForTies (t , result [`{label="c"}` ].Values , []float64 {10 , math .NaN (), 3 })
1718
+ }
1719
+
1720
+ func TestTiesInBottomK (t * testing.T ) {
1721
+ input := createSeriesSet (map [string ][]float64 {
1722
+ "a" : {10 , 5 , 1 },
1723
+ "b" : {10 , 4 , 2 },
1724
+ "c" : {10 , 3 , 3 },
1725
+ })
1726
+ result := processBottomK (input , 3 , 2 )
1727
+
1728
+ // because of ties, we can have different result at index 0
1729
+ // "a" can be [10, NaN, 1] OR [NaN, NaN, 1]
1730
+ // "b" can be [10, 4, 2] OR [NaN, 4, 2]
1731
+ // "c" can be [10, 3, NaN] OR [NaN, 3, NaN]
1732
+ checkEqualForTies (t , result [`{label="a"}` ].Values , []float64 {10 , math .NaN (), 1 })
1733
+ checkEqualForTies (t , result [`{label="b"}` ].Values , []float64 {10 , 4 , 2 })
1734
+ checkEqualForTies (t , result [`{label="c"}` ].Values , []float64 {10 , 3 , math .NaN ()})
1735
+ }
1736
+
1729
1737
func runTraceQLMetric (req * tempopb.QueryRangeRequest , inSpans ... []Span ) (SeriesSet , error ) {
1730
1738
e := NewEngine ()
1731
1739
@@ -1813,6 +1821,23 @@ func expectSeriesSet(t *testing.T, expected, result SeriesSet) {
1813
1821
}
1814
1822
}
1815
1823
1824
+ func checkEqualForTies (t * testing.T , result , expected []float64 ) {
1825
+ for i := range result {
1826
+ switch i {
1827
+ // at index 0, we have a tie so it can be sometimes NaN
1828
+ case 0 :
1829
+ require .True (t , math .IsNaN (result [0 ]) || result [0 ] == expected [0 ],
1830
+ "index 0: expected NaN or %v, got %v" , expected [0 ], result [0 ])
1831
+ default :
1832
+ if math .IsNaN (expected [i ]) {
1833
+ require .True (t , math .IsNaN (result [i ]), "index %d: expected NaN, got %v" , i , result [i ])
1834
+ } else {
1835
+ require .Equal (t , expected [i ], result [i ], "index %d: expected %v" , i , expected [i ])
1836
+ }
1837
+ }
1838
+ }
1839
+ }
1840
+
1816
1841
func BenchmarkSumOverTime (b * testing.B ) {
1817
1842
totalSpans := 1_000_000
1818
1843
in := make ([]Span , 0 , totalSpans )
0 commit comments