Example #1
0
class TestNode(TestCase):
    def setUp(self):
        self.channel = HistoryChannel(replicas=['A', 'B', 'C'])
        self.state = State(storage=InMemoryStorage("fakefile"))
        self.ledger = Ledger(storage=InMemoryStorage("fakefile2"))
        self.role = Node(ledger=self.ledger, state=self.state)
        self.role.notification = ImmediateNotificiation()

    def test_node_receives_higher_proposals(self):
        self.assertEqual(self.state.read(Node.PROPOSED), Proposal(None, 0))

        self.role.receive(Prepare.create(proposal=Proposal('A', 1)), self.channel)
        self.assertEqual(self.state.read(Node.PROPOSED), Proposal('A', 2))

        self.role.receive(Promise.create(proposal=Proposal('A', 3)), self.channel)
        self.assertEqual(self.state.read(Node.PROPOSED), Proposal('A', 4))

        self.role.receive(Accept.create(proposal=Proposal('A', 5)), self.channel)
        self.assertEqual(self.state.read(Node.PROPOSED), Proposal('A', 6))

        self.role.receive(Accepted.create(proposal=Proposal('A', 7)), self.channel)
        self.assertEqual(self.state.read(Node.PROPOSED), Proposal('A', 8))

    def test_role_behind_sends_sync_message(self):
        self.role.receive(Prepare.create(proposal=Proposal('A', 2)), self.channel)

        self.assertTrue(type(self.channel.unicast_messages[0]) is Sync)
Example #2
0
class TestAcceptor(TestCase):
    def setUp(self):
        self.channel = HistoryChannel()
        self.state = State(storage=InMemoryStorage("fakefile"))
        self.role = Acceptor(state=self.state)

    def test_acceptor_receives_higher_prepare(self):
        self.role.receive(Prepare.create(proposal=Proposal('A', 1)), self.channel)
        self.role.receive(Prepare.create(proposal=Proposal('A', 2)), self.channel)

        self.assertEqual(len(self.channel.unicast_messages), 2)
        self.assertEqual(self.state.read(Acceptor.PROMISED), Proposal('A', 2))
        self.assertTrue(type(self.channel.unicast_messages[-1]) is Promise)

    def test_acceptor_receives_lower_prepare(self):
        self.role.receive(Prepare.create(proposal=Proposal('A', 1)), self.channel)
        self.role.receive(Prepare.create(proposal=Proposal('A', 0)), self.channel)

        self.assertEqual(len(self.channel.unicast_messages), 2)
        self.assertEqual(self.state.read(Acceptor.PROMISED), Proposal('A', 1))
        self.assertTrue(type(self.channel.unicast_messages[-1]) is Nack)

    def test_acceptor_receivers_identical_prepare_from_same_replica(self):
        self.role.receive(Prepare.create(proposal=Proposal('A', 1)), self.channel)
        self.role.receive(Prepare.create(proposal=Proposal('A', 1)), self.channel)

        self.assertEqual(len(self.channel.unicast_messages), 2)
        self.assertEqual(self.state.read(Acceptor.PROMISED), Proposal('A', 1))
        self.assertEqual([type(t) for t in self.channel.unicast_messages], [Promise, Promise])

    def test_acceptor_receivers_identical_prepare_from_another_replica(self):
        self.role.receive(Prepare.create(proposal=Proposal('A', 1)), self.channel)
        self.role.receive(Prepare.create(proposal=Proposal('B', 1)), self.channel)

        self.assertEqual(len(self.channel.unicast_messages), 2)
        self.assertEqual(self.state.read(Acceptor.PROMISED), Proposal('A', 1))
        self.assertEqual([type(m) for m in self.channel.unicast_messages], [Promise, Nack])

    def test_acceptor_receives_lower_prepare_and_then_receives_accept(self):
        self.role.receive(Prepare.create(proposal=Proposal('A', 1)), self.channel)
        self.role.receive(Prepare.create(proposal=Proposal('A', 0)), self.channel)
        self.role.receive(Accept.create(proposal=Proposal('A', 1)), self.channel)

        self.assertTrue(type(self.channel.broadcast_messages[0]) is Accepted)

    def test_acceptor_receives_prepare_and_then_receives_lower_accept(self):
        self.role.receive(Prepare.create(proposal=Proposal('A', 1)), self.channel)
        self.role.receive(Accept.create(proposal=Proposal('A', 0)), self.channel)

        self.assertTrue(type(self.channel.unicast_messages[-1]) is Nack)
Example #3
0
 def setUp(self):
     self.channel = HistoryChannel()
     self.state = State(storage=InMemoryStorage("fakefile"))
     self.role = Acceptor(state=self.state)
Example #4
0
 def setUp(self):
     self.channel = HistoryChannel(replicas=['A', 'B', 'C'])
     self.state = State(storage=InMemoryStorage("fakefile"))
     self.ledger_storage = InMemoryStorage("fakefile2")
     self.ledger = Ledger(storage=self.ledger_storage)
     self.role = Learner(ledger=self.ledger, state=self.state)
