Skip to content

Commit

Permalink
Improve and clarify reporting of errors from neo4j-admin
Browse files Browse the repository at this point in the history
  • Loading branch information
benbc committed Sep 7, 2016
1 parent b8cd457 commit 0cf587f
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 99 deletions.
Expand Up @@ -129,18 +129,9 @@ private void failure( String message, Exception e )
{ {
if ( debug ) if ( debug )
{ {
failure( e, format( "%s: %s", message, e.getMessage() ) ); outsideWorld.printStacktrace( e );
} }
else failure( format( "%s: %s", message, e.getMessage() ) );
{
failure( e.getMessage() );
}
}

private void failure( Exception e, String message )
{
outsideWorld.printStacktrace( e );
failure( message );
} }


private void failure( String message ) private void failure( String message )
Expand Down
Expand Up @@ -25,4 +25,9 @@ public CommandFailed( String message, Exception cause )
{ {
super( message, cause ); super( message, cause );
} }

public CommandFailed( String message )
{
super( message );
}
} }
Expand Up @@ -26,22 +26,19 @@


import org.neo4j.helpers.collection.Iterables; import org.neo4j.helpers.collection.Iterables;


import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;


public class AdminToolTest public class AdminToolTest
{ {
@Test @Test
public void shouldExecuteTheCommand() public void shouldExecuteTheCommand() throws CommandFailed, IncorrectUsage
{ {
RecordingCommand command = new RecordingCommand(); AdminCommand command = mock( AdminCommand.class );
AdminCommand.Provider provider = command.provider(); new AdminTool( cannedCommand( "command", command ), new NullOutsideWorld(), false )
AdminTool tool = new AdminTool( new CannedLocator( provider ), new NullOutsideWorld(), false ); .execute( null, null, "command", "the", "other", "args" );
tool.execute( null, null, provider.name() ); verify( command ).execute( new String[]{"the", "other", "args"} );
assertThat( command.executed, is( true ) );
} }


@Test @Test
Expand All @@ -62,98 +59,136 @@ public void shouldAddTheHelpCommandToThoseProvidedByTheLocator()
} }


@Test @Test
public void shouldPrintUsageWhenNoCommandIsProvided() public void shouldProvideFeedbackWhenNoCommandIsProvided()
{ {
OutsideWorld outsideWorld = mock( OutsideWorld.class ); OutsideWorld outsideWorld = mock( OutsideWorld.class );
new AdminTool( new NullCommandLocator(), outsideWorld, false ).execute( null, null ); new AdminTool( new NullCommandLocator(), outsideWorld, false ).execute( null, null );
verify( outsideWorld ).stdErrLine( "you must provide a command" );
verify( outsideWorld ).stdErrLine( "Usage:" ); verify( outsideWorld ).stdErrLine( "Usage:" );
verify( outsideWorld ).exit( 1 );
} }


@Test @Test
public void shouldPrintASpecificMessageWhenNoCommandIsProvided() public void shouldProvideFeedbackIfTheCommandThrowsARuntimeException()
{ {
OutsideWorld outsideWorld = mock( OutsideWorld.class ); OutsideWorld outsideWorld = mock( OutsideWorld.class );
new AdminTool( new NullCommandLocator(), outsideWorld, false ).execute( null, null ); AdminCommand command = args ->
verify( outsideWorld ).stdErrLine( "you must provide a command" ); {
throw new RuntimeException( "the-exception-message" );
};
new AdminTool( cannedCommand( "exception", command ), outsideWorld, false )
.execute( null, null, "exception" );
verify( outsideWorld ).stdErrLine( "unexpected error: the-exception-message" );
verify( outsideWorld ).exit( 1 );
} }


@Test @Test
public void shouldExit1WhenNoCommandIsProvided() public void shouldPrintTheStacktraceWhenTheCommandThrowsARuntimeExceptionIfTheDebugFlagIsSet()
{ {
OutsideWorld outsideWorld = mock( OutsideWorld.class ); OutsideWorld outsideWorld = mock( OutsideWorld.class );
new AdminTool( new NullCommandLocator(), outsideWorld, false ).execute( null, null ); RuntimeException exception = new RuntimeException( "" );
verify( outsideWorld ).exit( 1 ); AdminCommand command = args ->
{
throw exception;
};
new AdminTool( cannedCommand( "exception", command ), outsideWorld, true )
.execute( null, null, "exception" );
verify( outsideWorld ).printStacktrace( exception );
} }


@Test @Test
public void shouldNotThrowAnExceptionEvenIfTheCommandDoesSo() public void shouldNotPrintTheStacktraceWhenTheCommandThrowsARuntimeExceptionIfTheDebugFlagIsNotSet()
{ {
new AdminTool( new CannedLocator( new ExceptionThrowingCommandProvider() ), new NullOutsideWorld(), false ) OutsideWorld outsideWorld = mock( OutsideWorld.class );
RuntimeException exception = new RuntimeException( "" );
AdminCommand command = args ->
{
throw exception;
};
new AdminTool( cannedCommand( "exception", command ), outsideWorld, false )
.execute( null, null, "exception" ); .execute( null, null, "exception" );
verify( outsideWorld, never() ).printStacktrace( exception );
} }


