docs(historian): #680 lane B review — QuestDB data-range lookups are partition scans, both-direction gate, all-Bad Count 0x80000401, outage-last parity test, CLAUDE.md per-sample bullet
This commit is contained in:
+43
@@ -491,6 +491,49 @@ public sealed class SdkAggregateParityTests
|
||||
.ShouldBe([0u, HistorianInfoBits.HistorianPartial, 0u, 0u]);
|
||||
}
|
||||
|
||||
/// <summary>#680 review: the data ends on an OUTAGE MARKER (+25) — the interval holding it is all-Bad.</summary>
|
||||
private static readonly StoredSample[] OutageEndsData =
|
||||
[
|
||||
S(-5, HistorianValue.FromDouble(1), Good), S(3, HistorianValue.FromDouble(2), Good),
|
||||
S(25, HistorianValue.Empty, BadNoCommunication),
|
||||
];
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 40, 10)]
|
||||
[InlineData(40, 0, 10)]
|
||||
public void An_outage_marker_as_the_last_sample_sets_no_end_of_data_Partial_on_its_Bad_interval(double from, double to,
|
||||
double intervalS)
|
||||
{
|
||||
// Documented divergence (remarks): the SDK sets the end-of-data Partial bit on that interval's Bad result too; ours
|
||||
// never puts Partial on a Bad result. Masked by clearing Partial on the SDK's Bad results only — every other bit,
|
||||
// timestamp and value (and every non-Bad interval's Partial) is still compared.
|
||||
var failures = new List<string>();
|
||||
var sawSdkPartialOnBad = false;
|
||||
foreach (var agg in PerSample)
|
||||
{
|
||||
var ours = Ours(agg, from, to, intervalS, OutageEndsData);
|
||||
var sdk = Sdk(agg, from, to, intervalS, OutageEndsData);
|
||||
sawSdkPartialOnBad |= sdk.Any(r => (r.StatusCode & 0x80000000u) != 0 && (r.StatusCode & 0x4u) != 0);
|
||||
var masked = sdk.Select(r => (r.StatusCode & 0x80000000u) != 0 ? r with { StatusCode = r.StatusCode & ~0x4u } : r)
|
||||
.ToList();
|
||||
try
|
||||
{
|
||||
SdkAggregateOracle.ShouldMatch(ours, masked, $"{agg} OutageEndsData {from}→{to}/{intervalS}s",
|
||||
compareCalculatedInterpolatedBits: false);
|
||||
// The interval holding the marker ((20,30] / [20,30)) is Bad and carries no Partial.
|
||||
var k = from < to ? 2 : 1;
|
||||
((ours[k].StatusCode & 0x80000000u) != 0).ShouldBeTrue($"{agg}: the outage interval is Bad");
|
||||
(ours[k].StatusCode & HistorianInfoBits.HistorianPartial).ShouldBe(0u, $"{agg}: no Partial on a Bad result");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
failures.Add(ex.Message);
|
||||
}
|
||||
}
|
||||
failures.ShouldBeEmpty(string.Join("\n", failures));
|
||||
sawSdkPartialOnBad.ShouldBeTrue("the mask is not vacuous: the SDK does flag the Bad interval Partial");
|
||||
}
|
||||
|
||||
/// <summary>The per-bucket statistics the backends' SQL computes, built in memory with <see cref="BucketPlan.IndexOf"/>.</summary>
|
||||
internal static IEnumerable<BucketRow> InMemoryRows(BucketPlan plan, IEnumerable<StoredSample> samples, bool maximum = false)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user