Skip to content
This repository was archived by the owner on Jul 6, 2023. It is now read-only.

Commit 083c3f5

Browse files
committed
Stop unwrapping Bolt exceptions.
Bolt throws sensible exceptions, we should not unwrap them. Also add integration tests for error messages if a DBMS is not reachable. One test ignored, since there is a problem in the Java Driver
1 parent 51d0b81 commit 083c3f5

File tree

3 files changed

+114
-45
lines changed

3 files changed

+114
-45
lines changed
Lines changed: 104 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,136 @@
11
package org.neo4j.shell;
22

3+
import org.junit.Ignore;
4+
import org.junit.Rule;
35
import org.junit.Test;
4-
import org.neo4j.shell.cli.CliArgs;
5-
import org.neo4j.shell.log.AnsiLogger;
6-
import org.neo4j.shell.log.Logger;
7-
import org.neo4j.shell.prettyprint.PrettyConfig;
6+
import org.junit.rules.ExpectedException;
87

98
import java.io.ByteArrayInputStream;
109
import java.io.ByteArrayOutputStream;
1110
import java.io.InputStream;
1211
import java.io.PrintStream;
1312

13+
import org.neo4j.driver.exceptions.ServiceUnavailableException;
14+
import org.neo4j.shell.cli.CliArgs;
15+
import org.neo4j.shell.log.AnsiLogger;
16+
import org.neo4j.shell.log.Logger;
17+
import org.neo4j.shell.prettyprint.PrettyConfig;
18+
1419
import static org.junit.Assert.assertEquals;
1520
import static org.junit.Assert.assertTrue;
1621

