Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class AtomicFactoryAsyncCacheTests
private readonly AtomicFactoryAsyncCache<int, int> cache = new(new ConcurrentLru<int, AsyncAtomicFactory<int, int>>(capacity));

private List<ItemRemovedEventArgs<int, int>> removedItems = new();
private List<ItemUpdatedEventArgs<int, int>> updatedItems = new();

[Fact]
public void WhenInnerCacheIsNullCtorThrows()
Expand Down Expand Up @@ -65,7 +66,7 @@ public void WhenNoInnerEventsNoOuterEvents()
}

[Fact]
public void WhenEventHandlerIsRegisteredItIsFired()
public void WhenRemovedEventHandlerIsRegisteredItIsFired()
{
this.cache.Events.Value.ItemRemoved += OnItemRemoved;

Expand All @@ -75,6 +76,19 @@ public void WhenEventHandlerIsRegisteredItIsFired()
this.removedItems.First().Key.Should().Be(1);
}

[Fact]
public void WhenUpdatedEventHandlerIsRegisteredItIsFired()
{
this.cache.Events.Value.ItemUpdated += OnItemUpdated;

this.cache.AddOrUpdate(1, 2);
this.cache.AddOrUpdate(1, 3);

this.updatedItems.First().Key.Should().Be(1);
this.updatedItems.First().OldValue.Should().Be(2);
this.updatedItems.First().NewValue.Should().Be(3);
}

[Fact]
public void WhenKeyDoesNotExistAddOrUpdateAddsNewItem()
{
Expand Down Expand Up @@ -193,5 +207,10 @@ private void OnItemRemoved(object sender, ItemRemovedEventArgs<int, int> e)
{
this.removedItems.Add(e);
}

private void OnItemUpdated(object sender, ItemUpdatedEventArgs<int, int> e)
{
this.updatedItems.Add(e);
}
}
}
21 changes: 20 additions & 1 deletion BitFaster.Caching.UnitTests/Atomic/AtomicFactoryCacheTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class AtomicFactoryCacheTests
private readonly AtomicFactoryCache<int, int> cache = new(new ConcurrentLru<int, AtomicFactory<int, int>>(capacity));

private List<ItemRemovedEventArgs<int, int>> removedItems = new();
private List<ItemUpdatedEventArgs<int, int>> updatedItems = new();

[Fact]
public void WhenInnerCacheIsNullCtorThrows()
Expand Down Expand Up @@ -54,7 +55,7 @@ public void WhenItemIsAddedThenLookedUpMetricsAreCorrect()
}

[Fact]
public void WhenEventHandlerIsRegisteredItIsFired()
public void WhenRemovedEventHandlerIsRegisteredItIsFired()
{
this.cache.Events.Value.ItemRemoved += OnItemRemoved;

Expand All @@ -64,6 +65,19 @@ public void WhenEventHandlerIsRegisteredItIsFired()
this.removedItems.First().Key.Should().Be(1);
}

[Fact]
public void WhenUpdatedEventHandlerIsRegisteredItIsFired()
{
this.cache.Events.Value.ItemUpdated += OnItemUpdated;

this.cache.AddOrUpdate(1, 2);
this.cache.AddOrUpdate(1, 3);

this.updatedItems.First().Key.Should().Be(1);
this.updatedItems.First().OldValue.Should().Be(2);
this.updatedItems.First().NewValue.Should().Be(3);
}

[Fact]
public void WhenNoInnerEventsNoOuterEvents()
{
Expand Down Expand Up @@ -193,5 +207,10 @@ private void OnItemRemoved(object sender, ItemRemovedEventArgs<int, int> e)
{
this.removedItems.Add(e);
}

private void OnItemUpdated(object sender, ItemUpdatedEventArgs<int, int> e)
{
this.updatedItems.Add(e);
}
}
}
73 changes: 64 additions & 9 deletions BitFaster.Caching.UnitTests/CacheEventProxyBaseTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BitFaster.Caching.Atomic;
using FluentAssertions;
using Xunit;
Expand All @@ -15,6 +13,7 @@ public class CacheEventProxyBaseTests
private EventProxy<int, int> eventProxy;

private List<ItemRemovedEventArgs<int, int>> removedItems = new();
private List<ItemUpdatedEventArgs<int, int>> updatedItems = new();

public CacheEventProxyBaseTests()
{
Expand All @@ -23,56 +22,107 @@ public CacheEventProxyBaseTests()
}

[Fact]
public void WhenEventHandlerIsRegisteredItIsFired()
public void WheRemovedEventHandlerIsRegisteredItIsFired()
{
this.eventProxy.ItemRemoved += OnItemRemoved;

this.testCacheEvents.Fire(1, new AtomicFactory<int, int>(1), ItemRemovedReason.Removed);
this.testCacheEvents.FireRemoved(1, new AtomicFactory<int, int>(1), ItemRemovedReason.Removed);

this.removedItems.First().Key.Should().Be(1);
}