@Test @Test
public void shouldExit1IfTheCommandThrowsAnException() public void shouldProvideFeedbackIfTheCommandFails()
{ {
OutsideWorld outsideWorld = mock( OutsideWorld.class ); OutsideWorld outsideWorld = mock( OutsideWorld.class );
new AdminTool( new CannedLocator( new ExceptionThrowingCommandProvider() ), outsideWorld, false ) AdminCommand command = args ->
{
throw new CommandFailed( "the-failure-message" );
};
new AdminTool( cannedCommand( "exception", command ), outsideWorld, false )
.execute( null, null, "exception" ); .execute( null, null, "exception" );
verify( outsideWorld ).stdErrLine( "command failed: the-failure-message" );
verify( outsideWorld ).exit( 1 ); verify( outsideWorld ).exit( 1 );
} }


@Test @Test
public void shouldPrintTheStacktraceWhenTheCommandThrowsAnExceptionIfTheDebugFlagIsSet() public void shouldPrintTheStacktraceWhenTheCommandFailsIfTheDebugFlagIsSet()
{ {
OutsideWorld outsideWorld = mock( OutsideWorld.class ); OutsideWorld outsideWorld = mock( OutsideWorld.class );
RuntimeException exception = new RuntimeException(); CommandFailed exception = new CommandFailed( "" );
new AdminTool( new CannedLocator( new ExceptionThrowingCommandProvider( exception ) ), outsideWorld, true ) AdminCommand command = args ->
{
throw exception;
};
new AdminTool( cannedCommand( "exception", command ), outsideWorld, true )
.execute( null, null, "exception" ); .execute( null, null, "exception" );
verify( outsideWorld ).printStacktrace( exception ); verify( outsideWorld ).printStacktrace( exception );
} }


@Test @Test
public void shouldNotPrintTheStacktraceWhenTheCommandThrowsAnExceptionIfTheDebugFlagIsNotSet() public void shouldNotPrintTheStacktraceWhenTheCommandFailsIfTheDebugFlagIsNotSet()
{ {
OutsideWorld outsideWorld = mock( OutsideWorld.class ); OutsideWorld outsideWorld = mock( OutsideWorld.class );
RuntimeException exception = new RuntimeException(); CommandFailed exception = new CommandFailed( "" );
new AdminTool( new CannedLocator( new ExceptionThrowingCommandProvider( exception ) ), outsideWorld, false ) AdminCommand command = args ->
{
throw exception;
};
new AdminTool( cannedCommand( "exception", command ), outsideWorld, false )
.execute( null, null, "exception" ); .execute( null, null, "exception" );
verify( outsideWorld, never() ).printStacktrace( exception ); verify( outsideWorld, never() ).printStacktrace( exception );
} }


private static class RecordingCommand implements AdminCommand @Test
public void shouldProvideFeedbackIfTheCommandReportsAUsageProblem()
{ {
public boolean executed; OutsideWorld outsideWorld = mock( OutsideWorld.class );

AdminCommand command = args ->
@Override
public void execute( String[] args )
{ {
executed = true; throw new IncorrectUsage( "the-usage-message" );
} };
new AdminTool( cannedCommand( "exception", command ), outsideWorld, false )
.execute( null, null, "exception" );
verify( outsideWorld ).stdErrLine( "neo4j-admin exception" );
verify( outsideWorld ).stdErrLine( "the-usage-message" );
verify( outsideWorld ).exit( 1 );
}


public Provider provider() private CannedLocator cannedCommand( final String name, AdminCommand command )
{
return new CannedLocator( new AdminCommand.Provider( name )
{ {
return new Provider( "recording" ) @Override
public Optional<String> arguments()
{ {
@Override return Optional.empty();
public Optional<String> arguments() }
{
throw new UnsupportedOperationException( "not implemented" );
}


@Override @Override
public String description() public String description()
{ {
throw new UnsupportedOperationException( "not implemented" ); return "";
} }


@Override @Override
public AdminCommand create( Path homeDir, Path configDir, OutsideWorld outsideWorld ) public AdminCommand create( Path homeDir, Path configDir, OutsideWorld outsideWorld )
{ {
return RecordingCommand.this; return command;
} }
}; } );
}
} }


private static class NullOutsideWorld implements OutsideWorld private static class NullOutsideWorld implements OutsideWorld
Expand Down Expand Up @@ -221,41 +256,4 @@ public AdminCommand create( Path homeDir, Path configDir, OutsideWorld outsideWo
}; };
} }
} }

private class ExceptionThrowingCommandProvider extends AdminCommand.Provider
{
private RuntimeException exception;

protected ExceptionThrowingCommandProvider()
{
this( new RuntimeException() );
}

public ExceptionThrowingCommandProvider( RuntimeException exception )
{
super( "exception" );
this.exception = exception;
}

@Override
public Optional<String> arguments()
{
return Optional.empty();
}

@Override
public String description()
{
return "";
}

@Override
public AdminCommand create( Path homeDir, Path configDir, OutsideWorld outsideWorld )
{
return args ->
{
throw exception;
};
}
}
} }

0 comments on commit 0cf587f

Please sign in to comment.