Merge "Bug 2415: Fixed intermittent RpcRegistry unit test failures"
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / behaviors / SnapshotTrackerTest.java
1 package org.opendaylight.controller.cluster.raft.behaviors;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.mockito.Mockito.mock;
5 import akka.event.LoggingAdapter;
6 import com.google.common.base.Optional;
7 import com.google.protobuf.ByteString;
8 import java.io.ByteArrayOutputStream;
9 import java.io.IOException;
10 import java.io.ObjectOutputStream;
11 import java.util.HashMap;
12 import java.util.Map;
13 import org.junit.Assert;
14 import org.junit.Before;
15 import org.junit.Test;
16
17 public class SnapshotTrackerTest {
18
19     Map<String, String> data;
20     ByteString byteString;
21     ByteString chunk1;
22     ByteString chunk2;
23     ByteString chunk3;
24
25     @Before
26     public void setup(){
27         data = new HashMap<>();
28         data.put("key1", "value1");
29         data.put("key2", "value2");
30         data.put("key3", "value3");
31
32         byteString = toByteString(data);
33         chunk1 = getNextChunk(byteString, 0, 10);
34         chunk2 = getNextChunk(byteString, 10, 10);
35         chunk3 = getNextChunk(byteString, 20, byteString.size());
36     }
37
38     @Test
39     public void testAddChunk() throws SnapshotTracker.InvalidChunkException {
40         SnapshotTracker tracker1 = new SnapshotTracker(mock(LoggingAdapter.class), 5);
41
42         tracker1.addChunk(1, chunk1, Optional.<Integer>absent());
43         tracker1.addChunk(2, chunk2, Optional.<Integer>absent());
44         tracker1.addChunk(3, chunk3, Optional.<Integer>absent());
45
46         // Verify that an InvalidChunkException is thrown when we try to add a chunk to a sealed tracker
47         SnapshotTracker tracker2 = new SnapshotTracker(mock(LoggingAdapter.class), 2);
48
49         tracker2.addChunk(1, chunk1, Optional.<Integer>absent());
50         tracker2.addChunk(2, chunk2, Optional.<Integer>absent());
51
52         try {
53             tracker2.addChunk(3, chunk3, Optional.<Integer>absent());
54             Assert.fail();
55         } catch(SnapshotTracker.InvalidChunkException e){
56             e.getMessage().startsWith("Invalid chunk");
57         }
58
59         // The first chunk's index must at least be FIRST_CHUNK_INDEX
60         SnapshotTracker tracker3 = new SnapshotTracker(mock(LoggingAdapter.class), 2);
61
62         try {
63             tracker3.addChunk(AbstractLeader.FIRST_CHUNK_INDEX - 1, chunk1, Optional.<Integer>absent());
64             Assert.fail();
65         } catch(SnapshotTracker.InvalidChunkException e){
66
67         }
68
69         // Out of sequence chunk indexes won't work
70         SnapshotTracker tracker4 = new SnapshotTracker(mock(LoggingAdapter.class), 2);
71
72         tracker4.addChunk(AbstractLeader.FIRST_CHUNK_INDEX, chunk1, Optional.<Integer>absent());
73
74         try {
75             tracker4.addChunk(AbstractLeader.FIRST_CHUNK_INDEX+2, chunk2, Optional.<Integer>absent());
76             Assert.fail();
77         } catch(SnapshotTracker.InvalidChunkException e){
78
79         }
80
81         // No exceptions will be thrown when invalid chunk is added with the right sequence
82         // If the lastChunkHashCode is missing
83         SnapshotTracker tracker5 = new SnapshotTracker(mock(LoggingAdapter.class), 2);
84
85         tracker5.addChunk(AbstractLeader.FIRST_CHUNK_INDEX, chunk1, Optional.<Integer>absent());
86         // Look I can add the same chunk again
87         tracker5.addChunk(AbstractLeader.FIRST_CHUNK_INDEX + 1, chunk1, Optional.<Integer>absent());
88
89         // An exception will be thrown when an invalid chunk is addedd with the right sequence
90         // when the lastChunkHashCode is present
91         SnapshotTracker tracker6 = new SnapshotTracker(mock(LoggingAdapter.class), 2);
92
93         tracker6.addChunk(AbstractLeader.FIRST_CHUNK_INDEX, chunk1, Optional.of(-1));
94
95         try {
96             // Here we add a second chunk and tell addChunk that the previous chunk had a hash code 777
97             tracker6.addChunk(AbstractLeader.FIRST_CHUNK_INDEX + 1, chunk2, Optional.of(777));
98             Assert.fail();
99         }catch(SnapshotTracker.InvalidChunkException e){
100
101         }
102
103     }
104
105     @Test
106     public void testGetSnapShot() throws SnapshotTracker.InvalidChunkException {
107
108         // Trying to get a snapshot before all chunks have been received will throw an exception
109         SnapshotTracker tracker1 = new SnapshotTracker(mock(LoggingAdapter.class), 5);
110
111         tracker1.addChunk(1, chunk1, Optional.<Integer>absent());
112         try {
113             tracker1.getSnapshot();
114             Assert.fail();
115         } catch(IllegalStateException e){
116
117         }
118
119         SnapshotTracker tracker2 = new SnapshotTracker(mock(LoggingAdapter.class), 3);
120
121         tracker2.addChunk(1, chunk1, Optional.<Integer>absent());
122         tracker2.addChunk(2, chunk2, Optional.<Integer>absent());
123         tracker2.addChunk(3, chunk3, Optional.<Integer>absent());
124
125         byte[] snapshot = tracker2.getSnapshot();
126
127         assertEquals(byteString, ByteString.copyFrom(snapshot));
128     }
129
130     @Test
131     public void testGetCollectedChunks() throws SnapshotTracker.InvalidChunkException {
132         SnapshotTracker tracker1 = new SnapshotTracker(mock(LoggingAdapter.class), 5);
133
134         ByteString chunks = chunk1.concat(chunk2);
135
136         tracker1.addChunk(1, chunk1, Optional.<Integer>absent());
137         tracker1.addChunk(2, chunk2, Optional.<Integer>absent());
138
139         assertEquals(chunks, tracker1.getCollectedChunks());
140     }
141
142     public ByteString getNextChunk (ByteString bs, int offset, int size){
143         int snapshotLength = bs.size();
144         int start = offset;
145         if (size > snapshotLength) {
146             size = snapshotLength;
147         } else {
148             if ((start + size) > snapshotLength) {
149                 size = snapshotLength - start;
150             }
151         }
152         return bs.substring(start, start + size);
153     }
154
155     private ByteString toByteString(Map<String, String> state) {
156         ByteArrayOutputStream b = null;
157         ObjectOutputStream o = null;
158         try {
159             try {
160                 b = new ByteArrayOutputStream();
161                 o = new ObjectOutputStream(b);
162                 o.writeObject(state);
163                 byte[] snapshotBytes = b.toByteArray();
164                 return ByteString.copyFrom(snapshotBytes);
165             } finally {
166                 if (o != null) {
167                     o.flush();
168                     o.close();
169                 }
170                 if (b != null) {
171                     b.close();
172                 }
173             }
174         } catch (IOException e) {
175             org.junit.Assert.fail("IOException in converting Hashmap to Bytestring:" + e);
176         }
177         return null;
178     }
179
180
181 }

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.