Skip to content

Commit dc4c783

Browse files
authored
Add tests for null, 0, and -1 tx timeout (#356)
Changes the protocol: * tx timeout in protocol is now an optional field
1 parent fb07a87 commit dc4c783

File tree

14 files changed

+144
-18
lines changed

14 files changed

+144
-18
lines changed

nutkit/frontend/session.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ def close(self, hooks=None):
1919
if not isinstance(res, protocol.Session):
2020
raise Exception("Should be session but was: %s" % res)
2121

22-
def run(self, cypher, params=None, tx_meta=None, timeout=None, hooks=None):
22+
def run(self, cypher, params=None, tx_meta=None, hooks=None, **kwargs):
2323
req = protocol.SessionRun(self._session.id, cypher, params,
24-
txMeta=tx_meta, timeout=timeout)
24+
txMeta=tx_meta, **kwargs)
2525
self._backend.send(req, hooks=hooks)
2626
while True:
2727
res = self._backend.receive(hooks=hooks)
@@ -91,23 +91,23 @@ def process_transaction(self, req, fn, config=None, hooks=None):
9191
elif isinstance(res, protocol.RetryableDone):
9292
return x
9393

94-
def read_transaction(self, fn, tx_meta=None, timeout=None, hooks=None):
94+
def read_transaction(self, fn, tx_meta=None, hooks=None, **kwargs):
9595
# Send request to enter transactional read function
9696
req = protocol.SessionReadTransaction(
97-
self._session.id, txMeta=tx_meta, timeout=timeout
97+
self._session.id, txMeta=tx_meta, **kwargs
9898
)
9999
return self.process_transaction(req, fn, hooks=hooks)
100100

101-
def write_transaction(self, fn, tx_meta=None, timeout=None, hooks=None):
101+
def write_transaction(self, fn, tx_meta=None, hooks=None, **kwargs):
102102
# Send request to enter transactional read function
103103
req = protocol.SessionWriteTransaction(
104-
self._session.id, txMeta=tx_meta, timeout=timeout
104+
self._session.id, txMeta=tx_meta, **kwargs
105105
)
106106
return self.process_transaction(req, fn, hooks=hooks)
107107

108-
def begin_transaction(self, tx_meta=None, timeout=None, hooks=None):
108+
def begin_transaction(self, tx_meta=None, hooks=None, **kwargs):
109109
req = protocol.SessionBeginTransaction(
110-
self._session.id, txMeta=tx_meta, timeout=timeout
110+
self._session.id, txMeta=tx_meta, **kwargs
111111
)
112112
res = self._backend.send_and_receive(req, hooks=hooks)
113113
if not isinstance(res, protocol.Transaction):

nutkit/protocol/requests.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,12 +238,13 @@ class SessionRun:
238238
Backend should respond with a Result response or an Error response.
239239
"""
240240

241-
def __init__(self, sessionId, cypher, params, txMeta=None, timeout=None):
241+
def __init__(self, sessionId, cypher, params, txMeta=None, **kwargs):
242242
self.sessionId = sessionId
243243
self.cypher = cypher
244244
self.params = params
245245
self.txMeta = txMeta
246-
self.timeout = timeout
246+
if "timeout" in kwargs:
247+
self.timeout = kwargs["timeout"]
247248

248249

249250
class SessionReadTransaction:
@@ -253,10 +254,11 @@ class SessionReadTransaction:
253254
Backend should respond with a RetryableTry response or an Error response.
254255
"""
255256

256-
def __init__(self, sessionId, txMeta=None, timeout=None):
257+
def __init__(self, sessionId, txMeta=None, **kwargs):
257258
self.sessionId = sessionId
258259
self.txMeta = txMeta
259-
self.timeout = timeout
260+
if "timeout" in kwargs:
261+
self.timeout = kwargs["timeout"]
260262

261263

262264
class SessionWriteTransaction:
@@ -266,10 +268,11 @@ class SessionWriteTransaction:
266268
Backend should respond with a RetryableTry response or an Error response.
267269
"""
268270

269-
def __init__(self, sessionId, txMeta=None, timeout=None):
271+
def __init__(self, sessionId, txMeta=None, **kwargs):
270272
self.sessionId = sessionId
271273
self.txMeta = txMeta
272-
self.timeout = timeout
274+
if "timeout" in kwargs:
275+
self.timeout = kwargs["timeout"]
273276

274277

275278
class SessionBeginTransaction:
@@ -279,10 +282,11 @@ class SessionBeginTransaction:
279282
Backend should respond with a Transaction response or an Error response.
280283
"""
281284

