|
6 | 6 | import org.junit.rules.ExpectedException; |
7 | 7 | import org.junit.rules.TemporaryFolder; |
8 | 8 | import org.neo4j.driver.exceptions.ClientException; |
| 9 | +import org.neo4j.driver.exceptions.DiscoveryException; |
| 10 | +import org.neo4j.driver.exceptions.ServiceUnavailableException; |
| 11 | +import org.neo4j.driver.exceptions.TransientException; |
9 | 12 | import org.neo4j.shell.ConnectionConfig; |
10 | 13 | import org.neo4j.shell.CypherShell; |
11 | 14 | import org.neo4j.shell.DatabaseManager; |
12 | 15 | import org.neo4j.shell.Historian; |
| 16 | +import org.neo4j.shell.OfflineTestShell; |
13 | 17 | import org.neo4j.shell.ShellParameterMap; |
14 | 18 | import org.neo4j.shell.StatementExecuter; |
15 | 19 | import org.neo4j.shell.TransactionHandler; |
16 | 20 | import org.neo4j.shell.UserMessagesHandler; |
| 21 | +import org.neo4j.shell.commands.CommandHelper; |
17 | 22 | import org.neo4j.shell.exception.CommandException; |
18 | 23 | import org.neo4j.shell.exception.ExitException; |
19 | 24 | import org.neo4j.shell.exception.NoMoreInputException; |
20 | 25 | import org.neo4j.shell.log.AnsiFormattedText; |
| 26 | +import org.neo4j.shell.log.AnsiLogger; |
21 | 27 | import org.neo4j.shell.log.Logger; |
22 | 28 | import org.neo4j.shell.parser.ShellStatementParser; |
23 | 29 | import org.neo4j.shell.parser.StatementParser; |
24 | 30 | import org.neo4j.shell.prettyprint.OutputFormatter; |
25 | 31 | import org.neo4j.shell.prettyprint.PrettyPrinter; |
26 | 32 | import org.neo4j.shell.state.BoltStateHandler; |
| 33 | + |
27 | 34 | import sun.misc.Signal; |
28 | 35 |
|
29 | 36 | import javax.annotation.Nonnull; |
30 | 37 | import java.io.ByteArrayInputStream; |
| 38 | +import java.io.ByteArrayOutputStream; |
31 | 39 | import java.io.File; |
32 | 40 | import java.io.IOException; |
33 | 41 | import java.io.InputStream; |
|
37 | 45 | import java.util.concurrent.atomic.AtomicReference; |
38 | 46 |
|
39 | 47 | import static java.lang.String.format; |
| 48 | +import static org.hamcrest.CoreMatchers.containsString; |
40 | 49 | import static org.hamcrest.CoreMatchers.is; |
41 | 50 | import static org.hamcrest.MatcherAssert.assertThat; |
42 | 51 | import static org.junit.Assert.assertEquals; |
|
49 | 58 | import static org.mockito.Mockito.verify; |
50 | 59 | import static org.mockito.Mockito.verifyNoMoreInteractions; |
51 | 60 | import static org.mockito.Mockito.when; |
| 61 | +import static org.neo4j.shell.cli.InteractiveShellRunner.DATABASE_UNAVAILABLE_ERROR_PROMPT_TEXT; |
52 | 62 |
|
53 | 63 | public class InteractiveShellRunnerTest { |
54 | 64 | @Rule |
@@ -293,6 +303,78 @@ public void testPrompt() throws Exception { |
293 | 303 | assertEquals(OutputFormatter.repeat(' ', wantedPrompt.length()), prompt.plainString()); |
294 | 304 | } |
295 | 305 |
|
| 306 | + @Test |
| 307 | + public void testPromptShowDatabaseAsSetByUserWhenServerReportNull() throws Exception { |
| 308 | + // given |
| 309 | + InputStream inputStream = new ByteArrayInputStream("".getBytes()); |
| 310 | + InteractiveShellRunner runner = new InteractiveShellRunner(cmdExecuter, txHandler, databaseManager, logger, statementParser, inputStream, |
| 311 | + historyFile, userMessagesHandler, connectionConfig); |
| 312 | + |
| 313 | + // when |
| 314 | + when(txHandler.isTransactionOpen()).thenReturn(false); |
| 315 | + when(databaseManager.getActiveDatabaseAsSetByUser()).thenReturn("foo"); |
| 316 | + when(databaseManager.getActualDatabaseAsReportedByServer()).thenReturn(null); |
| 317 | + AnsiFormattedText prompt = runner.updateAndGetPrompt(); |
| 318 | + |
| 319 | + // then |
| 320 | + String wantedPrompt = "myusername@foo> "; |
| 321 | + assertEquals(wantedPrompt, prompt.plainString()); |
| 322 | + } |
| 323 | + |
| 324 | + @Test |
| 325 | + public void testPromptShowDatabaseAsSetByUserWhenServerReportAbsent() throws Exception { |
| 326 | + // given |
| 327 | + InputStream inputStream = new ByteArrayInputStream("".getBytes()); |
| 328 | + InteractiveShellRunner runner = new InteractiveShellRunner(cmdExecuter, txHandler, databaseManager, logger, statementParser, inputStream, |
| 329 | + historyFile, userMessagesHandler, connectionConfig); |
| 330 | + |
| 331 | + // when |
| 332 | + when(txHandler.isTransactionOpen()).thenReturn(false); |
| 333 | + when(databaseManager.getActiveDatabaseAsSetByUser()).thenReturn("foo"); |
| 334 | + when(databaseManager.getActualDatabaseAsReportedByServer()).thenReturn(DatabaseManager.ABSENT_DB_NAME); |
| 335 | + AnsiFormattedText prompt = runner.updateAndGetPrompt(); |
| 336 | + |
| 337 | + // then |
| 338 | + String wantedPrompt = "myusername@foo> "; |
| 339 | + assertEquals(wantedPrompt, prompt.plainString()); |
| 340 | + } |
| 341 | + |
| 342 | + @Test |
| 343 | + public void testPromptShowUnresolvedDefaultDatabaseWhenServerReportNull() throws Exception { |
| 344 | + // given |
| 345 | + InputStream inputStream = new ByteArrayInputStream("".getBytes()); |
| 346 | + InteractiveShellRunner runner = new InteractiveShellRunner(cmdExecuter, txHandler, databaseManager, logger, statementParser, inputStream, |
| 347 | + historyFile, userMessagesHandler, connectionConfig); |
| 348 | + |
| 349 | + // when |
| 350 | + when(txHandler.isTransactionOpen()).thenReturn(false); |
| 351 | + when(databaseManager.getActiveDatabaseAsSetByUser()).thenReturn(DatabaseManager.ABSENT_DB_NAME); |
| 352 | + when(databaseManager.getActualDatabaseAsReportedByServer()).thenReturn(null); |
| 353 | + AnsiFormattedText prompt = runner.updateAndGetPrompt(); |
| 354 | + |
| 355 | + // then |
| 356 | + String wantedPrompt = format("myusername@%s> ", InteractiveShellRunner.UNRESOLVED_DEFAULT_DB_PROPMPT_TEXT); |
| 357 | + assertEquals(wantedPrompt, prompt.plainString()); |
| 358 | + } |
| 359 | + |
| 360 | + @Test |
| 361 | + public void testPromptShowUnresolvedDefaultDatabaseWhenServerReportAbsent() throws Exception { |
| 362 | + // given |
| 363 | + InputStream inputStream = new ByteArrayInputStream("".getBytes()); |
| 364 | + InteractiveShellRunner runner = new InteractiveShellRunner(cmdExecuter, txHandler, databaseManager, logger, statementParser, inputStream, |
| 365 | + historyFile, userMessagesHandler, connectionConfig); |
| 366 | + |
| 367 | + // when |
| 368 | + when(txHandler.isTransactionOpen()).thenReturn(false); |
| 369 | + when(databaseManager.getActiveDatabaseAsSetByUser()).thenReturn(DatabaseManager.ABSENT_DB_NAME); |
| 370 | + when(databaseManager.getActualDatabaseAsReportedByServer()).thenReturn(DatabaseManager.ABSENT_DB_NAME); |
| 371 | + AnsiFormattedText prompt = runner.updateAndGetPrompt(); |
| 372 | + |
| 373 | + // then |
| 374 | + String wantedPrompt = format("myusername@%s> ", InteractiveShellRunner.UNRESOLVED_DEFAULT_DB_PROPMPT_TEXT); |
| 375 | + assertEquals(wantedPrompt, prompt.plainString()); |
| 376 | + } |
| 377 | + |
296 | 378 | @Test |
297 | 379 | public void testLongPrompt() throws Exception { |
298 | 380 | // given |
@@ -499,4 +581,111 @@ public String getActualDatabaseAsReportedByServer() { |
499 | 581 | return DEFAULT_DEFAULT_DB_NAME; |
500 | 582 | } |
501 | 583 | } |
| 584 | + |
| 585 | + private static class TestInteractiveShellRunner { |
| 586 | + InteractiveShellRunner runner; |
| 587 | + ByteArrayOutputStream output; |
| 588 | + ByteArrayOutputStream error; |
| 589 | + BoltStateHandler mockedBoltStateHandler; |
| 590 | + |
| 591 | + TestInteractiveShellRunner(InteractiveShellRunner runner, ByteArrayOutputStream output, |
| 592 | + ByteArrayOutputStream error, BoltStateHandler mockedBoltStateHandler) { |
| 593 | + this.runner = runner; |
| 594 | + this.output = output; |
| 595 | + this.error = error; |
| 596 | + this.mockedBoltStateHandler = mockedBoltStateHandler; |
| 597 | + } |
| 598 | + } |
| 599 | + |
| 600 | + private TestInteractiveShellRunner setupInteractiveTestShellRunner(String input) throws Exception { |
| 601 | + // NOTE: Tests using this will test a bit more of the stack using OfflineTestShell |
| 602 | + ByteArrayOutputStream output = new ByteArrayOutputStream(); |
| 603 | + ByteArrayOutputStream error = new ByteArrayOutputStream(); |
| 604 | + |
| 605 | + BoltStateHandler mockedBoltStateHandler = mock(BoltStateHandler.class); |
| 606 | + when(mockedBoltStateHandler.getServerVersion()).thenReturn(""); |
| 607 | + |
| 608 | + final PrettyPrinter mockedPrettyPrinter = mock(PrettyPrinter.class); |
| 609 | + |
| 610 | + Logger logger = new AnsiLogger(false, Format.VERBOSE, new PrintStream(output), new PrintStream(error)); |
| 611 | + |
| 612 | + OfflineTestShell offlineTestShell = new OfflineTestShell(logger, mockedBoltStateHandler, mockedPrettyPrinter); |
| 613 | + CommandHelper commandHelper = new CommandHelper(logger, Historian.empty, offlineTestShell); |
| 614 | + offlineTestShell.setCommandHelper(commandHelper); |
| 615 | + |
| 616 | + InputStream inputStream = new ByteArrayInputStream(input.getBytes()); |
| 617 | + InteractiveShellRunner runner = new InteractiveShellRunner(offlineTestShell, offlineTestShell, offlineTestShell, logger, |
| 618 | + new ShellStatementParser(), inputStream, historyFile, userMessagesHandler, connectionConfig); |
| 619 | + |
| 620 | + return new TestInteractiveShellRunner(runner, output, error, mockedBoltStateHandler); |
| 621 | + } |
| 622 | + |
| 623 | + @Test |
| 624 | + public void testSwitchToUnavailableDatabase1() throws Exception { |
| 625 | + // given |
| 626 | + String input = ":use foo;\n"; |
| 627 | + TestInteractiveShellRunner sr = setupInteractiveTestShellRunner(input); |
| 628 | + |
| 629 | + // when |
| 630 | + when(sr.mockedBoltStateHandler.getActualDatabaseAsReportedByServer()).thenReturn("foo"); |
| 631 | + doThrow(new TransientException(DatabaseManager.DATABASE_UNAVAILABLE_ERROR_CODE, "Not available")) |
| 632 | + .when(sr.mockedBoltStateHandler).setActiveDatabase("foo"); |
| 633 | + |
| 634 | + sr.runner.runUntilEnd(); |
| 635 | + |
| 636 | + // then |
| 637 | + assertThat(sr.output.toString(), containsString(format("myusername@foo%s> ", DATABASE_UNAVAILABLE_ERROR_PROMPT_TEXT))); |
| 638 | + assertThat(sr.error.toString(), containsString("Not available")); |
| 639 | + } |
| 640 | + |
| 641 | + @Test |
| 642 | + public void testSwitchToUnavailableDatabase2() throws Exception { |
| 643 | + // given |
| 644 | + String input = ":use foo;\n"; |
| 645 | + TestInteractiveShellRunner sr = setupInteractiveTestShellRunner(input); |
| 646 | + |
| 647 | + // when |
| 648 | + when(sr.mockedBoltStateHandler.getActualDatabaseAsReportedByServer()).thenReturn("foo"); |
| 649 | + doThrow(new ServiceUnavailableException("Not available")).when(sr.mockedBoltStateHandler).setActiveDatabase("foo"); |
| 650 | + |
| 651 | + sr.runner.runUntilEnd(); |
| 652 | + |
| 653 | + // then |
| 654 | + assertThat(sr.output.toString(), containsString(format("myusername@foo%s> ", DATABASE_UNAVAILABLE_ERROR_PROMPT_TEXT))); |
| 655 | + assertThat(sr.error.toString(), containsString("Not available")); |
| 656 | + } |
| 657 | + |
| 658 | + @Test |
| 659 | + public void testSwitchToUnavailableDatabase3() throws Exception { |
| 660 | + // given |
| 661 | + String input = ":use foo;\n"; |
| 662 | + TestInteractiveShellRunner sr = setupInteractiveTestShellRunner(input); |
| 663 | + |
| 664 | + // when |
| 665 | + when(sr.mockedBoltStateHandler.getActualDatabaseAsReportedByServer()).thenReturn("foo"); |
| 666 | + doThrow(new DiscoveryException("Not available", null)).when(sr.mockedBoltStateHandler).setActiveDatabase("foo"); |
| 667 | + |
| 668 | + sr.runner.runUntilEnd(); |
| 669 | + |
| 670 | + // then |
| 671 | + assertThat(sr.output.toString(), containsString(format("myusername@foo%s> ", DATABASE_UNAVAILABLE_ERROR_PROMPT_TEXT))); |
| 672 | + assertThat(sr.error.toString(), containsString("Not available")); |
| 673 | + } |
| 674 | + |
| 675 | + @Test |
| 676 | + public void testSwitchToNonExistingDatabase() throws Exception { |
| 677 | + // given |
| 678 | + String input = ":use foo;\n"; |
| 679 | + TestInteractiveShellRunner sr = setupInteractiveTestShellRunner(input); |
| 680 | + |
| 681 | + // when |
| 682 | + when(sr.mockedBoltStateHandler.getActualDatabaseAsReportedByServer()).thenReturn("mydb"); |
| 683 | + doThrow(new ClientException("Non existing")).when(sr.mockedBoltStateHandler).setActiveDatabase("foo"); |
| 684 | + |
| 685 | + sr.runner.runUntilEnd(); |
| 686 | + |
| 687 | + // then |
| 688 | + assertThat(sr.output.toString(), containsString("myusername@mydb> ")); |
| 689 | + assertThat(sr.error.toString(), containsString("Non existing")); |
| 690 | + } |
502 | 691 | } |
0 commit comments