Skip to content

Commit c3d28ee

Browse files
committed
Migrating stub tests to testkit
- remove all migrated stub tests - some stub tests (or parts of them) got turned into unit tests - implement testkit messages ForcedRoutingTableUpdate and GetRoutingTable - send debug log output to testkit to easy test debugging for people running the backend in docker or similar
1 parent ecb7930 commit c3d28ee

17 files changed

+655
-1725
lines changed

testkitbackend/backend.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,31 @@
1414
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1515
# See the License for the specific language governing permissions and
1616
# limitations under the License.
17-
from inspect import getmembers, isfunction
17+
from inspect import (
18+
getmembers,
19+
isfunction,
20+
)
21+
import io
1822
from json import loads, dumps
1923
import logging
2024
import sys
2125
import traceback
2226

23-
from neo4j.exceptions import Neo4jError, DriverError, ServiceUnavailable
27+
from neo4j.exceptions import (
28+
DriverError,
29+
Neo4jError,
30+
UnsupportedServerProduct,
31+
)
2432

2533
import testkitbackend.requests as requests
2634

35+
buffer_handler = logging.StreamHandler(io.StringIO())
36+
buffer_handler.setLevel(logging.DEBUG)
37+
2738
handler = logging.StreamHandler(sys.stdout)
2839
handler.setLevel(logging.DEBUG)
2940
logging.getLogger("neo4j").addHandler(handler)
41+
logging.getLogger("neo4j").addHandler(buffer_handler)
3042
logging.getLogger("neo4j").setLevel(logging.DEBUG)
3143

3244
log = logging.getLogger("testkitbackend")
@@ -140,7 +152,7 @@ def _process(self, request):
140152
"Backend does not support some properties of the " + name +
141153
" request: " + ", ".join(unsused_keys)
142154
)
143-
except (Neo4jError, DriverError) as e:
155+
except (Neo4jError, DriverError, UnsupportedServerProduct) as e:
144156
log.debug(traceback.format_exc())
145157
if isinstance(e, Neo4jError):
146158
msg = "" if e.message is None else str(e.message)
@@ -161,6 +173,14 @@ def _process(self, request):
161173
def send_response(self, name, data):
162174
""" Sends a response to backend.
163175
"""
176+
buffer_handler.acquire()
177+
log_output = buffer_handler.stream.getvalue()
178+
buffer_handler.stream.truncate(0)
179+
buffer_handler.stream.seek(0)
180+
buffer_handler.release()
181+
if not log_output.endswith("\n"):
182+
log_output += "\n"
183+
self._wr.write(log_output.encode("utf-8"))
164184
response = {"name": name, "data": data}
165185
response = dumps(response)
166186
log.info(">>> " + name + dumps(data))

testkitbackend/requests.py

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,14 @@
2323
from testkitbackend.fromtestkit import to_meta_and_timeout
2424

2525

26-
with open(path.join(path.dirname(__file__), "skipped_tests.json"), "r") as fd:
27-
SKIPPED_TESTS = json.load(fd)
26+
def load_config():
27+
with open(path.join(path.dirname(__file__), "test_config.json"), "r") as fd:
28+
config = json.load(fd)
29+
return (config["skips"],
30+
[k for k, v in config["features"].items() if v is True])
31+
32+
33+
SKIPPED_TESTS, FEATURES = load_config()
2834

2935

3036
def StartTest(backend, data):
@@ -35,6 +41,10 @@ def StartTest(backend, data):
3541
backend.send_response("RunTest", {})
3642

3743

44+
def GetFeatures(backend, data):
45+
backend.send_response("FeatureList", {"features": FEATURES})
46+
47+
3848
def NewDriver(backend, data):
3949
auth_token = data["authorizationToken"]["data"]
4050
data["authorizationToken"].mark_item_as_read_if_equals(
@@ -294,7 +304,8 @@ def ResultConsume(backend, data):
294304
"serverInfo": {
295305
"protocolVersion":
296306
".".join(map(str, summary.server.protocol_version)),
297-
"agent": summary.server.agent
307+
"agent": summary.server.agent,
308+
# "address": ":".join(map(str, summary.server.address))
298309
}
299310
})
300311

@@ -310,3 +321,30 @@ def RetryableNegative(backend, data):
310321
session_tracker = backend.sessions[key]
311322
session_tracker.state = '-'
312323
session_tracker.error_id = data.get('errorId', '')
324+
325+
326+
def ForcedRoutingTableUpdate(backend, data):
327+
driver_id = data["driverId"]
328+
driver = backend.drivers[driver_id]
329+
database = data["database"]
330+
bookmarks = data["bookmarks"]
331+
with driver._pool.refresh_lock:
332+
driver._pool.create_routing_table(database)
333+
driver._pool.update_routing_table(database=database,
334+
bookmarks=bookmarks)
335+
backend.send_response("Driver", {"id": driver_id})
336+
337+
338+
def GetRoutingTable(backend, data):
339+
driver_id = data["driverId"]
340+
database = data["database"]
341+
driver = backend.drivers[driver_id]
342+
routing_table = driver._pool.routing_tables[database]
343+
response_data = {
344+
"database": routing_table.database,
345+
"ttl": routing_table.ttl,
346+
}
347+
for role in ("routers", "readers", "writers"):
348+
addresses = routing_table.__getattribute__(role)
349+
response_data[role] = list(map(str, addresses))
350+
backend.send_response("RoutingTable", response_data)

testkitbackend/skipped_tests.json

Lines changed: 0 additions & 28 deletions
This file was deleted.

