diff --git a/tests/Integration/Momento.Sdk.Tests/Cache/ReplicaReadTest.cs b/tests/Integration/Momento.Sdk.Tests/Cache/ReplicaReadTest.cs new file mode 100644 index 00000000..2967c492 --- /dev/null +++ b/tests/Integration/Momento.Sdk.Tests/Cache/ReplicaReadTest.cs @@ -0,0 +1,45 @@ +using System.Linq; +using System.Threading.Tasks; + +namespace Momento.Sdk.Tests.Integration.Cache; + +[Collection("CacheClient")] +public class ReplicaReadTest : TestBase +{ + private new readonly ICacheClient client; + public ReplicaReadTest(CacheClientFixture fixture) : base(fixture) + { + client = fixture.ClientWithBalancedReads; + } + + [Fact] + public async Task LatestValueAfterReplicationDelay() + { + const int numTrials = 10; + const int delayBetweenTrials = 100; + const int replicationDelayMs = 1000; + var random = new Random(); + + var trials = Enumerable.Range(0, numTrials).Select(async trialNumber => + { + var startDelay = trialNumber * delayBetweenTrials + (random.NextDouble() - 0.5) * 10; + await Task.Delay((int)startDelay); + + var key = Utils.NewGuidString(); + var value = Utils.NewGuidString(); + + var setResponse = await client.SetAsync(cacheName, key, value); + Assert.True(setResponse is CacheSetResponse.Success, $"Unexpected response: {setResponse}"); + + await Task.Delay(replicationDelayMs); + + var getResponse = await client.GetAsync(cacheName, key); + Assert.True(getResponse is CacheGetResponse.Hit, $"Unexpected response: {getResponse}"); + var hitResponse = (CacheGetResponse.Hit)getResponse; + string setValue = hitResponse.ValueString; + Assert.Equal(value, setValue); + }); + + await Task.WhenAll(trials); + } +} \ No newline at end of file diff --git a/tests/Integration/Momento.Sdk.Tests/Fixtures.cs b/tests/Integration/Momento.Sdk.Tests/Fixtures.cs index beec2056..3e4dd77d 100644 --- a/tests/Integration/Momento.Sdk.Tests/Fixtures.cs +++ b/tests/Integration/Momento.Sdk.Tests/Fixtures.cs @@ -11,11 +11,13 @@ namespace Momento.Sdk.Tests.Integration; /// public class CacheClientFixture : IDisposable { - public ICacheClient Client { get; private set; } - public ICredentialProvider AuthProvider { get; private set; } - public string CacheName { get; private set; } + public ICacheClient Client { get; } + public ICacheClient ClientWithConsistentReads { get; } + public ICacheClient ClientWithBalancedReads { get; } + public ICredentialProvider AuthProvider { get; } + public string CacheName { get; } - public TimeSpan DefaultTtl { get; private set; } = TimeSpan.FromSeconds(10); + public TimeSpan DefaultTtl { get; } = TimeSpan.FromSeconds(10); public CacheClientFixture() { @@ -35,14 +37,14 @@ public CacheClientFixture() builder.AddFilter("Grpc.Net.Client", LogLevel.Error); builder.SetMinimumLevel(LogLevel.Information); })); - - if (consistentReads) - { - config = config.WithReadConcern(ReadConcern.Consistent); - } + var configWithConsistentReads = config.WithReadConcern(ReadConcern.Consistent); + + ClientWithBalancedReads = new CacheClient(config, AuthProvider, defaultTtl: DefaultTtl); + ClientWithConsistentReads = new CacheClient(configWithConsistentReads, AuthProvider, defaultTtl: DefaultTtl); + Client = consistentReads ? ClientWithConsistentReads : ClientWithBalancedReads; CacheName = $"dotnet-integration-{Utils.NewGuidString()}"; - Client = new CacheClient(config, AuthProvider, defaultTtl: DefaultTtl); + Utils.CreateCacheForTest(Client, CacheName); }