public async Task CacheData_WhenCacheIsUnavailable_ReturnDefaultValueAndCheckConnectionTimeout() { // Arrange var tempCache = new CacheAccessor(new CacheConfig { ConnectionString = "invalid_connection_string" }); // configured with an incorrect server and will return null on error // Act var testValue = await tempCache.GetAsync <string>("lovely_non_existent_item"); Thread.Sleep(50); var status1 = tempCache.Status; await tempCache.InitialiseIfNecessaryAsync(); var status2 = tempCache.Status; // Assert Assert.IsNull(testValue); Assert.AreEqual(CacheAccessor.State.Connecting, status1); Assert.AreEqual(CacheAccessor.State.NotConnected, status2); Assert.IsTrue(tempCache.LastConnectionElapsedMilliseconds > 0 && tempCache.LastConnectionElapsedMilliseconds < 12000, "The connection timeout should be more than 0 but less than 12 seconds. Actual timeouts are never inline with the stated max timeout, so for 10ms, the actual timeout is ~5s"); }
public async Task Cache_NonDist_Test_That_Cache_Delete_Key_Works_OK() { // ARRANGE var ca1 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true, IsCentralCacheEnabled = false }); await ca1.InitialiseIfNecessaryAsync(); var KEY = CreateGuid(); var VALUE = CreateGuid(); // ACT await ca1.SetAsync(KEY, VALUE); // set the value await ca1.DeleteAsync(KEY); var evt1 = ca1.LastCachingEvent; var v2 = await ca1.GetWithMetaDataAsync <string>(KEY); // ASSERT Assert.IsNull(v2.Data); Assert.IsTrue(evt1 == eCacheEvent.KeyDeletedInMemory); Assert.IsTrue(ca1.LastCachingEvent == eCacheEvent.KeyValueGotFromMemoryAttempt); }
public async Task Cache_Dist_Test_InMemoryPerformance() { // Arrange var cacheAccessor1 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true }); var cacheAccessor2 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true }); await cacheAccessor1.InitialiseIfNecessaryAsync(); await cacheAccessor2.InitialiseIfNecessaryAsync(); var bigList = new List <int>(Enumerable.Range(0, 100000)); await cacheAccessor1.SetAsync("biglist", bigList); var v1 = await cacheAccessor1.GetWithMetaDataAsync <List <int> >("biglist"); // should return instantly from the originating cache accessor (it's in-memory) var v2 = await cacheAccessor2.GetWithMetaDataAsync <List <int> >("biglist"); // should return with some delay from the new cache accessor (it's on the central cache) var v3 = await cacheAccessor2.GetWithMetaDataAsync <List <int> >("biglist"); // should return instantly, having put the object into in-memory cache the last time it was called Assert.IsNotNull(v1.Data); Assert.IsTrue(v1.IsFromInMemoryCache, "Shoulda oughta a bin from the in-memory cache"); Assert.IsNotNull(v2.Data); Assert.IsTrue(v2.IsFromCentralCacheServer || v2.IsFromInMemoryCache, "Shoulda oughta a bin from the central / memory cache"); Assert.IsNotNull(v3.Data); Assert.IsTrue(v3.IsFromInMemoryCache, "Shoulda oughta a bin from the in-memory cache"); }
public async Task Cache_TestImmutableRefTypeObjectDoesNOTCauseAnException() { var ca1 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true, IsCentralCacheEnabled = false }); var ops = ca1; await ca1.InitialiseIfNecessaryAsync(); await ops.SetAsync(Guid.NewGuid().ToString(), "this object is immutable", null); }
public async Task Cache_TestValueTypeObject_Roundtrips() { var cache = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true, IsCentralCacheEnabled = false }); var ops = cache; var key = Guid.NewGuid().ToString("N"); var value = 4658792; await cache.InitialiseIfNecessaryAsync(); await ops.SetAsync(key, value, null); var value2 = await cache.GetAsync <int>(key); Assert.AreEqual(value, value2); }
public async Task Cache_TestWithoutRedis() { var cache = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true, IsCentralCacheEnabled = false }); var ops = cache; var key = Guid.NewGuid().ToString("N"); var value = new Employee(3456, "test"); await cache.InitialiseIfNecessaryAsync(); await ops.SetAsync(key, value, null); var value2 = await cache.GetAsync <Employee>(key); Assert.AreEqual(cache.AuditLog[0].CachingEvent, eCacheEvent.KeySetInMemory); Assert.AreEqual(cache.AuditLog[1].CachingEvent, eCacheEvent.KeyValueGotFromMemoryAttempt); Assert.AreEqual(cache.AuditLog[2].CachingEvent, eCacheEvent.KeyValueGotFromMemory); }
public async Task Cache_TestCustomObjects_AreNotClones() { var cache = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true, IsCentralCacheEnabled = false }); var ops = cache; var key = Guid.NewGuid().ToString("N"); var value = new Employee(3456, "test"); await cache.InitialiseIfNecessaryAsync(); await ops.SetAsync(key, value, null); var value2 = await cache.GetAsync <Employee>(key); Assert.AreEqual(value.Id, value2.Id); Assert.AreEqual(value.Name, value2.Name); Assert.AreNotEqual(value, value2); }
public async Task Cache_TestDictionaryObject_Roundtrips() { var cache = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true, IsCentralCacheEnabled = false }); var ops = cache; var key = Guid.NewGuid().ToString("N"); var value = (IDictionary <string, string>) new Dictionary <string, string> { { "k", "v" } }; await cache.InitialiseIfNecessaryAsync(); await ops.SetAsync(key, value, null); var value2 = await cache.GetAsync <Dictionary <string, string> >(key); Assert.AreEqual(value, value2); }
public async Task Cache_TestEnumerableObject_Roundtrips() { var cache = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true, IsCentralCacheEnabled = false }); var ops = cache; var key = Guid.NewGuid().ToString("N"); var value = (IEnumerable) new List <string> { "this is a thing in the list" }; await cache.InitialiseIfNecessaryAsync(); await ops.SetAsync(key, value, null); var value2 = await cache.GetAsync <IEnumerable>(key); Assert.AreEqual(value, value2); }
public async Task Cache_Dist_Test_Caching_Byte_Arrays() { // ARRANGE var ca1 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true }); var ca2 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true }); await ca1.InitialiseIfNecessaryAsync(); await ca2.InitialiseIfNecessaryAsync(); var KEY1 = CreateGuid(); var VALUE1 = new byte[] { 32, 34, 55 }; var KEY2 = CreateGuid(); var VALUE2 = new byte[] { 1, 11, 33 }; // ACT await ca1.SetAsync(KEY1, VALUE1); // set the value await ca2.WaitForEvent(eCacheEvent.KeySetInMemory); await ca2.SetAsync(KEY2, VALUE2); // set the value await ca1.WaitForEvent(eCacheEvent.KeySetInMemory); var data1 = await ca2.GetWithMetaDataAsync <byte[]>(KEY1); var data2 = await ca1.GetWithMetaDataAsync <byte[]>(KEY2); Assert.AreEqual(VALUE1.Length, data1.Data.Length); Assert.AreEqual(VALUE2.Length, data2.Data.Length); Assert.AreEqual(VALUE1[0], data1.Data[0]); Assert.AreEqual(VALUE1[1], data1.Data[1]); Assert.AreEqual(VALUE1[2], data1.Data[2]); Assert.AreEqual(VALUE2[0], data2.Data[0]); Assert.AreEqual(VALUE2[1], data2.Data[1]); Assert.AreEqual(VALUE2[2], data2.Data[2]); }
public async Task Cache_Dist_Test_That_Cache_Expiry_Works_OK() { // ARRANGE var ca1 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true }); var ca2 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true }); await ca1.InitialiseIfNecessaryAsync(); await ca2.InitialiseIfNecessaryAsync(); var KEY = CreateGuid(); var VALUE = CreateGuid(); // ACT await ca1.SetAsync(KEY, VALUE, TimeSpan.FromSeconds(5)); await ca2.WaitForEvent(eCacheEvent.KeySetInMemory); var v1 = await ca2.GetWithMetaDataAsync <string>(KEY); var v2 = await ca1.GetWithMetaDataAsync <string>(KEY); await Task.Delay(5000); var v3 = await ca2.GetWithMetaDataAsync <string>(KEY); var v4 = await ca1.GetWithMetaDataAsync <string>(KEY); Assert.IsNotNull(v1.Data); Assert.IsNotNull(v2.Data); Assert.IsTrue(v1.IsFromInMemoryCache); Assert.IsTrue(v2.IsFromInMemoryCache); Assert.IsNull(v3.Data); Assert.IsNull(v4.Data); Assert.IsTrue(v3.IsFromCentralCacheServer); Assert.IsTrue(v4.IsFromCentralCacheServer); }
public async Task Cache_Dist_Test_That_Cache_Delete_Key_Works_OK() { // ARRANGE var ca1 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true }); var ca2 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true }); await ca1.InitialiseIfNecessaryAsync(); await ca2.InitialiseIfNecessaryAsync(); var KEY = CreateGuid(); var VALUE = CreateGuid(); // ACT await ca1.SetAsync(KEY, VALUE); // set the value // Wait for propagation to ca2 await ca2.WaitForEvent(eCacheEvent.KeySetInMemory); var v1 = await ca2.GetWithMetaDataAsync <string>(KEY); await ca2.DeleteAsync(KEY); var propagationTimeInMS = await ca1.WaitForEvent(eCacheEvent.KeyDeletedInMemory); var v2 = await ca1.GetWithMetaDataAsync <string>(KEY); var v3 = await ca2.GetWithMetaDataAsync <string>(KEY); // ASSERT Assert.IsNotNull(v1.Data); Assert.IsTrue(v1.IsFromInMemoryCache); Assert.IsNull(v2.Data); Assert.IsTrue(v2.IsFromCentralCacheServer); Assert.IsNull(v3.Data); Assert.IsTrue(v3.IsFromCentralCacheServer); }
public async Task Cache_Dist_Test_LargeVolumeOfCacheAccessors() { // Arrange var inits = new List <Task>(); var caches = new List <CacheAccessor>(); const int MAX_CACHES = 20; // Create MAX_CACHES cache accessors and therefore MAX_CACHES connections to redis for (int i = 0; i < MAX_CACHES; i++) { var c = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true }); inits.Add(c.InitialiseIfNecessaryAsync()); caches.Add(c); } await Task.WhenAll(inits.ToArray()); // wait for initialisation var cacheOne = caches.First(); var KEY = Key(); var VALUE = new List <int>(Enumerable.Range(0, 1000)); // Clear audit logs of all caches caches.ForEach(x => x.AuditLog.Clear()); // ACT await cacheOne.SetAsync(KEY, VALUE); var valueFromOriginator = await cacheOne.GetWithMetaDataAsync <List <int> >(KEY); // Wait until the value has propagated var propagationTasks = new List <Task>(); foreach (var cacher in caches) { if (cacher == cacheOne) { continue; // ignore the originating cacher } propagationTasks.Add(cacher.WaitForEvent(eCacheEvent.KeySetInMemory, 60000)); } await Task.WhenAll(propagationTasks.ToArray()); var values = new List <CacheResponseDto <List <int> > >(); for (int i = 0; i < MAX_CACHES; i++) { var currentCache = caches[i]; values.Add(await currentCache.GetWithMetaDataAsync <List <int> >(KEY)); } // ASSERT Assert.AreEqual(VALUE, valueFromOriginator.Data); Assert.IsTrue(valueFromOriginator.IsFromInMemoryCache); foreach (var item in values) { Assert.AreEqual(VALUE, item.Data); Assert.IsTrue(item.IsFromInMemoryCache); } for (int i = 1; i < MAX_CACHES; i++) { Assert.IsTrue(caches[i].AuditLog.First().CachingEvent == eCacheEvent.KeySetInMemory); } }
public async Task Cache_Dist_TestKeyValuePairPropagation() { // Arrange var KEY = Key(); var VALUE = CreateGuid(); var cacheAccessor1 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true }); var cacheAccessor2 = new CacheAccessor(new CacheConfig { IsAuditingEnabled = true }); await cacheAccessor1.InitialiseIfNecessaryAsync(); await cacheAccessor2.InitialiseIfNecessaryAsync(); cacheAccessor1.AuditLog.Clear(); cacheAccessor2.AuditLog.Clear(); // Act var v1 = await cacheAccessor1.GetWithMetaDataAsync <string>(KEY); await cacheAccessor1.SetAsync(KEY, VALUE, TimeSpan.FromMinutes(2)); await Task.Delay(300); var logOfCA2 = cacheAccessor2.AuditLog.ToArray(); var v2 = await cacheAccessor2.GetWithMetaDataAsync <string>(KEY); var v3 = await cacheAccessor2.GetWithMetaDataAsync <string>(KEY); var cacheAccessor3 = new CacheAccessor(new CacheConfig()); await cacheAccessor3.InitialiseIfNecessaryAsync(); var v6 = await cacheAccessor3.GetWithMetaDataAsync <string>(KEY); var v7 = await cacheAccessor3.GetWithMetaDataAsync <string>(KEY); await cacheAccessor2.DeleteAsync(KEY); var v4_1 = await cacheAccessor1.GetWithMetaDataAsync <string>(KEY); var v5_1 = await cacheAccessor2.GetWithMetaDataAsync <string>(KEY); await Task.Delay(300); var v4 = await cacheAccessor1.GetWithMetaDataAsync <string>(KEY); var v5 = await cacheAccessor2.GetWithMetaDataAsync <string>(KEY); Assert.IsTrue(logOfCA2.First().CachingEvent == eCacheEvent.KeySetInMemory, "The next audit event should have been to receive the key update message"); Assert.IsTrue(v1.IsFromCentralCacheServer, "Trying to get something that isn't set, should _AT_LEAST_ try the central cache"); Assert.IsTrue(v2.IsFromInMemoryCache, "Getting an item after setting it should mean that the in-memory cache has had time to catch up"); Assert.IsTrue(v3.IsFromInMemoryCache, "The value should have propagated to cache accessor"); Assert.IsNull(v4.Data, "The value should be null"); Assert.IsNull(v5.Data, "The value should be null"); Assert.IsTrue(v4.IsFromCentralCacheServer, "If a value is null, it should have tried the central cache server"); Assert.IsTrue(v5.IsFromCentralCacheServer, "If a value is null, it should have tried the central cache server"); Assert.IsNotNull(v6.Data, "The data shouldn't be null"); Assert.IsTrue(v6.IsFromCentralCacheServer, "The value should have been retrieved from the central server"); Assert.IsNotNull(v7.Data, "The data shouldn't be null"); Assert.AreEqual(VALUE, v7.Data); Assert.IsTrue(v7.IsFromInMemoryCache, "The value should have been retrieved from the memory cache"); // This test is too subjective for the build server // Assert.IsTrue(v7.ElapsedMilliseconds < v6.ElapsedMilliseconds, "It should have been quicker to get the value the second time"); }