public void ResetChunkedDoesNothingIfEntryDoesNotExist() { // given var keyOne = new BeaconKey(1, 0); var keyTwo = new BeaconKey(666, 0); var target = new BeaconCache(logger); target.AddActionData(keyOne, 1000L, "a"); target.AddActionData(keyOne, 1001L, "iii"); target.AddEventData(keyOne, 1000L, "b"); target.AddEventData(keyOne, 1001L, "jjj"); target.PrepareDataForSending(keyOne); // do same step we'd do when we send the target.GetNextBeaconChunk(keyOne, "prefix", 10, '&'); // data has been copied, but still add some new event & action data target.AddActionData(keyOne, 6666L, "123"); target.AddEventData(keyOne, 6666L, "987"); var notifyCount = 0; target.RecordAdded += (s, a) => { notifyCount += 1; }; // and when resetting the previously copied data target.ResetChunkedData(keyTwo); // then Assert.That(target.NumBytesInCache, Is.EqualTo(12L)); Assert.That(notifyCount, Is.EqualTo(0)); }
public void ExecuteEvictionDoesNotLogIfStrategyIsDisabledAndInfoIsDisabledInLogger() { // given var configuration = MockBeaconCacheConfig(0L, 1000L, 2000L); var target = CreateTimeEvictionStrategyWith(configuration); var key = new BeaconKey(0, 0); mockLogger.IsInfoEnabled.Returns(false); // when executing the first time target.Execute(); // then _ = mockLogger.Received(1).IsInfoEnabled; mockLogger.DidNotReceiveWithAnyArgs().Info(string.Empty); mockBeaconCache.DidNotReceiveWithAnyArgs().EvictRecordsByAge(key, 0L); // and when executing a second time target.Execute(); // then _ = mockLogger.Received(2).IsInfoEnabled; mockLogger.DidNotReceiveWithAnyArgs().Info(string.Empty); mockBeaconCache.DidNotReceiveWithAnyArgs().EvictRecordsByAge(key, 0L); }
public void RemoveChunkedDataDoesNothingIfCalledWithNonExistingBeaconId() { // given var keyOne = new BeaconKey(1, 0); var keyTwo = new BeaconKey(42, 0); var target = new BeaconCache(logger); target.AddActionData(keyOne, 1000L, "a"); target.AddActionData(keyOne, 1001L, "iii"); target.AddActionData(keyTwo, 2000L, "z"); target.AddEventData(keyOne, 1000L, "b"); target.AddEventData(keyOne, 1001L, "jjj"); target.PrepareDataForSending(keyOne); // when retrieving the first chunk and removing the wrong beacon chunk target.GetNextBeaconChunk(keyOne, "prefix", 10, '&'); target.RemoveChunkedData(keyTwo); // then Assert.That(target.GetActionsBeingSent(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a"), new BeaconCacheRecord(1001L, "iii") })); var expectedEventRecords = new[] { new BeaconCacheRecord(1000L, "b"), new BeaconCacheRecord(1001L, "jjj") }; foreach (var record in expectedEventRecords) { record.MarkForSending(); } Assert.That(target.GetEventsBeingSent(keyOne), Is.EqualTo(expectedEventRecords)); }
public void ResetChunkedRestoresCacheSize() { // given var key = new BeaconKey(1, 0); var target = new BeaconCache(logger); target.AddActionData(key, 1000L, "a"); target.AddActionData(key, 1001L, "iii"); target.AddEventData(key, 1000L, "b"); target.AddEventData(key, 1001L, "jjj"); // do same step we'd do when we send the target.GetNextBeaconChunk(key, "prefix", 10, '&'); // data has been copied, but still add some new event & action data target.AddActionData(key, 6666L, "123"); target.AddEventData(key, 6666L, "987"); // and when resetting the previously copied data target.ResetChunkedData(key); // then Assert.That(target.NumBytesInCache, Is.EqualTo(28L)); }
public void DeleteCacheEntriesDoesNothingIfGivenBeaconIdIsNotInCache() { // given var keyOne = new BeaconKey(1, 0); var keyTwo = new BeaconKey(42, 0); var keyThree = new BeaconKey(666, 0); var target = new BeaconCache(logger); target.AddActionData(keyOne, 1000L, "a"); target.AddActionData(keyTwo, 1000L, "z"); target.AddEventData(keyOne, 1000L, "iii"); var notifyCount = 0; target.RecordAdded += (s, a) => { notifyCount += 1; }; var cachedSize = target.NumBytesInCache; // when target.DeleteCacheEntry(keyThree); // then Assert.That(target.BeaconKeys, Is.EqualTo(new HashSet <BeaconKey> { keyOne, keyTwo })); Assert.That(target.NumBytesInCache, Is.EqualTo(cachedSize)); Assert.That(notifyCount, Is.EqualTo(0)); }
public void GetNextBeaconChunkRetrievesNextChunk() { // given var keyOne = new BeaconKey(1, 0); var keyTwo = new BeaconKey(42, 0); var target = new BeaconCache(logger); target.AddActionData(keyOne, 1000L, "a"); target.AddActionData(keyOne, 1001L, "iii"); target.AddActionData(keyTwo, 2000L, "z"); target.AddEventData(keyOne, 1000L, "b"); target.AddEventData(keyOne, 1001L, "jjj"); target.PrepareDataForSending(keyOne); // when retrieving the first chunk var obtained = target.GetNextBeaconChunk(keyOne, "prefix", 10, '&'); // then Assert.That(obtained, Is.EqualTo("prefix&b&jjj")); // then Assert.That(target.GetActionsBeingSent(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a"), new BeaconCacheRecord(1001L, "iii") })); var expectedEventRecords = new[] { new BeaconCacheRecord(1000L, "b"), new BeaconCacheRecord(1001L, "jjj") }; foreach (var record in expectedEventRecords) { record.MarkForSending(); } Assert.That(target.GetEventsBeingSent(keyOne), Is.EqualTo(expectedEventRecords)); }
public void ExecuteEvictionStopsIfNumBytesInCacheFallsBelowLowerBoundBetweenTwoBeacons() { // given var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L); var target = CreateSpaceEvictionStrategyWith(configuration); mockBeaconCache.NumBytesInCache.Returns(configuration.CacheSizeUpperBound + 1, //should run method configuration.CacheSizeUpperBound, // first iteration configuration.CacheSizeUpperBound, // first iteration configuration.CacheSizeUpperBound, // first iteration (configuration.CacheSizeUpperBound + configuration.CacheSizeLowerBound) / 2, // second iteration (configuration.CacheSizeUpperBound + configuration.CacheSizeLowerBound) / 2, // second iteration configuration.CacheSizeLowerBound, // stops already (second iteration) 0L); // just for safety var keyOne = new BeaconKey(42, 0); var keyTwo = new BeaconKey(1, 0); mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> { keyOne, keyTwo }); // when executing target.Execute(); // then _ = mockBeaconCache.Received(8).NumBytesInCache; mockBeaconCache.Received(3).EvictRecordsByNumber(Arg.Any <BeaconKey>(), 1); }
public void ExecuteEvictionIsStoppedIfThreadGetsInterrupted() { // given var shutdown = false; isShutdownFunc = () => shutdown; var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L); var target = CreateTimeEvictionStrategyWith(configuration); var keyOne = new BeaconKey(1, 0); var keyTwo = new BeaconKey(42, 0); mockTimingProvider.ProvideTimestampInMilliseconds().Returns(1000L, 2099L); mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> { keyOne, keyTwo }); mockBeaconCache.EvictRecordsByAge(Arg.Any <BeaconKey>(), Arg.Any <long>()) .Returns(x => { shutdown = true; return(2); }); // when target.Execute(); // then verify interactions _ = mockBeaconCache.Received(1).BeaconKeys; mockBeaconCache.Received(1).EvictRecordsByAge(Arg.Any <BeaconKey>(), 2099L - configuration.MaxRecordAge); }
public void ExecuteEvictionDoesNotLogEvictionResultIfDebugIsDisabled() { // given var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L); var target = CreateSpaceEvictionStrategyWith(configuration); mockBeaconCache.NumBytesInCache.Returns(configuration.CacheSizeUpperBound + 1, configuration.CacheSizeUpperBound + 1, configuration.CacheSizeUpperBound + 1, configuration.CacheSizeUpperBound + 1, 0L); var keyOne = new BeaconKey(42, 0); var keyTwo = new BeaconKey(1, 0); mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> { keyOne, keyTwo }); mockBeaconCache.EvictRecordsByNumber(keyTwo, Arg.Any <int>()).Returns(5); mockBeaconCache.EvictRecordsByNumber(keyOne, Arg.Any <int>()).Returns(1); mockLogger.IsDebugEnabled.Returns(false); // when executing the first time target.Execute(); // then _ = mockLogger.Received(3).IsDebugEnabled; mockLogger.DidNotReceive().Debug(Arg.Any <string>()); }
public void ExecuteEvictionRunsUntilTheCacheSizeIsLessThanOrEqualToLowerBound() { // given var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L); var target = CreateSpaceEvictionStrategyWith(configuration); mockBeaconCache.NumBytesInCache.Returns(configuration.CacheSizeUpperBound + 1, //should run method configuration.CacheSizeUpperBound, // first iteration configuration.CacheSizeUpperBound, // first iteration configuration.CacheSizeUpperBound, // first iteration (configuration.CacheSizeUpperBound + configuration.CacheSizeLowerBound) / 2, // second iteration (configuration.CacheSizeUpperBound + configuration.CacheSizeLowerBound) / 2, // second iteration (configuration.CacheSizeUpperBound + configuration.CacheSizeLowerBound) / 2, // second iteration configuration.CacheSizeLowerBound, // stops already 0L); // just for safety var keyOne = new BeaconKey(42, 0); var keyTwo = new BeaconKey(1, 0); mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> { keyOne, keyTwo }); // when executing the first time target.Execute(); // then _ = mockBeaconCache.Received(8).NumBytesInCache; mockBeaconCache.Received(2).EvictRecordsByNumber(keyTwo, 1); mockBeaconCache.Received(2).EvictRecordsByNumber(keyOne, 1); }
public void ExecuteEvictionLogsEvictionResultIfDebugIsEnabled() { // given var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L); var target = CreateSpaceEvictionStrategyWith(configuration); mockBeaconCache.NumBytesInCache.Returns(configuration.CacheSizeUpperBound + 1, configuration.CacheSizeUpperBound + 1, configuration.CacheSizeUpperBound + 1, configuration.CacheSizeUpperBound + 1, 0L); var keyOne = new BeaconKey(42, 0); var keyTwo = new BeaconKey(1, 0); mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> { keyOne, keyTwo }); mockBeaconCache.EvictRecordsByNumber(keyTwo, Arg.Any <int>()).Returns(5); mockBeaconCache.EvictRecordsByNumber(keyOne, Arg.Any <int>()).Returns(1); mockLogger.IsDebugEnabled.Returns(true); // when executing the first time target.Execute(); // then _ = mockLogger.Received(3).IsDebugEnabled; mockLogger.Received(1).Debug($"{target.GetType().Name} - Removed 1 records from Beacon with key {keyOne}"); mockLogger.Received(1).Debug($"{target.GetType().Name} - Removed 5 records from Beacon with key {keyTwo}"); }
public void ExecuteEvictionCallsCacheMethodForEachBeacon() { // given var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L); var target = CreateSpaceEvictionStrategyWith(configuration); mockBeaconCache.NumBytesInCache.Returns(configuration.CacheSizeUpperBound + 1, configuration.CacheSizeUpperBound + 1, configuration.CacheSizeUpperBound + 1, configuration.CacheSizeUpperBound + 1, 0L); var keyOne = new BeaconKey(42, 0); var keyTwo = new BeaconKey(1, 0); mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> { keyOne, keyTwo }); // when executing the first time target.Execute(); // then _ = mockBeaconCache.Received(5).NumBytesInCache; mockBeaconCache.Received(1).EvictRecordsByNumber(keyTwo, 1); mockBeaconCache.Received(1).EvictRecordsByNumber(keyOne, 1); }
public virtual string GetNextBeaconChunk(BeaconKey beaconKey, string chunkPrefix, int maxSize, char delimiter) { var entry = GetCachedEntry(beaconKey); if (entry == null) { // a cache entry for the given beaconKey does not exist return null; } if (entry.NeedsDataCopyBeforeChunking) { // both entries are null, prepare data for sending long numBytes; try { entry.Lock(); numBytes = entry.TotalNumBytes; entry.CopyDataForChunking(); } finally { entry.Unlock(); } // assumption: sending will work fine, and everything we copied will be removed quite soon Interlocked.Add(ref cacheSizeInBytes, -1L * numBytes); } // data for chunking is available return entry.GetChunk(chunkPrefix, maxSize, delimiter); }
public int EvictRecordsByNumber(BeaconKey beaconKey, int numRecords) { var entry = GetCachedEntry(beaconKey); if (entry == null) { // already removed return 0; } int numRecordsRemoved; try { entry.Lock(); numRecordsRemoved = entry.RemoveOldestRecords(numRecords); } finally { entry.Unlock(); } if (logger.IsDebugEnabled) { var logString = new StringBuilder(GetType().Name) .Append(" EvictRecordsByNumber(sn=").Append(beaconKey.BeaconId.ToInvariantString()) .Append(", seq=").Append(beaconKey.BeaconSeqNo.ToInvariantString()) .Append(", numRecords=").Append(numRecords.ToInvariantString()) .Append(")") .Append(" has evicted ").Append(numRecordsRemoved.ToInvariantString()).Append(" records") .ToString(); logger.Debug(logString); } return numRecordsRemoved; }
public void DeleteCacheEntry(BeaconKey beaconKey) { if (logger.IsDebugEnabled) { var logString = new StringBuilder(GetType().Name) .Append(" DeleteCacheEntry(sn=").Append(beaconKey.BeaconId.ToInvariantString()) .Append(", seq=").Append(beaconKey.BeaconSeqNo.ToInvariantString()) .Append(")") .ToString(); logger.Debug(logString); } BeaconCacheEntry entry = null; try { globalCacheLock.EnterWriteLock(); if (beacons.ContainsKey(beaconKey)) { entry = beacons[beaconKey]; beacons.Remove(beaconKey); } } finally { globalCacheLock.ExitWriteLock(); } if (entry != null) { Interlocked.Add(ref cacheSizeInBytes, -1L * entry.TotalNumBytes); } }
public void ExecuteEvictionLogsTheNumberOfRecordsRemoved() { // given var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L); var target = CreateTimeEvictionStrategyWith(configuration); var keyOne = new BeaconKey(1, 0); var keyTwo = new BeaconKey(42, 0); mockTimingProvider.ProvideTimestampInMilliseconds().Returns(1000L, 2099L); mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> { keyOne, keyTwo }); mockBeaconCache.EvictRecordsByAge(keyOne, Arg.Any <long>()).Returns(2); mockBeaconCache.EvictRecordsByAge(keyTwo, Arg.Any <long>()).Returns(5); mockLogger.IsDebugEnabled.Returns(true); // when target.Execute(); // then verify that the logger was invoked _ = mockLogger.Received(2).IsDebugEnabled; mockLogger.Received(1).Debug($"{target.GetType().Name} - Removed 2 records from Beacon with key {keyOne}"); mockLogger.Received(1).Debug($"{target.GetType().Name} - Removed 5 records from Beacon with key {keyTwo}"); }
public void PrepareDataForSending(BeaconKey beaconKey) { var entry = GetCachedEntry(beaconKey); if (entry == null) { // a cache entry for the given beaconKey does not exist return; } if (entry.NeedsDataCopyBeforeSending) { // both entries are null, prepare data for sending long numBytes; try { entry.Lock(); numBytes = entry.TotalNumBytes; entry.CopyDataForSending(); } finally { entry.Unlock(); } // assumption: sending will work fine, and everything we copied will be removed quite soon Interlocked.Add(ref cacheSizeInBytes, -1L * numBytes); } }
public void DeleteCacheEntryRemovesTheGivenBeacon() { // given var keyOne = new BeaconKey(1, 0); var keyTwo = new BeaconKey(42, 0); var target = new BeaconCache(logger); target.AddActionData(keyOne, 1000L, "a"); target.AddActionData(keyTwo, 1000L, "z"); target.AddEventData(keyOne, 1000L, "iii"); // when removing beacon with id 1 target.DeleteCacheEntry(keyOne); // then Assert.That(target.BeaconKeys, Is.EqualTo(new HashSet <BeaconKey> { keyTwo })); // and when removing beacon with id 42 target.DeleteCacheEntry(keyTwo); // then Assert.That(target.BeaconKeys, Is.Empty); }
public void ResetChunkedData(BeaconKey beaconKey) { var entry = GetCachedEntry(beaconKey); if (entry == null) { // a cache entry for the given beaconKey does not exist return; } long numBytes; try { entry.Lock(); var oldSize = entry.TotalNumBytes; entry.ResetDataMarkedForSending(); var newSize = entry.TotalNumBytes; numBytes = newSize - oldSize; } finally { entry.Unlock(); } Interlocked.Add(ref cacheSizeInBytes, numBytes); // notify observers OnDataAdded(); }
public void GetNextBeaconChunkDoesNotCopyDataForSending() { // given var keyOne = new BeaconKey(1, 0); var keyTwo = new BeaconKey(42, 0); var target = new BeaconCache(logger); target.AddActionData(keyOne, 1000L, "a"); target.AddActionData(keyOne, 1001L, "iii"); target.AddActionData(keyTwo, 2000L, "z"); target.AddEventData(keyOne, 1000L, "b"); target.AddEventData(keyOne, 1001L, "jjj"); // when var obtained = target.GetNextBeaconChunk(keyOne, "prefix", 0, '&'); // then Assert.That(obtained, Is.Empty); Assert.That(target.GetActions(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a"), new BeaconCacheRecord(1001L, "iii") })); Assert.That(target.GetEvents(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "b"), new BeaconCacheRecord(1001L, "jjj") })); Assert.That(target.GetActionsBeingSent(keyOne), Is.Null); Assert.That(target.GetEventsBeingSent(keyOne), Is.Null); }
/// <summary> /// Get cached <see cref="BeaconCacheEntry"/> or insert new one if nothing exists for given <paramref name="beaconKey"/>. /// </summary> /// <param name="beaconKey">The beacon key to search for.</param> /// <returns>The already cached entry or newly created one.</returns> private BeaconCacheEntry GetCachedEntryOrInsert(BeaconKey beaconKey) { // get the appropriate cache entry var entry = GetCachedEntry(beaconKey); if (entry == null) { try { // does not exist, and needs to be inserted globalCacheLock.EnterWriteLock(); if (!beacons.ContainsKey(beaconKey)) { // double check since this could have been added in the mean time entry = new BeaconCacheEntry(); beacons.Add(beaconKey, entry); } else { entry = beacons[beaconKey]; } } finally { globalCacheLock.ExitWriteLock(); } } return(entry); }
public void AddEventDataAddsBeaconIdToCache() { // given var target = new BeaconCache(logger); var keyOne = new BeaconKey(1, 0); var keyTwo = new BeaconKey(2, 0); // when adding beacon with id 1 target.AddEventData(keyOne, 1000L, "a"); // then Assert.That(target.BeaconKeys, Is.EqualTo(new HashSet <BeaconKey> { keyOne })); Assert.That(target.GetEvents(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a") })); // and when adding beacon with id 2 target.AddEventData(keyTwo, 1100L, "b"); // then Assert.That(target.BeaconKeys, Is.EqualTo(new HashSet <BeaconKey> { keyOne, keyTwo })); Assert.That(target.GetEvents(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a") })); Assert.That(target.GetEvents(keyTwo), Is.EqualTo(new[] { new BeaconCacheRecord(1100L, "b") })); }
public void AddEventData(BeaconKey beaconKey, long timestamp, string data) { if (logger.IsDebugEnabled) { var logString = new StringBuilder(GetType().Name) .Append(" AddEventData(sn=").Append(beaconKey.BeaconId.ToInvariantString()) .Append(", seq=").Append(beaconKey.BeaconSeqNo.ToInvariantString()) .Append(", timestamp=").Append(timestamp.ToInvariantString()) .Append(", data='").Append(data).Append("')").ToString(); logger.Debug(logString); } // get a reference to the cache entry var entry = GetCachedEntryOrInsert(beaconKey); // add event data for that beacon var record = new BeaconCacheRecord(timestamp, data); try { entry.Lock(); entry.AddEventData(record); } finally { entry.Unlock(); } // update cache stats Interlocked.Add(ref cacheSizeInBytes, record.DataSizeInBytes); // handle event listeners OnDataAdded(); }
public void ResetChunkedRestoresData() { // given var key = new BeaconKey(1, 0); var target = new BeaconCache(logger); target.AddActionData(key, 1000L, "a"); target.AddActionData(key, 1001L, "iii"); target.AddEventData(key, 1000L, "b"); target.AddEventData(key, 1001L, "jjj"); // do same step we'd do when we send the target.GetNextBeaconChunk(key, "prefix", 10, '&'); // data has been copied, but still add some new event & action data target.AddActionData(key, 6666L, "123"); target.AddEventData(key, 6666L, "987"); // and when resetting the previously copied data target.ResetChunkedData(key); // then Assert.That(target.GetActionsBeingSent(key), Is.Null); Assert.That(target.GetEventsBeingSent(key), Is.Null); Assert.That(target.GetActions(key), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a"), new BeaconCacheRecord(1001L, "iii"), new BeaconCacheRecord(6666L, "123") })); Assert.That(target.GetEvents(key), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "b"), new BeaconCacheRecord(1001L, "jjj"), new BeaconCacheRecord(6666L, "987") })); }
public void ExecuteEvictionLogsAMessageOnceAndReturnsIfStrategyIsDisabled() { // given var configuration = MockBeaconCacheConfig(0L, 1000L, 2000L); var target = CreateTimeEvictionStrategyWith(configuration); var key = new BeaconKey(0, 0); mockLogger.IsInfoEnabled.Returns(true); // when executing the first time target.Execute(); // then _ = mockLogger.Received(1).IsInfoEnabled; mockLogger.ReceivedWithAnyArgs(1).Info(string.Empty); mockBeaconCache.DidNotReceiveWithAnyArgs().EvictRecordsByAge(key, 0L); // and when executing a second time mockLogger.ClearReceivedCalls(); target.Execute(); // then _ = mockLogger.DidNotReceive().IsInfoEnabled; mockLogger.DidNotReceiveWithAnyArgs().Info(string.Empty); mockBeaconCache.DidNotReceiveWithAnyArgs().EvictRecordsByAge(key, 0L); }
public void ResetChunkedRaisesEvent() { // given var key = new BeaconKey(1, 0); var target = new BeaconCache(logger); target.AddActionData(key, 1000L, "a"); target.AddActionData(key, 1001L, "iii"); target.AddEventData(key, 1000L, "b"); target.AddEventData(key, 1001L, "jjj"); // do same step we'd do when we send the target.GetNextBeaconChunk(key, "prefix", 10, '&'); // data has been copied, but still add some new event & action data target.AddActionData(key, 6666L, "123"); target.AddEventData(key, 6666L, "987"); var notifyCount = 0; target.RecordAdded += (s, a) => { notifyCount += 1; }; // and when resetting the previously copied data target.ResetChunkedData(key); // then Assert.That(notifyCount, Is.EqualTo(1)); }
public void ExecuteEvictionCallsEvictionForEachBeaconSeparately() { // given var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L); var target = CreateTimeEvictionStrategyWith(configuration); var keyOne = new BeaconKey(1, 0); var keyTwo = new BeaconKey(42, 0); mockTimingProvider.ProvideTimestampInMilliseconds().Returns(1000L, 2099L); mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> { keyOne, keyTwo }); // when target.Execute(); // then verify interactions _ = mockBeaconCache.Received(1).BeaconKeys; mockBeaconCache.Received(1).EvictRecordsByAge(keyOne, 2099L - configuration.MaxRecordAge); mockBeaconCache.Received(1).EvictRecordsByAge(keyTwo, 2099L - configuration.MaxRecordAge); mockTimingProvider.Received(3).ProvideTimestampInMilliseconds(); // also ensure that the last run timestamp was updated Assert.That(target.LastRunTimestamp, Is.EqualTo(2099L)); }
public void RemoveChunkedDataClearsAlreadyRetrievedChunks() { // given var keyOne = new BeaconKey(1, 0); var keyTwo = new BeaconKey(42, 0); var target = new BeaconCache(logger); target.AddActionData(keyOne, 1000L, "a"); target.AddActionData(keyOne, 1001L, "iii"); target.AddActionData(keyTwo, 2000L, "z"); target.AddEventData(keyOne, 1000L, "b"); target.AddEventData(keyOne, 1001L, "jjj"); // when retrieving the first chunk and removing retrieved chunks var obtained = target.GetNextBeaconChunk(keyOne, "prefix", 10, '&'); target.RemoveChunkedData(keyOne); // then Assert.That(obtained, Is.EqualTo("prefix&b&jjj")); Assert.That(target.GetActionsBeingSent(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a"), new BeaconCacheRecord(1001L, "iii") })); Assert.That(target.GetEventsBeingSent(keyOne), Is.Empty); // when retrieving the second chunk and removing retrieved chunks obtained = target.GetNextBeaconChunk(keyOne, "prefix", 10, '&'); target.RemoveChunkedData(keyOne); // then Assert.That(obtained, Is.EqualTo("prefix&a&iii")); Assert.That(target.GetActionsBeingSent(keyOne), Is.Empty); Assert.That(target.GetEventsBeingSent(keyOne), Is.Empty); }
public void InstancesWithDifferentBeaconIdHaveDifferentHash() { // given var keyOne = new BeaconKey(37, 18); var keyTwo = new BeaconKey(38, 18); // when, then Assert.That(keyOne.GetHashCode(), Is.Not.EqualTo(keyTwo.GetHashCode())); }
public void InstancesWithSameValuesHaveSameHash() { // given var keyOne = new BeaconKey(17, 18); var keyTwo = new BeaconKey(17, 18); // when, then Assert.That(keyOne.GetHashCode(), Is.EqualTo(keyTwo.GetHashCode())); }