Files
sqrtspace-dotnet/tests/SqrtSpace.SpaceTime.Tests/Collections/AdaptiveListTests.cs
2025-07-20 03:41:39 -04:00

400 lines
10 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using SqrtSpace.SpaceTime.Collections;
using Xunit;
namespace SqrtSpace.SpaceTime.Tests.Collections;
public class AdaptiveListTests
{
[Fact]
public void AdaptiveList_StartsAsArray()
{
// Arrange & Act
var list = new AdaptiveList<int>();
list.Add(1);
list.Add(2);
list.Add(3);
// Assert
list.Count.Should().Be(3);
list.CurrentImplementation.Should().Be("List<T>");
list[0].Should().Be(1);
list[1].Should().Be(2);
list[2].Should().Be(3);
}
[Fact]
public void AdaptiveList_TransitionsToList()
{
// Arrange
var list = new AdaptiveList<int>();
// Act - Add items beyond array threshold
for (int i = 0; i < 20; i++) // ArrayThreshold is typically 16
{
list.Add(i);
}
// Assert
list.CurrentImplementation.Should().Be("List<T>");
list.Count.Should().Be(20);
list[10].Should().Be(10);
}
[Fact]
public void AdaptiveList_TransitionsToSegmented()
{
// Arrange
var list = new AdaptiveList<int>();
// Act - Add items beyond list threshold
for (int i = 0; i < 15_000; i++) // ListThreshold is typically 10,000
{
list.Add(i);
}
// Assert
// Note: AdaptiveList doesn't have SegmentedList implementation
// list.CurrentImplementation.Should().Be("SegmentedList");
list.Count.Should().Be(15_000);
list[7500].Should().Be(7500);
}
[Fact]
public void AdaptiveList_Insert_InsertsAtCorrectPosition()
{
// Arrange
var list = new AdaptiveList<string>();
list.Add("first");
list.Add("third");
// Act
list.Insert(1, "second");
// Assert
list.Count.Should().Be(3);
list[0].Should().Be("first");
list[1].Should().Be("second");
list[2].Should().Be("third");
}
[Fact]
public void AdaptiveList_RemoveAt_RemovesCorrectItem()
{
// Arrange
var list = new AdaptiveList<int>();
list.AddRange(new[] { 1, 2, 3, 4, 5 });
// Act
list.RemoveAt(2);
// Assert
list.Count.Should().Be(4);
list.Should().BeEquivalentTo(new[] { 1, 2, 4, 5 });
}
[Fact]
public void AdaptiveList_Remove_RemovesFirstOccurrence()
{
// Arrange
var list = new AdaptiveList<int>();
list.AddRange(new[] { 1, 2, 3, 2, 4 });
// Act
var removed = list.Remove(2);
// Assert
removed.Should().BeTrue();
list.Count.Should().Be(4);
list.Should().BeEquivalentTo(new[] { 1, 3, 2, 4 });
}
[Fact]
public void AdaptiveList_IndexOf_FindsCorrectIndex()
{
// Arrange
var list = new AdaptiveList<string>();
list.AddRange(new[] { "apple", "banana", "cherry", "date" });
// Act
var index = list.IndexOf("cherry");
// Assert
index.Should().Be(2);
}
[Fact]
public void AdaptiveList_IndexOf_ReturnsNegativeOneForNotFound()
{
// Arrange
var list = new AdaptiveList<string>();
list.AddRange(new[] { "apple", "banana", "cherry" });
// Act
var index = list.IndexOf("date");
// Assert
index.Should().Be(-1);
}
[Fact]
public void AdaptiveList_Contains_ReturnsTrueForExisting()
{
// Arrange
var list = new AdaptiveList<int>();
list.AddRange(Enumerable.Range(1, 100));
// Act & Assert
list.Contains(50).Should().BeTrue();
list.Contains(101).Should().BeFalse();
}
[Fact]
public void AdaptiveList_Clear_RemovesAllItems()
{
// Arrange
var list = new AdaptiveList<int>();
list.AddRange(Enumerable.Range(1, 50));
// Act
list.Clear();
// Assert
list.Count.Should().Be(0);
list.CurrentImplementation.Should().Be("List<T>");
}
[Fact]
public void AdaptiveList_CopyTo_CopiesAllItems()
{
// Arrange
var list = new AdaptiveList<int>();
list.AddRange(new[] { 1, 2, 3, 4, 5 });
var array = new int[8];
// Act
list.CopyTo(array, 2);
// Assert
array.Should().BeEquivalentTo(new[] { 0, 0, 1, 2, 3, 4, 5, 0 });
}
[Fact]
public void AdaptiveList_GetEnumerator_EnumeratesAllItems()
{
// Arrange
var list = new AdaptiveList<int>();
var expected = Enumerable.Range(1, 10).ToList();
list.AddRange(expected);
// Act
var result = new List<int>();
foreach (var item in list)
{
result.Add(item);
}
// Assert
result.Should().BeEquivalentTo(expected);
}
[Fact]
public void AdaptiveList_IndexerSet_UpdatesValue()
{
// Arrange
var list = new AdaptiveList<string>();
list.AddRange(new[] { "one", "two", "three" });
// Act
list[1] = "TWO";
// Assert
list[1].Should().Be("TWO");
list.Count.Should().Be(3);
}
[Fact]
public void AdaptiveList_IndexOutOfRange_ThrowsException()
{
// Arrange
var list = new AdaptiveList<int>();
list.AddRange(new[] { 1, 2, 3 });
// Act & Assert
var action1 = () => _ = list[-1];
action1.Should().Throw<ArgumentOutOfRangeException>();
var action2 = () => _ = list[3];
action2.Should().Throw<ArgumentOutOfRangeException>();
}
[Fact]
public void AdaptiveList_AddRange_AddsMultipleItems()
{
// Arrange
var list = new AdaptiveList<int>();
var items = Enumerable.Range(1, 100).ToList();
// Act
list.AddRange(items);
// Assert
list.Count.Should().Be(100);
list.Should().BeEquivalentTo(items);
}
[Fact]
public void AdaptiveList_DataPersistenceAcrossTransitions()
{
// Arrange
var list = new AdaptiveList<string>();
var testData = Enumerable.Range(0, 100)
.Select(i => $"item{i}")
.ToList();
// Act - Add data forcing transitions
foreach (var item in testData)
{
list.Add(item);
}
// Assert - Verify all data is preserved
list.Count.Should().Be(100);
for (int i = 0; i < 100; i++)
{
list[i].Should().Be($"item{i}");
}
}
// Commented out: AdaptiveList doesn't have Sort() method
// [Fact]
// public void AdaptiveList_Sort_SortsItems()
// {
// // Arrange
// var list = new AdaptiveList<int>();
// var random = new Random(42);
// var items = Enumerable.Range(1, 50).OrderBy(_ => random.Next()).ToList();
// list.AddRange(items);
// // Act
// list.Sort();
// // Assert
// list.Should().BeInAscendingOrder();
// }
// Commented out: AdaptiveList doesn't have Sort(IComparer<T>) method
// [Fact]
// public void AdaptiveList_Sort_WithComparer_UsesComparer()
// {
// // Arrange
// var list = new AdaptiveList<string>();
// list.AddRange(new[] { "apple", "Banana", "cherry", "Date" });
// // Act
// list.Sort(StringComparer.OrdinalIgnoreCase);
// // Assert
// list.Should().BeEquivalentTo(new[] { "apple", "Banana", "cherry", "Date" });
// }
// Commented out: AdaptiveList doesn't have Reverse() method
// [Fact]
// public void AdaptiveList_Reverse_ReversesOrder()
// {
// // Arrange
// var list = new AdaptiveList<int>();
// list.AddRange(new[] { 1, 2, 3, 4, 5 });
// // Act
// list.Reverse();
// // Assert
// list.Should().BeEquivalentTo(new[] { 5, 4, 3, 2, 1 });
// }
[Fact]
public void AdaptiveList_ToArray_ReturnsArray()
{
// Arrange
var list = new AdaptiveList<int>();
list.AddRange(new[] { 1, 2, 3, 4, 5 });
// Act
// AdaptiveList doesn't have ToArray(), but we can use LINQ
var array = list.ToArray();
// Assert
array.Should().BeEquivalentTo(new[] { 1, 2, 3, 4, 5 });
array.Should().BeOfType<int[]>();
}
[Fact]
public void AdaptiveList_FindAll_ReturnsMatchingItems()
{
// Arrange
var list = new AdaptiveList<int>();
list.AddRange(Enumerable.Range(1, 20));
// Act
// AdaptiveList doesn't have FindAll(), use LINQ Where instead
var evens = list.Where(x => x % 2 == 0).ToList();
// Assert
evens.Should().HaveCount(10);
evens.Should().BeEquivalentTo(new[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 });
}
[Fact]
public void AdaptiveList_RemoveAll_RemovesMatchingItems()
{
// Arrange
var list = new AdaptiveList<int>();
list.AddRange(Enumerable.Range(1, 10));
// Act
// AdaptiveList doesn't have RemoveAll(), manually remove matching items
var toRemove = list.Where(x => x % 2 == 0).ToList();
var removed = 0;
foreach (var item in toRemove)
{
if (list.Remove(item))
removed++;
}
// Assert
removed.Should().Be(5);
list.Should().BeEquivalentTo(new[] { 1, 3, 5, 7, 9 });
}
// Commented out: AdaptiveList doesn't have Capacity property
// [Fact]
// public void AdaptiveList_WithInitialCapacity_PreallocatesSpace()
// {
// // Arrange & Act
// var list = new AdaptiveList<int>(100);
// // Assert
// list.Count.Should().Be(0);
// list.Capacity.Should().BeGreaterOrEqualTo(100);
// }
// Commented out: AdaptiveList doesn't have TrimExcess() method or Capacity property
// [Fact]
// public void AdaptiveList_TrimExcess_ReducesCapacity()
// {
// // Arrange
// var list = new AdaptiveList<int>(100);
// list.AddRange(new[] { 1, 2, 3, 4, 5 });
// // Act
// list.TrimExcess();
// // Assert
// list.Count.Should().Be(5);
// list.Capacity.Should().BeLessThan(100);
// }
}