summaryrefslogtreecommitdiff
path: root/src/test/java/protocols
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-26 23:25:13 +0200
committerPaul Buetow <paul@buetow.org>2026-03-26 23:25:13 +0200
commit3820f2fe179995aa6aa12e1fd2ab9b07a7938620 (patch)
tree04f84003462ae7c15ef4295e2caf1c102fa74a51 /src/test/java/protocols
parent0881fac983503a5320f5b093c738ebc44cc06a70 (diff)
Fix Raft jitter deadline election guard (0bac83d3-1322-4940-a9ee-58eb1e0d6245)
Diffstat (limited to 'src/test/java/protocols')
-rw-r--r--src/test/java/protocols/implementations/VSRaftProtocolTest.java38
1 files changed, 32 insertions, 6 deletions
diff --git a/src/test/java/protocols/implementations/VSRaftProtocolTest.java b/src/test/java/protocols/implementations/VSRaftProtocolTest.java
index 0ae52ba..8028711 100644
--- a/src/test/java/protocols/implementations/VSRaftProtocolTest.java
+++ b/src/test/java/protocols/implementations/VSRaftProtocolTest.java
@@ -120,7 +120,7 @@ class VSRaftProtocolTest {
}
@Test
- void testOnClientInitSchedulesRandomizedElectionTimeout() {
+ void testOnClientInitSchedulesRandomizedElectionTimeout() throws Exception {
protocol.currentContextIsServer(false);
ArgumentCaptor<VSTask> taskCaptor = ArgumentCaptor.forClass(VSTask.class);
@@ -132,6 +132,7 @@ class VSRaftProtocolTest {
VSTask task = taskCaptor.getValue();
assertEquals(4600L, task.getTaskTime());
+ assertEquals(4600L, getLongField("electionDeadline"));
assertFalse(((VSProtocolScheduleEvent) task.getEvent()).isServerSchedule());
}
@@ -140,7 +141,7 @@ class VSRaftProtocolTest {
protocol.currentContextIsServer(false);
protocol.onClientInit();
clearInvocations(mockProcess, mockTaskManager);
- when(mockProcess.getTime()).thenReturn(4200L);
+ when(mockProcess.getTime()).thenReturn(4700L, 4700L, 4700L);
ArgumentCaptor<VSMessage> messageCaptor =
ArgumentCaptor.forClass(VSMessage.class);
@@ -160,7 +161,8 @@ class VSRaftProtocolTest {
assertFalse(getBooleanField("isLeader"));
assertEquals(1, getIntField("votesReceived"));
assertEquals(7, getIntField("votedFor"));
- assertEquals(8700L, taskCaptor.getValue().getTaskTime());
+ assertEquals(9200L, taskCaptor.getValue().getTaskTime());
+ assertEquals(9200L, getLongField("electionDeadline"));
assertFalse(
((VSProtocolScheduleEvent) taskCaptor.getValue().getEvent())
.isServerSchedule());
@@ -186,14 +188,31 @@ class VSRaftProtocolTest {
}
@Test
+ void testOnClientScheduleDoesNotStartElectionInJitterWindow() throws Exception {
+ protocol.currentContextIsServer(false);
+ protocol.onClientInit();
+ clearInvocations(mockProcess, mockTaskManager);
+ when(mockProcess.getTime()).thenReturn(4500L);
+
+ protocol.onClientSchedule();
+
+ verify(mockProcess, never()).sendMessage(any());
+ verify(mockTaskManager, never()).removeAllTasks(any());
+ verify(mockTaskManager, never()).addTask(any());
+ assertFalse(getBooleanField("isCandidate"));
+ assertEquals(0, getIntField("currentTerm"));
+ assertEquals(4600L, getLongField("electionDeadline"));
+ }
+
+ @Test
void testCandidateTimeoutStartsNewElectionAndReschedules() throws Exception {
protocol.currentContextIsServer(false);
protocol.onClientInit();
- when(mockProcess.getTime()).thenReturn(4200L, 4200L, 4200L);
+ when(mockProcess.getTime()).thenReturn(4700L, 4700L, 4700L);
protocol.onClientSchedule();
clearInvocations(mockProcess, mockTaskManager);
- when(mockProcess.getTime()).thenReturn(8401L, 8401L, 8401L);
+ when(mockProcess.getTime()).thenReturn(9401L, 9401L, 9401L);
ArgumentCaptor<VSMessage> messageCaptor =
ArgumentCaptor.forClass(VSMessage.class);
@@ -210,7 +229,8 @@ class VSRaftProtocolTest {
assertEquals(2, voteRequest.getInteger("term"));
assertEquals(2, getIntField("currentTerm"));
assertEquals(1, getIntField("votesReceived"));
- assertEquals(12901L, taskCaptor.getValue().getTaskTime());
+ assertEquals(13901L, taskCaptor.getValue().getTaskTime());
+ assertEquals(13901L, getLongField("electionDeadline"));
}
@Test
@@ -261,4 +281,10 @@ class VSRaftProtocolTest {
field.setAccessible(true);
return field.getBoolean(protocol);
}
+
+ private long getLongField(String fieldName) throws Exception {
+ Field field = VSRaftProtocol.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ return field.getLong(protocol);
+ }
}