def test_should_refresh(self): with StubCluster({9001: "router.script", 9006: "empty.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector, address) as pool: assert not pool.routing_table.is_fresh() _ = pool.acquire_for_write() assert pool.routing_table.is_fresh()
def _test_server_outcome(self, server_outcomes, overall_outcome): print("%r -> %r" % (server_outcomes, overall_outcome)) servers = {} routers = [] for port, outcome in enumerate(server_outcomes, 9001): if outcome is None: servers[port] = "router_no_writers.script" elif outcome is RoutingTable: servers[port] = "router.script" elif outcome is ServiceUnavailable: servers[port] = "non_router.script" else: assert False, "Unexpected server outcome %r" % outcome routers.append(("127.0.0.1", port)) with StubCluster(servers): with RoutingConnectionPool(connector, *routers) as pool: if overall_outcome is RoutingTable: pool.update_routing_table() table = pool.routing_table assert table.routers == {("127.0.0.1", 9001), ("127.0.0.1", 9002), ("127.0.0.1", 9003)} assert table.readers == {("127.0.0.1", 9004), ("127.0.0.1", 9005)} assert table.writers == {("127.0.0.1", 9006)} assert table.ttl == 300 elif overall_outcome is ServiceUnavailable: with self.assertRaises(ServiceUnavailable): pool.update_routing_table() else: assert False, "Unexpected overall outcome %r" % overall_outcome
def test_connected_to_writer(self): with StubCluster({9001: "router.script", 9006: "empty.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector, address) as pool: assert not pool.routing_table.is_fresh() connection = pool.acquire_for_write() assert connection.server.address in pool.routing_table.writers
def test_should_remove_router_if_connection_drops(self): with StubCluster({9001: "rude_router.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector, address) as pool: assert address in pool.routing_table.routers _ = pool.fetch_routing_info(address) assert address not in pool.routing_table.routers
def test_should_not_fail_if_absent(self): with StubCluster({9001: "router.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector, address) as pool: pool.refresh_routing_table() target = ("127.0.0.1", 9007) pool.remove(target)
def test_cannot_discover_servers_on_silent_router(self): with StubCluster({9001: "silent_router.script"}): uri = "bolt+routing://127.0.0.1:9001" with self.assertRaises(ProtocolError): with GraphDatabase.driver(uri, auth=AUTH_TOKEN, encrypted=False): pass
def test_cannot_discover_servers_on_non_router(self): with StubCluster({9001: "non_router.script"}): uri = "bolt+routing://127.0.0.1:9001" with self.assertRaises(ServiceUnavailable): with GraphDatabase.driver(uri, auth=AUTH_TOKEN, encrypted=False): pass
def test_direct_disconnect_on_pull_all(self): with StubCluster({9001: "disconnect_on_pull_all.script"}): uri = "bolt://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=AUTH_TOKEN, encrypted=False) as driver: with driver.session() as session: with self.assertRaises(ServiceUnavailable): session.run("RETURN $x", {"x": 1}).consume()
def test_should_remove_writer_from_routing_table_if_present(self): with StubCluster({9001: "router.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector, address) as pool: pool.refresh_routing_table() target = ("127.0.0.1", 9006) assert target in pool.routing_table.writers pool.remove(target) assert target not in pool.routing_table.writers
def test_should_not_update_if_fresh(self): with StubCluster({9001: "router.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector, address) as pool: pool.refresh_routing_table() first_updated_time = pool.routing_table.last_updated_time pool.refresh_routing_table() second_updated_time = pool.routing_table.last_updated_time assert second_updated_time == first_updated_time
def test_should_be_able_to_read(self): with StubCluster({9001: "router.script", 9004: "return_1.script"}): uri = "bolt+routing://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=AUTH_TOKEN, encrypted=False) as driver: with driver.session(READ_ACCESS) as session: result = session.run("RETURN $x", {"x": 1}) for record in result: assert record["x"] == 1 assert session.connection.server.address == ('127.0.0.1', 9004)
def test_routing_disconnect_on_pull_all(self): with StubCluster({ 9001: "router.script", 9004: "disconnect_on_pull_all.script" }): uri = "bolt+routing://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=AUTH_TOKEN, encrypted=False) as driver: with driver.session(READ_ACCESS) as session: with self.assertRaises(SessionExpired): session.run("RETURN $x", {"x": 1}).consume()
def test_should_retry_if_first_writer_fails(self): with StubCluster({ 9001: "router_with_multiple_writers.script", 9006: "fail_on_init.script", 9007: "empty.script" }): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector, address) as pool: assert not pool.routing_table.is_fresh() _ = pool.acquire_for_write() assert ("127.0.0.1", 9006) not in pool.routing_table.writers assert ("127.0.0.1", 9007) in pool.routing_table.writers
def test_should_discover_servers_on_driver_construction(self): with StubCluster({9001: "router.script"}): uri = "bolt+routing://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=AUTH_TOKEN, encrypted=False) as driver: table = driver.pool.routing_table assert table.routers == {('127.0.0.1', 9001), ('127.0.0.1', 9002), ('127.0.0.1', 9003)} assert table.readers == {('127.0.0.1', 9004), ('127.0.0.1', 9005)} assert table.writers == {('127.0.0.1', 9006)}
def test_should_retry_if_first_reader_fails(self): with StubCluster({ 9001: "router.script", 9004: "fail_on_init.script", 9005: "empty.script" }): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector, address) as pool: assert not pool.routing_table.is_fresh() _ = pool.acquire_for_read() assert ("127.0.0.1", 9004) not in pool.routing_table.readers assert ("127.0.0.1", 9005) in pool.routing_table.readers
def test_should_get_table_from_router(self): with StubCluster({9001: "router.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector) as pool: table = pool.fetch_routing_table(address) assert table.routers == {("127.0.0.1", 9001), ("127.0.0.1", 9002), ("127.0.0.1", 9003)} assert table.readers == {("127.0.0.1", 9004), ("127.0.0.1", 9005)} assert table.writers == {("127.0.0.1", 9006)} assert table.ttl == 300
def test_should_be_able_to_write_as_default(self): with StubCluster({9001: "router.script", 9006: "create_a.script"}): uri = "bolt+routing://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=AUTH_TOKEN, encrypted=False) as driver: with driver.session() as session: result = session.run("CREATE (a $x)", {"x": { "name": "Alice" }}) assert not list(result) assert session.connection.server.address == ('127.0.0.1', 9006)
def test_should_get_info_from_router(self): with StubCluster({9001: "router.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector) as pool: result = pool.fetch_routing_info(address) assert len(result) == 1 record = result[0] assert record["ttl"] == 300 assert record["servers"] == [ { "role": "ROUTE", "addresses": ["127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"] }, { "role": "READ", "addresses": ["127.0.0.1:9004", "127.0.0.1:9005"] }, { "role": "WRITE", "addresses": ["127.0.0.1:9006"] }, ]
def test_should_fail_if_database_error(self): with StubCluster({9001: "broken_router.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector, address) as pool: with self.assertRaises(ServiceUnavailable): _ = pool.fetch_routing_info(address)
def test_no_writers_should_return_null_table(self): with StubCluster({9001: "router_no_writers.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector) as pool: table = pool.fetch_routing_table(address) assert table is None
def test_no_readers_should_raise_protocol_error(self): with StubCluster({9001: "router_no_readers.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector) as pool: with self.assertRaises(ProtocolError): _ = pool.fetch_routing_table(address)
def test_bolt_plus_routing_uri_constructs_routing_driver(self): with StubCluster({9001: "router.script"}): uri = "bolt+routing://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=AUTH_TOKEN, encrypted=False) as driver: assert isinstance(driver, RoutingDriver)
def test_should_return_none_if_connection_drops(self): with StubCluster({9001: "rude_router.script"}): address = ("127.0.0.1", 9001) with RoutingConnectionPool(connector, address) as pool: result = pool.fetch_routing_info(address) assert result is None