# HG changeset patch # User Andriy Petrus # Date 1373382236 14400 # Node ID 2932f90a008fab923ca3546661f52d14bdcc83ac # Parent c70ab9ec00f5fa2523d937af72a0b0a7cc7c38cd PR1451: Blocked console after "service" command error message Reviewed-by: omajid, vanaltj Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-July/007241.html diff -r c70ab9ec00f5 -r 2932f90a008f agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/ServiceCommand.java --- a/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/ServiceCommand.java Tue Jul 09 15:10:03 2013 +0200 +++ b/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/ServiceCommand.java Tue Jul 09 11:03:56 2013 -0400 @@ -68,6 +68,7 @@ private Semaphore agentBarrier = new Semaphore(0); private BundleContext context; private Launcher launcher; + private boolean storageFailed = false; public ServiceCommand(BundleContext context) { this.context = context; @@ -86,6 +87,12 @@ launcher.run(storageStartArgs, listeners, false); agentBarrier.acquireUninterruptibly(); + if (storageFailed) { + storageFailed = false; + context.ungetService(launcherRef); + throw new CommandException(translator.localize(LocaleResources.SERVICE_FAILED_TO_START_DB)); + } + String[] storageStopArgs = new String[] { "storage", "--stop" }; launcher.run(storageStopArgs, false); @@ -106,16 +113,16 @@ String[] agentArgs = new String[] {"agent", "-d", dbUrl}; System.err.println(translator.localize(LocaleResources.STARTING_AGENT).getContents()); launcher.run(agentArgs, false); - agentBarrier.release(); break; case FAIL: - System.err.println(translator.localize(LocaleResources.ERROR_STARTING_DB).getContents()); + storageFailed = true; Object payload = actionEvent.getPayload(); if (payload instanceof StorageAlreadyRunningException) { System.err.println(translator.localize(LocaleResources.STORAGE_ALREADY_RUNNING).getContents()); } break; } + agentBarrier.release(); } } diff -r c70ab9ec00f5 -r 2932f90a008f agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/locale/LocaleResources.java --- a/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/locale/LocaleResources.java Tue Jul 09 15:10:03 2013 +0200 +++ b/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/locale/LocaleResources.java Tue Jul 09 11:03:56 2013 -0400 @@ -46,7 +46,7 @@ STORAGE_ALREADY_RUNNING, STORAGE_ALREADY_RUNNING_WITH_PID, - ERROR_STARTING_DB, + SERVICE_FAILED_TO_START_DB, SERVER_SHUTDOWN_COMPLETE, LOG_FILE_AT, CANNOT_START_SERVER, diff -r c70ab9ec00f5 -r 2932f90a008f agent/cli/src/main/resources/com/redhat/thermostat/agent/cli/impl/strings.properties --- a/agent/cli/src/main/resources/com/redhat/thermostat/agent/cli/impl/strings.properties Tue Jul 09 15:10:03 2013 +0200 +++ b/agent/cli/src/main/resources/com/redhat/thermostat/agent/cli/impl/strings.properties Tue Jul 09 11:03:56 2013 -0400 @@ -2,7 +2,7 @@ COMMAND_STORAGE_ARGUMENT_REQUIRED = either --start or --stop must be given -ERROR_STARTING_DB = error starting db +SERVICE_FAILED_TO_START_DB = Service failed to start due to error starting storage. STORAGE_ALREADY_RUNNING = Storage is already running. Please use "agent --start" to start the agent STORAGE_ALREADY_RUNNING_WITH_PID = Storage is already running with pid {0} SERVER_SHUTDOWN_COMPLETE = server shutdown complete: {0} diff -r c70ab9ec00f5 -r 2932f90a008f agent/cli/src/test/java/com/redhat/thermostat/agent/cli/impl/ServiceCommandTest.java --- a/agent/cli/src/test/java/com/redhat/thermostat/agent/cli/impl/ServiceCommandTest.java Tue Jul 09 15:10:03 2013 +0200 +++ b/agent/cli/src/test/java/com/redhat/thermostat/agent/cli/impl/ServiceCommandTest.java Tue Jul 09 11:03:56 2013 -0400 @@ -36,26 +36,188 @@ package com.redhat.thermostat.agent.cli.impl; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.isA; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.never; + +import java.util.Collection; + +import junit.framework.Assert; + import org.junit.After; import org.junit.Before; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.osgi.framework.ServiceReference; +import com.redhat.thermostat.agent.cli.impl.db.DBStartupConfiguration; +import com.redhat.thermostat.agent.cli.impl.db.StorageCommand; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.ActionNotifier; +import com.redhat.thermostat.common.Launcher; +import com.redhat.thermostat.common.cli.CommandContext; +import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.common.tools.ApplicationState; import com.redhat.thermostat.testutils.StubBundleContext; public class ServiceCommandTest { - private ServiceCommand thermostatService; + private Launcher mockLauncher; + private ServiceCommand serviceCommand; + private CommandContext mockCommandContext; + + private static ActionEvent mockActionEvent; + private static Collection> listeners; + private static final String[] STORAGE_START_ARGS = { "storage", "--start" }; + private static final String[] STORAGE_STOP_ARGS = { "storage", "--stop" }; + private static final String[] AGENT_ARGS = {"agent", "-d", "Test String"}; + + private static int count = 0; + + @SuppressWarnings("unchecked") @Before public void setUp() { - StubBundleContext context = new StubBundleContext(); - thermostatService = new ServiceCommand(context); + StubBundleContext bundleContext = new StubBundleContext(); + mockLauncher = mock(Launcher.class); + bundleContext.registerService(Launcher.class, mockLauncher, null); + serviceCommand = new ServiceCommand(bundleContext); + + StorageCommand mockStorageCommand = mock(StorageCommand.class); + mockActionEvent = mock(ActionEvent.class); + when(mockActionEvent.getSource()).thenReturn(mockStorageCommand); + mockCommandContext = mock(CommandContext.class); + + ActionNotifier mockNotifier = mock(ActionNotifier.class); + DBStartupConfiguration mockDbsConfiguration = mock(DBStartupConfiguration.class); + when(mockStorageCommand.getNotifier()).thenReturn(mockNotifier); + when(mockStorageCommand.getConfiguration()).thenReturn(mockDbsConfiguration); + when(mockDbsConfiguration.getDBConnectionString()).thenReturn(new String("Test String")); } @After public void tearDown() { - thermostatService = null; + count = 0; + listeners = null; + mockLauncher = null; + serviceCommand = null; + mockActionEvent = null; + mockCommandContext = null; + } + + @SuppressWarnings("unchecked") + @Test(timeout=1000) + public void testRunOnce() throws CommandException { + doAnswer(new Answer() { + public Void answer(InvocationOnMock invocation) throws Throwable { + Object[] args = invocation.getArguments(); + listeners = (Collection>)args[1]; + + when(mockActionEvent.getActionId()).thenReturn(ApplicationState.START); + + for(ActionListener listener : listeners) { + listener.actionPerformed(mockActionEvent); + } + return null; + } + }).when(mockLauncher).run(eq(STORAGE_START_ARGS), isA(Collection.class), anyBoolean()); + + boolean exTriggered = false; + try { + serviceCommand.run(mockCommandContext); + } catch (CommandException e) { + exTriggered = true; + } + Assert.assertFalse(exTriggered); + + verify(mockLauncher, times(1)).run(eq(STORAGE_START_ARGS), isA(Collection.class), anyBoolean()); + verify(mockLauncher, times(1)).run(eq(STORAGE_STOP_ARGS), anyBoolean()); + verify(mockLauncher, times(1)).run(eq(AGENT_ARGS), anyBoolean()); + verify(mockActionEvent, times(1)).getActionId(); } - // TODO really need to add more tests for service + @SuppressWarnings("unchecked") + @Test(timeout=1000) + public void testMultipleRun() throws CommandException { + doAnswer(new Answer() { + public Void answer(InvocationOnMock invocation) throws Throwable { + Object[] args = invocation.getArguments(); + listeners = (Collection>)args[1]; + + if (count == 0) { + when(mockActionEvent.getActionId()).thenReturn(ApplicationState.START); + } else { + when(mockActionEvent.getActionId()).thenReturn(ApplicationState.FAIL); + } + ++count; + + for(ActionListener listener : listeners) { + listener.actionPerformed(mockActionEvent); + } + return null; + } + }).when(mockLauncher).run(eq(STORAGE_START_ARGS), isA(Collection.class), anyBoolean()); + + boolean exTriggered = false; + try { + serviceCommand.run(mockCommandContext); + } catch (CommandException e) { + exTriggered = true; + } + Assert.assertFalse(exTriggered); + + try { + serviceCommand.run(mockCommandContext); + } catch (CommandException e) { + exTriggered = true; + Assert.assertEquals(e.getLocalizedMessage(), "Service failed to start due to error starting storage."); + } + Assert.assertTrue(exTriggered); + + verify(mockLauncher, times(2)).run(eq(STORAGE_START_ARGS), isA(Collection.class), anyBoolean()); + verify(mockLauncher, times(1)).run(eq(STORAGE_STOP_ARGS), anyBoolean()); + verify(mockLauncher, times(1)).run(eq(AGENT_ARGS), anyBoolean()); + verify(mockActionEvent, times(2)).getActionId(); + } + + @SuppressWarnings("unchecked") + @Test(timeout=1000) + public void testStorageFailStart() throws CommandException { + doAnswer(new Answer() { + public Void answer(InvocationOnMock invocation) throws Throwable { + Object[] args = invocation.getArguments(); + listeners = (Collection>)args[1]; + + when(mockActionEvent.getActionId()).thenReturn(ApplicationState.FAIL); + + for(ActionListener listener : listeners) { + listener.actionPerformed(mockActionEvent); + } + return null; + } + }).when(mockLauncher).run(eq(STORAGE_START_ARGS), isA(Collection.class), anyBoolean()); + + boolean exTriggered = false; + try { + serviceCommand.run(mockCommandContext); + } catch (CommandException e) { + exTriggered = true; + } + Assert.assertTrue(exTriggered); + + verify(mockLauncher, times(1)).run(eq(STORAGE_START_ARGS), isA(Collection.class), anyBoolean()); + verify(mockLauncher, never()).run(eq(STORAGE_STOP_ARGS), anyBoolean()); + verify(mockLauncher, never()).run(eq(AGENT_ARGS), anyBoolean()); + verify(mockActionEvent, times(1)).getActionId(); + } + }