Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions BlitzCache.Tests/BlitzCacheCore.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JunitXml.TestLogger" Version="6.1.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageReference Include="JunitXml.TestLogger" Version="7.1.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="nunit" Version="3.14.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="nunit" Version="4.4.0" />
<PackageReference Include="NUnit3TestAdapter" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
5 changes: 2 additions & 3 deletions BlitzCache.Tests/BlitzCacheLoggingServiceTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using BlitzCacheCore.Logging;
using BlitzCacheCore.Statistics;
using BlitzCacheCore.Tests.Helpers;
using NUnit.Framework;
using System;
Expand Down Expand Up @@ -161,7 +160,7 @@ public async Task WorksWithNoInstances()
await loggingService.StopAsync(cancellationToken);

var logs = testLogger.GetLogs();
Assert.AreEqual(2, logs.Count);
Assert.That(logs.Count, Is.EqualTo(2));
Assert.That(logs.Any(l => l.Contains("BlitzCache statistics logging started")), Is.True);
Assert.That(logs.Any(l => l.Contains("BlitzCache statistics logging stopped")), Is.True);
}
Expand All @@ -174,7 +173,7 @@ public void RegisterBlitzCacheInstanceIsIdempotent()
BlitzCacheLoggingService.Add(cacheInstance, "CacheInstance1", testInterval);
BlitzCacheLoggingService.Add(cacheInstance, "CacheInstance2", testInterval);

Assert.AreEqual(1, BlitzCacheLoggingService.GetInstances().Count, "Should only register once even with multiple calls");
Assert.That(BlitzCacheLoggingService.GetInstances().Count, Is.EqualTo(1), "Should only register once even with multiple calls");
}

private async Task GenerateCacheActivity()
Expand Down
16 changes: 8 additions & 8 deletions BlitzCache.Tests/CapacityAccountingInvariantTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,17 @@ public void Overfill_Cache_Accounting_Invariants_Hold_Sync()
long evictionCountAfter = after.EvictionCount;
long memoryAfter = after.ApproximateMemoryBytes;

Assert.Greater(evictionCountAfter, evictionCountBefore, "Eviction count should have increased");
Assert.GreaterOrEqual(memoryAfter, 0, "Approximate memory should never be negative");
Assert.LessOrEqual(memoryAfter, maxCacheSizeBytes, "Approximate memory should be within limit");
Assert.That(evictionCountAfter, Is.GreaterThan(evictionCountBefore), "Eviction count should have increased");
Assert.That(memoryAfter, Is.GreaterThanOrEqualTo(0), "Approximate memory should never be negative");
Assert.That(memoryAfter, Is.LessThanOrEqualTo(maxCacheSizeBytes), "Approximate memory should be within limit");

var inserted = totalInsert; // each call creates a new key
var netEntryIncrease = entryCountAfter - entryCountBefore;
var evicted = evictionCountAfter - evictionCountBefore;
var expectedEvicted = inserted - netEntryIncrease;

// Allow small race tolerance (+/-1) for timing of eviction callbacks
Assert.LessOrEqual(Math.Abs(evicted - expectedEvicted), 1, $"Eviction delta mismatch. Inserted={inserted} NetIncrease={netEntryIncrease} Evicted={evicted} Expected={expectedEvicted}");
Assert.That(Math.Abs(evicted - expectedEvicted), Is.LessThanOrEqualTo(1), $"Eviction delta mismatch. Inserted={inserted} NetIncrease={netEntryIncrease} Evicted={evicted} Expected={expectedEvicted}");
}

[Test]
Expand Down Expand Up @@ -90,15 +90,15 @@ public async Task Overfill_Cache_Accounting_Invariants_Hold_Async()
long evictionCountAfter = after.EvictionCount;
long memoryAfter = after.ApproximateMemoryBytes;

Assert.Greater(evictionCountAfter, evictionCountBefore, "Eviction count should have increased (async)");
Assert.GreaterOrEqual(memoryAfter, 0, "Approximate memory should never be negative (async)");
Assert.LessOrEqual(memoryAfter, maxCacheSizeBytes, "Approximate memory should be within limit (async)");
Assert.That(evictionCountAfter, Is.GreaterThan(evictionCountBefore), "Eviction count should have increased (async)");
Assert.That(memoryAfter, Is.GreaterThanOrEqualTo(0), "Approximate memory should never be negative (async)");
Assert.That(memoryAfter, Is.LessThanOrEqualTo(maxCacheSizeBytes), "Approximate memory should be within limit (async)");