[Fact]
public void WhenEventHandlerIsAddedThenRemovedItIsNotFired()
public void WhenRemovedEventHandlerIsAddedThenRemovedItIsNotFired()
{
this.eventProxy.ItemRemoved += OnItemRemoved;
this.eventProxy.ItemRemoved -= OnItemRemoved;

this.testCacheEvents.Fire(1, new AtomicFactory<int, int>(1), ItemRemovedReason.Removed);
this.testCacheEvents.FireRemoved(1, new AtomicFactory<int, int>(1), ItemRemovedReason.Removed);

this.removedItems.Count.Should().Be(0);
}

[Fact]
public void WhenTwoEventHandlersAddedThenOneRemovedEventIsFired()
public void WhenTwoRemovedEventHandlersAddedThenOneRemovedEventIsFired()
{
this.eventProxy.ItemRemoved += OnItemRemoved;
this.eventProxy.ItemRemoved += OnItemRemovedThrow;
this.eventProxy.ItemRemoved -= OnItemRemovedThrow;

this.testCacheEvents.Fire(1, new AtomicFactory<int, int>(1), ItemRemovedReason.Removed);
this.testCacheEvents.FireRemoved(1, new AtomicFactory<int, int>(1), ItemRemovedReason.Removed);

this.removedItems.First().Key.Should().Be(1);
}

[Fact]
public void WheUpdatedEventHandlerIsRegisteredItIsFired()
{
this.eventProxy.ItemUpdated += OnItemUpdated;

this.testCacheEvents.FireUpdated(1, new AtomicFactory<int, int>(2), new AtomicFactory<int, int>(3));

this.updatedItems.First().Key.Should().Be(1);
this.updatedItems.First().OldValue.Should().Be(2);
this.updatedItems.First().NewValue.Should().Be(3);
}

[Fact]
public void WhenUpdatedEventHandlerIsAddedThenRemovedItIsNotFired()
{
this.eventProxy.ItemUpdated += OnItemUpdated;
this.eventProxy.ItemUpdated -= OnItemUpdated;

this.testCacheEvents.FireUpdated(1, new AtomicFactory<int, int>(2), new AtomicFactory<int, int>(3));

this.updatedItems.Count.Should().Be(0);
}

[Fact]
public void WhenTwoUpdatedEventHandlersAddedThenOneRemovedEventIsFired()
{
this.eventProxy.ItemUpdated += OnItemUpdated;
this.eventProxy.ItemUpdated += OnItemUpdatedThrow;
this.eventProxy.ItemUpdated -= OnItemUpdatedThrow;

this.testCacheEvents.FireUpdated(1, new AtomicFactory<int, int>(2), new AtomicFactory<int, int>(3));

this.updatedItems.First().Key.Should().Be(1);
}

private void OnItemRemoved(object sender, ItemRemovedEventArgs<int, int> e)
{
this.removedItems.Add(e);
}

private void OnItemUpdated(object sender, ItemUpdatedEventArgs<int, int> e)
{
this.updatedItems.Add(e);
}

private void OnItemRemovedThrow(object sender, ItemRemovedEventArgs<int, int> e)
{
throw new Exception("Should never happen");
}

private void OnItemUpdatedThrow(object sender, ItemUpdatedEventArgs<int, int> e)
{
throw new Exception("Should never happen");
}

private class TestCacheEvents<K, V> : ICacheEvents<K, AtomicFactory<K, V>>
{
public event EventHandler<ItemRemovedEventArgs<K, AtomicFactory<K, V>>> ItemRemoved;
public event EventHandler<ItemUpdatedEventArgs<K, AtomicFactory<K, V>>> ItemUpdated;

public void Fire(K key, AtomicFactory<K, V> value, ItemRemovedReason reason)
public void FireRemoved(K key, AtomicFactory<K, V> value, ItemRemovedReason reason)
{
ItemRemoved?.Invoke(this, new ItemRemovedEventArgs<K, AtomicFactory<K, V>>(key, value, reason));
}

public void FireUpdated(K key, AtomicFactory<K, V> oldValue, AtomicFactory<K, V> newValue)
{
ItemUpdated?.Invoke(this, new ItemUpdatedEventArgs<K, AtomicFactory<K, V>>(key, oldValue, newValue));
}
}

private class EventProxy<K, V> : CacheEventProxyBase<K, AtomicFactory<K, V>, V>
Expand All @@ -86,6 +136,11 @@ protected override ItemRemovedEventArgs<K, V> TranslateOnRemoved(ItemRemovedEven
{
return new ItemRemovedEventArgs<K, V>(inner.Key, inner.Value.ValueIfCreated, inner.Reason);
}

protected override ItemUpdatedEventArgs<K, V> TranslateOnUpdated(ItemUpdatedEventArgs<K, AtomicFactory<K, V>> inner)
{
return new ItemUpdatedEventArgs<K, V>(inner.Key, inner.OldValue.ValueIfCreated, inner.NewValue.ValueIfCreated);
}
}
}
}
58 changes: 56 additions & 2 deletions BitFaster.Caching.UnitTests/Lru/ConcurrentLruTests.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
using FluentAssertions;
using BitFaster.Caching.Lru;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
using System.Collections;

