using NUnit.Framework; using VMdemo.Simulation; namespace VMdemo.Tests.EditMode { public class Step3TlbCacheTests { [Test] public void Constructor_CapacityLessThanOne_Throws() { Assert.Throws(() => new TlbCache(0)); Assert.Throws(() => 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)); } } }