Skip to content

Commit 008d872

Browse files
authored
Add 4.4 to integration tests (#241)
- Update test matrix to be more comprehensive - Run suitable integration tests also on cluster configurations
1 parent e2b7663 commit 008d872

File tree

11 files changed

+252
-167
lines changed

11 files changed

+252
-167
lines changed

main.py

Lines changed: 84 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -46,75 +46,83 @@
4646

4747

4848
def initialise_configurations():
49-
configurations = []
50-
configurations.append(neo4j.Config(
51-
name="4.2-cluster",
52-
image="neo4j:4.2-enterprise",
53-
version="4.2",
54-
edition="enterprise",
55-
cluster=True,
56-
suite="", # TODO: Define cluster suite
57-
scheme="neo4j",
58-
download=None,
59-
stress_test_duration=90))
60-
61-
configurations.append(neo4j.Config(
62-
name="3.5-enterprise",
63-
image="neo4j:3.5-enterprise",
64-
version="3.5",
65-
edition="enterprise",
66-
cluster=False,
67-
suite="3.5",
68-
scheme="bolt",
69-
download=None,
70-
stress_test_duration=0))
71-
72-
configurations.append(neo4j.Config(
73-
name="4.0-community",
74-
version="4.0",
75-
image="neo4j:4.0",
76-
edition="community",
77-
cluster=False,
78-
suite="4.0",
79-
scheme="neo4j",
80-
download=None,
81-
stress_test_duration=0))
82-
83-
configurations.append(neo4j.Config(
84-
name="4.1-enterprise",
85-
image="neo4j:4.1-enterprise",
86-
version="4.1",
87-
edition="enterprise",
88-
cluster=False,
89-
suite="4.1",
90-
scheme="neo4j",
91-
download=None,
92-
stress_test_duration=0))
93-
94-
if in_teamcity:
95-
configurations.append(neo4j.Config(
96-
name="4.2-tc-enterprise",
97-
image="neo4j:4.2.12-enterprise",
98-
version="4.2",
99-
edition="enterprise",
100-
cluster=False,
101-
suite="4.2",
102-
scheme="neo4j",
103-
download=teamcity.DockerImage(
104-
"neo4j-enterprise-4.2.12-docker-loadable.tar"),
105-
stress_test_duration=0))
106-
107-
configurations.append(neo4j.Config(
108-
name="4.3-tc-enterprise",
109-
image="neo4j:4.3.4-enterprise",
110-
version="4.3",
111-
edition="enterprise",
112-
cluster=False,
113-
suite="4.3",
114-
scheme="neo4j",
49+
def generate_config(version, enterprise, cluster, scheme, stress_test):
50+
assert (cluster and scheme == "neo4j"
51+
or not cluster and scheme in ("neo4j", "bolt"))
52+
edition = "enterprise" if enterprise else "community"
53+
name = "%s-%s%s-%s" % (version, edition,
54+
"-cluster" if cluster else "", scheme)
55+
return neo4j.Config(
56+
name=name,
57+
image="neo4j:%s%s" % (version, "-enterprise" if enterprise else ""),
58+
version=version,
59+
edition=edition,
60+
cluster=cluster,
61+
suite=version,
62+
scheme=scheme,
63+
download=None,
64+
stress_test_duration=stress_test
65+
)
66+
67+
def generate_tc_config(version, enterprise, cluster, scheme, stress_test):
68+
if not in_teamcity:
69+
return None
70+
assert (cluster and scheme == "neo4j"
71+
or not cluster and scheme in ("neo4j", "bolt"))
72+
edition = "enterprise" if enterprise else "community"
73+
name = "%s-tc-%s%s-%s" % (version, edition,
74+
"-cluster" if cluster else "", scheme)
75+
version_without_drop = ".".join(version.split(".")[:2])
76+
return neo4j.Config(
77+
name=name,
78+
image="neo4j:%s%s" % (version, "-enterprise" if enterprise else ""),
79+
version=version_without_drop,
80+
edition=edition,
81+
cluster=cluster,
82+
suite=version_without_drop,
83+
scheme=scheme,
11584
download=teamcity.DockerImage(
116-
"neo4j-enterprise-4.3.4-docker-loadable.tar"),
117-
stress_test_duration=0))
85+
"neo4j-%s-%s-docker-loadable.tar" % (edition, version)
86+
),
87+
stress_test_duration=stress_test
88+
)
89+
90+
configurations = [
91+
generate_config(version_, enterprise_, cluster_, scheme_, stress_test_)
92+
for (version_, enterprise_, cluster_, scheme_, stress_test_) in (
93+
# LTS version
94+
# 3.5 servers only support routing scheme if configured as cluster
95+
("3.5", False, False, "bolt", 0),
96+
("3.5", True, False, "bolt", 0),
97+
("3.5", True, True, "neo4j", 60),
98+
# not officially supported versions
99+
("4.0", True, False, "neo4j", 0),
100+
("4.1", True, False, "neo4j", 0),
101+
("4.2", True, False, "neo4j", 0),
102+
# official backwards-compatibility
103+
("4.3", False, False, "bolt", 0),
104+
("4.3", False, False, "neo4j", 0),
105+
("4.3", True, False, "bolt", 0),
106+
("4.3", True, False, "neo4j", 0),
107+
("4.3", True, True, "neo4j", 90),
108+
)
109+
]
110+
configurations += [
111+
generate_tc_config(version_, enterprise_, cluster_, scheme_,
112+
stress_test_)
113+
for (version_, enterprise_, cluster_, scheme_, stress_test_) in (
114+
# nightly build of official backwards-compatible version
115+
("4.3.4", True, True, "neo4j", 60),
116+
# latest version
117+
("4.4.0-dev", False, False, "bolt", 0),
118+
("4.4.0-dev", False, False, "neo4j", 0),
119+
("4.4.0-dev", True, False, "bolt", 90),
120+
("4.4.0-dev", True, False, "neo4j", 0),
121+
("4.4.0-dev", True, True, "neo4j", 90),
122+
)
123+
]
124+
125+
configurations = list(filter(lambda conf: conf is not None, configurations))
118126
return configurations
119127

