public void CheckAutoFlush(int attempt) { const int maxAttempts = 10; const double autoFlushSeconds = 1d; // Don't retry if we don't have too. if (_success) { Assert.True(true); return; } // Detect errors on other threads. _unhandledException = null; ExceptionManager.UnhandledException += (source, args) => { if (!args.Exception.StackTrace.Contains(@"InMemoryCache", StringComparison.OrdinalIgnoreCase)) { return; } _unhandledException = args.Exception; }; var c = new InMemoryCache <string, DisposableMock>(TimeSpan.FromSeconds(autoFlushSeconds), s => { var mock = new DisposableMock { Id = s }; return(mock); }, true, false); const string key = @"TEST"; var x1 = c[key]; Assert.Equal(key, x1.Id); Thread.Sleep(TimeSpan.FromSeconds(autoFlushSeconds * 1.5d)); // x1 hasn't been disposed of because AutoFlush is off. Assert.False(x1.IsDisposed); var x2 = c[key]; // x1 will be disposed of now because it will have been cleared when the item was selected Assert.True(x1.IsDisposed); Assert.False(x2.IsDisposed); Assert.NotSame(x1, x2); // Now clear the cache and try again. c.Flush(); c.Clear(); c.Flush(); var flushCount = 0; c.Flushed += (a, b) => { Interlocked.Increment(ref flushCount); }; c.AutoDispose = true; c.AutoDispose = true; c.AutoFlush = true; c.AutoFlush = true; // The second call should take a different path - we can check in code coverage to ensure this is the case. Assert.True(c.AutoFlush); flushCount = 0; x1 = c[key]; Assert.Equal(key, x1.Id); Assert.False(x1.IsDisposed); var loops = 0; const int maxLoops = 5; Assert.Equal(c.AutoDispose, true); Assert.Equal(c.AutoFlush, true); // Allow multiple iterations in case there is some thread starvation. while ((loops++ < maxLoops) && (flushCount <= 0)) { Assert.Equal(c.AutoDispose, true); Assert.Equal(c.AutoFlush, true); // While we are asleep all expired members of the cache should be automatically disposed of Thread.Sleep(TimeSpan.FromSeconds(autoFlushSeconds)); Assert.Equal(c.AutoDispose, true); Assert.Equal(c.AutoFlush, true); } try { Assert.Null(_unhandledException); // Now x1 has been disposed, even though it hasn't been re-fetched. Assert.True(x1.IsDisposed, "Cached value has been disposed of."); // There has been a flush, without us needing to do anything. Assert.True(flushCount >= 1, "Auto-flush is responsible for disposing of the cached value."); _success = true; } catch { if (attempt >= maxAttempts) { // Allow a couple of attempts because occasionally it fails for no reason. throw; } } }
public void Update(IReadOnlyCollection <AssetInvestment> assetInvestments) { _cache.Clear(); _cache.Set(assetInvestments); }