def test_candidate_server_wins_election(self): board = MemoryBoard() state = Follower() server0 = Server(0, state, [], board, []) board = MemoryBoard() state = Follower() oserver = Server(1, state, [], board, []) board = MemoryBoard() state = Candidate() server = Server(2, state, [], board, [oserver, server0]) server0._neighbors.append(server) oserver._neighbors.append(server) oserver.on_message(oserver._messageBoard.get_message()) server0.on_message(server0._messageBoard.get_message()) server._total_nodes = 3 server.on_message(server._messageBoard.get_message()) server.on_message(server._messageBoard.get_message()) self.assertEqual(type(server._state), Leader)
def setUp(self): board = MemoryBoard() state = Follower() self.oserver = Server(0, state, [], board, []) board = MemoryBoard() state = Follower() self.server = Server(1, state, [], board, [self.oserver])
def setUp(self): board = MemoryBoard() state = Follower() self.oserver = Server(0, state, [], board, []) board = MemoryBoard() state = Candidate() self.server = Server(1, state, [], board, [self.oserver]) self.oserver._neighbors.append(self.server)
def test_two_candidates_tie(self): followers = [] for i in range(4): board = MemoryBoard() state = Follower() followers.append(Server(i, state, [], board, [])) board = MemoryBoard() state = Candidate() c0 = Server(5, state, [], board, followers[0:2]) board = MemoryBoard() state = Candidate() c1 = Server(6, state, [], board, followers[2:]) for i in range(2): followers[i]._neighbors.append(c0) followers[i].on_message(followers[i]._messageBoard.get_message()) for i in range(2, 4): followers[i]._neighbors.append(c1) followers[i].on_message(followers[i]._messageBoard.get_message()) c0._total_nodes = 6 c1._total_nodes = 6 for i in range(2): c0.on_message(c0._messageBoard.get_message()) c1.on_message(c1._messageBoard.get_message()) self.assertEqual(type(c0._state), Candidate) self.assertEqual(type(c1._state), Candidate)
def setUp(self): followers = [] for i in range(1, 4): board = MemoryBoard() state = Follower() followers.append(Server(i, state, [], board, [])) board = MemoryBoard() state = Leader() self.leader = Server(0, state, [], board, followers) for i in followers: i._neighbors.append(self.leader)
class TestLeaderServer(unittest.TestCase): def setUp(self): followers = [] for i in range(1, 4): board = MemoryBoard() state = Follower() followers.append(Server(i, state, [], board, [])) board = MemoryBoard() state = Leader() self.leader = Server(0, state, [], board, followers) for i in followers: i._neighbors.append(self.leader) def _perform_hearbeat(self): self.leader._state._send_heart_beat() for i in self.leader._neighbors: i.on_message(i._messageBoard.get_message()) for i in self.leader._messageBoard._board: self.leader.on_message(i) def test_leader_server_sends_heartbeat_to_all_neighbors(self): self._perform_hearbeat() self.assertEqual( {1: 0, 2: 0, 3: 0}, self.leader._state._nextIndexes) def test_leader_server_sends_appendentries_to_all_neighbors_and_is_appended_to_their_logs(self): self._perform_hearbeat() msg = AppendEntriesMessage(0, None, 1, { "prevLogIndex": 0, "prevLogTerm": 0, "leaderCommit": 1, "entries": [{"term": 1, "value": 100}]}) self.leader.send_message(msg) for i in self.leader._neighbors: i.on_message(i._messageBoard.get_message()) for i in self.leader._neighbors: self.assertEqual([{"term": 1, "value": 100}], i._log) def test_leader_server_sends_appendentries_to_all_neighbors_but_some_have_dirtied_logs(self): self.leader._neighbors[0]._log.append({"term": 2, "value": 100}) self.leader._neighbors[0]._log.append({"term": 2, "value": 200}) self.leader._neighbors[1]._log.append({"term": 3, "value": 200}) self.leader._log.append({"term": 1, "value": 100}) self._perform_hearbeat() msg = AppendEntriesMessage(0, None, 1, { "prevLogIndex": 0, "prevLogTerm": 0, "leaderCommit": 1, "entries": [{"term": 1, "value": 100}]}) self.leader.send_message(msg) for i in self.leader._neighbors: i.on_message(i._messageBoard.get_message()) for i in self.leader._neighbors: self.assertEqual([{"term": 1, "value": 100}], i._log)
from boards.memory_board import MemoryBoard from messages.append_entries import AppendEntriesMessage from messages.request_vote import RequestVoteMessage from servers.server import Server from states.follower import Follower """ follower-0 follower-1 oserver server sender receiver """ board = MemoryBoard() state = Follower() oserver = Server(0, state, [], board, []) # print(oserver) """ _name: 0, _state: <states.follower.Follower object at 0x1047fbd68>, _log: [], _messageBoard: board: [], _neighbors: [], _total_nodes: 0, _commitIndex: 0, _currentTerm: 0, _lastApplied: 0, _lastLogIndex: 0, _lastLogTerm: None """
class TestCandidateServer(unittest.TestCase): def setUp(self): board = MemoryBoard() state = Follower() self.oserver = Server(0, state, [], board, []) board = MemoryBoard() state = Candidate() self.server = Server(1, state, [], board, [self.oserver]) self.oserver._neighbors.append(self.server) def test_candidate_server_had_intiated_the_election(self): self.assertEqual(1, len(self.oserver._messageBoard._board)) self.oserver.on_message(self.oserver._messageBoard.get_message()) self.assertEqual(1, len(self.server._messageBoard._board)) self.assertEqual( True, self.server._messageBoard.get_message().data["response"]) def test_candidate_server_had_gotten_the_vote(self): self.oserver.on_message(self.oserver._messageBoard.get_message()) self.assertEqual(1, len(self.server._messageBoard._board)) self.assertEqual( True, self.server._messageBoard.get_message().data["response"]) def test_candidate_server_wins_election(self): board = MemoryBoard() state = Follower() server0 = Server(0, state, [], board, []) board = MemoryBoard() state = Follower() oserver = Server(1, state, [], board, []) board = MemoryBoard() state = Candidate() server = Server(2, state, [], board, [oserver, server0]) server0._neighbors.append(server) oserver._neighbors.append(server) oserver.on_message(oserver._messageBoard.get_message()) server0.on_message(server0._messageBoard.get_message()) server._total_nodes = 3 server.on_message(server._messageBoard.get_message()) server.on_message(server._messageBoard.get_message()) self.assertEqual(type(server._state), Leader) def test_two_candidates_tie(self): followers = [] for i in range(4): board = MemoryBoard() state = Follower() followers.append(Server(i, state, [], board, [])) board = MemoryBoard() state = Candidate() c0 = Server(5, state, [], board, followers[0:2]) board = MemoryBoard() state = Candidate() c1 = Server(6, state, [], board, followers[2:]) for i in range(2): followers[i]._neighbors.append(c0) followers[i].on_message(followers[i]._messageBoard.get_message()) for i in range(2, 4): followers[i]._neighbors.append(c1) followers[i].on_message(followers[i]._messageBoard.get_message()) c0._total_nodes = 6 c1._total_nodes = 6 for i in range(2): c0.on_message(c0._messageBoard.get_message()) c1.on_message(c1._messageBoard.get_message()) self.assertEqual(type(c0._state), Candidate) self.assertEqual(type(c1._state), Candidate) def test_two_candidates_one_wins(self): followers = [] for i in range(6): board = MemoryBoard() state = Follower() followers.append(Server(i, state, [], board, [])) board = MemoryBoard() state = Candidate() c0 = Server(7, state, [], board, followers[0:2]) board = MemoryBoard() state = Candidate() c1 = Server(8, state, [], board, followers[2:]) for i in range(2): followers[i]._neighbors.append(c0) followers[i].on_message(followers[i]._messageBoard.get_message()) for i in range(2, 6): followers[i]._neighbors.append(c1) followers[i].on_message(followers[i]._messageBoard.get_message()) c0._total_nodes = 7 c1._total_nodes = 7 for i in range(2): c0.on_message(c0._messageBoard.get_message()) for i in range(4): c1.on_message(c1._messageBoard.get_message()) self.assertEqual(type(c0._state), Candidate) self.assertEqual(type(c1._state), Leader) def test_candidate_fails_to_win_election_so_resend_request(self): pass def test_multiple_candidates_fail_to_win_so_resend_requests(self): pass
import socket import datetime import time import sys import threading from server_config import CONFIG as server_config from servers.server import Server, ZeroMQServer #from states.follower import Follower from blocks.block import BlockChain from boards.memory_board import MemoryBoard import logging from states.characters import Follower if __name__ == '__main__': server_id = int(sys.argv[1]) logging.basicConfig(filename='server_' + str(server_id) + '.log', level=logging.DEBUG) observers = [ Server('localhost\t' + str(server_config[i]), Follower(), BlockChain(), MemoryBoard(), [], True) for i in server_config if i != server_id ] #for this_item in observers: # this_item._state.set_server(this_item) ZeroMQServer('localhost\t' + str(server_config[server_id]), Follower(), BlockChain(), MemoryBoard(), observers) #ZeroMQServer(this_server) while True: time.sleep(10)
class TestFollowerServer(unittest.TestCase): def setUp(self): board = MemoryBoard() state = Follower() self.oserver = Server(0, state, [], board, []) board = MemoryBoard() state = Follower() self.server = Server(1, state, [], board, [self.oserver]) def test_follower_server_on_message(self): msg = AppendEntriesMessage(0, 1, 2, {}) self.server.on_message(msg) def test_follower_server_on_receive_message_with_lesser_term(self): msg = AppendEntriesMessage(0, 1, -1, {}) self.server.on_message(msg) self.assertEqual( False, self.oserver._messageBoard.get_message().data["response"]) def test_follower_server_on_receive_message_with_greater_term(self): msg = AppendEntriesMessage(0, 1, 2, {}) self.server.on_message(msg) self.assertEqual(2, self.server._currentTerm) def test_follower_server_on_receive_message_where_log_does_not_have_prevLogTerm( self): self.server._log.append({"term": 100, "value": 2000}) msg = AppendEntriesMessage( 0, 1, 2, { "prevLogIndex": 0, "prevLogTerm": 1, "leaderCommit": 1, "entries": [{ "term": 1, "value": 100 }] }) self.server.on_message(msg) self.assertEqual( False, self.oserver._messageBoard.get_message().data["response"]) self.assertEqual([], self.server._log) def test_follower_server_on_receive_message_where_log_contains_conflicting_entry_at_new_index( self): self.server._log.append({"term": 1, "value": 0}) self.server._log.append({"term": 1, "value": 200}) self.server._log.append({"term": 1, "value": 300}) self.server._log.append({"term": 2, "value": 400}) msg = AppendEntriesMessage( 0, 1, 2, { "prevLogIndex": 0, "prevLogTerm": 1, "leaderCommit": 1, "entries": [{ "term": 1, "value": 100 }] }) self.server.on_message(msg) self.assertEqual({"term": 1, "value": 100}, self.server._log[1]) self.assertEqual([{ "term": 1, "value": 0 }, { "term": 1, "value": 100 }], self.server._log) def test_follower_server_on_receive_message_where_log_is_empty_and_receives_its_first_value( self): msg = AppendEntriesMessage( 0, 1, 2, { "prevLogIndex": 0, "prevLogTerm": 100, "leaderCommit": 1, "entries": [{ "term": 1, "value": 100 }] }) self.server.on_message(msg) self.assertEqual({"term": 1, "value": 100}, self.server._log[0]) def test_follower_server_on_receive_vote_request_message(self): msg = RequestVoteMessage(0, 1, 2, { "lastLogIndex": 0, "lastLogTerm": 0, "entries": [] }) self.server.on_message(msg) self.assertEqual(0, self.server._state._last_vote) self.assertEqual( True, self.oserver._messageBoard.get_message().data["response"]) def test_follower_server_on_receive_vote_request_after_sending_a_vote( self): msg = RequestVoteMessage(0, 1, 2, { "lastLogIndex": 0, "lastLogTerm": 0, "entries": [] }) self.server.on_message(msg) msg = RequestVoteMessage(2, 1, 2, {}) self.server.on_message(msg) self.assertEqual(0, self.server._state._last_vote)
class TestFollowerServer(unittest.TestCase): def setUp(self): board = MemoryBoard() state = Follower() self.oserver = Server(0, state, [], board, []) board = MemoryBoard() state = Follower() self.server = Server(1, state, [], board, [self.oserver]) def test_follower_server_on_message(self): msg = AppendEntriesMessage(0, 1, 2, {}) self.server.on_message(msg) def test_follower_server_on_receive_message_with_lesser_term(self): msg = AppendEntriesMessage(0, 1, -1, {}) self.server.on_message(msg) self.assertEqual( False, self.oserver._messageBoard.get_message().data["response"]) def test_follower_server_on_receive_message_with_greater_term(self): msg = AppendEntriesMessage(0, 1, 2, {}) self.server.on_message(msg) self.assertEqual(2, self.server._currentTerm) def test_follower_server_on_receive_message_where_log_does_not_have_prevLogTerm(self): self.server._log.append({"term": 100, "value": 2000}) msg = AppendEntriesMessage(0, 1, 2, { "prevLogIndex": 0, "prevLogTerm": 1, "leaderCommit": 1, "entries": [{"term": 1, "value": 100}]}) self.server.on_message(msg) self.assertEqual( False, self.oserver._messageBoard.get_message().data["response"]) self.assertEqual([], self.server._log) def test_follower_server_on_receive_message_where_log_contains_conflicting_entry_at_new_index(self): self.server._log.append({"term": 1, "value": 0}) self.server._log.append({"term": 1, "value": 200}) self.server._log.append({"term": 1, "value": 300}) self.server._log.append({"term": 2, "value": 400}) msg = AppendEntriesMessage(0, 1, 2, { "prevLogIndex": 0, "prevLogTerm": 1, "leaderCommit": 1, "entries": [{"term": 1, "value": 100}]}) self.server.on_message(msg) self.assertEqual({"term": 1, "value": 100}, self.server._log[1]) self.assertEqual( [{"term": 1, "value": 0}, {"term": 1, "value": 100}], self.server._log) def test_follower_server_on_receive_message_where_log_is_empty_and_receives_its_first_value(self): msg = AppendEntriesMessage(0, 1, 2, { "prevLogIndex": 0, "prevLogTerm": 100, "leaderCommit": 1, "entries": [{"term": 1, "value": 100}]}) self.server.on_message(msg) self.assertEqual({"term": 1, "value": 100}, self.server._log[0]) def test_follower_server_on_receive_vote_request_message(self): msg = RequestVoteMessage( 0, 1, 2, {"lastLogIndex": 0, "lastLogTerm": 0, "entries": []}) self.server.on_message(msg) self.assertEqual(0, self.server._state._last_vote) self.assertEqual( True, self.oserver._messageBoard.get_message().data["response"]) def test_follower_server_on_receive_vote_request_after_sending_a_vote(self): msg = RequestVoteMessage( 0, 1, 2, {"lastLogIndex": 0, "lastLogTerm": 0, "entries": []}) self.server.on_message(msg) msg = RequestVoteMessage(2, 1, 2, {}) self.server.on_message(msg) self.assertEqual(0, self.server._state._last_vote)
import argparse from servers.server import Server if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('port', type=int) parser.parse_args() args = parser.parse_args() host = 'localhost' try: server = Server(host, args.port) server.serve() except Exception as ex: print("couldn't start the server because:") print(ex)
class TestLeaderServer(unittest.TestCase): def setUp(self): followers = [] for i in range(1, 4): board = MemoryBoard() state = Follower() followers.append(Server(i, state, [], board, [])) board = MemoryBoard() state = Leader() self.leader = Server(0, state, [], board, followers) for i in followers: i._neighbors.append(self.leader) def _perform_hearbeat(self): self.leader._state._send_heart_beat() for i in self.leader._neighbors: i.on_message(i._messageBoard.get_message()) for i in self.leader._messageBoard._board: self.leader.on_message(i) def test_leader_server_sends_heartbeat_to_all_neighbors(self): self._perform_hearbeat() self.assertEqual({1: 0, 2: 0, 3: 0}, self.leader._state._nextIndexes) def test_leader_server_sends_appendentries_to_all_neighbors_and_is_appended_to_their_logs( self): self._perform_hearbeat() msg = AppendEntriesMessage( 0, None, 1, { "prevLogIndex": 0, "prevLogTerm": 0, "leaderCommit": 1, "entries": [{ "term": 1, "value": 100 }] }) self.leader.send_message(msg) for i in self.leader._neighbors: i.on_message(i._messageBoard.get_message()) for i in self.leader._neighbors: self.assertEqual([{"term": 1, "value": 100}], i._log) def test_leader_server_sends_appendentries_to_all_neighbors_but_some_have_dirtied_logs( self): self.leader._neighbors[0]._log.append({"term": 2, "value": 100}) self.leader._neighbors[0]._log.append({"term": 2, "value": 200}) self.leader._neighbors[1]._log.append({"term": 3, "value": 200}) self.leader._log.append({"term": 1, "value": 100}) self._perform_hearbeat() msg = AppendEntriesMessage( 0, None, 1, { "prevLogIndex": 0, "prevLogTerm": 0, "leaderCommit": 1, "entries": [{ "term": 1, "value": 100 }] }) self.leader.send_message(msg) for i in self.leader._neighbors: i.on_message(i._messageBoard.get_message()) for i in self.leader._neighbors: self.assertEqual([{"term": 1, "value": 100}], i._log)
import unittest from boards.memory_board import MemoryBoard from messages.append_entries import AppendEntriesMessage from messages.request_vote import RequestVoteMessage from servers.server import Server from states.follower import Follower from states.candidate import Candidate from states.leader import Leader board = MemoryBoard() state = Follower() oserver = Server(0, state, [], board, []) # print(oserver) """ _name: 0, _state: Follower ** _timeout: 500, _timeoutTime: 1581685132.670627, _last_vote: None, _log: [], _messageBoard: board: [], _neighbors: [], _total_nodes: 0, _commitIndex: 0, _currentTerm: 0, _lastApplied: 0, _lastLogIndex: 0, _lastLogTerm: None """ board = MemoryBoard() state = Candidate() # 候选人 # print(state) # Candidate ** _last_vote: None, _votes: None