120128

@@ -340,25 +348,28 @@ def run_fail_wrapper(func, *args, **kwargs):
340348

341349
# Start a Neo4j server
342350
if cluster:
343-
print("Starting neo4j cluster (%s)" % server_name)
351+
print("\n Starting neo4j cluster (%s)\n" % server_name)
344352
server = neo4j.Cluster(neo4j_config.image,
345353
server_name,
346354
neo4j_artifacts_path)
347355
else:
348-
print("Starting neo4j standalone server (%s)" % server_name)
356+
print("\n Starting neo4j standalone server (%s)\n" % server_name)
349357
server = neo4j.Standalone(neo4j_config.image,
350358
server_name,
351359
neo4j_artifacts_path,
352360
"neo4jserver", 7687,
353361
neo4j_config.edition)
354362
server.start(networks[0])
355-
hostname, port = server.address()
363+
addresses = server.addresses()
364+
hostname, port = addresses[0]
356365

357366
# Wait until server is listening before running tests
358367
# Use driver container to check for Neo4j availability since connect
359368
# will be done from there
360-
print("Waiting for neo4j service port to be available")
361-
driver_container.poll_host_and_port_until_available(hostname, port)
369+
for address in addresses:
370+
print("Waiting for neo4j service at %s to be available"
371+
% (address,))
372+
driver_container.poll_host_and_port_until_available(*address)
362373
print("Neo4j is reachable from driver")
363374

364375
if test_flags["TESTKIT_TESTS"]:

neo4j.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ def start(self, network):
4545
env_map=env_map,
4646
network=network)
4747

48-
def address(self):
49-
return (self._hostname, self._port)
48+
def addresses(self):
49+
return [(self._hostname, self._port)]
5050

5151
def stop(self):
5252
self._container.rm()
@@ -74,8 +74,8 @@ def start(self, network):
7474
for core in self._cores:
7575
core.start(self._image, initial_members, network)
7676

77-
def address(self):
78-
return ("core0", 7687)
77+
def addresses(self):
78+
return [("core%d" % i, 7687) for i in range(self._num_cores)]
7979

8080
def stop(self):
8181
for core in self._cores:

tests/neo4j/authentication.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,17 @@
33
from nutkit.frontend import Driver
44
import nutkit.protocol as types
55
from tests.neo4j.shared import (
6+
cluster_unsafe_test,
67
env_neo4j_user,
78
env_neo4j_pass,
8-
get_neo4j_host_and_port,
9+
get_driver,
910
)
1011
from tests.shared import TestkitTestCase
1112

1213

1314
class TestAuthenticationBasic(TestkitTestCase):
1415
def setUp(self):
1516
super().setUp()
16-
self._host, self._port = get_neo4j_host_and_port()
17-
self._scheme = "bolt://%s:%d" % (self._host, self._port)
1817
self._driver = None
1918
self._session = None
2019

@@ -26,15 +25,17 @@ def tearDown(self):
2625
super().tearDown()
2726

2827
def createDriverAndSession(self, token):
29-
self._driver = Driver(self._backend, self._scheme, token)
28+
self._driver = get_driver(self._backend, auth=token)
3029
self._session = self._driver.session("r")
3130

31+
@cluster_unsafe_test
3232
def verifyConnectivity(self, auth_token):
3333
self.createDriverAndSession(auth_token)
3434
result = self._session.run("RETURN 2 as Number")
3535
self.assertEqual(
3636
result.next(), types.Record(values=[types.CypherInt(2)]))
3737

