def test_connected_to_writer(self): with StubCluster({9001: "v1/router.script", 9006: "v1/empty.script"}): address = ("127.0.0.1", 9001) with RoutingPool(address) as pool: assert not pool.routing_table.is_fresh(WRITE_ACCESS) connection = pool.acquire(access_mode=WRITE_ACCESS) assert connection.server.address in pool.routing_table.writers assert not pool.missing_writer
def test_should_refresh_with_read(): with StubCluster({9001: "v3/router.script", 9004: "v3/empty.script"}): address = ("127.0.0.1", 9001) with RoutingPool(address) as pool: assert not pool.routing_table.is_fresh(READ_ACCESS) _ = pool.acquire(access_mode=READ_ACCESS) assert pool.routing_table.is_fresh(READ_ACCESS) assert not pool.missing_writer
def test_connected_to_reader(): with StubCluster({9001: "v3/router.script", 9004: "v3/empty.script"}): address = ("127.0.0.1", 9001) with RoutingPool(address) as pool: assert not pool.routing_table.is_fresh(READ_ACCESS) connection = pool.acquire(access_mode=READ_ACCESS) assert connection.server.address in pool.routing_table.readers assert not pool.missing_writer
def test_should_be_able_to_set_multiple_bookmarks(self): with StubCluster({9001: "router.script"}): uri = "bolt+routing://localhost:9001" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False) as driver: with driver.session(bookmarks=[":1", ":2"]) as session: assert session.last_bookmark() == ":2"
def test_disconnect_after_init(self): with StubCluster({9001: "v1/disconnect_after_init.script"}): address = ("127.0.0.1", 9001) with connect(address, auth=self.auth_token, encrypted=False) as cx: with self.assertRaises(ServiceUnavailable): metadata = {} cx.run("RETURN $x", {"x": 1}, on_success=metadata.update) cx.sync()
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(RoutingProtocolError): with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False): pass
def test_should_be_no_bookmark_in_new_session(self): with StubCluster({9001: "router.script"}): uri = "bolt+routing://localhost:9001" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False) as driver: with driver.session() as session: assert session.last_bookmark() is None
def test_default_load_balancing_strategy_is_least_connected(self): from neobolt.routing import RoutingConnectionPool with StubCluster({9001: "router.script"}): uri = "neo4j://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False) as driver: self.assertIsInstance(driver, RoutingDriver) self.assertIsInstance(driver._pool, RoutingConnectionPool) self.assertIsInstance(driver._pool.load_balancing_strategy, LeastConnectedLoadBalancingStrategy)
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=self.auth_token, encrypted=False): pass
def test_should_refresh(self): with StubCluster({9001: "v1/router.script", 9006: "v1/empty.script"}): address = ("127.0.0.1", 9001) with RoutingPool(address) as pool: assert not pool.routing_table.is_fresh(WRITE_ACCESS) _ = pool.acquire(access_mode=WRITE_ACCESS) assert pool.routing_table.is_fresh(WRITE_ACCESS) assert not pool.missing_writer
def test_should_be_able_to_write(self): with StubCluster({9001: "router.script", 9006: "create_a.script"}): uri = "neo4j://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False) as driver: with driver.session(access_mode=WRITE_ACCESS) as session: result = session.run("CREATE (a $x)", {"x": {"name": "Alice"}}) assert not list(result) assert result.summary().server.address == ('127.0.0.1', 9006)
def test_should_flag_reading_without_writer(self): with StubCluster({9001: "v1/router_no_writers.script"}): address = ("127.0.0.1", 9001) with RoutingPool(address) as pool: assert not pool.routing_table.is_fresh(READ_ACCESS) assert not pool.routing_table.is_fresh(WRITE_ACCESS) pool.ensure_routing_table_is_fresh(READ_ACCESS) assert pool.missing_writer
def test_should_disconnect_after_fetching_autocommit_result(self): with StubCluster({9001: "router.script", 9004: "return_1.script"}): uri = "neo4j://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False) as driver: with driver.session(access_mode=READ_ACCESS) as session: result = session.run("RETURN $x", {"x": 1}) assert session._connection is not None result.consume() assert session._connection is None
def test_should_call_get_routing_table_with_context(self): with StubCluster({9001: "get_routing_table_with_context.script", 9002: "return_1.script"}): uri = "neo4j://127.0.0.1:9001/?name=molly&age=1" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False) as driver: with driver.session(access_mode=READ_ACCESS) as session: result = session.run("RETURN $x", {"x": 1}) for record in result: assert record["x"] == 1 assert result.summary().server.address == ('127.0.0.1', 9002)
def test_should_connect_to_read_in_absent_of_writer(self): with StubCluster({9001: "v1/router_no_writers.script", 9004: "v1/empty.script"}): address = ("127.0.0.1", 9001) with RoutingPool(address) as pool: assert not pool.routing_table.is_fresh(READ_ACCESS) connection = pool.acquire(access_mode=READ_ACCESS) assert connection.server.address in pool.routing_table.readers assert not pool.routing_table.is_fresh(WRITE_ACCESS) assert pool.missing_writer
def test_disconnect_after_init(): with StubCluster({9001: "v3/disconnect_after_init.script"}): address = ("127.0.0.1", 9001) with connect(address) as cx: with raises(ServiceUnavailable): metadata = {} cx.run("RETURN $x", {"x": 1}, on_success=metadata.update) cx.send_all() cx.fetch_all()
def test_should_serve_read_when_missing_writer(self): with StubCluster({9001: "router_no_writers.script", 9005: "return_1.script"}): uri = "bolt+routing://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False) as driver: with driver.session(access_mode=READ_ACCESS) as session: result = session.run("RETURN $x", {"x": 1}) for record in result: assert record["x"] == 1 assert result.summary().server.address == ('127.0.0.1', 9005)
def test_should_remove_writer_from_routing_table_if_present(self): with StubCluster({9001: "router.script"}): address = ("127.0.0.1", 9001) with RoutingPool(address) as pool: pool.ensure_routing_table_is_fresh(WRITE_ACCESS) target = ("127.0.0.1", 9006) assert target in pool.routing_table.writers pool.deactivate(target) assert target not in pool.routing_table.writers
def test_connection_error_on_explicit_commit(self): with StubCluster({9001: "connection_error_on_commit.script"}): uri = "bolt://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False, max_retry_time=0) as driver: with driver.session() as session: tx = session.begin_transaction() tx.run("CREATE (n {name:'Bob'})").data() with self.assertRaises(ServiceUnavailable): tx.commit()
def test_should_be_able_to_read(self): with StubCluster({9001: "router.script", 9004: "return_1.script"}): uri = "neo4j://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False) as driver: with driver.session(access_mode=READ_ACCESS) as session: result = session.run("RETURN $x", {"x": 1}) for record in result: assert record["x"] == 1 assert result.summary().server.address == ('127.0.0.1', 9004)
def test_no_other_load_balancing_strategies_are_available(self): with StubCluster({9001: "router.script"}): uri = "bolt+routing://127.0.0.1:9001" with self.assertRaises(ValueError): with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False, load_balancing_strategy=-1): 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=self.auth_token, encrypted=False) as driver: with self.assertRaises(ServiceUnavailable): with driver.session() as session: session.run("RETURN $x", {"x": 1}).consume()
def test_should_discover_servers_on_driver_construction(self): with StubCluster({9001: "router.script"}): uri = "neo4j://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=self.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_can_select_round_robin_load_balancing_strategy(self): from neobolt.routing import RoutingConnectionPool with StubCluster({9001: "router.script"}): uri = "neo4j://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False, load_balancing_strategy=LOAD_BALANCING_STRATEGY_ROUND_ROBIN) as driver: self.assertIsInstance(driver, RoutingDriver) self.assertIsInstance(driver._pool, RoutingConnectionPool) self.assertIsInstance(driver._pool.load_balancing_strategy, RoundRobinLoadBalancingStrategy)
def test_should_error_to_writer_in_absent_of_reader(self): with StubCluster({9001: "router_no_readers.script"}): address = ("127.0.0.1", 9001) with RoutingPool(address) as pool: assert not pool.routing_table.is_fresh(WRITE_ACCESS) with self.assertRaises(ProtocolError): _ = pool.acquire(access_mode=WRITE_ACCESS) assert not pool.routing_table.is_fresh(READ_ACCESS) assert not pool.routing_table.is_fresh(WRITE_ACCESS) assert not pool.missing_writer
def test_should_not_update_if_fresh(self): with StubCluster({9001: "router.script"}): address = ("127.0.0.1", 9001) with RoutingPool(address) as pool: pool.ensure_routing_table_is_fresh(WRITE_ACCESS) first_updated_time = pool.routing_table.last_updated_time pool.ensure_routing_table_is_fresh(WRITE_ACCESS) second_updated_time = pool.routing_table.last_updated_time assert second_updated_time == first_updated_time assert not pool.missing_writer
def test_no_retry_write_on_user_canceled_tx(self): with StubCluster({9001: "router.script", 9006: "user_canceled_tx.script.script"}): uri = "bolt+routing://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False) as driver: with driver.session() as session: def unit_of_work(tx): tx.run("RETURN 1") with self.assertRaises(TransientError): _ = session.write_transaction(unit_of_work)
def test_should_retry_if_first_reader_fails(self): with StubCluster({9001: "v1/router.script", 9004: "v1/fail_on_init.script", 9005: "v1/empty.script"}): address = ("127.0.0.1", 9001) with RoutingPool(address) as pool: assert not pool.routing_table.is_fresh(READ_ACCESS) _ = pool.acquire(access_mode=READ_ACCESS) 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_retry_if_first_writer_fails(self): with StubCluster({9001: "v1/router_with_multiple_writers.script", 9006: "v1/fail_on_init.script", 9007: "v1/empty.script"}): address = ("127.0.0.1", 9001) with RoutingPool(address) as pool: assert not pool.routing_table.is_fresh(WRITE_ACCESS) _ = pool.acquire(access_mode=WRITE_ACCESS) 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_direct_session_close_after_server_close(self): with StubCluster({9001: "disconnect_after_init.script"}): uri = "bolt://127.0.0.1:9001" with GraphDatabase.driver(uri, auth=self.auth_token, encrypted=False, max_retry_time=0) as driver: with driver.session() as session: with self.assertRaises(ServiceUnavailable): session.write_transaction( lambda tx: tx.run("CREATE (a:Item)"))