Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion boltstub/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import math
from os import path
import re
import sys
from textwrap import wrap
import threading
from time import sleep
Expand Down Expand Up @@ -1220,6 +1221,10 @@ def parse(script: str, substitutions: Optional[dict] = None) -> Script:

def parse_file(filename):
with open(filename) as fd:
script = parse(fd.read())
try:
script = parse(fd.read())
except Exception:
print("Error while parsing %s" % filename, file=sys.stderr)
raise
script.filename = filename
return script
9 changes: 5 additions & 4 deletions nutkit/frontend/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ def close(self):
raise Exception("Should be driver")

def session(self, accessMode, bookmarks=None, database=None,
fetchSize=None):
req = protocol.NewSession(self._driver.id, accessMode,
bookmarks=bookmarks, database=database,
fetchSize=fetchSize)
fetchSize=None, impersonatedUser=None):
req = protocol.NewSession(
self._driver.id, accessMode, bookmarks=bookmarks, database=database,
fetchSize=fetchSize, impersonatedUser=impersonatedUser
)
res = self._backend.sendAndReceive(req)
if not isinstance(res, protocol.Session):
raise Exception("Should be session")
Expand Down
4 changes: 4 additions & 0 deletions nutkit/protocol/feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class Feature(Enum):
# The driver supports Kerberos authentication by providing a dedicated auth
# token API.
AUTH_KERBEROS = "Feature:Auth:Kerberos"
# The driver supports Bolt protocol version 4.4
BOLT_4_4 = "Feature:Bolt:4.4"
# The driver supports impersonation
IMPERSONATION = "Feature:Impersonation"

