Skip to content

Commit c7390d3

Browse files
Copilotblaze6950
andauthored
Fix TryGet returning false for empty subranges with exclusive parent boundaries (#3)
* Initial plan * Add test case demonstrating bug with empty subranges in exclusive-start parents Co-authored-by: blaze6950 <32897401+blaze6950@users.noreply.github.com> * Fix bug where empty subranges with negative indices returned false instead of empty RangeData Co-authored-by: blaze6950 <32897401+blaze6950@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: blaze6950 <32897401+blaze6950@users.noreply.github.com>
1 parent ffd2926 commit c7390d3

2 files changed

Lines changed: 65 additions & 7 deletions

File tree

src/Intervals.NET.Data/RangeData.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,6 @@ public bool TryGet(Range<TRangeType> subRange, out RangeData<TRangeType, TDataTy
219219
endIndex--;
220220
}
221221

222-
// Guard against index overflow (long → int cast)
223-
if (startIndex < 0 || startIndex > int.MaxValue || endIndex < 0 || endIndex > int.MaxValue)
224-
{
225-
data = null;
226-
return false;
227-
}
228-
229222
// Calculate the count of elements to take
230223
// If adjusted indices result in startIndex > endIndex, the range is empty
231224
var count = endIndex - startIndex + 1;
@@ -236,6 +229,15 @@ public bool TryGet(Range<TRangeType> subRange, out RangeData<TRangeType, TDataTy
236229
return true;
237230
}
238231

232+
// Guard against index overflow (long → int cast)
233+
// Note: We check this after the empty-range handling because a negative endIndex
234+
// combined with count <= 0 indicates a logically empty range, not an error
235+
if (startIndex < 0 || startIndex > int.MaxValue || endIndex < 0 || endIndex > int.MaxValue)
236+
{
237+
data = null;
238+
return false;
239+
}
240+
239241
// Guard against count overflow
240242
if (count > int.MaxValue)
241243
{

tests/Intervals.NET.Data.Tests/RangeDataTests.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,62 @@ public void TryGet_SubRange_WithEmptyRange_ReturnsTrueWithEmptyData()
325325
Assert.Empty(result.Data);
326326
}
327327

328+
[Fact]
329+
public void TryGet_SubRange_EmptyButContained_WithExclusiveStartParent_ReturnsTrueWithEmptyData()
330+
{
331+
// Arrange - Parent range: (10,20] means it contains 11, 12, ..., 20
332+
var parentRange = Range.OpenClosed<int>(10, 20);
333+
var data = new[] { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
334+
var rangeData = new RangeData<int, int, IntegerFixedStepDomain>(parentRange, data, _domain);
335+
336+
// Act - Sub-range (10,10] is logically empty but contained in parent
337+
// This tests the fix for the bug where endIndex becomes -1, and the negative-index guard
338+
// would return false before the empty-range handling was reached
339+
var subRange = Range.OpenClosed<int>(10, 10);
340+
var success = rangeData.TryGet(subRange, out var result);
341+
342+
// Assert - Should return true with empty data, not false
343+
Assert.True(success);
344+
Assert.NotNull(result);
345+
Assert.Empty(result.Data);
346+
}
347+
348+
[Fact]
349+
public void TryGet_SubRange_EmptyAtStartBoundary_WithClosedOpenParent_ReturnsTrueWithEmptyData()
350+
{
351+
// Arrange - Parent range: [10,20) means it contains 10, 11, ..., 19
352+
var parentRange = Range.ClosedOpen(10, 20);
353+
var data = new[] { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
354+
var rangeData = new RangeData<int, int, IntegerFixedStepDomain>(parentRange, data, _domain);
355+
356+
// Act - Sub-range [10,10) is logically empty
357+
var subRange = Range.ClosedOpen(10, 10);
358+
var success = rangeData.TryGet(subRange, out var result);
359+
360+
// Assert - Should return true with empty data
361+
Assert.True(success);
362+
Assert.NotNull(result);
363+
Assert.Empty(result.Data);
364+
}
365+
366+
[Fact]
367+
public void TryGet_SubRange_EmptyAtEndBoundary_WithOpenClosedParent_ReturnsTrueWithEmptyData()
368+
{
369+
// Arrange - Parent range: (10,20] means it contains 11, 12, ..., 20
370+
var parentRange = Range.OpenClosed<int>(10, 20);
371+
var data = new[] { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
372+
var rangeData = new RangeData<int, int, IntegerFixedStepDomain>(parentRange, data, _domain);
373+
374+
// Act - Sub-range [20,20) is logically empty but at the end boundary
375+
var subRange = Range.ClosedOpen(20, 20);
376+
var success = rangeData.TryGet(subRange, out var result);
377+
378+
// Assert - Should return true with empty data
379+
Assert.True(success);
380+
Assert.NotNull(result);
381+
Assert.Empty(result.Data);
382+
}
383+
328384
#endregion
329385

330386
#region TryGet Tests - Point

0 commit comments

Comments
 (0)