/* * Copyright 2009 Amit Levy, Jeff Prouty, Rylan Hawkins * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package edu.washington.cs.cse490h.donut; import static org.junit.Assert.assertEquals; import java.util.List; import org.junit.Test; import edu.washington.cs.cse490h.donut.business.Node; import edu.washington.cs.cse490h.donut.business.TNode; import edu.washington.cs.cse490h.donut.util.DonutTestCase; import edu.washington.cs.cse490h.donut.util.DonutTestRunner; /** * @author alevy, jprouty, rylan */ public class DonutJoinLeaveTest { private static final int DEFAULT_TIME_TO_FIX_FINGERS = (int) (Constants.FIX_FINGERS_INTERVAL * 64 * 2); @Test public void testJoinOneNodeRing() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(0); donutTestRunner.addEvent(0).join(0, 0); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); assertEquals(node0.getTNode(), node0.getPredecessor()); // All of node0's fingers should be pointing to node0 for (int i = 0; i < Constants.KEY_SPACE; ++i) { assertEquals("Incorrect finger " + i, node0.getTNode(), node0.getFinger(i)); } List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), node0.getTNode()); } } }); donutTestRunner.run(); } @Test public void testJoinTwoPositives() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(100, 1124); donutTestRunner.addEvent(0).join(0, 0); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).join(1, 0); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS * 2).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); Node node1 = donutTestRunner.node(1); assertEquals(node1.getTNode(), node0.getPredecessor()); assertEquals(node0.getTNode(), node1.getPredecessor()); // node0's first 11 fingers should be pointing to node1 // The rest should be at node0 (itself) for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 11) assertEquals("Incorrect finger " + i, node1.getTNode(), node0.getFinger(i)); else assertEquals("Incorrect finger " + i, node0.getTNode(), node0.getFinger(i)); } // All of node1's fingers should be pointing to node0 for (int i = 0; i < Constants.KEY_SPACE; ++i) { assertEquals("Incorrect finger " + i, node0.getTNode(), node1.getFinger(i)); } assertEquals(node0.getTNode(), node1.getPredecessor()); List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node1.getTNode() : node0.getTNode()); } list = node1.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node0.getTNode() : node1.getTNode()); } } }); donutTestRunner.run(); } @Test public void testJoinTwoPositiveAndNegative() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(0, -0x2000000000000000L); donutTestRunner.addEvent(0).join(0, 0); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).join(1, 0); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS * 2).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); Node node1 = donutTestRunner.node(1); assertEquals(node1.getTNode(), node0.getPredecessor()); assertEquals(node0.getTNode(), node1.getPredecessor()); // All of node0's fingers should be pointing to node1 for (int i = 0; i < Constants.KEY_SPACE; ++i) { assertEquals("Incorrect finger " + i, node1.getTNode(), node0.getFinger(i)); } // node1's first 62 fingers should be pointing to node0 // The rest should be at node1 (itself) for (int i = 0; i < Constants.KEY_SPACE - 2; ++i) { if (i < 62) assertEquals("Incorrect finger " + i, node0.getTNode(), node1.getFinger(i)); else assertEquals("Incorrect finger " + i, node1.getTNode(), node1.getFinger(i)); } List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node1.getTNode() : node0.getTNode()); } list = node1.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node0.getTNode() : node1.getTNode()); } } }); donutTestRunner.run(); } @Test public void testJoinTwoPositiveAndNegativeAllAtOnce() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(0, -0x2000000000000000L); donutTestRunner.addEvent(0).join(1, 1); donutTestRunner.addEvent(0).join(0, 1); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); Node node1 = donutTestRunner.node(1); assertEquals(node1.getTNode(), node0.getPredecessor()); assertEquals(node0.getTNode(), node1.getPredecessor()); // All of node0's fingers should be pointing to node1 for (int i = 0; i < Constants.KEY_SPACE; ++i) { assertEquals("Incorrect finger " + i, node1.getTNode(), node0.getFinger(i)); } // node1's first 62 fingers should be pointing to node0 // The rest should be at node1 (itself) for (int i = 0; i < Constants.KEY_SPACE - 2; ++i) { if (i < 62) assertEquals("Incorrect finger " + i, node0.getTNode(), node1.getFinger(i)); else assertEquals("Incorrect finger " + i, node1.getTNode(), node1.getFinger(i)); } List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node1.getTNode() : node0.getTNode()); } list = node1.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node0.getTNode() : node1.getTNode()); } } }); donutTestRunner.run(); } @Test public void testJoinTwoPositiveAndNegativeAllAtOnceWithEachOtherAsKnown() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(0, -0x2000000000000000L); donutTestRunner.addEvent(0).join(1, 0); donutTestRunner.addEvent(0).join(0, 1); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); Node node1 = donutTestRunner.node(1); assertEquals(node1.getTNode(), node0.getPredecessor()); assertEquals(node0.getTNode(), node1.getPredecessor()); // All of node0's fingers should be pointing to node1 for (int i = 0; i < Constants.KEY_SPACE; ++i) { assertEquals("Incorrect finger " + i, node1.getTNode(), node0.getFinger(i)); } // node1's first 62 fingers should be pointing to node0 // The rest should be at node1 (itself) for (int i = 0; i < Constants.KEY_SPACE - 2; ++i) { if (i < 62) assertEquals("Incorrect finger " + i, node0.getTNode(), node1.getFinger(i)); else assertEquals("Incorrect finger " + i, node1.getTNode(), node1.getFinger(i)); } List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node1.getTNode() : node0.getTNode()); } list = node1.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node0.getTNode() : node1.getTNode()); } } }); donutTestRunner.run(); } @Test public void testJoinFourAllAtOnce() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(0x0L, 0x4000000000000000L, 0x8000000000000000L, 0xC000000000000000L); // Joining nodes in different orders and by linking different known hosts donutTestRunner.addEvent(0).join(3, 3); donutTestRunner.addEvent(0).join(2, 3); donutTestRunner.addEvent(0).join(0, 3); donutTestRunner.addEvent(0).join(1, 0); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); Node node1 = donutTestRunner.node(1); Node node2 = donutTestRunner.node(2); Node node3 = donutTestRunner.node(3); // node0 -> node1 -> node2 -> node3 -> ... (node0) assertEquals(node3.getTNode(), node0.getPredecessor()); assertEquals(node0.getTNode(), node1.getPredecessor()); assertEquals(node1.getTNode(), node2.getPredecessor()); assertEquals(node2.getTNode(), node3.getPredecessor()); // node0's first 63 fingers should be pointing to node1 // node0's last finger should be pointing to node2 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node1.getTNode(), node0.getFinger(i)); else assertEquals("Incorrect finger " + i, node2.getTNode(), node0.getFinger(i)); } // node1's first 63 fingers should be pointing to node2 // node1's last finger should be pointing to node3 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node2.getTNode(), node1.getFinger(i)); else assertEquals("Incorrect finger " + i, node3.getTNode(), node1.getFinger(i)); } // node2's first 63 fingers should be pointing to node3 // node2's last finger should be pointing to node0 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node3.getTNode(), node2.getFinger(i)); else assertEquals("Incorrect finger " + i, node0.getTNode(), node2.getFinger(i)); } // node3's first 63 fingers should be pointing to node3 // node3's last finger should be pointing to node1 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node0.getTNode(), node3.getFinger(i)); else assertEquals("Incorrect finger " + i, node1.getTNode(), node3.getFinger(i)); } List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((1 + i) % 4).getTNode()); } list = node1.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((2 + i) % 4).getTNode()); } list = node2.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((3 + i) % 4).getTNode()); } list = node3.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((4 + i) % 4).getTNode()); } } }); donutTestRunner.run(); } @Test public void testJoinFourOutOfOrder() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(0x0L, 0x4000000000000000L, 0x8000000000000000L, 0xC000000000000000L); // Joining nodes in different orders and by linking different known hosts donutTestRunner.addEvent(0).join(2, 2); donutTestRunner.addEvent(0).join(0, 2); donutTestRunner.addEvent(0).join(3, 0); donutTestRunner.addEvent(0).join(1, 2); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); Node node1 = donutTestRunner.node(1); Node node2 = donutTestRunner.node(2); Node node3 = donutTestRunner.node(3); // node0 -> node1 -> node2 -> node3 -> ... (node0) assertEquals(node3.getTNode(), node0.getPredecessor()); assertEquals(node0.getTNode(), node1.getPredecessor()); assertEquals(node1.getTNode(), node2.getPredecessor()); assertEquals(node2.getTNode(), node3.getPredecessor()); // node0's first 63 fingers should be pointing to node1 // node0's last finger should be pointing to node2 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node1.getTNode(), node0.getFinger(i)); else assertEquals("Incorrect finger " + i, node2.getTNode(), node0.getFinger(i)); } // node1's first 63 fingers should be pointing to node2 // node1's last finger should be pointing to node3 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node2.getTNode(), node1.getFinger(i)); else assertEquals("Incorrect finger " + i, node3.getTNode(), node1.getFinger(i)); } // node2's first 63 fingers should be pointing to node3 // node2's last finger should be pointing to node0 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node3.getTNode(), node2.getFinger(i)); else assertEquals("Incorrect finger " + i, node0.getTNode(), node2.getFinger(i)); } // node3's first 63 fingers should be pointing to node3 // node3's last finger should be pointing to node1 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node0.getTNode(), node3.getFinger(i)); else assertEquals("Incorrect finger " + i, node1.getTNode(), node3.getFinger(i)); } List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((1 + i) % 4).getTNode()); } list = node1.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((2 + i) % 4).getTNode()); } list = node2.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((3 + i) % 4).getTNode()); } list = node3.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((4 + i) % 4).getTNode()); } } }); donutTestRunner.run(); } @Test public void testJoinFourLeaveOne() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(0x0L, 0x4000000000000000L, 0x8000000000000000L, 0xC000000000000000L); donutTestRunner.addEvent(0).join(0, 0); donutTestRunner.addEvent(0).join(1, 0); donutTestRunner.addEvent(0).join(2, 0); donutTestRunner.addEvent(0).join(3, 0); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); Node node1 = donutTestRunner.node(1); Node node2 = donutTestRunner.node(2); Node node3 = donutTestRunner.node(3); // node0 -> node1 -> node2 -> node3 -> ... (node0) assertEquals(node3.getTNode(), node0.getPredecessor()); assertEquals(node0.getTNode(), node1.getPredecessor()); assertEquals(node1.getTNode(), node2.getPredecessor()); assertEquals(node2.getTNode(), node3.getPredecessor()); // node0's first 63 fingers should be pointing to node1 // node0's last finger should be pointing to node2 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node1.getTNode(), node0.getFinger(i)); else assertEquals("Incorrect finger " + i, node2.getTNode(), node0.getFinger(i)); } // node1's first 63 fingers should be pointing to node2 // node1's last finger should be pointing to node3 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node2.getTNode(), node1.getFinger(i)); else assertEquals("Incorrect finger " + i, node3.getTNode(), node1.getFinger(i)); } // node2's first 63 fingers should be pointing to node3 // node2's last finger should be pointing to node0 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node3.getTNode(), node2.getFinger(i)); else assertEquals("Incorrect finger " + i, node0.getTNode(), node2.getFinger(i)); } // node3's first 63 fingers should be pointing to node3 // node3's last finger should be pointing to node1 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node0.getTNode(), node3.getFinger(i)); else assertEquals("Incorrect finger " + i, node1.getTNode(), node3.getFinger(i)); } List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((1 + i) % 4).getTNode()); } list = node1.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((2 + i) % 4).getTNode()); } list = node2.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((3 + i) % 4).getTNode()); } list = node3.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((4 + i) % 4).getTNode()); } } }); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS * 2).leave(3); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS * 3).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); Node node1 = donutTestRunner.node(1); Node node2 = donutTestRunner.node(2); // node0 -> node1 -> node2 -> ... (node0) assertEquals(node2.getTNode(), node0.getPredecessor()); assertEquals(node0.getTNode(), node1.getPredecessor()); assertEquals(node1.getTNode(), node2.getPredecessor()); // node0's first 63 fingers should be pointing to node1 // node0's last finger should be pointing to node2 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node1.getTNode(), node0.getFinger(i)); else assertEquals("Incorrect finger " + i, node2.getTNode(), node0.getFinger(i)); } // node1's first 63 fingers should be pointing to node2 // node1's last finger should be pointing to node0 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node2.getTNode(), node1.getFinger(i)); else assertEquals("Incorrect finger " + i, node0.getTNode(), node1.getFinger(i)); } // All of node2's fingers should be pointing to node0 for (int i = 0; i < Constants.KEY_SPACE; ++i) { assertEquals("Incorrect finger " + i, node0.getTNode(), node2.getFinger(i)); } List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(donutTestRunner.node((1 + i) % 3).getTNode(), list.get(i)); } list = node1.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(donutTestRunner.node((2 + i) % 3).getTNode(), list.get(i)); } list = node2.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(donutTestRunner.node((3 + i) % 3).getTNode(), list.get(i)); } } }); donutTestRunner.run(); } @Test public void testJoinFourLeaveTwo() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(0x0L, 0x4000000000000000L, 0x8000000000000000L, 0xC000000000000000L); donutTestRunner.addEvent(0).join(0, 1); donutTestRunner.addEvent(0).join(1, 2); donutTestRunner.addEvent(0).join(2, 3); donutTestRunner.addEvent(0).join(3, 0); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).leave(2); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS * 2).leave(1); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS * 3).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); Node node3 = donutTestRunner.node(3); assertEquals(node3.getTNode(), node0.getPredecessor()); assertEquals(node0.getTNode(), node3.getPredecessor()); for (int i = 0; i < Constants.KEY_SPACE; ++i) { assertEquals("Incorrect finger " + i, node3.getTNode(), node0.getFinger(i)); } for (int i = 0; i < Constants.KEY_SPACE - 1; ++i) { assertEquals("Incorrect finger " + i, node0.getTNode(), node3.getFinger(i)); } assertEquals("Incorrect finger " + (Constants.KEY_SPACE - 1), node3.getTNode(), node3.getFinger(Constants.KEY_SPACE - 1)); List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node3.getTNode() : node0.getTNode()); } list = node3.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node0.getTNode() : node3.getTNode()); } } }); donutTestRunner.run(); } @Test public void testJoinFourLeaveTwoNonConigousAtTheSameTime() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(0x0L, 0x4000000000000000L, 0x8000000000000000L, 0xC000000000000000L); donutTestRunner.addEvent(0).join(0, 1); donutTestRunner.addEvent(0).join(1, 2); donutTestRunner.addEvent(0).join(2, 3); donutTestRunner.addEvent(0).join(3, 0); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).leave(1); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).leave(3); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS * 2).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); Node node2 = donutTestRunner.node(2); assertEquals(node2.getTNode(), node0.getPredecessor()); assertEquals(node0.getTNode(), node2.getPredecessor()); for (int i = 0; i < Constants.KEY_SPACE; ++i) { assertEquals("Incorrect finger " + i, node2.getTNode(), node0.getFinger(i)); } for (int i = 0; i < Constants.KEY_SPACE; ++i) { assertEquals("Incorrect finger " + i, node0.getTNode(), node2.getFinger(i)); } List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node2.getTNode() : node0.getTNode()); } list = node2.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node0.getTNode() : node2.getTNode()); } } }); donutTestRunner.run(); } @Test public void testJoinFourLeaveTwoConigousAtTheSameTime() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(0x0L, 0x4000000000000000L, 0x8000000000000000L, 0xC000000000000000L); donutTestRunner.addEvent(0).join(0, 1); donutTestRunner.addEvent(0).join(1, 2); donutTestRunner.addEvent(0).join(2, 3); donutTestRunner.addEvent(0).join(3, 0); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).leave(1); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).leave(2); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS * 2).test(new DonutTestCase() { public void test() { Node node0 = donutTestRunner.node(0); Node node3 = donutTestRunner.node(3); assertEquals(node3.getTNode(), node0.getPredecessor()); assertEquals(node0.getTNode(), node3.getPredecessor()); for (int i = 0; i < Constants.KEY_SPACE; ++i) { assertEquals("Incorrect finger " + i, node3.getTNode(), node0.getFinger(i)); } for (int i = 0; i < Constants.KEY_SPACE - 1; ++i) { assertEquals("Incorrect finger " + i, node0.getTNode(), node3.getFinger(i)); } assertEquals("Incorrect finger " + (Constants.KEY_SPACE - 1), node3.getTNode(), node3.getFinger(Constants.KEY_SPACE - 1)); List<TNode> list = node0.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node3.getTNode() : node0.getTNode()); } list = node3.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), (i % 2 == 0) ? node0.getTNode() : node3.getTNode()); } } }); donutTestRunner.run(); } @Test public void testJoinFourLeaveOneThenRejoin() throws Exception { final DonutTestRunner donutTestRunner = new DonutTestRunner(0x0L, 0x4000000000000000L, 0x8000000000000000L, 0xC000000000000000L); donutTestRunner.addEvent(0).join(2, 2); donutTestRunner.addEvent(0).join(0, 2); donutTestRunner.addEvent(0).join(3, 0); donutTestRunner.addEvent(0).join(1, 2); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS).leave(0); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS * 2).joinNewNode(2, "node4", 0x0L); donutTestRunner.addEvent(DEFAULT_TIME_TO_FIX_FINGERS * 3).test(new DonutTestCase() { public void test() { Node node4 = donutTestRunner.node(4); Node node1 = donutTestRunner.node(1); Node node2 = donutTestRunner.node(2); Node node3 = donutTestRunner.node(3); // node4 -> node1 -> node2 -> node3 -> ... (node4) assertEquals(node3.getTNode(), node4.getPredecessor()); assertEquals(node4.getTNode(), node1.getPredecessor()); assertEquals(node1.getTNode(), node2.getPredecessor()); assertEquals(node2.getTNode(), node3.getPredecessor()); // node0's first 63 fingers should be pointing to node1 // node0's last finger should be pointing to node2 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node1.getTNode(), node4.getFinger(i)); else assertEquals("Incorrect finger " + i, node2.getTNode(), node4.getFinger(i)); } // node1's first 63 fingers should be pointing to node2 // node1's last finger should be pointing to node3 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node2.getTNode(), node1.getFinger(i)); else assertEquals("Incorrect finger " + i, node3.getTNode(), node1.getFinger(i)); } // node2's first 63 fingers should be pointing to node3 // node2's last finger should be pointing to node0 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node3.getTNode(), node2.getFinger(i)); else assertEquals("Incorrect finger " + i, node4.getTNode(), node2.getFinger(i)); } // node3's first 63 fingers should be pointing to node3 // node3's last finger should be pointing to node1 for (int i = 0; i < Constants.KEY_SPACE; ++i) { if (i < 63) assertEquals("Incorrect finger " + i, node4.getTNode(), node3.getFinger(i)); else assertEquals("Incorrect finger " + i, node1.getTNode(), node3.getFinger(i)); } List<TNode> list = node4.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((i) % 4 + 1).getTNode()); } list = node1.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((1 + i) % 4 + 1).getTNode()); } list = node2.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((2 + i) % 4 + 1).getTNode()); } list = node3.getSuccessorList(); for (int i = 0; i < Constants.SUCCESSOR_LIST_SIZE; ++i) { assertEquals(list.get(i), donutTestRunner.node((3 + i) % 4 + 1).getTNode()); } } }); donutTestRunner.run(); } }