var inserted = totalInsert;
var netEntryIncrease = entryCountAfter - entryCountBefore;
var evicted = evictionCountAfter - evictionCountBefore;
var expectedEvicted = inserted - netEntryIncrease;
Assert.LessOrEqual(Math.Abs(evicted - expectedEvicted), 1, $"Eviction delta mismatch (async). Inserted={inserted} NetIncrease={netEntryIncrease} Evicted={evicted} Expected={expectedEvicted}");
Assert.That(Math.Abs(evicted - expectedEvicted), Is.LessThanOrEqualTo(1), $"Eviction delta mismatch (async). Inserted={inserted} NetIncrease={netEntryIncrease} Evicted={evicted} Expected={expectedEvicted}");
}
}
}
12 changes: 6 additions & 6 deletions BlitzCache.Tests/CapacityEnforcerDoubleCountTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ public void ProactiveRemovals_AreCountedOnce()
var stats = cache.Statistics!;
// EntryCount + EvictionCount should be close to totalEntries (allow 1 off for timing races)
var accounted = stats.EntryCount + stats.EvictionCount;
Assert.Greater(stats.EvictionCount, 0, "Should have evictions after exceeding size limit");
Assert.LessOrEqual(stats.ApproximateMemoryBytes, maxCacheSizeBytes, "Approximate memory should be within limit");
Assert.LessOrEqual(Math.Abs(accounted - totalEntries), 1, $"Inconsistent accounting: entries({stats.EntryCount}) + evictions({stats.EvictionCount}) vs inserted({totalEntries})");
Assert.That(stats.EvictionCount, Is.GreaterThan(0), "Should have evictions after exceeding size limit");
Assert.That(stats.ApproximateMemoryBytes, Is.LessThanOrEqualTo(maxCacheSizeBytes), "Approximate memory should be within limit");
Assert.That(Math.Abs(accounted - totalEntries), Is.LessThanOrEqualTo(1), $"Inconsistent accounting: entries({stats.EntryCount}) + evictions({stats.EvictionCount}) vs inserted({totalEntries})");
}

[Test]
Expand Down Expand Up @@ -68,9 +68,9 @@ public async Task ProactiveRemovals_AreCountedOnce_Async()

var stats = cache.Statistics!;
var accounted = stats.EntryCount + stats.EvictionCount;
Assert.Greater(stats.EvictionCount, 0, "Should have evictions after exceeding size limit (async)");
Assert.LessOrEqual(stats.ApproximateMemoryBytes, maxCacheSizeBytes, "Approximate memory should be within limit (async)");
Assert.LessOrEqual(Math.Abs(accounted - totalEntries), 1, $"Inconsistent accounting (async): entries({stats.EntryCount}) + evictions({stats.EvictionCount}) vs inserted({totalEntries})");
Assert.That(stats.EvictionCount, Is.GreaterThan(0), "Should have evictions after exceeding size limit (async)");
Assert.That(stats.ApproximateMemoryBytes, Is.LessThanOrEqualTo(maxCacheSizeBytes), "Approximate memory should be within limit (async)");
Assert.That(Math.Abs(accounted - totalEntries), Is.LessThanOrEqualTo(1), $"Inconsistent accounting (async): entries({stats.EntryCount}) + evictions({stats.EvictionCount}) vs inserted({totalEntries})");
}
}
}
10 changes: 5 additions & 5 deletions BlitzCache.Tests/CapacityEvictionStrategyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ public void LargestFirst_Removes_Fewer_Items_To_Reclaim_Same_Bytes()
var sfStats = smallestFirstCache.Statistics!;
var lfStats = largestFirstCache.Statistics!;

Assert.Greater(sfStats.EvictionCount, 0, "Smallest-first should have evictions");
Assert.Greater(lfStats.EvictionCount, 0, "Largest-first should have evictions");
Assert.LessOrEqual(sfStats.ApproximateMemoryBytes, maxCacheSizeBytes);
Assert.LessOrEqual(lfStats.ApproximateMemoryBytes, maxCacheSizeBytes);
Assert.That(sfStats.EvictionCount, Is.GreaterThan(0), "Smallest-first should have evictions");
Assert.That(lfStats.EvictionCount, Is.GreaterThan(0), "Largest-first should have evictions");
Assert.That(sfStats.ApproximateMemoryBytes, Is.LessThanOrEqualTo(maxCacheSizeBytes));
Assert.That(lfStats.ApproximateMemoryBytes, Is.LessThanOrEqualTo(maxCacheSizeBytes));

