class _TestRoutingManager: def maintenance(self, expected_node=None, ld=0): query = self.rm.do_maintenance() if query and expected_node: msg = query.msg node_ = query.dstnode eq_(node_, expected_node) if ld: eq_(msg.query, message.FIND_NODE) eq_(tc.CLIENT_NODE.id.log_distance(msg.target), ld) else: eq_(msg.query, message.FIND_NODE)#FIXME: ping elif expected_node is None: ok_(query is None) else: assert 0, 'Query expected, but got no query.' def setup(self): global time time = routing_manager.time = MockTime() self.rm = RoutingManager(tc.CLIENT_NODE, BOOTSTRAP_NODES) def test_bootstrap(self): self.maintenance(BOOTSTRAP_NODES[0], -1) self.maintenance(BOOTSTRAP_NODES[1], -1) self.maintenance(BOOTSTRAP_NODES[2], -1) self.maintenance(BOOTSTRAP_NODES[3], -1) self.maintenance(BOOTSTRAP_NODES[4], -1) self.maintenance() def test_found_nodes(self): for node_ in BOOTSTRAP_NODES: self.rm.do_maintenance() self.maintenance() self.rm.on_response_received(tc.NODES_LD_CL[157][1], .3) self.rm.on_nodes_found((tc.NODES_LD_CL[158][5], tc.NODES_LD_CL[158][6])) self.maintenance(tc.NODES_LD_CL[158][5], -1) self.maintenance(tc.NODES_LD_CL[158][6], -1) def test_maintenance(self): for node_ in BOOTSTRAP_NODES: self.rm.do_maintenance() self.maintenance() self.rm.on_response_received(tc.NODES_LD_CL[157][1], .1) self.maintenance() time.sleep(30*60) self.maintenance(tc.NODES_LD_CL[157][1], -1) def test_querier(self): for node_ in BOOTSTRAP_NODES: self.rm.do_maintenance() self.maintenance() self.rm.on_query_received(tc.NODES_LD_CL[148][5]) self.maintenance(tc.NODES_LD_CL[148][5], -1)
class _TestRoutingManager: def setup(self): for n in tc.NODES + [tc.SERVER_NODE, tc.SERVER2_NODE]: n.is_ns = False for n in tc.NODES2 + [tc.CLIENT_NODE]: n.is_ns = True self.querier = querier.Querier(tc.CLIENT_ID) self.routing_m = RoutingManager(tc.CLIENT_NODE, self.querier, tc.NODES) def exercise_mock(self, mode): # If this happens, we want to know assert_raises(Exception, self.routing_m.on_timeout, tc.CLIENT_NODE) # node is nowhere (timeout is ignored) self.routing_m.on_timeout(tc.SERVER_NODE) # main: CLIENT_NODE, replacement: empty eq_(self.routing_m.get_closest_rnodes(tc.SERVER_ID), [tc.CLIENT_NODE]) self.routing_m.on_response_received(tc.SERVER_NODE) # main: client_node, server_node, replacement: empty # this should reset refresh task self.routing_m.on_response_received(tc.SERVER_NODE) eq_(self.routing_m.get_closest_rnodes(tc.SERVER_ID), [tc.SERVER_NODE, tc.CLIENT_NODE]) self.routing_m.on_timeout(tc.SERVER_NODE) # main: client_node, replacement: server_node eq_(self.routing_m.get_closest_rnodes(tc.SERVER_ID), [tc.CLIENT_NODE]) self.routing_m.on_response_received(tc.SERVER2_NODE) # main: client_node, server_node, replacement: server2_node(q) eq_(self.routing_m.get_closest_rnodes(tc.SERVER_ID), [tc.SERVER2_NODE, tc.CLIENT_NODE]) self.routing_m.on_response_received(tc.SERVER_NODE) # main: client_node, server_node, replacement: server2_node(q) eq_(self.routing_m.get_closest_rnodes(tc.SERVER_ID), [tc.SERVER_NODE, tc.SERVER2_NODE, tc.CLIENT_NODE]) eq_(self.routing_m.get_closest_rnodes(tc.SERVER2_ID), [tc.SERVER2_NODE, tc.CLIENT_NODE]) eq_(self.routing_m.get_closest_rnodes(tc.CLIENT_ID), [tc.CLIENT_NODE, tc.SERVER2_NODE]) for n in tc.NODES: self.routing_m.on_response_received(n) """ Main Routing Table # -1 client # 154 server2 # 159 server nodes[0:7] """ eq_(self.routing_m.get_closest_rnodes(tc.CLIENT_ID), [tc.CLIENT_NODE]) for n in tc.NODES: eq_(self.routing_m.get_closest_rnodes(n.id), [tc.SERVER_NODE] + tc.NODES[:7]) # bucket full (NODES[7] in replacement self.routing_m.on_query_received(tc.NODES[7]) eq_(self.routing_m.get_closest_rnodes(n.id), [tc.SERVER_NODE] + tc.NODES[:7]) # nodes[0] is kicked out from main # all nodes in replacement are refreshed (pinged) self.routing_m.on_timeout(tc.NODES[0]) eq_(self.routing_m.get_closest_rnodes(tc.NODES[0].id), [tc.SERVER_NODE] + tc.NODES[1:7] + [tc.SERVER2_NODE]) # nodes[7] is refreshed self.routing_m.on_query_received(tc.NODES[7]) # nodes[7] still in replacement (queries don't cause movements) eq_(self.routing_m.get_closest_rnodes(tc.NODES[0].id), [tc.SERVER_NODE] + tc.NODES[1:7] + [tc.SERVER2_NODE]) # nodes[7] is moved to the main table (response to refresh ping) self.routing_m.on_response_received(tc.NODES[7]) eq_(self.routing_m.get_closest_rnodes(tc.NODES[0].id), [tc.SERVER_NODE] + tc.NODES[1:8]) # nodes[7] is refreshed (no change to the tables) self.routing_m.on_query_received(tc.NODES[7]) eq_(self.routing_m.get_closest_rnodes(tc.NODES[0].id), [tc.SERVER_NODE] + tc.NODES[1:8]) # nodes[7] is in main and get response self.routing_m.on_response_received(tc.NODES[7]) # nodes[0] gets strike 2, 3 and 4 (timeouts) self.routing_m.on_timeout(tc.NODES[0]) self.routing_m.on_timeout(tc.NODES[0]) self.routing_m.on_timeout(tc.NODES[0]) # and can be expelled from the replacement table # nodes2[:] send responses #TODO2: rnode(nodes[0] report 5 timeouts eq_(self.routing_m.replacement.get_rnode( tc.NODES[0]).timeouts_in_a_row(), 5) if mode is message.QUERY: for n in tc.NODES2: self.routing_m.on_query_received(n) elif mode is message.RESPONSE: for n in tc.NODES2: self.routing_m.on_response_received(n) # nodes[0] comes back but the repl bucket is full self.routing_m.on_response_received(tc.NODES[0]) # nodes[0] sends error (routing manager ignores it) self.routing_m.on_error_received(tc.NODES[0]) # timeout from node without id (ignored) # nodes[0] comes back but the repl bucket is full self.routing_m.on_timeout(tc.EXTERNAL_NODE) # nodes found (but no room in main self.routing_m.on_nodes_found(tc.NODES) # nodes[1] (in main) timeout and repl bucket is full # find worst node in repl (nodes[7]) and replace it # all nodes in repl bucket get refreshed (not nodes[1] self.routing_m.on_timeout(tc.NODES[1]) eq_(self.routing_m.get_closest_rnodes(tc.NODES[0].id), [tc.SERVER_NODE] + tc.NODES[2:8] +[tc.SERVER2_NODE]) # nodes found (there is room now) # nodes2[0:1] get refreshed (pinged self.routing_m.on_nodes_found(tc.NODES2) # nodes2[0] replies (and is added to main) self.routing_m.on_response_received(tc.NODES2[0]) eq_(self.routing_m.get_closest_rnodes(tc.NODES2[0].id), [tc.SERVER_NODE] + tc.NODES[2:8] +tc.NODES2[0:1]) if mode == message.QUERY: expected_main = [tc.SERVER2_NODE] + \ [tc.SERVER_NODE] + tc.NODES[2:8] + tc.NODES2[0:1] + \ [tc.CLIENT_NODE] expected_replacement = tc.NODES[0:2] elif mode == message.RESPONSE: expected_main = [tc.SERVER2_NODE] + \ [tc.SERVER_NODE] + tc.NODES[2:8] + tc.NODES2[0:1] + \ [tc.CLIENT_NODE] expected_replacement = tc.NODES2[1:7] + tc.NODES[1:2] all_main, all_replacement = self.routing_m.get_all_rnodes() for n, expected in zip(all_main, expected_main): eq_(n, expected) for n, expected in zip(all_replacement, expected_replacement): eq_(n, expected) eq_(len(all_main), len(expected_main)) eq_(len(all_replacement), len(expected_replacement)) def test_query(self): self.exercise_mock(message.QUERY) def test_response(self): self.exercise_mock(message.RESPONSE) def test_bootstrap(self): self.routing_m.do_bootstrap() fn_r = message.OutgoingFindNodeResponse(tc.NODES[0].id, tc.NODES2[0:1]) fn_r = message.IncomingMsg(fn_r.encode('\0\0'), tc.CLIENT_ADDR) self.querier.on_response_received(fn_r, tc.NODES[0].addr) def test_routing_m_mock(self): # Just testing interface rm = RoutingManagerMock() eq_(rm.get_closest_rnodes(tc.TARGET_ID), tc.NODES) def test_complete_coverage(self): self.routing_m._do_nothing() self.routing_m._refresh_now_callback()