|
4 | 4 | package simplex_test |
5 | 5 |
|
6 | 6 | import ( |
| 7 | + "bytes" |
7 | 8 | "context" |
8 | 9 | "simplex" |
9 | 10 | "simplex/testutil" |
@@ -172,6 +173,72 @@ func TestReplicationStartsBeforeCurrentRound(t *testing.T) { |
172 | 173 | } |
173 | 174 | } |
174 | 175 |
|
| 176 | +// TestReplicationAfterNodeDisconnects tests the replication process of a node that |
| 177 | +// disconnects from the network and reconnects after the rest of the network has made progress. |
| 178 | +func TestReplicationAfterNodeDisconnects(t *testing.T) { |
| 179 | + bb := newTestControlledBlockBuilder(t) |
| 180 | + nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("lagging")} |
| 181 | + net := newInMemNetwork(t, nodes) |
| 182 | + startDisconnect := uint64(5) |
| 183 | + endDisconnect := uint64(18) |
| 184 | + |
| 185 | + normalNode1 := newSimplexNode(t, nodes[0], net, bb, true) |
| 186 | + normalNode2 := newSimplexNode(t, nodes[1], net, bb, true) |
| 187 | + normalNode3 := newSimplexNode(t, nodes[2], net, bb, true) |
| 188 | + laggingNode := newSimplexNode(t, nodes[3], net, bb, true) |
| 189 | + |
| 190 | + require.Equal(t, uint64(0), normalNode1.storage.Height()) |
| 191 | + require.Equal(t, uint64(0), normalNode2.storage.Height()) |
| 192 | + require.Equal(t, uint64(0), normalNode3.storage.Height()) |
| 193 | + require.Equal(t, uint64(0), laggingNode.storage.Height()) |
| 194 | + |
| 195 | + bb.triggerNewBlock() |
| 196 | + |
| 197 | + net.startInstances() |
| 198 | + |
| 199 | + for i := uint64(0); i < startDisconnect; i++ { |
| 200 | + for _, n := range net.instances { |
| 201 | + n.storage.waitForBlockCommit(i) |
| 202 | + } |
| 203 | + |
| 204 | + bb.triggerNewBlock() |
| 205 | + } |
| 206 | + |
| 207 | + require.Equal(t, startDisconnect, normalNode1.storage.Height()) |
| 208 | + require.Equal(t, startDisconnect, normalNode2.storage.Height()) |
| 209 | + require.Equal(t, startDisconnect, normalNode3.storage.Height()) |
| 210 | + require.Equal(t, startDisconnect, laggingNode.storage.Height()) |
| 211 | + |
| 212 | + // lagging node disconnects |
| 213 | + net.Disconnect(nodes[3]) |
| 214 | + |
| 215 | + // normal nodes continue to make progress |
| 216 | + for i := startDisconnect; i < endDisconnect; i++ { |
| 217 | + if bytes.Equal(simplex.LeaderForRound(nodes, i), nodes[3]) { |
| 218 | + // TODO: build empty block |
| 219 | + } |
| 220 | + for _, n := range net.instances[:3] { |
| 221 | + n.storage.waitForBlockCommit(i) |
| 222 | + } |
| 223 | + bb.triggerNewBlock() |
| 224 | + } |
| 225 | + |
| 226 | + require.Equal(t, endDisconnect, normalNode1.storage.Height()) |
| 227 | + require.Equal(t, endDisconnect, normalNode2.storage.Height()) |
| 228 | + require.Equal(t, endDisconnect, normalNode3.storage.Height()) |
| 229 | + require.Equal(t, startDisconnect, laggingNode.storage.Height()) |
| 230 | + |
| 231 | + // lagging node reconnects |
| 232 | + net.Connect(nodes[3]) |
| 233 | + |
| 234 | + // lagging node catches up |
| 235 | + bb.triggerNewBlock() |
| 236 | + require.Equal(t, endDisconnect+1, laggingNode.storage.Height()) |
| 237 | + require.Equal(t, endDisconnect+1, normalNode1.storage.Height()) |
| 238 | + require.Equal(t, endDisconnect+1, normalNode2.storage.Height()) |
| 239 | + require.Equal(t, endDisconnect+1, normalNode3.storage.Height()) |
| 240 | +} |
| 241 | + |
175 | 242 | func createBlocks(t *testing.T, nodes []simplex.NodeID, bb simplex.BlockBuilder, seqCount uint64) []simplex.FinalizedBlock { |
176 | 243 | logger := testutil.MakeLogger(t, int(0)) |
177 | 244 | ctx := context.Background() |
|
0 commit comments