2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.cluster.raft;
10 import static org.junit.Assert.assertEquals;
12 import akka.actor.ActorRef;
13 import akka.persistence.SaveSnapshotSuccess;
14 import akka.testkit.TestActorRef;
15 import java.util.List;
17 import org.junit.Before;
18 import org.junit.Test;
19 import org.opendaylight.controller.cluster.raft.persisted.ApplyJournalEntries;
20 import org.opendaylight.controller.cluster.raft.persisted.Snapshot;
21 import org.opendaylight.controller.cluster.raft.utils.InMemoryJournal;
22 import org.opendaylight.controller.cluster.raft.utils.InMemorySnapshotStore;
23 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * Recovery Integration Test for single node.
30 public class RecoveryIntegrationSingleNodeTest extends AbstractRaftActorIntegrationTest {
32 static final Logger LOG = LoggerFactory.getLogger(RecoveryIntegrationSingleNodeTest.class);
36 leaderConfigParams = newLeaderConfigParams();
41 public void testJournalReplayAfterSnapshotWithSingleNode() {
43 String persistenceId = factory.generateActorId("singleNode");
44 TestActorRef<AbstractRaftActorIntegrationTest.TestRaftActor> singleNodeActorRef =
45 newTestRaftActor(persistenceId, Map.of(), leaderConfigParams);
47 waitUntilLeader(singleNodeActorRef);
49 ActorRef singleNodeCollectorActor = singleNodeActorRef.underlyingActor().collectorActor();
50 final RaftActorContext singleNodeContext = singleNodeActorRef.underlyingActor().getRaftActorContext();
52 InMemoryJournal.addWriteMessagesCompleteLatch(persistenceId, 6, ApplyJournalEntries.class);
54 final MockRaftActorContext.MockPayload payload0 = sendPayloadData(singleNodeActorRef, "zero");
55 final MockRaftActorContext.MockPayload payload1 = sendPayloadData(singleNodeActorRef, "one");
56 final MockRaftActorContext.MockPayload payload2 = sendPayloadData(singleNodeActorRef, "two");
58 MessageCollectorActor.expectMatching(singleNodeCollectorActor, ApplyJournalEntries.class, 3);
60 // this should trigger a snapshot
61 final MockRaftActorContext.MockPayload payload3 = sendPayloadData(singleNodeActorRef, "three");
63 MessageCollectorActor.expectMatching(singleNodeCollectorActor, ApplyJournalEntries.class, 4);
66 final MockRaftActorContext.MockPayload payload4 = sendPayloadData(singleNodeActorRef, "four");
67 final MockRaftActorContext.MockPayload payload5 = sendPayloadData(singleNodeActorRef, "five");
70 // Wait for snapshot complete.
71 MessageCollectorActor.expectFirstMatching(singleNodeCollectorActor, SaveSnapshotSuccess.class);
73 MessageCollectorActor.expectMatching(singleNodeCollectorActor, ApplyJournalEntries.class, 6);
75 assertEquals("Last applied", 5, singleNodeContext.getLastApplied());
77 assertEquals("Incorrect State after snapshot success is received ",
78 List.of(payload0, payload1, payload2, payload3, payload4, payload5),
79 singleNodeActorRef.underlyingActor().getState());
81 InMemoryJournal.waitForWriteMessagesComplete(persistenceId);
83 // we get 2 log entries (4 and 5 indexes) and 3 ApplyJournalEntries (for 3, 4, and 5 indexes)
84 assertEquals(5, InMemoryJournal.get(persistenceId).size());
86 List<Snapshot> persistedSnapshots = InMemorySnapshotStore.getSnapshots(persistenceId, Snapshot.class);
87 assertEquals(1, persistedSnapshots.size());
89 List<Object> snapshottedState = MockRaftActor.fromState(persistedSnapshots.get(0).getState());
90 assertEquals("Incorrect Snapshot", List.of(payload0, payload1, payload2, payload3), snapshottedState);
92 //recovery logic starts
93 killActor(singleNodeActorRef);
95 singleNodeActorRef = newTestRaftActor(persistenceId, Map.of(), leaderConfigParams);
97 singleNodeActorRef.underlyingActor().waitForRecoveryComplete();
99 assertEquals("Incorrect State after Recovery ",
100 List.of(payload0, payload1, payload2, payload3, payload4, payload5),
101 singleNodeActorRef.underlyingActor().getState());