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_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)
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 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)
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
_neighbors: [<servers.server.Server object at 0x1055104a8>], _total_nodes: 0, _commitIndex: 0, _currentTerm: 0, _lastApplied: 0, _lastLogIndex: 0, _lastLogTerm: None """ msg = oserver._messageBoard.get_message() # print(msg) """ AppendEntries: 0, RequestVote: 1, RequestVoteResponse: 2, Response: 3, _timestamp: 1581684927, _sender: 1, _receiver: 0, _data: {'lastLogIndex': 0, 'lastLogTerm': None}, _term: 1, _type: 1 """ oserver.on_message(msg) # print(oserver) # print(server) """ _name: 0, _state: Follower ** _timeout: 500, _timeoutTime: 1581685712.0402, _last_vote: 1, _log: [], _messageBoard: board: [], _neighbors: [<servers.server.Server object at 0x1055104a8>], _total_nodes: 0, _commitIndex: 0, _currentTerm: 1, _lastApplied: 0, _lastLogIndex: 0,
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 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)
_neighbors: [<servers.server.Server object at 0x10ef71cf8>], _total_nodes: 0, _commitIndex: 0, _currentTerm: 0, _lastApplied: 0, _lastLogIndex: 0, _lastLogTerm: None """ msg = AppendEntriesMessage(0, 1, 2, {}) # print(msg) """ AppendEntries: 0, RequestVote: 1, RequestVoteResponse: 2, Response: 3, _timestamp: 1581654239, _sender: 0, _receiver: 1, _data: {}, _term: 2, _type: 0 """ server.on_message(msg) # print(server) """ _name: 1, _state: <states.follower.Follower object at 0x10d08afd0>, _log: [], _messageBoard: board: [], _neighbors: [<servers.server.Server object at 0x10d08acf8>], _total_nodes: 0, _commitIndex: 0, _currentTerm: 2, _lastApplied: 0, _lastLogIndex: 0, _lastLogTerm: None """