38+
@cluster_unsafe_test
3839
def testErrorOnIncorrectCredentials(self):
3940
auth_token = types.AuthorizationToken(scheme="basic",
4041
principal="fake",
@@ -44,6 +45,7 @@ def testErrorOnIncorrectCredentials(self):
4445
self.verifyConnectivity(auth_token)
4546

4647
# Tests both basic with realm specified and also custom auth token. All
48+
@cluster_unsafe_test
4749
def testSuccessOnProvideRealmWithBasicToken(self):
4850
auth_token = types.AuthorizationToken(
4951
scheme="basic",
@@ -52,6 +54,7 @@ def testSuccessOnProvideRealmWithBasicToken(self):
5254
credentials=os.environ.get(env_neo4j_pass, "pass"))
5355
self.verifyConnectivity(auth_token)
5456

57+
@cluster_unsafe_test
5558
def testSuccessOnBasicToken(self):
5659
auth_token = types.AuthorizationToken(
5760
scheme="basic",

tests/neo4j/datatypes.py

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,14 @@
44
from nutkit.frontend import Driver
55
import nutkit.protocol as types
66
from tests.neo4j.shared import (
7-
env_neo4j_pass,
8-
env_neo4j_user,
9-
get_neo4j_host_and_port,
7+
get_driver
108
)
119
from tests.shared import TestkitTestCase, get_driver_name
1210

1311

1412
class TestDataTypes(TestkitTestCase):
1513
def setUp(self):
1614
super().setUp()
17-
self._host, self._port = get_neo4j_host_and_port()
18-
self._scheme = "bolt://%s:%d" % (self._host, self._port)
1915
self._session = None
2016
self._driver = None
2117

@@ -27,19 +23,18 @@ def tearDown(self):
2723
super().tearDown()
2824

2925
def create_driver_and_session(self):
30-
auth_token = types.AuthorizationToken(
31-
scheme="basic",
32-
principal=os.environ.get(env_neo4j_user, "neo4j"),
33-
credentials=os.environ.get(env_neo4j_pass, "pass")
34-
)
35-
self._driver = Driver(self._backend, self._scheme, auth_token)
26+
self._driver = get_driver(self._backend)
3627
self._session = self._driver.session("w")
3728

3829
def verify_can_echo(self, val):
39-
result = self._session.run("RETURN $x as y", params={"x": val})
40-
record = result.next()
30+
def work(tx):
31+
result = tx.run("RETURN $x as y", params={"x": val})
32+
record_ = result.next()
33+
assert isinstance(result.next(), types.NullRecord)
34+
return record_
35+
36+
record = self._session.readTransaction(work)
4137
self.assertEqual(record, types.Record(values=[val]))
42-
assert isinstance(result.next(), types.NullRecord)
4338

4439
def test_should_echo_back(self):
4540
vals = [
@@ -146,10 +141,15 @@ def test_should_echo_nested_lists(self):
146141
self.verify_can_echo(types.CypherList(test_lists))
147142

148143
def test_should_echo_node(self):
144+
def work(tx):
145+
result = tx.run("CREATE (n:TestLabel {num: 1, txt: 'abc'}) RETURN n")
146+
record_ = result.next()
147+
assert isinstance(result.next(), types.NullRecord)
148+
return record_
149+
149150
self.create_driver_and_session()
150151

151-
result = self._session.run("CREATE (n:TestLabel {num: 1, txt: 'abc'}) RETURN n")
152-
record = result.next()
152+
record = self._session.writeTransaction(work)
153153
self.assertIsInstance(record, types.Record)
154154

155155
node = record.values[0]
@@ -161,11 +161,17 @@ def test_should_echo_relationship(self):
161161
# TODO: remove this block once all languages work
162162
if get_driver_name() in ["java"]:
163163
self.skipTest("Backend does not serialize relationships.")
164+
165+
def work(tx):
166+
result = tx.run("CREATE (a)-[r:KNOWS {since:1999}]->(b) "
167+
"RETURN a, b, r")
168+
record_ = result.next()
169+
assert isinstance(result.next(), types.NullRecord)
170+
return record_
171+
164172
self.create_driver_and_session()
165173

166-
result = self._session.run("CREATE (a)-[r:KNOWS {since:1999}]->(b) "
167-
"RETURN a, b, r")
168-
record = result.next()
174+
record = self._session.writeTransaction(work)
169175
self.assertIsInstance(record, types.Record)
170176
values = record.values
171177
self.assertEqual(len(values), 3)
@@ -185,11 +191,17 @@ def test_should_echo_path(self):
185191
# TODO: remove this block once all languages work
186192
if get_driver_name() in ["java"]:
187193
self.skipTest("Backend does not serialize paths.")
194+
195+
def work(tx):
196+
result = tx.run("CREATE p=(a)-[ab:X]->(b)-[bc:X]->(c) "
197+
"RETURN a, b, c, ab, bc, p")
198+
record_ = result.next()
199+
assert isinstance(result.next(), types.NullRecord)
200+
return record_
201+
188202
self.create_driver_and_session()
189203

190-
result = self._session.run("CREATE p=(a)-[ab:X]->(b)-[bc:X]->(c) "
191-
"RETURN a, b, c, ab, bc, p")
192-
record = result.next()
204+
record = self._session.writeTransaction(work)
193205
self.assertIsInstance(record, types.Record)
194206
values = record.values
195207
self.assertEqual(len(values), 6)
@@ -282,6 +294,3 @@ def test_should_echo_map_of_lists(self):
282294
}
283295
self.create_driver_and_session()
284296
self.verify_can_echo(types.CypherMap(test_map))
285-
286-
# def test_path(self):
287-
# todo: need to implement the cypher path type to do this test.

0 commit comments

Comments
 (0)