Skip to content
Open
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
108 changes: 108 additions & 0 deletions OptimizelySDK.Tests/OdpTests/LruCacheTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,5 +208,113 @@ public void ShouldHandleWhenCacheIsReset()

Assert.AreEqual(0, cache.CurrentCacheKeysForTesting().Length);
}

[Test]
public void ShouldHandleRemoveNonExistentKey()
{
var cache = new LruCache<List<string>>();
cache.Save("user1", _segments1And2);
cache.Save("user2", _segments3And4);

// Remove a key that doesn't exist
cache.Remove("user3");

// Existing keys should still be there
Assert.AreEqual(_segments1And2, cache.Lookup("user1"));
Assert.AreEqual(_segments3And4, cache.Lookup("user2"));
}

[Test]
public void ShouldHandleRemoveExistingKey()
{
var cache = new LruCache<List<string>>();

cache.Save("user1", _segments1And2);
cache.Save("user2", _segments3And4);
cache.Save("user3", _segments5And6);

Assert.AreEqual(_segments1And2, cache.Lookup("user1"));
Assert.AreEqual(_segments3And4, cache.Lookup("user2"));
Assert.AreEqual(_segments5And6, cache.Lookup("user3"));

cache.Remove("user2");

Assert.AreEqual(_segments1And2, cache.Lookup("user1"));
Assert.IsNull(cache.Lookup("user2"));
Assert.AreEqual(_segments5And6, cache.Lookup("user3"));
}

[Test]
public void ShouldHandleRemoveFromZeroSizedCache()
{
var cache = new LruCache<List<string>>(0);

cache.Save("user1", _segments1And2);
cache.Remove("user1");

Assert.IsNull(cache.Lookup("user1"));
Assert.AreEqual(0, cache.CurrentCacheKeysForTesting().Length);
}

[Test]
public void ShouldHandleRemoveAndAddBack()
{
var cache = new LruCache<List<string>>();

cache.Save("user1", _segments1And2);
cache.Save("user2", _segments3And4);
cache.Save("user3", _segments5And6);

// Remove user2 and add it back with different data
cache.Remove("user2");
cache.Save("user2", _segments1And2);

Assert.AreEqual(_segments1And2, cache.Lookup("user1"));
Assert.AreEqual(_segments1And2, cache.Lookup("user2"));
Assert.AreEqual(_segments5And6, cache.Lookup("user3"));

Assert.AreEqual(3, cache.CurrentCacheKeysForTesting().Length);
}

[Test]
public void ShouldHandleThreadSafetyWithRemove()
{
var cache = new LruCache<string>(100);

for (int i = 1; i <= 100; i++)
{
cache.Save($"key{i}", $"value{i}");
}

var threads = new List<Thread>();

for (int i = 1; i <= 50; i++)
{
int localI = i; // Capture variable for closure
var thread = new Thread(() => cache.Remove($"key{localI}"));
threads.Add(thread);
thread.Start();
}

// Wait for all threads to complete
foreach (var thread in threads)
{
thread.Join();
}

for (int i = 1; i <= 100; i++)
{
if (i <= 50)
{
Assert.IsNull(cache.Lookup($"key{i}"), $"key{i} should be removed");
}
else
{
Assert.AreEqual($"value{i}", cache.Lookup($"key{i}"), $"key{i} should still exist");
}
}

Assert.AreEqual(50, cache.CurrentCacheKeysForTesting().Length);
}
}
}
12 changes: 12 additions & 0 deletions OptimizelySDK/Odp/LruCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,18 @@ public void Reset()
}
}

/// <summary>
/// Remove the element associated with the provided key from the cache
/// </summary>
/// <param name="key">Key of element to remove from the cache</param>
public void Remove(string key)
{
lock (_mutex)
{
_cache.Remove(key);
}
}

/// <summary>
/// Wrapping class around a generic value stored in the cache
/// </summary>
Expand Down
Loading