Skip to content

Commit a255661

Browse files
committed
Added TCK for python. TCK tests are set to run with runtests.sh
1 parent 5b44eda commit a255661

File tree

6 files changed

+420
-0
lines changed

6 files changed

+420
-0
lines changed

runtests.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ echo "Running tests with $(python --version)"
6262
pip install --upgrade -r ${DRIVER_HOME}/test_requirements.txt
6363
echo ""
6464
TEST_RUNNER="coverage run -m ${UNITTEST} discover -vfs ${TEST}"
65+
BEHAVE_RUNNER="behave test/tck"
6566
if [ ${RUNNING} -eq 1 ]
6667
then
6768
${TEST_RUNNER}
@@ -73,6 +74,11 @@ else
7374
then
7475
coverage report --show-missing
7576
fi
77+
python -c 'from test.tck.configure_feature_files import *; set_up()'
78+
echo "Feature files downloaded"
79+
neokit/neorun ${NEORUN_OPTIONS} "${BEHAVE_RUNNER}" ${VERSIONS}
80+
python -c 'from test.tck.configure_feature_files import *; clean_up()'
81+
echo "Feature files removed"
7682
fi
7783

7884
# Exit correctly

test/tck/__init__.py

Whitespace-only changes.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import os
2+
import tarfile
3+
import urllib2
4+
5+
6+
def clean_up():
7+
dir_path = (os.path.dirname(os.path.realpath(__file__)))#'test/tck/'
8+
files = os.listdir(dir_path)
9+
for f in files:
10+
if not os.path.isdir(f) and ".feature" in f:
11+
os.remove(os.path.join(dir_path, f))
12+
13+
14+
def set_up():
15+
dir_path = (os.path.dirname(os.path.realpath(__file__)))
16+
feature_url = "https://s3-eu-west-1.amazonaws.com/remoting.neotechnology.com/driver-compliance/tck.tar.gz"
17+
file_name = feature_url.split('/')[-1]
18+
tar = open(file_name, 'w')
19+
response = urllib2.urlopen(feature_url)
20+
block_sz = 1024
21+
while True:
22+
buffer = response.read(block_sz)
23+
if not buffer:
24+
break
25+
tar.write(buffer)
26+
tar.close()
27+
tar = tarfile.open(file_name)
28+
tar.extractall(dir_path)
29+
tar.close()
30+
os.remove(file_name)

test/tck/environment.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import logging
2+
3+
from test.tck import tck_util
4+
from behave.log_capture import capture
5+
6+
7+
def before_all(context):
8+
# -- SET LOG LEVEL: behave --logging-level=ERROR ...
9+
# on behave command-line or in "behave.ini".
10+
context.config.setup_logging()
11+
12+
13+
@capture
14+
def after_scenario(context, scenario):
15+
for step in scenario.steps:
16+
if step.status == 'failed':
17+
logging.error("Scenario :'%s' at step: '%s' failed! ", scenario.name, step.name)
18+
logging.debug("Expected result: %s", tck_util.as_cypger_text(context.expected))
19+
logging.debug("Actual result: %s", tck_util.as_cypger_text(context.results))
20+
if step.status == 'skipped':
21+
logging.warn("Scenario :'%s' at step: '%s' was skipped! ", scenario.name, step.name)
22+
if step.status == 'passed':
23+
logging.debug("Scenario :'%s' at step: '%s' was passed! ", scenario.name, step.name)