# === OPTIMIZATIONS ===
# On receiving Neo.ClientError.Security.AuthorizationExpired, the driver
Expand Down
3 changes: 2 additions & 1 deletion nutkit/protocol/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ class NewSession:
"""

def __init__(self, driverId, accessMode, bookmarks=None,
database=None, fetchSize=None):
database=None, fetchSize=None, impersonatedUser=None):
# Id of driver on backend that session should be created on
self.driverId = driverId
# Session accessmode: 'r' for read access and 'w' for write access.
Expand All @@ -158,6 +158,7 @@ def __init__(self, driverId, accessMode, bookmarks=None,
self.bookmarks = bookmarks
self.database = database
self.fetchSize = fetchSize
self.impersonatedUser = impersonatedUser


class SessionClose:
Expand Down
24 changes: 12 additions & 12 deletions tests/stub/disconnects/test_disconnects.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class TestDisconnects(TestkitTestCase):
def setUp(self):
super().setUp()
self._server = StubServer(9001)
self._driverName = get_driver_name()
self._driver_name = get_driver_name()
auth = types.AuthorizationToken("basic", principal="neo4j",
credentials="pass")
uri = "bolt://%s" % self._server.address
Expand Down Expand Up @@ -97,7 +97,7 @@ def test_disconnect_on_hello(self):
self._server.done()

expected_step = "after run"
if self._driverName in ["javascript"]:
if self._driver_name in ["javascript"]:
expected_step = "after first next"
self.assertEqual(step, expected_step)

Expand All @@ -116,7 +116,7 @@ def test_disconnect_after_hello(self):
self._server.done()

expected_step = "after run"
if self._driverName in ["dotnet", "javascript"]:
if self._driver_name in ["dotnet", "javascript"]:
expected_step = "after first next"
self.assertEqual(step, expected_step)

Expand All @@ -131,7 +131,7 @@ def test_disconnect_session_on_run(self):
self._server.done()

expected_step = "after run"
if self._driverName in ["dotnet", "javascript"]:
if self._driver_name in ["dotnet", "javascript"]:
expected_step = "after first next"
self.assertEqual(step, expected_step)

Expand Down Expand Up @@ -164,7 +164,7 @@ def test_disconnect_session_on_pull_after_record(self):
def test_disconnect_on_tx_begin(self):
# Verifies how the driver handles when server disconnects right after
# driver sent bolt BEGIN message.
if self._driverName in ["go"]:
if self._driver_name in ["go"]:
self.skipTest("Driver fails on session.close")
self._server.start(path=self.script_path("exit_after_tx_begin.script"),
vars=self.get_vars())
Expand All @@ -174,16 +174,16 @@ def test_disconnect_on_tx_begin(self):
self._server.done()

expected_step = "after begin"
if self._driverName in ["go"]:
if self._driver_name in ["go"]:
expected_step = "after run"
elif self._driverName in ["javascript"]:
elif self._driver_name in ["javascript"]:
expected_step = "after first next"
self.assertEqual(step, expected_step)

def test_disconnect_on_tx_run(self):
# Verifies how the driver handles when server disconnects right after
# driver sent bolt RUN message within a transaction.
if self._driverName in ["go"]:
if self._driver_name in ["go"]:
self.skipTest("Driver fails on session.close")
self._server.start(path=self.script_path("exit_after_tx_run.script"),
vars=self.get_vars())
Expand All @@ -193,14 +193,14 @@ def test_disconnect_on_tx_run(self):
self._server.done()

expected_step = "after run"
if self._driverName in ["javascript", "dotnet"]:
if self._driver_name in ["javascript", "dotnet"]:
expected_step = "after first next"
self.assertEqual(step, expected_step)

def test_disconnect_on_tx_pull(self):
# Verifies how the driver handles when server disconnects right after
# driver sent bolt PULL message within a transaction.
if self._driverName in ["go"]:
if self._driver_name in ["go"]:
self.skipTest("Driver fails on session.close")
self._server.start(path=self.script_path("exit_after_tx_pull.script"),
vars=self.get_vars())
Expand All @@ -216,7 +216,7 @@ def test_disconnect_session_on_tx_pull_after_record(self):
# Verifies how the driver handles when server disconnects after driver
# sent bolt RUN message and received a RECORD but no summary within a
# transaction.
if self._driverName in ["go"]:
if self._driver_name in ["go"]:
self.skipTest("Driver fails on session.close")
self._server.start(path=self.script_path("exit_after_tx_record.script"),
vars=self.get_vars())
Expand Down Expand Up @@ -286,7 +286,7 @@ def get_vars(self):
}

def get_extra_hello_props(self):
if self._driverName == "dotnet":
if self._driver_name == "dotnet":
return ', "routing": null'
else:
return ""
52 changes: 52 additions & 0 deletions tests/stub/optimizations/scripts/v4x4/all_default.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
!: BOLT 4.4

C: HELLO {"user_agent": "*", "scheme": "basic", "principal": "*", "credentials": "*"}
S: SUCCESS {"server": "Neo4j/4.4.0", "connection_id": "example-connection-id:1"}
*: RESET
{{
# transaction
C: BEGIN {}
S: SUCCESS {}
C: RUN "*" {} {}
S: SUCCESS {"fields": ["1"], "qid": 1}
{{
C: PULL {"n": "*"}
S: RECORD [1]
SUCCESS {"has_more": true}
{{
C: PULL {"n": "*"}
S: RECORD [1]
----
# Drivers that pipeline a PULL will takes this path in the discarding tests
C: DISCARD {"n": "*"}
}}
----
# Drivers that don't pipeline a PULL will takes this path in the discarding tests
C: DISCARD {"n": "*"}
}}
S: SUCCESS {}
C: COMMIT
S: SUCCESS {"type": "w", "bookmark": "bookmark:1"}
----
# auto commit transaction
C: RUN "*" {} {}
S: SUCCESS {"fields": ["1"]}
{{
C: PULL {"n": "*"}
S: RECORD [1]
SUCCESS {"has_more": true}
{{
C: PULL {"n": "*"}
S: RECORD [1]
----
# Drivers that pipeline a PULL will takes this path in the discarding tests
C: DISCARD {"n": "*"}
}}
----
# Drivers that don't pipeline a PULL will takes this path in the discarding tests
C: DISCARD {"n": "*"}
}}
S: SUCCESS {"type": "w", "bookmark": "bookmark:1"}
}}
*: RESET
?: GOODBYE
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
!: BOLT 4.4

C: HELLO {"user_agent": "*", "scheme": "basic", "principal": "*", "credentials": "*"}
S: SUCCESS {"server": "Neo4j/4.4.0", "connection_id": "example-connection-id:1"}
*: RESET
C: BEGIN {}
S: SUCCESS {}
C: RUN "*" {} {}
S: SUCCESS {"fields": ["1"], "qid": 1}
{{
C: PULL {"n": "*"}
S: RECORD [1]
SUCCESS {"has_more": true}
{{
C: PULL {"n": "*"}
S: RECORD [1]
----
# Drivers that pipeline a PULL will takes this path in the discarding tests
C: DISCARD {"n": "*"}
}}
----
# Drivers that don't pipeline a PULL will takes this path in the discarding tests
C: DISCARD {"n": "*"}
}}
S: SUCCESS {}
C: RUN "*" {} {}
S: SUCCESS {"fields": ["2"], "qid": 2}
{{
C: PULL {"n": "*"}
S: RECORD [1]
SUCCESS {"has_more": true}
{{
C: PULL {"n": "*"}
S: RECORD [1]
----
# Drivers that pipeline a PULL will takes this path in the discarding tests
C: DISCARD {"n": "*"}
}}
----
# Drivers that don't pipeline a PULL will takes this path in the discarding tests
C: DISCARD {"n": "*"}
}}
S: SUCCESS {}
C: COMMIT
S: SUCCESS {"type": "w", "bookmark": "bookmark:1"}
*: RESET
?: GOODBYE
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
!: BOLT 4.4

C: HELLO {"user_agent": "*", "scheme": "basic", "principal": "*", "credentials": "*"}
S: SUCCESS {"server": "Neo4j/4.4.0", "connection_id": "example-connection-id:1"}
*: RESET
C: BEGIN {}
S: SUCCESS {}
C: RUN "*" {} {}
S: SUCCESS {"fields": ["1"], "qid": 1}
C: PULL {"n": "*"}
S: RECORD [1]
SUCCESS {"has_more": true}
{?
# Eager drivers might pull a record in advance
C: PULL {"n": "*"}
S: RECORD [1]
SUCCESS {"has_more": true}
?}
C: RUN "*" {} {}
S: SUCCESS {"fields": ["2"], "qid": 2}
{{
C: PULL {"n": "*"}
S: RECORD [1]
SUCCESS {"has_more": true}
{{
C: PULL {"n": "*"}
S: RECORD [1]
----
# Drivers that pipeline a PULL will takes this path in the discarding tests
C: DISCARD {"n": "*"}
}}
----
# Drivers that don't pipeline a PULL will takes this path in the discarding tests
C: DISCARD {"n": "*"}
}}
S: SUCCESS {}
{{
C: PULL {"n": "*", "qid": 1}
S: RECORD [1]
----
# Drivers that pipeline a PULL will takes this path in the discarding tests
C: DISCARD {"n": "*", "qid": 1}
}}
S: SUCCESS {}
C: COMMIT
S: SUCCESS {"type": "w", "bookmark": "bookmark:1"}
*: RESET
?: GOODBYE
12 changes: 12 additions & 0 deletions tests/stub/optimizations/scripts/v4x4/all_default_router.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
!: BOLT 4.4
!: ALLOW CONCURRENT

C: HELLO {"user_agent": "*", "scheme": "basic", "principal": "*", "credentials": "*", "routing": {"{}": "*"}}
S: SUCCESS {"server": "Neo4j/4.4.0", "connection_id": "example-connection-id:0"}
*: RESET
{*
C: ROUTE "*" "*" "*"
S: SUCCESS { "rt": { "ttl": 1000, "servers": [{"addresses": ["#HOST#:9000"], "role":"ROUTE"}, {"addresses": ["#HOST#:9001"], "role":"READ"}, {"addresses": ["#HOST#:9001"], "role":"WRITE"}]}}
*: RESET
*}
?: GOODBYE
35 changes: 35 additions & 0 deletions tests/stub/optimizations/scripts/v4x4/all_default_routing.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
!: BOLT 4.4

C: HELLO {"user_agent": "*", "scheme": "basic", "principal": "*", "credentials": "*", "routing": {"{}": "*"}}
S: SUCCESS {"server": "Neo4j/4.4.0", "connection_id": "example-connection-id:1"}
*: RESET
{{
# transaction
C: BEGIN {}
S: SUCCESS {}
C: RUN "*" {} {}
S: SUCCESS {"fields": ["1"]}
{{
C: PULL {"n": "*"}
S: RECORD [1]
----
C: DISCARD {}
}}
S: SUCCESS {}
C: COMMIT
S: SUCCESS {"type": "w", "bookmark": "bookmark:1"}
----
# auto commit transaction
C: RUN "*" {} {}
S: SUCCESS {"fields": ["1"]}
{{
C: PULL {"n": "*"}
S: RECORD [1]
----
C: DISCARD {}
}}
S: RECORD [1]
SUCCESS {"type": "w", "bookmark": "bookmark:1"}
}}
*: RESET
?: GOODBYE
Loading