131 lines
4.3 KiB
C#
131 lines
4.3 KiB
C#
using NUnit.Framework;
|
|
using VMdemo.Simulation;
|
|
|
|
namespace VMdemo.Tests.EditMode
|
|
{
|
|
public class Step3TlbCacheTests
|
|
{
|
|
[Test]
|
|
public void Constructor_CapacityLessThanOne_Throws()
|
|
{
|
|
Assert.Throws<System.ArgumentOutOfRangeException>(() => new TlbCache(0));
|
|
Assert.Throws<System.ArgumentOutOfRangeException>(() => new TlbCache(-1));
|
|
}
|
|
|
|
[Test]
|
|
public void TryLookup_Miss_ReturnsFalseAndCountsMiss()
|
|
{
|
|
var cache = new TlbCache(2);
|
|
|
|
var hit = cache.TryLookup(10UL, out var pfn);
|
|
|
|
Assert.IsFalse(hit);
|
|
Assert.That(pfn, Is.EqualTo(0UL));
|
|
Assert.That(cache.HitCount, Is.EqualTo(0));
|
|
Assert.That(cache.MissCount, Is.EqualTo(1));
|
|
}
|
|
|
|
[Test]
|
|
public void InsertOrUpdate_AndLookup_HitReturnsMappedPfn()
|
|
{
|
|
var cache = new TlbCache(2);
|
|
cache.InsertOrUpdate(10UL, 100UL);
|
|
|
|
var hit = cache.TryLookup(10UL, out var pfn);
|
|
|
|
Assert.IsTrue(hit);
|
|
Assert.That(pfn, Is.EqualTo(100UL));
|
|
Assert.That(cache.HitCount, Is.EqualTo(1));
|
|
Assert.That(cache.MissCount, Is.EqualTo(0));
|
|
}
|
|
|
|
[Test]
|
|
public void InsertOrUpdate_ExistingEntry_UpdatesPfnAndMovesToMostRecent()
|
|
{
|
|
var cache = new TlbCache(3);
|
|
cache.InsertOrUpdate(1UL, 11UL);
|
|
cache.InsertOrUpdate(2UL, 22UL);
|
|
cache.InsertOrUpdate(3UL, 33UL);
|
|
|
|
cache.InsertOrUpdate(1UL, 111UL);
|
|
|
|
var entries = cache.GetEntriesMostRecentFirst();
|
|
|
|
Assert.That(entries.Count, Is.EqualTo(3));
|
|
Assert.That(entries[0].Vpn, Is.EqualTo(1UL));
|
|
Assert.That(entries[0].Pfn, Is.EqualTo(111UL));
|
|
Assert.That(entries[1].Vpn, Is.EqualTo(3UL));
|
|
Assert.That(entries[2].Vpn, Is.EqualTo(2UL));
|
|
}
|
|
|
|
[Test]
|
|
public void OverCapacity_EvictsLeastRecentlyUsedEntry()
|
|
{
|
|
var cache = new TlbCache(3);
|
|
cache.InsertOrUpdate(1UL, 11UL);
|
|
cache.InsertOrUpdate(2UL, 22UL);
|
|
cache.InsertOrUpdate(3UL, 33UL);
|
|
|
|
cache.TryLookup(1UL, out _); // refresh 1 as MRU
|
|
cache.InsertOrUpdate(4UL, 44UL); // should evict 2
|
|
|
|
Assert.That(cache.Count, Is.EqualTo(3));
|
|
Assert.IsFalse(cache.TryLookup(2UL, out _));
|
|
Assert.IsTrue(cache.TryLookup(1UL, out var pfn1));
|
|
Assert.That(pfn1, Is.EqualTo(11UL));
|
|
|
|
var entries = cache.GetEntriesMostRecentFirst();
|
|
Assert.That(entries[0].Vpn, Is.EqualTo(1UL));
|
|
Assert.That(entries[1].Vpn, Is.EqualTo(4UL));
|
|
Assert.That(entries[2].Vpn, Is.EqualTo(3UL));
|
|
}
|
|
|
|
[Test]
|
|
public void Remove_ExistingAndMissingKeys_BehaveAsExpected()
|
|
{
|
|
var cache = new TlbCache(2);
|
|
cache.InsertOrUpdate(5UL, 55UL);
|
|
|
|
var removedFirst = cache.Remove(5UL);
|
|
var removedSecond = cache.Remove(5UL);
|
|
|
|
Assert.IsTrue(removedFirst);
|
|
Assert.IsFalse(removedSecond);
|
|
Assert.That(cache.Count, Is.EqualTo(0));
|
|
}
|
|
|
|
[Test]
|
|
public void Clear_ResetsEntriesAndCounters()
|
|
{
|
|
var cache = new TlbCache(2);
|
|
cache.InsertOrUpdate(1UL, 10UL);
|
|
cache.InsertOrUpdate(2UL, 20UL);
|
|
cache.TryLookup(1UL, out _);
|
|
cache.TryLookup(99UL, out _);
|
|
|
|
cache.Clear();
|
|
|
|
Assert.That(cache.Count, Is.EqualTo(0));
|
|
Assert.That(cache.HitCount, Is.EqualTo(0));
|
|
Assert.That(cache.MissCount, Is.EqualTo(0));
|
|
Assert.That(cache.GetEntriesMostRecentFirst().Count, Is.EqualTo(0));
|
|
}
|
|
|
|
[Test]
|
|
public void ContinuousLookup_TracksHitAndMissCountsAccurately()
|
|
{
|
|
var cache = new TlbCache(2);
|
|
cache.InsertOrUpdate(1UL, 10UL);
|
|
cache.InsertOrUpdate(2UL, 20UL);
|
|
|
|
cache.TryLookup(1UL, out _); // hit
|
|
cache.TryLookup(3UL, out _); // miss
|
|
cache.TryLookup(2UL, out _); // hit
|
|
cache.TryLookup(3UL, out _); // miss
|
|
|
|
Assert.That(cache.HitCount, Is.EqualTo(2));
|
|
Assert.That(cache.MissCount, Is.EqualTo(2));
|
|
}
|
|
}
|
|
}
|