// Largest-first should usually require fewer evictions (allow equality to avoid flakiness from overhead)
Assert.LessOrEqual(lfStats.EvictionCount, sfStats.EvictionCount, $"Expected largest-first to evict fewer or equal entries (sf={sfStats.EvictionCount}, lf={lfStats.EvictionCount})");
Assert.That(lfStats.EvictionCount, Is.LessThanOrEqualTo(sfStats.EvictionCount), $"Expected largest-first to evict fewer or equal entries (sf={sfStats.EvictionCount}, lf={lfStats.EvictionCount})");
}
}
}
24 changes: 12 additions & 12 deletions BlitzCache.Tests/ConcurrencyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public async Task ConcurrentAsyncCalls_ShouldExecuteOnlyOnce()
await AsyncRepeater.Go(TestConstants.ConcurrentOperationsCount, () => cache.BlitzGet(cacheKey, slowClassAsync.ProcessQuickly, 10000));

// Assert
Assert.AreEqual(1, slowClassAsync.Counter, $"Expensive async operation should only execute once despite {TestConstants.ConcurrentOperationsCount} concurrent calls");
Assert.That(slowClassAsync.Counter, Is.EqualTo(1), $"Expensive async operation should only execute once despite {TestConstants.ConcurrentOperationsCount} concurrent calls");
}

[Test]
Expand All @@ -53,10 +53,10 @@ public async Task ConcurrentCalls_ShouldWaitForFirstExecution_AndReceiveSameResu
var testResult = await AsyncRepeater.GoWithResults(TestConstants.SmallLoopCount, () => cache.BlitzGet(cacheKey, slowClassAsync.ProcessSlowly, TestConstants.LongTimeoutMs));

// Assert
Assert.AreEqual(1, slowClassAsync.Counter, "Expensive operation should only execute once");
Assert.AreEqual(TestConstants.SmallLoopCount, testResult.ResultCount, $"Should have {TestConstants.SmallLoopCount} results (one per concurrent call)");
Assert.AreEqual(1, testResult.UniqueResultCount, "All calls should receive the same result");
Assert.IsTrue(testResult.AllResultsIdentical, "All results should be identical");
Assert.That(slowClassAsync.Counter, Is.EqualTo(1), "Expensive operation should only execute once");
Assert.That(testResult.ResultCount, Is.EqualTo(TestConstants.SmallLoopCount), $"Should have {TestConstants.SmallLoopCount} results (one per concurrent call)");
Assert.That(testResult.UniqueResultCount, Is.EqualTo(1), "All calls should receive the same result");
Assert.That(testResult.AllResultsIdentical, Is.True, "All results should be identical");
}

[Test]
Expand All @@ -71,8 +71,8 @@ public async Task ConcurrentAsyncCalls_WithRealisticTiming_ShouldQueue()
staggerDelayMs: TestConstants.VeryShortTimeoutMs);

// Assert
Assert.AreEqual(1, slowClassAsync.Counter, "Only one execution should have occurred");
Assert.IsTrue(testResult.AllResultsIdentical, "All results should be identical");
Assert.That(slowClassAsync.Counter, Is.EqualTo(1), "Only one execution should have occurred");
Assert.That(testResult.AllResultsIdentical, Is.True, "All results should be identical");
Assert.That(testResult.ElapsedMilliseconds, Is.LessThan(1300),
"Total time should be close to single execution time, indicating queuing worked");
}
Expand All @@ -90,7 +90,7 @@ public void SyncConcurrentCalls_ShouldExecuteOnlyOnce()
});

// Assert
Assert.AreEqual(1, slowClass.Counter, $"Expensive sync operation should only execute once despite {TestConstants.ConcurrentOperationsCount} concurrent calls");
Assert.That(slowClass.Counter, Is.EqualTo(1), $"Expensive sync operation should only execute once despite {TestConstants.ConcurrentOperationsCount} concurrent calls");
}

[Test]
Expand All @@ -103,10 +103,10 @@ public void SyncConcurrentCalls_ShouldAllReceiveSameResult()
var testResult = AsyncRepeater.GoSyncWithResults(8, () => cache.BlitzGet(cacheKey, slowClass.ProcessSlowly, 10000));

// Assert
Assert.AreEqual(1, slowClass.Counter, "Expensive sync operation should only execute once");
Assert.AreEqual(8, testResult.ResultCount, "Should have 8 results");
Assert.AreEqual(1, testResult.UniqueResultCount, "All sync calls should receive the same result");
Assert.IsTrue(testResult.AllResultsIdentical, "All results should be identical");
Assert.That(slowClass.Counter, Is.EqualTo(1), "Expensive sync operation should only execute once");
Assert.That(testResult.ResultCount, Is.EqualTo(8), "Should have 8 results");
Assert.That(testResult.UniqueResultCount, Is.EqualTo(1), "All sync calls should receive the same result");
Assert.That(testResult.AllResultsIdentical, Is.True, "All results should be identical");
}

[Test]
Expand Down
Loading
Loading