1
+ package redis .clients .jedis .mcf ;
2
+
3
+ import eu .rekawek .toxiproxy .Proxy ;
4
+ import eu .rekawek .toxiproxy .ToxiproxyClient ;
5
+ import eu .rekawek .toxiproxy .model .ToxicDirection ;
6
+ import org .junit .jupiter .api .AfterAll ;
7
+ import org .junit .jupiter .api .BeforeAll ;
8
+ import org .junit .jupiter .api .BeforeEach ;
9
+ import org .junit .jupiter .api .Test ;
10
+ import org .junit .jupiter .api .Tag ;
11
+ import redis .clients .jedis .DefaultJedisClientConfig ;
12
+ import redis .clients .jedis .EndpointConfig ;
13
+ import redis .clients .jedis .HostAndPort ;
14
+ import redis .clients .jedis .HostAndPorts ;
15
+ import redis .clients .jedis .JedisClientConfig ;
16
+ import redis .clients .jedis .UnifiedJedis ;
17
+
18
+ import java .io .IOException ;
19
+
20
+ import static org .junit .jupiter .api .Assertions .*;
21
+
22
+ @ Tag ("failover" )
23
+ public class EchoStrategyIntegrationTest {
24
+
25
+ private static final EndpointConfig endpoint = HostAndPorts .getRedisEndpoint ("redis-failover-1" );
26
+ private static final HostAndPort proxyHostAndPort = endpoint .getHostAndPort ();
27
+ private static final ToxiproxyClient tp = new ToxiproxyClient ("localhost" , 8474 );
28
+ private static Proxy redisProxy ;
29
+
30
+ @ BeforeAll
31
+ public static void setupProxy () throws IOException {
32
+ if (tp .getProxyOrNull ("redis-health-test" ) != null ) {
33
+ tp .getProxy ("redis-health-test" ).delete ();
34
+ }
35
+ redisProxy = tp .createProxy ("redis-health-test" , "0.0.0.0:29379" , "redis-failover-1:9379" );
36
+ }
37
+
38
+ @ AfterAll
39
+ public static void cleanupProxy () throws IOException {
40
+ if (redisProxy != null ) {
41
+ redisProxy .delete ();
42
+ }
43
+ }
44
+
45
+ @ BeforeEach
46
+ public void resetProxy () throws IOException {
47
+ redisProxy .enable ();
48
+ redisProxy .toxics ().getAll ().forEach (toxic -> {
49
+ try {
50
+ toxic .remove ();
51
+ } catch (IOException e ) {
52
+ throw new RuntimeException (e );
53
+ }
54
+ });
55
+ }
56
+
57
+ @ Test
58
+ public void testEchoStrategyRecoversAfterDisconnect () throws Exception {
59
+ JedisClientConfig config = DefaultJedisClientConfig .builder ().socketTimeoutMillis (1000 )
60
+ .connectionTimeoutMillis (1000 ).build ();
61
+
62
+ UnifiedJedis jedis = new UnifiedJedis (proxyHostAndPort , config );
63
+ jedis .ping ();
64
+ EchoStrategy strategy = new EchoStrategy (proxyHostAndPort , config , 1000 , 500 );
65
+
66
+ // Initial health check should work
67
+ HealthStatus initialStatus = strategy .doHealthCheck (proxyHostAndPort );
68
+ assertEquals (HealthStatus .HEALTHY , initialStatus );
69
+
70
+ // Disable the proxy to simulate network failure
71
+ redisProxy .disable ();
72
+
73
+ // Health check should now fail - this will expose the bug
74
+ HealthStatus statusAfterDisable = strategy .doHealthCheck (proxyHostAndPort );
75
+ assertEquals (HealthStatus .UNHEALTHY , statusAfterDisable );
76
+
77
+ // Re-enable proxy
78
+ redisProxy .enable ();
79
+ // Health check should recover
80
+ HealthStatus statusAfterEnable = strategy .doHealthCheck (proxyHostAndPort );
81
+ assertEquals (HealthStatus .HEALTHY , statusAfterEnable );
82
+ }
83
+
84
+ @ Test
85
+ public void testEchoStrategyWithConnectionTimeout () throws Exception {
86
+ JedisClientConfig config = DefaultJedisClientConfig .builder ().socketTimeoutMillis (100 )
87
+ .connectionTimeoutMillis (100 ).build ();
88
+
89
+ EchoStrategy strategy = new EchoStrategy (proxyHostAndPort , config , 1000 , 300 );
90
+
91
+ // Initial health check should work
92
+ assertEquals (HealthStatus .HEALTHY , strategy .doHealthCheck (proxyHostAndPort ));
93
+
94
+ // Add latency toxic to simulate slow network
95
+ redisProxy .toxics ().latency ("slow-connection" , ToxicDirection .DOWNSTREAM , 1000 );
96
+
97
+ // Health check should timeout and return unhealthy
98
+ HealthStatus slowStatus = strategy .doHealthCheck (proxyHostAndPort );
99
+ assertEquals (HealthStatus .UNHEALTHY , slowStatus , "Health check should fail with high latency" );
100
+
101
+ // Remove toxic
102
+ redisProxy .toxics ().get ("slow-connection" ).remove ();
103
+
104
+ // Health check should recover
105
+ HealthStatus recoveredStatus = strategy .doHealthCheck (proxyHostAndPort );
106
+ assertEquals (HealthStatus .HEALTHY , recoveredStatus , "Health check should recover from high latency" );
107
+ }
108
+
109
+ @ Test
110
+ public void testConnectionDropDuringHealthCheck () throws Exception {
111
+ JedisClientConfig config = DefaultJedisClientConfig .builder ().socketTimeoutMillis (2000 ).build ();
112
+
113
+ EchoStrategy strategy = new EchoStrategy (proxyHostAndPort , config , 1000 , 1500 );
114
+
115
+ // Initial health check
116
+ assertEquals (HealthStatus .HEALTHY , strategy .doHealthCheck (proxyHostAndPort ));
117
+
118
+ // Simulate connection drop by limiting data transfer
119
+ redisProxy .toxics ().limitData ("connection-drop" , ToxicDirection .UPSTREAM , 10 );
120
+
121
+ // This should fail due to connection issues
122
+ HealthStatus droppedStatus = strategy .doHealthCheck (proxyHostAndPort );
123
+ assertEquals (HealthStatus .UNHEALTHY , droppedStatus );
124
+
125
+ // Remove toxic
126
+ redisProxy .toxics ().get ("connection-drop" ).remove ();
127
+
128
+ // Health check should recover
129
+ HealthStatus afterRecovery = strategy .doHealthCheck (proxyHostAndPort );
130
+ assertEquals (HealthStatus .HEALTHY , afterRecovery );
131
+
132
+ }
133
+ }
0 commit comments