using MeterVault.Core.Domain; using MeterVault.Core.Normalization; using MeterVault.Infrastructure.Import; using static MeterVault.Integration.Tests.Reconciliation.ReconciliationSupport; namespace MeterVault.Integration.Tests.Reconciliation; /// /// Gap splitting apportions a long unread stretch across the months it covers. The reference sheets /// are read monthly and must never trigger it, or their months would silently shift and the whole /// golden-fixture oracle (SDD §13) would be measuring the splitter instead of the normalizer. /// /// /// The reconciliation suites already compare month by month, so a spurious split would surface there /// as a numeric failure. This asserts the mechanism directly instead of relying on that side effect: /// it proves the rule was evaluated against real fixture cadence and declined to fire, rather than /// the fixtures simply having no gaps to find. /// public sealed class GapSplittingIsInertOnFixturesTests { [Theory] [InlineData(ReferenceProfiles.Haus, MeterMode.CumulativeCounter)] [InlineData(ReferenceProfiles.Netz, MeterMode.CumulativeCounter)] [InlineData(ReferenceProfiles.Auto, MeterMode.CumulativeCounter)] [InlineData(ReferenceProfiles.Solar1, MeterMode.GenerationCounter)] [InlineData(ReferenceProfiles.Solar2, MeterMode.GenerationCounter)] public void Electricity_meters_produce_exactly_one_row_per_reading(int meterId, MeterMode mode) { var staged = Stage(ReferenceProfiles.Electricity(), Electricity); var readings = staged.Readings.Count(r => r.MeterId == meterId); var computed = Normalize(staged, new MeterConfig { MeterId = meterId, Mode = mode, Unit = "kWh" }); Assert.True(readings > 20, $"meter {meterId}: expected a real series, got {readings} readings."); Assert.Equal(readings, computed.Count); } [Fact] public void No_fixture_interval_is_long_enough_to_split() { var staged = Stage(ReferenceProfiles.Electricity(), Electricity); foreach (var group in staged.Readings.GroupBy(r => r.MeterId)) { var times = group.Select(r => r.Time).OrderBy(t => t).ToList(); for (var i = 1; i < times.Count; i++) { Assert.False( GapAttribution.ShouldSplit(times[i - 1], times[i]), $"meter {group.Key}: {times[i - 1]:yyyy-MM-dd} → {times[i]:yyyy-MM-dd} would be split."); } } } }