174 lines
6.7 KiB
C#
174 lines
6.7 KiB
C#
using FluentAssertions;
|
|
using SqrtSpace.SpaceTime.Core;
|
|
using Xunit;
|
|
|
|
namespace SqrtSpace.SpaceTime.Tests.Core;
|
|
|
|
public class SpaceTimeCalculatorTests
|
|
{
|
|
[Theory]
|
|
[InlineData(100, 10)]
|
|
[InlineData(1_000, 31)]
|
|
[InlineData(10_000, 100)]
|
|
[InlineData(1_000_000, 1_000)]
|
|
[InlineData(1_000_000_000, 31_622)]
|
|
public void CalculateSqrtInterval_ReturnsCorrectValue(long dataSize, int expectedInterval)
|
|
{
|
|
// Act
|
|
var result = SpaceTimeCalculator.CalculateSqrtInterval(dataSize);
|
|
|
|
// Assert
|
|
result.Should().BeCloseTo(expectedInterval, 1);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(64, 8, 8)] // Single cache line
|
|
[InlineData(4096, 4, 256)] // Should align to cache line
|
|
[InlineData(10_000, 8, 96)] // Should be multiple of cache line elements
|
|
public void CalculateSqrtInterval_WithElementSize_AlignsToCache(long dataSize, int elementSize, int expectedInterval)
|
|
{
|
|
// Act
|
|
var result = SpaceTimeCalculator.CalculateSqrtInterval(dataSize, elementSize);
|
|
|
|
// Assert
|
|
result.Should().Be(expectedInterval);
|
|
// Verify cache alignment
|
|
var elementsPerCacheLine = 64 / elementSize;
|
|
(result % elementsPerCacheLine).Should().Be(0);
|
|
}
|
|
|
|
[Fact]
|
|
public void CalculateSqrtInterval_WithInvalidInput_ThrowsException()
|
|
{
|
|
// Act & Assert
|
|
var action = () => SpaceTimeCalculator.CalculateSqrtInterval(-1);
|
|
action.Should().Throw<ArgumentOutOfRangeException>()
|
|
.WithMessage("*Data size must be positive*");
|
|
|
|
var action2 = () => SpaceTimeCalculator.CalculateSqrtInterval(0);
|
|
action2.Should().Throw<ArgumentOutOfRangeException>();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1_000_000_000, 500_000_000, 31_622)]
|
|
[InlineData(1_000_000, 2_000_000, 1_000)]
|
|
[InlineData(1_000_000, 100_000, 100_000)]
|
|
[InlineData(1_000_000, 10_000, 10_000)] // Available memory is limiting factor
|
|
public void CalculateOptimalBufferSize_ReturnsCorrectValue(long totalDataSize, long availableMemory, long expectedSize)
|
|
{
|
|
// Act
|
|
var result = SpaceTimeCalculator.CalculateOptimalBufferSize(totalDataSize, availableMemory);
|
|
|
|
// Assert
|
|
result.Should().Be(expectedSize);
|
|
}
|
|
|
|
[Fact]
|
|
public void CalculateOptimalBufferSize_WithInvalidInputs_ThrowsException()
|
|
{
|
|
// Act & Assert
|
|
var action1 = () => SpaceTimeCalculator.CalculateOptimalBufferSize(-1, 1000);
|
|
action1.Should().Throw<ArgumentOutOfRangeException>();
|
|
|
|
var action2 = () => SpaceTimeCalculator.CalculateOptimalBufferSize(1000, -1);
|
|
action2.Should().Throw<ArgumentOutOfRangeException>();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1_000_000, CheckpointStrategy.SqrtN, 1_000)]
|
|
[InlineData(1_000_000, CheckpointStrategy.Linear, 1_000)]
|
|
[InlineData(1_024, CheckpointStrategy.Logarithmic, 10)]
|
|
[InlineData(1_000_000, CheckpointStrategy.None, 0)]
|
|
[InlineData(100, CheckpointStrategy.SqrtN, 10)]
|
|
[InlineData(16, CheckpointStrategy.Logarithmic, 4)]
|
|
public void CalculateCheckpointCount_ReturnsCorrectValue(long totalOperations, CheckpointStrategy strategy, int expectedCount)
|
|
{
|
|
// Act
|
|
var result = SpaceTimeCalculator.CalculateCheckpointCount(totalOperations, strategy);
|
|
|
|
// Assert
|
|
result.Should().Be(expectedCount);
|
|
}
|
|
|
|
[Fact]
|
|
public void CalculateCheckpointCount_WithInvalidInput_ThrowsException()
|
|
{
|
|
// Act & Assert
|
|
var action = () => SpaceTimeCalculator.CalculateCheckpointCount(-1, CheckpointStrategy.SqrtN);
|
|
action.Should().Throw<ArgumentOutOfRangeException>();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1_000_000_000, 1_000_000, 96.8)]
|
|
[InlineData(10_000, 10_000, 99.0)]
|
|
[InlineData(1_000_000, 100, 68.4)] // sqrt(100) = 10, savings = 1 - 10/sqrt(1M) = 99%
|
|
public void EstimateMemorySavings_ReturnsCorrectPercentage(long standardMemory, long dataSize, double expectedSavings)
|
|
{
|
|
// Act
|
|
var result = SpaceTimeCalculator.EstimateMemorySavings(standardMemory, dataSize);
|
|
|
|
// Assert
|
|
result.Should().BeApproximately(expectedSavings, 0.1);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1024, 8 * 1024 * 1024, 8, 64)] // 8MB L3 cache
|
|
[InlineData(100, 1 * 1024 * 1024, 8, 50)] // 1MB L3 cache
|
|
[InlineData(512, 256 * 1024, 4, 32)] // 256KB L2 cache
|
|
public void CalculateCacheBlockSize_ReturnsOptimalBlockSize(int matrixSize, long cacheSize, int elementSize, int expectedBlockSize)
|
|
{
|
|
// Act
|
|
var result = SpaceTimeCalculator.CalculateCacheBlockSize(matrixSize, cacheSize, elementSize);
|
|
|
|
// Assert
|
|
result.Should().BeLessThanOrEqualTo(expectedBlockSize);
|
|
result.Should().BeGreaterThan(0);
|
|
// Verify it fits in cache
|
|
var blockMemory = (long)result * result * elementSize;
|
|
blockMemory.Should().BeLessThanOrEqualTo(cacheSize / 2); // Use half cache for safety
|
|
}
|
|
|
|
[Fact]
|
|
public void CalculateCacheBlockSize_WithInvalidInputs_ThrowsException()
|
|
{
|
|
// Act & Assert
|
|
var action1 = () => SpaceTimeCalculator.CalculateCacheBlockSize(-1, 1024, 8);
|
|
action1.Should().Throw<ArgumentOutOfRangeException>();
|
|
|
|
var action2 = () => SpaceTimeCalculator.CalculateCacheBlockSize(100, -1, 8);
|
|
action2.Should().Throw<ArgumentOutOfRangeException>();
|
|
|
|
var action3 = () => SpaceTimeCalculator.CalculateCacheBlockSize(100, 1024, -1);
|
|
action3.Should().Throw<ArgumentOutOfRangeException>();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1_000_000, 1.5, 668)] // Time complexity O(n^1.5) -> sqrt(n)
|
|
[InlineData(10_000, 2.0, 100)] // Time complexity O(n^2) -> sqrt(n)
|
|
[InlineData(1_000_000, 1.0, 1_000)] // Time complexity O(n) -> sqrt(n)
|
|
public void CalculateSpaceForTimeComplexity_ReturnsOptimalSpace(long dataSize, double timeExponent, int expectedSpace)
|
|
{
|
|
// Act
|
|
var result = SpaceTimeCalculator.CalculateSpaceForTimeComplexity(dataSize, timeExponent);
|
|
|
|
// Assert
|
|
result.Should().BeCloseTo(expectedSpace, 10);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1000, 100)] // 1KB -> 100 bytes
|
|
[InlineData(1_000_000, 1_000)] // 1MB -> 1KB
|
|
[InlineData(1_000_000_000, 31_622)] // 1GB -> ~31KB
|
|
public void EstimateExternalStorageOverhead_ReturnsReasonableOverhead(long dataSize, long expectedOverhead)
|
|
{
|
|
// Act
|
|
var blockSize = SpaceTimeCalculator.CalculateSqrtInterval(dataSize);
|
|
var result = SpaceTimeCalculator.EstimateExternalStorageOverhead(dataSize, blockSize);
|
|
|
|
// Assert
|
|
result.Should().BeApproximately(expectedOverhead, expectedOverhead * 0.1);
|
|
// Overhead should be proportional to sqrt(n)
|
|
var ratio = (double)result / Math.Sqrt(dataSize);
|
|
ratio.Should().BeApproximately(1.0, 0.2);
|
|
}
|
|
} |