public void TestCascadingEagerCache() { // We set one cell and two caches in cascade var cell = new Cell <int>(2); var cache1 = new EagerCache <int>(() => cell.Value + 1); var cache2 = new EagerCache <int>(() => cache1.Value * 2); Assert.AreEqual(1, cache1.BeaconCount); Assert.AreEqual(1, cache2.BeaconCount); Assert.AreEqual(6, cache2.Value); // Checking that setting the base cell invalidate all caches cell.Value = 3; Assert.AreEqual(1, cache1.BeaconCount); Assert.AreEqual(1, cache2.BeaconCount); Assert.AreEqual(8, cache2.Value); // Set cache1 to an arbitrary value. This should invalidate the cache2 cache1.Value = 34; Assert.AreEqual(0, cache1.BeaconCount); Assert.AreEqual(1, cache2.BeaconCount); Assert.AreEqual(68, cache2.Value); // Setting the cell to a different value should have no impact cell.Value++; Assert.AreEqual(0, cache1.BeaconCount); Assert.AreEqual(1, cache2.BeaconCount); Assert.AreEqual(68, cache2.Value); // Clearing the cache1 should invalidate cache2 cache1.Clear(); Assert.AreEqual(1, cache1.BeaconCount); Assert.AreEqual(1, cache2.BeaconCount); Assert.AreEqual(10, cache2.Value); }
public void TestBasicEagerCache() { // Setting a cell and a cache depending on that cell var cell = new Cell <int>(2); var count = 0; var cache = new EagerCache <int>(() => { count++; return(cell.Value * 2); }); // The cache is already initialized Assert.IsFalse(cache.IsSet); Assert.AreEqual(1, count); Assert.AreEqual(1, cache.BeaconCount); // Confirming the value var value = cache.Value; Assert.AreEqual(4, value); // Reading the value again doesn't trigger a recalculation value = cache.Value; Assert.AreEqual(4, value); Assert.IsFalse(cache.IsSet); Assert.AreEqual(1, count); Assert.AreEqual(1, cache.BeaconCount); // If we change the cell, the cache recalculates immediately cell.Value = 3; Assert.IsFalse(cache.IsSet); Assert.AreEqual(2, count); Assert.AreEqual(1, cache.BeaconCount); Assert.AreEqual(6, cache.Value); // Setting the cache cuts all dependencies cache.Value = 28; Assert.IsTrue(cache.IsSet); Assert.AreEqual(28, cache.Value); Assert.AreEqual(0, cache.BeaconCount); // This time, no dependencies on cell cell.Value++; Assert.AreEqual(28, cache.Value); // If we clear the cache, it recalculates its value based on its callback cache.Clear(); Assert.IsFalse(cache.IsSet); Assert.AreEqual(1, cache.BeaconCount); Assert.AreEqual(8, cache.Value); }
public void TestEagerCacheAndSnapshot() { // Creating the cell and monitor var beacon = new Beacon(); var snapshot = false; var cell = new Cell <int>(18); var cache = new EagerCache <int>(() => 11); var count = 0; int last = -1; var monitor = new Monitor(() => { beacon.Register(); var value1 = cell.Value; if (snapshot) { using (new Snapshot()) { last = cache.Value + value1 + 1; } } else { last = cache.Value - value1 + 1; } count++; }); // We're initially in the case where we don't use snapshots Assert.AreEqual(1, count); Assert.AreEqual(-6, last); Assert.AreEqual(1, cell.MonitorCount); Assert.AreEqual(1, cache.MonitorCount); // Monitor is bound to cell1, cache and the beacon Assert.AreEqual(3, monitor.BeaconCount); // If we change the cache, we get the monitor to rerun cache.Value = 23; Assert.AreEqual(2, count); Assert.AreEqual(6, last); // Same thing for the cell cell.Value = 7; Assert.AreEqual(3, count); Assert.AreEqual(17, last); // Now we turn the snapshotting on and signal it snapshot = true; beacon.Signal(); Assert.AreEqual(4, count); Assert.AreEqual(31, last); Assert.AreEqual(1, cell.MonitorCount); Assert.AreEqual(0, cache.MonitorCount); Assert.AreEqual(2, monitor.BeaconCount); // If we change cell, we still have the rerun cell.Value++; Assert.AreEqual(5, count); Assert.AreEqual(32, last); // But if we change cache, nothing happens cache.Value++; Assert.AreEqual(5, count); Assert.AreEqual(32, last); // We need to change cell or the lone beacon to get an update beacon.Signal(); Assert.AreEqual(6, count); Assert.AreEqual(33, last); }