test/tck/steps/bolt_type_steps.py

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
from behave import *
2+
3+
from test.tck import tck_util
4+
5+
from neo4j.v1.typesystem import Node, Relationship, Path
6+
7+
use_step_matcher("re")
8+
9+
10+
@given("A running database")
11+
def step_impl(context):
12+
return None
13+
# check if running
14+
15+
16+
@given("a value (?P<Input>.+) of type (?P<BoltType>.+)")
17+
def step_impl(context, Input, BoltType):
18+
context.expected = tck_util.get_bolt_value(BoltType, Input)
19+
20+
21+
@given("a value of type (?P<BoltType>.+)")
22+
def step_impl(context, BoltType):
23+
context.expected = tck_util.get_bolt_value(BoltType, u' ')
24+
25+
26+
@given("a list value (?P<Input>.+) of type (?P<BoltType>.+)")
27+
def step_impl(context, Input, BoltType):
28+
context.expected = tck_util.get_list_from_feature_file(Input, BoltType)
29+
30+
31+
@given("an empty list L")
32+
def step_impl(context):
33+
context.L = []
34+
35+
36+
@given("an empty map M")
37+
def step_impl(context):
38+
context.M = {}
39+
40+
41+
@given("an empty node N")
42+
def step_impl(context):
43+
context.N = Node()
44+
45+
46+
@given("a node N with properties and labels")
47+
def step_impl(context):
48+
context.N = Node({"Person"}, {"name": "Alice", "age": 33})
49+
50+
51+
@given("a String of size (?P<size>\d+)")
52+
def step_impl(context, size):
53+
context.expected = tck_util.get_random_string(int(size))
54+
55+
56+
@given("a List of size (?P<size>\d+) and type (?P<Type>.+)")
57+
def step_impl(context, size, Type):
58+
context.expected = tck_util.get_list_of_random_type(int(size), Type)
59+
60+
61+
@given("a Map of size (?P<size>\d+) and type (?P<Type>.+)")
62+
def step_impl(context, size, Type):
63+
context.expected = tck_util.get_dict_of_random_type(int(size), Type)
64+
65+
66+
@step("adding a table of lists to the list L")
67+
def step_impl(context):
68+
for row in context.table:
69+
context.L.append(tck_util.get_list_from_feature_file(row[1], row[0]))
70+
71+
72+
@step("adding a table of values to the list L")
73+
def step_impl(context):
74+
for row in context.table:
75+
context.L.append(tck_util.get_bolt_value(row[0], row[1]))
76+
77+
78+
@step("adding a table of values to the map M")
79+
def step_impl(context):
80+
for row in context.table:
81+
context.M['a' + str(len(context.M))] = tck_util.get_bolt_value(row[0], row[1])
82+
83+
84+
@step("adding map M to list L")
85+
def step_impl(context):
86+
context.L.append(context.M)
87+
88+
89+
@when("adding a table of lists to the map M")
90+
def step_impl(context):
91+
for row in context.table:
92+
context.M['a' + str(len(context.M))] = tck_util.get_list_from_feature_file(row[1], row[0])
93+
94+
95+
@step("adding a copy of map M to map M")
96+
def step_impl(context):
97+
context.M['a' + str(len(context.M))] = context.M.copy()
98+
99+
100+
@when("the driver asks the server to echo this value back")
101+
def step_impl(context):
102+
context.results = {}
103+
context.results["as_string"] = tck_util.send_string("RETURN " + tck_util.as_cypger_text(context.expected))
104+
context.results["as_parameters"] = tck_util.send_parameters("RETURN {input}", {'input': context.expected})
105+
106+
107+
@when("the driver asks the server to echo this list back")
108+
def step_impl(context):
109+
context.expected = context.L
110+
context.results = {}
111+
context.results["as_string"] = tck_util.send_string("RETURN " + tck_util.as_cypger_text(context.expected))
112+
context.results["as_parameters"] = tck_util.send_parameters("RETURN {input}", {'input': context.expected})
113+
114+
115+
@when("the driver asks the server to echo this map back")
116+
def step_impl(context):
117+
context.expected = context.M
118+
context.results = {}
119+
context.results["as_string"] = tck_util.send_string("RETURN " + tck_util.as_cypger_text(context.expected))
120+
context.results["as_parameters"] = tck_util.send_parameters("RETURN {input}", {'input': context.expected})
121+
122+
123+
@when("the driver asks the server to echo this node back")
124+
def step_impl(context):
125+
context.expected = context.N
126+
context.results = {}
127+
context.results["as_parameters"] = tck_util.send_parameters("RETURN {input}", {'input': context.expected})
128+
129+
130+
@then("the result returned from the server should be a single record with a single value")
131+
def step_impl(context):
132+
assert len(context.results) > 0
133+
for result in context.results.values():
134+
assert len(result) == 1
135+
assert len(result[0]) == 1
136+
137+
138+
@step("the value given in the result should be the same as what was sent")
139+
def step_impl(context):
140+
assert len(context.results) > 0
141+
for result in context.results.values():
142+
result_value = result[0].values()[0]
143+
assert result_value == context.expected
144+
145+
146+
@step("the node value given in the result should be the same as what was sent")
147+
def step_impl(context):
148+
assert len(context.results) > 0
149+
for result in context.results.values():
150+
result_value = result[0].values()[0]
151+
assert result_value == context.expected
152+
assert result_value.labels == context.expected.labels
153+
assert result_value.keys() == context.expected.keys()
154+
assert result_value.values() == context.expected.values()
155+
assert result_value.items() == context.expected.items()
156+
assert len(result_value) == len(context.expected)
157+
assert iter(result_value) == iter(context.expected)
158+
159+
160+
##CURRENTLY NOT SUPPORTED IN PYTHON DRIVERS
161+
162+
@given("a relationship R")
163+
def step_impl(context):
164+
alice = Node({"Person"}, {"name": "Alice", "age": 33})
165+
bob = Node({"Person"}, {"name": "Bob", "age": 44})
166+
context.R = Relationship(alice, bob, "KNOWS", {"since": 1999})
167+
168+
169+
@when("the driver asks the server to echo this relationship R back")
170+
def step_impl(context):
171+
context.expected = context.R
172+
context.results = {}
173+
context.results["as_parameters"] = tck_util.send_parameters("RETURN {input}", {'input': context.expected})
174+
175+
176+
@step("the relationship value given in the result should be the same as what was sent")
177+
def step_impl(context):
178+
assert len(context.results) > 0
179+
for result in context.results.values():
180+
result_value = result[0].values()[0]
181+
assert result_value == context.expected
182+
assert result_value.start == context.expected.start
183+
assert result_value.type == context.expected.type
184+
assert result_value.end == context.expected.end
185+
assert result_value.items() == context.expected.items()
186+
assert result_value.keys() == context.expected.keys()
187+
assert result_value.values() == context.expected.values()
188+
189+
190+
@given("a zero length path P")
191+
def step_impl(context):
192+
context.P = Path(Node({"Person"}, {"name": "Alice", "age": 33}))
193+
194+
195+
@given("a arbitrary long path P")
196+
def step_impl(context):
197+
alice = Node({"Person"}, {"name": "Alice", "age": 33})
198+
bob = Node({"Person"}, {"name": "Bob", "age": 44})
199+
carol = Node({"Person"}, {"name": "Carol", "age": 55})
200+
alice_knows_bob = Relationship(alice, bob, "KNOWS", {"since": 1999})
201+
carol_dislikes_bob = Relationship(carol, bob, "DISLIKES")
202+
context.P = Path(alice, alice_knows_bob, bob, carol_dislikes_bob, carol)
203+
204+
205+
@when("the driver asks the server to echo this path back")
206+
def step_impl(context):
207+
context.expected = context.P
208+
context.results = {}
209+
context.results["as_parameters"] = tck_util.send_parameters("RETURN {input}", {'input': context.expected})
210+
211+
212+
@step("the path value given in the result should be the same as what was sent")
213+
def step_impl(context):
214+
assert len(context.results) > 0
215+
for result in context.results.values():
216+
result_value = result[0].values()[0]
217+
assert result_value == context.expected
218+
assert result_value.start == context.expected.start
219+
assert result_value.end == context.expected.end
220+
assert result_value.nodes == context.expected.nodes
221+
assert result_value.relationships == context.expected.relationships
222+
assert list(result_value) == list(context.expected)
223+
224+
225+
@given("a Node with great amount of properties and labels")
226+
def step_impl(context):
227+
context.N = Node(tck_util.get_list_of_random_type(1000, "String"),
228+
tck_util.get_dict_of_random_type(1000, "String"))
229+
230+
231+
@given("a path P of size (?P<size>\d+)")
232+
def step_impl(context, size):
233+
nodes_and_rels = [Node({tck_util.get_random_string(5)}, tck_util.get_dict_of_random_type(3, "String"))]
234+
for i in range(1, int(12)):
235+
n = nodes_and_rels.append(Node({tck_util.get_random_string(5)}, tck_util.get_dict_of_random_type(3, "String")))
236+
r = Relationship(nodes_and_rels[-1], n, tck_util.get_random_string(4),
237+
tck_util.get_dict_of_random_type(3, "String"))
238+
nodes_and_rels.append(r)
239+
nodes_and_rels.append(n)
240+
241+
context.P = Path(nodes_and_rels[0], nodes_and_rels[1:])

0 commit comments

Comments
 (0)