Skip to content

Commit 749e2ab

Browse files
committed
fix: Root node was not checked for emptiness
1 parent b56d71a commit 749e2ab

File tree

3 files changed

+113
-5
lines changed

3 files changed

+113
-5
lines changed

src/IntSet.Tests/IntSetTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,10 @@ public void FullSetTest(int from, int to)
220220
}
221221

222222
[Theory]
223-
[InlineData(int.MinValue, int.MinValue + 1000000, 997)]
224-
[InlineData(int.MaxValue - 1000000, int.MaxValue, 997)]
225-
[InlineData(-5000000, 5000000, 997)]
226-
[InlineData(int.MinValue, int.MaxValue, 2147477)]
223+
[InlineData(int.MinValue, int.MinValue + 100000, 997)]
224+
[InlineData(int.MaxValue - 100000, int.MaxValue, 997)]
225+
[InlineData(-500000, 500000, 997)]
226+
[InlineData(int.MinValue, int.MaxValue, 214747777)]
227227
public void FullSteppedSetTest(int from, int to, int step)
228228
{
229229
var intSet = new Kibnet.IntSet(false, true);

src/IntSet.Tests/StrykerTests.cs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,5 +213,113 @@ public void NullChecks_OnVariousPredicates_ThrowArgumentNullException()
213213
Assert.Throws<ArgumentNullException>(() => set.Overlaps(null));
214214
Assert.Throws<ArgumentNullException>(() => set.SetEquals(null));
215215
}
216+
217+
[Fact]
218+
public void IsFastest_SetFalse_RemainsFalse()
219+
{
220+
var set = new Kibnet.IntSet(new[] { 1, 2, 3 });
221+
set.IsFastest = false;
222+
// На прямую поле недоступно, но можно косвенно проверить:
223+
// добавим элемент, и убеждаемся, что удаление идёт по «медленному» пути (Bytes != null)
224+
set.Add(4);
225+
Assert.True(set.Contains(4));
226+
// здесь важнее, что при IsFastest = false в методе Remove не сбрасывается Bytes раньше времени
227+
// (иначе Remove мог бы возвращать неверно)
228+
}
229+
230+
[Theory]
231+
[InlineData(false)]
232+
[InlineData(true)]
233+
public void Remove_VariousIsFastestPaths_DoNotThrow(bool isFastest)
234+
{
235+
var set = new Kibnet.IntSet(new[] { 5 });
236+
set.IsFastest = isFastest;
237+
// при любом значении флага метод Remove должен вернуть true
238+
Assert.True(set.Remove(5));
239+
Assert.False(set.Contains(5));
240+
}
241+
242+
[Fact]
243+
public void Remove_CascadeEmptyCards_RemovesAllLevels()
244+
{
245+
// строим IntSet, в котором один элемент лежит глубоко в дереве
246+
var value = 555;
247+
var set = new Kibnet.IntSet([value]);
248+
// удаляем этот элемент — он должен снять все четыре уровня Card
249+
bool removed = set.Remove(value);
250+
Assert.True(removed);
251+
// Теперь в дереве должна быть только корневая карточка с пустой Bytes/картами
252+
Assert.False(set.Contains(value));
253+
Assert.True(set.root.Cards == null);
254+
}
255+
256+
[Theory]
257+
[InlineData(0)]
258+
[InlineData(1)]
259+
[InlineData(2)]
260+
public void ElementAt_ValidAndInvalidIndexes(int idx)
261+
{
262+
var set = new Kibnet.IntSet(new[] { 10, 20, 30 });
263+
if (idx < set.Count)
264+
Assert.Equal(new[] { 10, 20, 30 }[idx], set.ElementAt(idx));
265+
else
266+
Assert.Throws<ArgumentOutOfRangeException>(() => _ = set.ElementAt(idx));
267+
}
268+
269+
[Fact]
270+
public void CopyTo_ExactSpace_CopiesAllElements()
271+
{
272+
var set = new Kibnet.IntSet(new[] { 7, 8, 9 });
273+
var dst = new int[5];
274+
// оставляем ровно 3 места в конце: 5 - 2 = 3
275+
set.CopyTo(dst, 2, set.Count);
276+
Assert.Equal(new[] { 0, 0, 7, 8, 9 }, dst);
277+
}
278+
279+
[Fact]
280+
public void CheckEmpty_BytesMinValue_ReturnsTrue()
281+
{
282+
var set = new Kibnet.IntSet(new[] { 1 });
283+
// добиваем Bytes вручную (рефлексия) или через публичный API:
284+
// например, удаляем все элементы, чтобы остались только нули
285+
set.Clear();
286+
// Пусть внутренне Bytes будут не null и все = 0
287+
Assert.True(set.root.CheckEmpty());
288+
}
289+
290+
[Fact]
291+
public void CheckEmpty_BytesNotMinValue_ReturnsFalse()
292+
{
293+
var set = new Kibnet.IntSet(new[] { 1 });
294+
Assert.False(set.root.CheckEmpty());
295+
}
296+
297+
[Fact]
298+
public void CheckFull_AllBytesMax_ClearsBytesAndReturnsTrue()
299+
{
300+
// создаём IntSet так, чтобы внутренний массив Bytes заполнен byte.MaxValue
301+
var set = new Kibnet.IntSet();
302+
// через публичный API добавить все возможные элементы до заполнения одной «карты»
303+
foreach (var i in Enumerable.Range(0, 16384).ToArray())
304+
{
305+
set.Add(i);
306+
}
307+
Assert.False(set.root.Full);
308+
Assert.False(set.root.Cards[0].Full);
309+
Assert.False(set.root.Cards[0].Cards[0].Full);
310+
Assert.True(set.root.Cards[0].Cards[0].Cards[0].Full);
311+
Assert.Null(set.root.Cards[0].Cards[0].Cards[0].Cards);
312+
// после этого Bytes должен стать null
313+
Assert.Null(set.root.Cards[0].Cards[0].Cards[0].Bytes);
314+
}
315+
316+
[Fact]
317+
public void CheckFull_NonFull_DoesNotClearBytes()
318+
{
319+
var set = new Kibnet.IntSet(new[] { 1 });
320+
Assert.False(set.root.Full);
321+
// Bytes остаётся ненулевым
322+
Assert.NotNull(set.root.Cards[0].Cards[0].Cards[0].Cards[0].Bytes);
323+
}
216324
}
217325
}

src/IntSet/IntSet.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ protected bool InternalRemove(int item, bool isFastest)
289289
if (parentCard2.CheckEmpty())
290290
if (parentCard1.CheckEmpty())
291291
if (parentCard0.CheckEmpty())
292-
;
292+
root.CheckEmpty();
293293
}
294294
}
295295

0 commit comments

Comments
 (0)