testkitbackend/test_config.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"skips": {
3+
"stub.routing.Routing.test_should_retry_write_until_success_with_leader_change_using_tx_function":
4+
"Driver closes connection to router if DNS resolved name not in routing table",
5+
"stub.routing.RoutingV3.test_should_retry_write_until_success_with_leader_change_using_tx_function":
6+
"Driver closes connection to router if DNS resolved name not in routing table",
7+
"stub.routing.RoutingV4.test_should_retry_write_until_success_with_leader_change_using_tx_function":
8+
"Driver closes connection to router if DNS resolved name not in routing table",
9+
"stub.routing.Routing.test_should_retry_write_until_success_with_leader_shutdown_during_tx_using_tx_function":
10+
"Driver closes connection to router if DNS resolved name not in routing table",
11+
"stub.routing.RoutingV3.test_should_retry_write_until_success_with_leader_shutdown_during_tx_using_tx_function":
12+
"Driver closes connection to router if DNS resolved name not in routing table",
13+
"stub.routing.RoutingV4.test_should_retry_write_until_success_with_leader_shutdown_during_tx_using_tx_function":
14+
"Driver closes connection to router if DNS resolved name not in routing table",
15+
"stub.routing.Routing.test_should_successfully_acquire_rt_when_router_ip_changes":
16+
"Test makes assumptions about how verify_connectivity is implemented",
17+
"stub.routing.RoutingV3.test_should_successfully_acquire_rt_when_router_ip_changes":
18+
"Test makes assumptions about how verify_connectivity is implemented",
19+
"stub.routing.RoutingV4.test_should_successfully_acquire_rt_when_router_ip_changes":
20+
"Test makes assumptions about how verify_connectivity is implemented",
21+
"stub.retry.TestRetryClustering.test_retry_ForbiddenOnReadOnlyDatabase_ChangingWriter":
22+
"Test makes assumptions about how verify_connectivity is implemented",
23+
"stub.authorization.AuthorizationTests.test_should_retry_on_auth_expired_on_begin_using_tx_function":
24+
"Flaky: test requires the driver to contact servers in a specific order",
25+
"stub.authorization.AuthorizationTestsV3.test_should_retry_on_auth_expired_on_begin_using_tx_function":
26+
"Flaky: test requires the driver to contact servers in a specific order",
27+
"stub.authorization.AuthorizationTestsV4.test_should_retry_on_auth_expired_on_begin_using_tx_function":
28+
"Flaky: test requires the driver to contact servers in a specific order"
29+
},
30+
"features": {
31+
"AuthorizationExpiredTreatment": true,
32+
"Optimization:ImplicitDefaultArguments": true,
33+
"Optimization:MinimalResets": "Driver resets some clean connections when put back into pool",
34+
"Optimization:ConnectionReuse": true,
35+
"Optimization:PullPipelining": true
36+
}
37+
}

tests/performance/test_results.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ class ReadWorkload(object):
3636
def setup_class(cls):
3737
cls.server = server = RemoteGraphDatabaseServer()
3838
server.start()
39-
cls.driver = GraphDatabase.driver(server.server_uri, auth=server.auth_token, encrypted=server.encrypted)
39+
cls.driver = GraphDatabase.driver(server.server_uri,
40+
auth=server.auth_token,
41+
encrypted=server.encrypted)
4042

4143
@classmethod
4244
def teardown_class(cls):
@@ -62,13 +64,25 @@ def _(tx):
6264
p = {"record_count": record_count, "x": value}
6365
for record in tx.run(s, p):
6466
assert all(x == value for x in record.values())
67+
print(value)
6568

6669
return _
6770

71+
# @mark.parametrize("record_count,record_width,value", product(
72+
# [1, 1000], # record count
73+
# [1, 10], # record width
74+
# [1, u'hello, world'], # value
75+
# ))
6876
@mark.parametrize("record_count,record_width,value", product(
69-
[1, 1000], # record count
70-
[1, 10], # record width
71-
[1, u'hello, world'], # value
77+
[10000], # record count
78+
[768], # record width
79+
[1.234], # value
7280
))
7381
def test_1x1(self, benchmark, record_count, record_width, value):
74-
benchmark(self.work(self.uow(record_count, record_width, value)))
82+
# benchmark(self.work(self.uow(record_count, record_width, value)))
83+
try:
84+
import cProfile as profile
85+
except ImportError:
86+
import profile
87+
work = self.work(self.uow(record_count, record_width, value))
88+
profile.runctx("work()", globals=globals(), locals=locals())

tests/performance/tools.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,17 @@
1919
# limitations under the License.
2020

2121

22-
from test.integration.tools import IntegrationTestCase
23-
24-
from os import makedirs, remove
25-
from os.path import basename, dirname, join as path_join, realpath, isfile, expanduser
26-
import platform
2722
from unittest import TestCase, SkipTest
28-
from shutil import copyfile
29-
from sys import exit, stderr
3023

3124
try:
3225
from urllib.request import urlretrieve
3326
except ImportError:
3427
from urllib import urlretrieve
3528

36-
from boltkit.controller import WindowsController, UnixController
37-
3829
from neo4j import GraphDatabase
3930
from neo4j.exceptions import AuthError
4031

41-
from test.env import NEO4J_USER, NEO4J_PASSWORD, NEO4J_SERVER_URI
32+
from tests.env import NEO4J_USER, NEO4J_PASSWORD, NEO4J_SERVER_URI
4233

4334

4435
def is_listening(address):

tests/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ coverage
33
pytest
44
pytest-benchmark
55
pytest-cov
6+
pytest-mock
67
teamcity-messages

0 commit comments

Comments
 (0)