refactor(kpi): K4/K10/K12 review fixups — test data-race + faulted-tick liveness, dead-branch/unused removal, NaN-guard assertions, value clamp + doc
This commit is contained in:
@@ -190,33 +190,47 @@ public class KpiSeriesBucketerTests
|
||||
[Fact]
|
||||
public void Bucket_PointAtToUtc_LandsInLastBucket()
|
||||
{
|
||||
// 60-minute window / 3 buckets → 20 min each.
|
||||
// A point exactly at T(60) = toUtc must go to bucket 2, not overflow.
|
||||
// 60-minute window / 2 buckets → 30 min each.
|
||||
// A point exactly at T(60) = toUtc must go to bucket 1 (the last bucket),
|
||||
// not overflow to an out-of-range index.
|
||||
// T(10) → bucket 0: [0, 30); T(35) → bucket 1: [30, 60]; T(60) → bucket 1.
|
||||
var raw = new[]
|
||||
{
|
||||
new KpiSeriesPoint(T(10), 1.0),
|
||||
new KpiSeriesPoint(T(30), 2.0),
|
||||
new KpiSeriesPoint(T(60), 99.0), // right edge — must land in last bucket
|
||||
};
|
||||
|
||||
// raw.Count (3) == maxPoints (3) so it normally returns as-is;
|
||||
// use maxPoints=2 to force downsampling and expose the edge behaviour.
|
||||
// Window: [T(0), T(60)], 2 buckets → 30 min each.
|
||||
// T(10) → bucket 0, T(30) → bucket 1, T(60) → bucket 1 (last).
|
||||
var raw2 = new[]
|
||||
{
|
||||
new KpiSeriesPoint(T(10), 5.0),
|
||||
new KpiSeriesPoint(T(35), 6.0),
|
||||
new KpiSeriesPoint(T(60), 7.0), // exactly toUtc → bucket 1
|
||||
new KpiSeriesPoint(T(60), 7.0), // exactly toUtc → must land in last bucket
|
||||
};
|
||||
|
||||
var result = KpiSeriesBucketer.Bucket(raw2, T(0), T(60), maxPoints: 2);
|
||||
var result = KpiSeriesBucketer.Bucket(raw, T(0), T(60), maxPoints: 2);
|
||||
|
||||
Assert.Equal(2, result.Count);
|
||||
// Bucket 1 holds both T(35) and T(60); T(60) is later → wins.
|
||||
Assert.Equal(7.0, result[1].Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bucket_ThreeBucketWindow_PointAtToUtc_LandsInLastBucket()
|
||||
{
|
||||
// 60-minute window / 3 buckets → 20 min each.
|
||||
// A point exactly at T(60) = toUtc must land in bucket 2 (the last),
|
||||
// not overflow. Use 4 raw points so downsampling is forced (4 > 3).
|
||||
// T(5) → bucket 0: [0,20); T(25) → bucket 1: [20,40);
|
||||
// T(45) → bucket 2: [40,60]; T(60) → bucket 2 (right edge, later → wins).
|
||||
var raw = new[]
|
||||
{
|
||||
new KpiSeriesPoint(T(5), 1.0),
|
||||
new KpiSeriesPoint(T(25), 2.0),
|
||||
new KpiSeriesPoint(T(45), 3.0),
|
||||
new KpiSeriesPoint(T(60), 99.0), // right edge — must land in last bucket
|
||||
};
|
||||
|
||||
var result = KpiSeriesBucketer.Bucket(raw, T(0), T(60), maxPoints: 3);
|
||||
|
||||
Assert.Equal(3, result.Count);
|
||||
// Bucket 2 holds T(45)=3.0 and T(60)=99.0; T(60) is later → wins.
|
||||
Assert.Equal(99.0, result[2].Value);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Empty buckets omitted — no gap-filling
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user