Skip to content

Commit e85d6c6

Browse files
committed
move KeyIdle[Async]Tests to a server without replication
1 parent 8f47bf6 commit e85d6c6

2 files changed

Lines changed: 33 additions & 7 deletions

File tree

tests/StackExchange.Redis.Tests/KeyIdleAsyncTests.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ namespace StackExchange.Redis.Tests;
88
[RunPerProtocol]
99
public class KeyIdleAsyncTests(ITestOutputHelper output, SharedConnectionFixture fixture) : TestBase(output, fixture)
1010
{
11+
// Target the standalone secure server (6381) rather than the default primary (6379).
12+
// OBJECT IDLETIME is reset via the value's LRU access clock, but Redis deliberately
13+
// suppresses that update while a save/AOF/replication-sync child is active (copy-on-write
14+
// avoidance). The default primary has a replica attached, and every replica full-sync forks
15+
// such a child; if one overlaps a touch/read in these tests, the idle time isn't reset and the
16+
// test flakes (observed on Windows CI). 6381 has no replica and no persistence, so no fork ever
17+
// suppresses the reset and the behaviour is deterministic. Overriding GetConfiguration here also
18+
// opts these tests out of the shared connection fixture, giving each a dedicated 6381 connection.
19+
protected override string GetConfiguration()
20+
=> TestConfig.Current.SecureServerAndPort + ",password=" + TestConfig.Current.SecurePassword;
21+
1122
[Fact]
1223
public async Task IdleTimeAsync()
1324
{
@@ -17,13 +28,14 @@ public async Task IdleTimeAsync()
1728
var db = conn.GetDatabase();
1829
db.KeyDelete(key, CommandFlags.FireAndForget);
1930
db.StringSet(key, "new value", flags: CommandFlags.FireAndForget);
31+
var timer = Stopwatch.StartNew();
2032
await Task.Delay(2000).ForAwait();
2133
var idleTime = await db.KeyIdleTimeAsync(key).ForAwait();
22-
Assert.True(idleTime > TimeSpan.Zero, "First check");
34+
Assert.True(idleTime > TimeSpan.Zero, $"First check: {idleTime} should be > 0; elapsed: {timer.ElapsedMilliseconds}ms");
2335

2436
db.StringSet(key, "new value2", flags: CommandFlags.FireAndForget);
2537
var idleTime2 = await db.KeyIdleTimeAsync(key).ForAwait();
26-
Assert.True(idleTime2 < idleTime, "Second check");
38+
Assert.True(idleTime2 < idleTime, $"Second check: {idleTime2} should be < {idleTime}; elapsed: {timer.ElapsedMilliseconds}ms");
2739

2840
db.KeyDelete(key);
2941
var idleTime3 = await db.KeyIdleTimeAsync(key).ForAwait();

tests/StackExchange.Redis.Tests/KeyIdleTests.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using System.Threading.Tasks;
34
using Xunit;
45

@@ -7,6 +8,17 @@ namespace StackExchange.Redis.Tests;
78
[RunPerProtocol]
89
public class KeyIdleTests(ITestOutputHelper output, SharedConnectionFixture fixture) : TestBase(output, fixture)
910
{
11+
// Target the standalone secure server (6381) rather than the default primary (6379).
12+
// OBJECT IDLETIME is reset via the value's LRU access clock, but Redis deliberately
13+
// suppresses that update while a save/AOF/replication-sync child is active (copy-on-write
14+
// avoidance). The default primary has a replica attached, and every replica full-sync forks
15+
// such a child; if one overlaps a touch/read in these tests, the idle time isn't reset and the
16+
// test flakes (observed on Windows CI). 6381 has no replica and no persistence, so no fork ever
17+
// suppresses the reset and the behaviour is deterministic. Overriding GetConfiguration here also
18+
// opts these tests out of the shared connection fixture, giving each a dedicated 6381 connection.
19+
protected override string GetConfiguration()
20+
=> TestConfig.Current.SecureServerAndPort + ",password=" + TestConfig.Current.SecurePassword;
21+
1022
[Fact]
1123
public async Task IdleTime()
1224
{
@@ -16,13 +28,14 @@ public async Task IdleTime()
1628
var db = conn.GetDatabase();
1729
db.KeyDelete(key, CommandFlags.FireAndForget);
1830
db.StringSet(key, "new value", flags: CommandFlags.FireAndForget);
31+
var timer = Stopwatch.StartNew();
1932
await Task.Delay(2000).ForAwait();
2033
var idleTime = db.KeyIdleTime(key);
21-
Assert.True(idleTime > TimeSpan.Zero);
34+
Assert.True(idleTime > TimeSpan.Zero, $"First check: {idleTime} should be > 0; elapsed: {timer.ElapsedMilliseconds}ms");
2235

2336
db.StringSet(key, "new value2", flags: CommandFlags.FireAndForget);
2437
var idleTime2 = db.KeyIdleTime(key);
25-
Assert.True(idleTime2 < idleTime);
38+
Assert.True(idleTime2 < idleTime, $"Second check: {idleTime2} should be < {idleTime}; elapsed: {timer.ElapsedMilliseconds}ms");
2639

2740
db.KeyDelete(key);
2841
var idleTime3 = db.KeyIdleTime(key);
@@ -38,12 +51,13 @@ public async Task TouchIdleTime()
3851
var db = conn.GetDatabase();
3952
db.KeyDelete(key, CommandFlags.FireAndForget);
4053
db.StringSet(key, "new value", flags: CommandFlags.FireAndForget);
54+
var timer = Stopwatch.StartNew();
4155
await Task.Delay(2000).ForAwait();
4256
var idleTime = db.KeyIdleTime(key);
43-
Assert.True(idleTime > TimeSpan.Zero, "First check");
57+
Assert.True(idleTime > TimeSpan.Zero, $"First check: {idleTime} should be > 0; elapsed: {timer.ElapsedMilliseconds}ms");
4458

45-
Assert.True(db.KeyTouch(key), "Second check");
59+
Assert.True(db.KeyTouch(key), $"Second check: should be True; elapsed: {timer.ElapsedMilliseconds}ms");
4660
var idleTime1 = db.KeyIdleTime(key);
47-
Assert.True(idleTime1 < idleTime, "Third check");
61+
Assert.True(idleTime1 < idleTime, $"Third check: {idleTime1} should be < {idleTime}; elapsed: {timer.ElapsedMilliseconds}ms");
4862
}
4963
}

0 commit comments

Comments
 (0)