diff --git a/build.gradle b/build.gradle index f3324763..ed820e1b 100644 --- a/build.gradle +++ b/build.gradle @@ -65,7 +65,7 @@ ext { argparse4jVersion = '0.7.0' junitVersion = '4.12' - neo4jJavaVersion = '1.1.0-M06' + neo4jJavaVersion = '1.1.0' findbugsVersion = '3.0.0' jansiVersion = '1.13' jlineVersion = '2.14.2' diff --git a/cypher-shell/src/main/java/org/neo4j/shell/state/BoltStateHandler.java b/cypher-shell/src/main/java/org/neo4j/shell/state/BoltStateHandler.java index ce957fe6..0d28ec7a 100644 --- a/cypher-shell/src/main/java/org/neo4j/shell/state/BoltStateHandler.java +++ b/cypher-shell/src/main/java/org/neo4j/shell/state/BoltStateHandler.java @@ -30,6 +30,7 @@ public class BoltStateHandler implements TransactionHandler, Connector { protected Driver driver; protected Session session; protected Transaction tx = null; + private String version; public BoltStateHandler() { this(GraphDatabase::driver); @@ -103,7 +104,9 @@ public void connect(@Nonnull ConnectionConfig connectionConfig) throws CommandEx driver = getDriver(connectionConfig, authToken); session = driver.session(); // Bug in Java driver forces us to run a statement to make it actually connect - session.run("RETURN 1").consume(); + StatementResult run = session.run( "RETURN 1" ); + this.version = run.summary().server().version(); + run.consume(); } catch (Throwable t) { try { silentDisconnect(); @@ -118,7 +121,6 @@ public void connect(@Nonnull ConnectionConfig connectionConfig) throws CommandEx @Override public String getServerVersion() { if (isConnected()) { - String version = session.server(); if (version == null) { // On versions before 3.1.0-M09 version = ""; diff --git a/cypher-shell/src/test/java/org/neo4j/shell/state/BoltStateHandlerTest.java b/cypher-shell/src/test/java/org/neo4j/shell/state/BoltStateHandlerTest.java index a6150978..dad2facb 100644 --- a/cypher-shell/src/test/java/org/neo4j/shell/state/BoltStateHandlerTest.java +++ b/cypher-shell/src/test/java/org/neo4j/shell/state/BoltStateHandlerTest.java @@ -10,6 +10,8 @@ import org.neo4j.driver.v1.Session; import org.neo4j.driver.v1.StatementResult; import org.neo4j.driver.v1.Transaction; +import org.neo4j.driver.v1.summary.ResultSummary; +import org.neo4j.driver.v1.summary.ServerInfo; import org.neo4j.shell.ConnectionConfig; import org.neo4j.shell.TriFunction; import org.neo4j.shell.exception.CommandException; @@ -53,18 +55,13 @@ public Driver apply(String uri, AuthToken authToken, Config config) { return new FakeDriver() { @Override public Session session() { - return new FakeSession() { - @Override - public String server() { - return null; - } - }; + return new FakeSession(); } }; } }; BoltStateHandler handler = new BoltStateHandler(provider); - ConnectionConfig config = new ConnectionConfig( logger, "bolt://", "", -1, "", "", false); + ConnectionConfig config = new ConnectionConfig(logger, "bolt://", "", -1, "", "", false); handler.connect(config); assertEquals("", handler.getServerVersion()); @@ -72,30 +69,32 @@ public String server() { @Test public void versionIsNotEmptyAfterConnect() throws CommandException { - RecordingDriverProvider provider = new RecordingDriverProvider() { - @Override - public Driver apply(String uri, AuthToken authToken, Config config) { - super.apply(uri, authToken, config); - return new FakeDriver() { - @Override - public Session session() { - return new FakeSession() { - @Override - public String server() { - return "Neo4j/9.4.1-ALPHA"; - } - }; - } - }; - } - }; - BoltStateHandler handler = new BoltStateHandler(provider); + Session sessionMock = mock(Session.class); + StatementResult resultMock = mock(StatementResult.class); + Driver driverMock = mock(Driver.class); + + stubVersion(resultMock, "Neo4j/9.4.1-ALPHA"); + when(driverMock.session()).thenReturn(sessionMock); + when(sessionMock.run("RETURN 1")).thenReturn(resultMock); + + when(sessionMock.isOpen()).thenReturn(true); + + BoltStateHandler handler = new BoltStateHandler((s, authToken, config) -> driverMock); ConnectionConfig config = new ConnectionConfig(logger, "bolt://", "", -1, "", "", false); handler.connect(config); assertEquals("9.4.1-ALPHA", handler.getServerVersion()); } + private void stubVersion(StatementResult resultMock, String value) { + ResultSummary resultSummary = mock(ResultSummary.class); + ServerInfo serverInfo = mock(ServerInfo.class); + + when(resultSummary.server()).thenReturn(serverInfo); + when(serverInfo.version()).thenReturn(value); + when(resultMock.summary()).thenReturn(resultSummary); + } + @Test public void closeTransactionAfterRollback() throws CommandException { boltStateHandler.connect(); @@ -117,13 +116,16 @@ public void exceptionsFromSilentDisconnectAreSuppressedToReportOriginalErrors() Driver mockedDriver = mock(Driver.class); Session session = mock(Session.class); StatementResult resultMock = mock(StatementResult.class); + RuntimeException originalException = new RuntimeException("original exception"); RuntimeException thrownFromSilentDisconnect = new RuntimeException("exception from silent disconnect"); OfflineBoltStateHandler boltStateHandler = new OfflineBoltStateHandler(mockedDriver); + stubVersion(resultMock, "neo4j-version"); when(mockedDriver.session()).thenReturn(session); when(session.run("RETURN 1")).thenReturn(resultMock); + when(resultMock.consume()).thenThrow(originalException); doThrow(thrownFromSilentDisconnect).when(session).close(); @@ -229,6 +231,7 @@ public void resetSessionOnReset() throws Exception { Driver driverMock = mock(Driver.class); Transaction transactionMock = mock(Transaction.class); + stubVersion(resultMock, "neo4j-version"); when(driverMock.session()).thenReturn(sessionMock); when(sessionMock.run("RETURN 1")).thenReturn(resultMock); when(sessionMock.isOpen()).thenReturn(true); @@ -288,6 +291,7 @@ public void turnOnEncryptionIfRequested() throws CommandException { * Bolt state with faked bolt interactions */ private static class OfflineBoltStateHandler extends BoltStateHandler { + public OfflineBoltStateHandler(Driver driver) { super((uri, authToken, config) -> driver); } diff --git a/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeResultSummary.java b/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeResultSummary.java index 44352299..3c844ce7 100644 --- a/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeResultSummary.java +++ b/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeResultSummary.java @@ -61,4 +61,23 @@ public long resultAvailableAfter(TimeUnit unit) { public long resultConsumedAfter(TimeUnit unit) { return 0; } + + @Override + public ServerInfo server() + { + return new ServerInfo() + { + @Override + public String address() + { + throw new Util.NotImplementedYetException("Not implemented yet"); + } + + @Override + public String version() + { + return null; + } + }; + } } diff --git a/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeSession.java b/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeSession.java index 85c99332..6cd3f15c 100644 --- a/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeSession.java +++ b/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeSession.java @@ -40,11 +40,6 @@ public void close() { open = false; } - @Override - public String server() { - return null; - } - @Override public StatementResult run(String statementTemplate, Value parameters) { return FakeStatementResult.parseStatement(statementTemplate); diff --git a/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeStatementResult.java b/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeStatementResult.java index 464dc7e1..47f994a5 100644 --- a/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeStatementResult.java +++ b/cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeStatementResult.java @@ -18,7 +18,7 @@ /** * A fake StatementResult with fake records and fake values */ -public class FakeStatementResult implements StatementResult { +class FakeStatementResult implements StatementResult { private final List records; private int currentRecord = -1; @@ -71,6 +71,12 @@ public ResultSummary consume() { return new FakeResultSummary(); } + @Override + public ResultSummary summary() + { + return new FakeResultSummary(); + } + /** * Supports fake parsing of very limited cypher statements, only for basic test purposes */