namespace BitFaster.Caching.UnitTests.Lru
{
Expand All @@ -23,12 +22,18 @@ public class ConcurrentLruTests
private ValueFactory valueFactory = new ValueFactory();

private List<ItemRemovedEventArgs<int, int>> removedItems = new List<ItemRemovedEventArgs<int, int>>();
private List<ItemUpdatedEventArgs<int, int>> updatedItems = new List<ItemUpdatedEventArgs<int, int>>();

private void OnLruItemRemoved(object sender, ItemRemovedEventArgs<int, int> e)
{
removedItems.Add(e);
}

private void OnLruItemUpdated(object sender, ItemUpdatedEventArgs<int, int> e)
{
updatedItems.Add(e);
}

public ConcurrentLruTests(ITestOutputHelper testOutputHelper)
{
this.testOutputHelper = testOutputHelper;
Expand Down Expand Up @@ -708,6 +713,55 @@ public void WhenKeyDoesNotExistAddOrUpdateMaintainsLruOrder()
lru.WarmCount.Should().Be(1); // items must have been enqueued and cycled for one of them to reach the warm queue
}

[Fact]
public void WhenItemExistsAddOrUpdateFiresUpdateEvent()
{
var lruEvents = new ConcurrentLru<int, int>(1, new EqualCapacityPartition(6), EqualityComparer<int>.Default);
lruEvents.Events.Value.ItemUpdated += OnLruItemUpdated;

lruEvents.AddOrUpdate(1, 2);
lruEvents.AddOrUpdate(2, 3);

lruEvents.AddOrUpdate(1, 3);

this.updatedItems.Count.Should().Be(1);
this.updatedItems[0].Key.Should().Be(1);
this.updatedItems[0].OldValue.Should().Be(2);
this.updatedItems[0].NewValue.Should().Be(3);
}

[Fact]
public void WhenItemExistsTryUpdateFiresUpdateEvent()
{
var lruEvents = new ConcurrentLru<int, int>(1, new EqualCapacityPartition(6), EqualityComparer<int>.Default);
lruEvents.Events.Value.ItemUpdated += OnLruItemUpdated;

lruEvents.AddOrUpdate(1, 2);
lruEvents.AddOrUpdate(2, 3);

lruEvents.TryUpdate(1, 3);

this.updatedItems.Count.Should().Be(1);
this.updatedItems[0].Key.Should().Be(1);
this.updatedItems[0].OldValue.Should().Be(2);
this.updatedItems[0].NewValue.Should().Be(3);
}

[Fact]
public void WhenItemUpdatedEventIsUnregisteredEventIsNotFired()
{
var lruEvents = new ConcurrentLru<int, int>(1, 6, EqualityComparer<int>.Default);

lruEvents.Events.Value.ItemUpdated += OnLruItemUpdated;
lruEvents.Events.Value.ItemUpdated -= OnLruItemUpdated;

lruEvents.AddOrUpdate(1, 2);
lruEvents.AddOrUpdate(1, 2);
lruEvents.AddOrUpdate(1, 2);

updatedItems.Count.Should().Be(0);
}

[Fact]
public void WhenCacheIsEmptyClearIsNoOp()
{
Expand Down
18 changes: 13 additions & 5 deletions BitFaster.Caching.UnitTests/Lru/NoTelemetryPolicyTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using FluentAssertions;
using BitFaster.Caching.Lru;
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace BitFaster.Caching.UnitTests.Lru
Expand Down Expand Up @@ -62,7 +59,7 @@ public void IncrementTotalCountIsNoOp()
[Fact]
public void OnItemUpdatedIsNoOp()
{
counter.Invoking(c => c.OnItemUpdated(1, 2)).Should().NotThrow();
counter.Invoking(c => c.OnItemUpdated(1, 2, 3)).Should().NotThrow();
}

[Fact]
Expand All @@ -72,14 +69,25 @@ public void OnItemRemovedIsNoOp()
}

[Fact]
public void RegisterEventHandlerIsNoOp()
public void RegisterRemovedEventHandlerIsNoOp()
{
counter.ItemRemoved += OnItemRemoved;
counter.ItemRemoved -= OnItemRemoved;
}

[Fact]
public void RegisterUpdateEventHandlerIsNoOp()
{
counter.ItemUpdated += OnItemUpdated;
counter.ItemUpdated -= OnItemUpdated;
}

private void OnItemRemoved(object sender, ItemRemovedEventArgs<int, int> e)
{
}

private void OnItemUpdated(object sender, ItemUpdatedEventArgs<int, int> e)
{
}
}
}
Loading