17-
public class MainIntegrationTest {
22+
public class MainIntegrationTest
23+
{
24+
25+
private static class ShellAndConnection
26+
{
27+
CypherShell shell;
28+
ConnectionConfig connectionConfig;
29+
30+
ShellAndConnection( CypherShell shell, ConnectionConfig connectionConfig )
31+
{
32+
this.shell = shell;
33+
this.connectionConfig = connectionConfig;
34+
}
35+
}
36+
37+
@Rule
38+
public final ExpectedException exception = ExpectedException.none();
1839

1940
@Test
20-
public void connectInteractivelyPromptOnWrongAuthentication() throws Exception {
41+
public void connectInteractivelyPromptOnWrongAuthentication() throws Exception
42+
{
2143
// given
22-
// what the user inputs when prompted
23-
String inputString = String.format( "neo4j%nneo%n" );
24-
InputStream inputStream = new ByteArrayInputStream(inputString.getBytes());
25-
2644
ByteArrayOutputStream baos = new ByteArrayOutputStream();
27-
PrintStream ps = new PrintStream(baos);
28-
29-
Main main = new Main(inputStream, ps);
45+
Main main = getMain( baos );
3046

3147
CliArgs cliArgs = new CliArgs();
32-
cliArgs.setUsername("", "");
48+
cliArgs.setUsername( "", "" );
3349
cliArgs.setPassword( "", "" );
3450

35-
Logger logger = new AnsiLogger(cliArgs.getDebugMode());
36-
PrettyConfig prettyConfig = new PrettyConfig(cliArgs);
37-
ConnectionConfig connectionConfig = new ConnectionConfig(
38-
cliArgs.getScheme(),
39-
cliArgs.getHost(),
40-
cliArgs.getPort(),
41-
cliArgs.getUsername(),
42-
cliArgs.getPassword(),
43-
cliArgs.getEncryption(),
44-
cliArgs.getDatabase());
45-
46-
CypherShell shell = new CypherShell(logger, prettyConfig, true);
51+
ShellAndConnection sac = getShell( cliArgs );
52+
CypherShell shell = sac.shell;
53+
ConnectionConfig connectionConfig = sac.connectionConfig;
4754

4855
// when
49-
assertEquals("", connectionConfig.username());
50-
assertEquals("", connectionConfig.password());
56+
assertEquals( "", connectionConfig.username() );
57+
assertEquals( "", connectionConfig.password() );
5158

52-
main.connectMaybeInteractively(shell, connectionConfig, true);
59+
main.connectMaybeInteractively( shell, connectionConfig, true );
5360

5461
// then
5562
// should be connected
56-
assertTrue(shell.isConnected());
63+
assertTrue( shell.isConnected() );
5764
// should have prompted and set the username and password
58-
assertEquals("neo4j", connectionConfig.username());
59-
assertEquals("neo", connectionConfig.password());
65+
assertEquals( "neo4j", connectionConfig.username() );
66+
assertEquals( "neo", connectionConfig.password() );
6067

6168
String out = baos.toString();
6269
assertEquals( String.format( "username: neo4j%npassword: ***%n" ), out );
6370
}
71+
72+
@Test
73+
public void wrongPortWithBolt() throws Exception
74+
{
75+
// given
76+
Main main = getMain( new ByteArrayOutputStream() );
77+
78+
CliArgs cliArgs = new CliArgs();
79+
cliArgs.setScheme( "bolt://", "" );
80+
cliArgs.setPort( 1234 );
81+
82+
ShellAndConnection sac = getShell( cliArgs );
83+
CypherShell shell = sac.shell;
84+
ConnectionConfig connectionConfig = sac.connectionConfig;
85+
86+
exception.expect( ServiceUnavailableException.class );
87+
exception.expectMessage( "Unable to connect to localhost:1234, ensure the database is running and that there is a working network connection to it" );
88+
main.connectMaybeInteractively( shell, connectionConfig, true );
89+
}
90+
91+
@Ignore
92+
public void wrongPortWithNeo4j() throws Exception
93+
{
94+
// given
95+
Main main = getMain( new ByteArrayOutputStream() );
96+
97+
CliArgs cliArgs = new CliArgs();
98+
cliArgs.setScheme( "neo4j://", "" );
99+
cliArgs.setPort( 1234 );
100+
101+
ShellAndConnection sac = getShell( cliArgs );
102+
CypherShell shell = sac.shell;
103+
ConnectionConfig connectionConfig = sac.connectionConfig;
104+
105+
exception.expect( ServiceUnavailableException.class );
106+
exception.expectMessage( "Unable to connect to localhost:1234, ensure the database is running and that there is a working network connection to it" );
107+
main.connectMaybeInteractively( shell, connectionConfig, true );
108+
}
109+
110+
private Main getMain( ByteArrayOutputStream baos )
111+
{
112+
// what the user inputs when prompted
113+
String inputString = String.format( "neo4j%nneo%n" );
114+
InputStream inputStream = new ByteArrayInputStream( inputString.getBytes() );
115+
116+
PrintStream ps = new PrintStream( baos );
117+
118+
return new Main( inputStream, ps );
119+
}
120+
121+
private ShellAndConnection getShell( CliArgs cliArgs )
122+
{
123+
Logger logger = new AnsiLogger( cliArgs.getDebugMode() );
124+
PrettyConfig prettyConfig = new PrettyConfig( cliArgs );
125+
ConnectionConfig connectionConfig = new ConnectionConfig(
126+
cliArgs.getScheme(),
127+
cliArgs.getHost(),
128+
cliArgs.getPort(),
129+
cliArgs.getUsername(),
130+
cliArgs.getPassword(),
131+
cliArgs.getEncryption(),
132+
cliArgs.getDatabase() );
133+
134+
return new ShellAndConnection( new CypherShell( logger, prettyConfig, true ), connectionConfig );
135+
}
64136
}

cypher-shell/src/main/java/org/neo4j/shell/cli/CliArgs.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class CliArgs {
3232
/**
3333
* Set the scheme to the primary value, or if null, the fallback value.
3434
*/
35-
void setScheme(@Nullable String primary, @Nonnull String fallback) {
35+
public void setScheme(@Nullable String primary, @Nonnull String fallback) {
3636
scheme = primary == null ? fallback : primary;
3737
}
3838

@@ -46,7 +46,7 @@ void setHost(@Nullable String primary, @Nonnull String fallback) {
4646
/**
4747
* Set the port to the value.
4848
*/
49-
void setPort(int port) {
49+
public void setPort(int port) {
5050
this.port = port;
5151
}
5252

cypher-shell/src/main/java/org/neo4j/shell/log/AnsiLogger.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,23 +122,20 @@ String getFormattedMessage(@Nonnull final Throwable e) {
122122
e.printStackTrace(ps);
123123
msg.append(new String(baos.toByteArray(), StandardCharsets.UTF_8));
124124
} else {
125-
//noinspection ThrowableResultOfMethodCallIgnored
126-
final Throwable cause = getRootCause(e);
127-
128-
if (cause instanceof AnsiFormattedException) {
129-
msg = msg.append(((AnsiFormattedException) cause).getFormattedMessage());
130-
} else if (cause instanceof ClientException &&
131-
cause.getMessage() != null && cause.getMessage().contains("Missing username")) {
125+
if (e instanceof AnsiFormattedException) {
126+
msg = msg.append(((AnsiFormattedException) e).getFormattedMessage());
127+
} else if (e instanceof ClientException &&
128+
e.getMessage() != null && e.getMessage().contains("Missing username")) {
132129
// Username and password was not specified
133-
msg = msg.append(cause.getMessage())
130+
msg = msg.append(e.getMessage())
134131
.append("\nPlease specify --username, and optionally --password, as argument(s)")
135132
.append("\nor as environment variable(s), NEO4J_USERNAME, and NEO4J_PASSWORD respectively.")
136133
.append("\nSee --help for more info.");
137134
} else {
138-
if (cause.getMessage() != null) {
139-
msg = msg.append(cause.getMessage());
135+
if (e.getMessage() != null) {
136+
msg = msg.append(e.getMessage());
140137
} else {
141-
msg = msg.append(cause.getClass().getSimpleName());
138+
msg = msg.append(e.getClass().getSimpleName());
142139
}
143140
}
144141
}

0 commit comments

Comments
 (0)