Skip to content

Commit

Permalink
Throw meaningful ArgumentException for inconsistent source data (#56)
Browse files Browse the repository at this point in the history
instead of hard to understand exception from base class
  • Loading branch information
hf-kklein authored Oct 4, 2023
1 parent 0ad4793 commit 60bf56f
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
18 changes: 17 additions & 1 deletion ChronoJsonDiffPatch/ChronoJsonDiffPatch/TimeRangePatchChain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,23 @@ private static IEnumerable<TimeRangePatch> PrepareForTimePeriodChainConstructor(
return new List<TimeRangePatch>();
}

return timeperiods.OrderBy(tp => tp.Start);
var result = timeperiods.OrderBy(tp => tp.Start);
var ambigousStarts = result.GroupBy(tp => tp.To).Where(g => g.Count() > 1).Select(g => g.Select(x => x.Start).Distinct());
var ambigousEnds = result.GroupBy(tp => tp.End).Where(g => g.Count() > 1).Select(g => g.Select(x => x.End).Distinct()); ;
bool baseConstructorIsLikelyToCrash = ambigousStarts.Any() || ambigousEnds.Any();
if (baseConstructorIsLikelyToCrash)
{
try
{
_ = new TimePeriodChain(result); // a test if the base constructor will actually crash?
}
catch (InvalidOperationException invalidOpException) when (invalidOpException.Message.EndsWith("out of range"))
{
// if it would crash and we do know the reasons, then we throw a more meaningful exception here instead of waiting for the base class to crash
throw new ArgumentException($"The given periods contain ambiguous starts ({ambigousStarts}) or ends ({ambigousEnds})", innerException: invalidOpException);
}
}
return result;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -719,4 +719,39 @@ public void Test_Patching_Backwards()
AssertBasicSanity(myEntity, trpCollection);
*/
}

[Fact]
public void Test_Patching_Backwards_Throws_Meaningful_Error_For_Inconsistent_Data()
{
var trpCollection = new TimeRangePatchChain<DummyClass>(patchingDirection: PatchingDirection.ParallelWithTime);
var myEntity = new DummyClass
{
MyProperty = "Foo"
};
{
var keyDate1 = new DateTimeOffset(2034, 1, 1, 0, 0, 0, TimeSpan.Zero);
var myChangedEntity = new DummyClass
{
MyProperty = "Bar"
};
trpCollection.Add(myEntity, myChangedEntity, keyDate1);
}
{
var keyDate2 = new DateTimeOffset(2035, 1, 1, 0, 0, 0, TimeSpan.Zero);
var myChangedEntity = new DummyClass
{
MyProperty = "Baz"
};
trpCollection.Add(myEntity, myChangedEntity, keyDate2);
}
var allPatches = trpCollection.GetAll().ToList();
allPatches.Should().HaveCount(3);

allPatches[1].End = DateTime.MaxValue; // let's a create chain, that is no longer self-consistent and has 2 elements with +infinity as end date
allPatches.Where(p => p.End == DateTime.MaxValue).Should().HaveCount(2);
Action creatingAChainFromInconsistentPatches = () => new TimeRangePatchChain<DummyClass>(allPatches, PatchingDirection.ParallelWithTime);
creatingAChainFromInconsistentPatches.Should().Throw<ArgumentException>()
.Where(ae => ae.Message.Contains("The given periods contain ambiguous starts"))
.And.InnerException.Should().BeOfType<InvalidOperationException>();
}
}

0 comments on commit 60bf56f

Please sign in to comment.