Example #5
0
class TestLearner(TestCase):
    def setUp(self):
        self.channel = HistoryChannel(replicas=['A', 'B', 'C'])
        self.state = State(storage=InMemoryStorage("fakefile"))
        self.ledger_storage = InMemoryStorage("fakefile2")
        self.ledger = Ledger(storage=self.ledger_storage)
        self.role = Learner(ledger=self.ledger, state=self.state)

    def test_learner_receives_quorum_of_accepteds(self):
        self.role.receive(Accepted.create(proposal=Proposal('A', 1), sender='A'), self.channel)
        self.role.receive(Accepted.create(proposal=Proposal('A', 1), sender='B'), self.channel)
        self.role.receive(Accepted.create(proposal=Proposal('A', 1), sender='C'), self.channel)

        self.assertTrue(type(self.channel.unicast_messages[0]) is Request)
        self.assertTrue(type(self.channel.unicast_messages[1]) is Response)

    def test_learner_receives_quorum_of_accepteds_causes_proposal_to_increment(self):
        self.role.receive(Accepted.create(proposal=Proposal('A', 1), sender='A'), self.channel)
        self.role.receive(Accepted.create(proposal=Proposal('A', 1), sender='B'), self.channel)
        self.role.receive(Accepted.create(proposal=Proposal('A', 1), sender='C'), self.channel)

        self.assertTrue(self.state.read(Role.PROPOSED), Proposal('A', 2))


    def test_learner_ignores_duplicate_accepteds(self):
        self.role.receive(Accepted.create(proposal=Proposal('A', 1), sender='A'), self.channel)
        self.role.receive(Accepted.create(proposal=Proposal('A', 1), sender='A'), self.channel)
        self.role.receive(Accepted.create(proposal=Proposal('A', 1), sender='A'), self.channel)

        self.assertFalse(self.channel.unicast_messages)

    def test_learner_receives_sync(self):
        self.ledger.append(LedgerEntry(number=1, value="value_1"))
        self.ledger.append(LedgerEntry(number=2, value="value_2"))
        self.ledger.append(LedgerEntry(number=3, value="value_3"))

        self.role.receive(Sync.create(proposal=Proposal('A', 1), sender='A'), self.channel)

        message = self.channel.unicast_messages[-1]
        self.assert_equal(message.proposal[0], LedgerEntry(number=1, value="value_1"))
        self.assert_equal(message.proposal[1], LedgerEntry(number=2, value="value_2"))
        self.assert_equal(message.proposal[2], LedgerEntry(number=3, value="value_3"))

    def test_learner_receives_synced(self):
        proposals = [LedgerEntry(number=1, value="v_1"),
                     LedgerEntry(number=2, value="v_2"),
                     LedgerEntry(number=3, value="v_3")]

        self.role.receive(Synced.create(proposal=proposals, sender='A'), self.channel)

        def get_entry(line):
            return LedgerEntry(*line.split(LedgerEntry.SEPARATOR))

        self.assert_equal(get_entry(self.ledger_storage[0]), LedgerEntry(number=1, value="v_1"))
        self.assert_equal(get_entry(self.ledger_storage[1]), LedgerEntry(number=2, value="v_2"))
        self.assert_equal(get_entry(self.ledger_storage[2]), LedgerEntry(number=3, value="v_3"))

    def test_learner_receives_synced_and_merges_results(self):
        self.ledger_storage.append(str(LedgerEntry(number=1, value="v_1")))

        proposals = [LedgerEntry(number=1, value="v_1"),
                     LedgerEntry(number=2, value="v_2"),
                     LedgerEntry(number=3, value="v_3")]

        self.role.receive(Synced.create(proposal=proposals, sender='A'), self.channel)

        def get_entry(line):
            return LedgerEntry(*line.split(LedgerEntry.SEPARATOR))

        self.assert_equal(get_entry(self.ledger_storage[0]), LedgerEntry(number=1, value="v_1"))
        self.assert_equal(get_entry(self.ledger_storage[1]), LedgerEntry(number=2, value="v_2"))
        self.assert_equal(get_entry(self.ledger_storage[2]), LedgerEntry(number=3, value="v_3"))

    def test_learner_sync_messages(self):
        for i in range(Learner.SYNC_SIZE + 1):
            self.ledger.append(LedgerEntry(number=i, value="value_{0}".format(i)))

        self.role.receive(Sync.create(proposal=Proposal('A', 1), sender='A'), self.channel)

        message = self.channel.unicast_messages[-1]
        self.assertEqual(Learner.SYNC_SIZE, len(message.proposal))
        self.assertTrue(not message.finished)

    def assert_equal(self, actual_entry, expected_entry):
        self.assertEqual(actual_entry.number, expected_entry.number)
        self.assertEqual(actual_entry.value, expected_entry.value)
Example #6
0
 def setUp(self):
     self.channel = HistoryChannel(replicas=['A', 'B', 'C'])
     self.state = State(storage=InMemoryStorage("fakefile"))
     self.ledger = Ledger(storage=InMemoryStorage("fakefile2"))
     self.role = Node(ledger=self.ledger, state=self.state)
     self.role.notification = ImmediateNotificiation()