282-
def __init__(self, sessionId, txMeta=None, timeout=None):
285+
def __init__(self, sessionId, txMeta=None, **kwargs):
283286
self.sessionId = sessionId
284287
self.txMeta = txMeta
285-
self.timeout = timeout
288+
if "timeout" in kwargs:
289+
self.timeout = kwargs["timeout"]
286290

287291

288292
class SessionLastBookmarks:
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
!: BOLT 4.4
2+
3+
A: HELLO {"{}": "*"}
4+
*: RESET
5+
# We expect the driver to not even try this. So should it do so nonetheless,
6+
# we will let is pass to not cause any error. The error should be generated
7+
# inside the driver.
8+
C: BEGIN {"[tx_timeout]": "*"}
9+
S: SUCCESS {"fields": ["n"]}
10+
C: PULL {"n": 1000}
11+
S: RECORD [1]
12+
SUCCESS {"type": "w"}
13+
*: RESET
14+
?: GOODBYE
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
!: BOLT 4.4
2+
3+
A: HELLO {"{}": "*"}
4+
*: RESET
5+
C: RUN "RETURN 1 as n" {} {"tx_timeout": 0}
6+
S: SUCCESS {"fields": ["n"]}
7+
C: PULL {"n": 1000}
8+
S: RECORD [1]
9+
SUCCESS {"type": "w"}
10+
*: RESET
11+
?: GOODBYE
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
!: BOLT 4.4
2+
3+
A: HELLO {"{}": "*"}
4+
*: RESET
5+
C: RUN "RETURN 1 as n" {} {"[tx_timeout]": null}
6+
S: SUCCESS {"fields": ["n"]}
7+
C: PULL {"n": 1000}
8+
S: RECORD [1]
9+
SUCCESS {"type": "w"}
10+
*: RESET
11+
?: GOODBYE

tests/stub/session_run_parameters/test_session_run_parameters.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,29 @@ def test_tx_meta(self):
122122
def test_timeout(self):
123123
for routing in (True, False):
124124
with self.subTest("routing" if routing else "direct"):
125-
self._run("timeout", routing,
125+
self._run("timeout_17", routing,
126126
session_args=("w",), run_kwargs={"timeout": 17})
127127

128+
@driver_feature(types.Feature.BOLT_4_4)
129+
def test_0_timeout(self):
130+
self._run("timeout_0", routing=False,
131+
session_args=("w",), run_kwargs={"timeout": 0})
132+
133+
@driver_feature(types.Feature.BOLT_4_4)
134+
def test_null_timeout(self):
135+
self._run("timeout_null", routing=False,
136+
session_args=("w",), run_kwargs={"timeout": None})
137+
138+
@driver_feature(types.Feature.BOLT_4_4)
139+
def test_default_timeout(self):
140+
self._run("timeout_null", routing=False, session_args=("w",))
141+
142+
@driver_feature(types.Feature.BOLT_4_4)
143+
def test_negative_timeout(self):
144+
with self.assertRaises(types.DriverError):
145+
self._run("timeout_-1", routing=False,
146+
session_args=("w",), run_kwargs={"timeout": -1})
147+
128148
@driver_feature(types.Feature.IMPERSONATION,
129149
types.Feature.BOLT_4_4)
130150
def test_database(self):
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
!: BOLT 4.4
2+
3+
A: HELLO {"{}": "*"}
4+
*: RESET
5+
# We expect the driver to not even try this. So should it do so nonetheless,
6+
# we will let is pass to not cause any error. The error should be generated
7+
# inside the driver.
8+
C: BEGIN {"[tx_timeout]": "*"}
9+
S: SUCCESS {}
10+
C: RUN "RETURN 1 as n" {} {}
11+
S: SUCCESS {"fields": ["n"]}
12+
C: PULL {"n": 1000}
13+
S: SUCCESS {"type": "r"}
14+
C: COMMIT
15+
S: SUCCESS {}
16+
*: RESET
17+
?: GOODBYE
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
!: BOLT 4.4
2+
3+
A: HELLO {"{}": "*"}
4+
*: RESET
5+
C: BEGIN {"tx_timeout": 0}
6+
S: SUCCESS {}
7+
C: RUN "RETURN 1 as n" {} {}
8+
S: SUCCESS {"fields": ["n"]}
9+
C: PULL {"n": 1000}
10+
S: SUCCESS {"type": "r"}
11+
C: COMMIT
12+
S: SUCCESS {}
13+
*: RESET
14+
?: GOODBYE

0 commit comments

Comments
 (0)