]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7488 add listener to ComputationStepExecutor
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 1 Apr 2016 12:18:30 +0000 (14:18 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Wed, 6 Apr 2016 13:42:53 +0000 (15:42 +0200)
server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationStepExecutor.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepExecutorTest.java

index ee8ed09c2467f1444f3c3a459c90821583ebbcdd..7b67aaebdf26aa62b8ba6f245a8d56d4e7c9b365 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.server.computation.step;
 
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.core.util.logs.Profiler;
@@ -27,17 +29,44 @@ public final class ComputationStepExecutor {
   private static final Logger LOGGER = Loggers.get(ComputationStepExecutor.class);
 
   private final ComputationSteps steps;
+  @CheckForNull
+  private final Listener listener;
 
+  /**
+   * Used when no {@link org.sonar.server.computation.step.ComputationStepExecutor.Listener} is available in pico
+   * container.
+   */
   public ComputationStepExecutor(ComputationSteps steps) {
+    this(steps, null);
+  }
+
+  public ComputationStepExecutor(ComputationSteps steps, @Nullable Listener listener) {
     this.steps = steps;
+    this.listener = listener;
   }
 
   public void execute() {
     Profiler stepProfiler = Profiler.create(LOGGER);
+    boolean allStepsExecuted = false;
+    try {
+      executeSteps(stepProfiler);
+      allStepsExecuted = true;
+    } finally {
+      if (listener != null) {
+        listener.finished(allStepsExecuted);
+      }
+    }
+  }
+
+  private void executeSteps(Profiler stepProfiler) {
     for (ComputationStep step : steps.instances()) {
       stepProfiler.start();
       step.execute();
       stepProfiler.stopInfo(step.getDescription());
     }
   }
+
+  public interface Listener {
+    void finished(boolean allStepsExecuted);
+  }
 }
index d3aaf0cbc2da69401178758e770fb9de7b683d50..153d8f2974030a9029fc026a5d54f75e2565f93b 100644 (file)
@@ -29,9 +29,12 @@ import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
 public class ComputationStepExecutorTest {
@@ -40,12 +43,13 @@ public class ComputationStepExecutorTest {
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
 
+  private final ComputationStepExecutor.Listener listener = mock(ComputationStepExecutor.Listener.class);
+  private final ComputationStep computationStep1 = mockComputationStep("step1");
+  private final ComputationStep computationStep2 = mockComputationStep("step2");
+  private final ComputationStep computationStep3 = mockComputationStep("step3");
+
   @Test
   public void execute_call_execute_on_each_ComputationStep_in_order_returned_by_instances_method() {
-    ComputationStep computationStep1 = mockComputationStep("step1");
-    ComputationStep computationStep2 = mockComputationStep("step2");
-    ComputationStep computationStep3 = mockComputationStep("step3");
-
     new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2, computationStep3))
       .execute();
 
@@ -78,9 +82,6 @@ public class ComputationStepExecutorTest {
 
   @Test
   public void execute_logs_end_timing_for_each_ComputationStep_called() {
-    ComputationStep computationStep1 = mockComputationStep("step1");
-    ComputationStep computationStep2 = mockComputationStep("step2");
-
     new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2))
         .execute();
 
@@ -90,6 +91,34 @@ public class ComputationStepExecutorTest {
     assertThat(infoLogs.get(1)).contains("step2 | time=");
   }
 
+  @Test
+  public void execute_calls_listener_finished_method_with_all_step_runs() {
+    new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2), listener)
+        .execute();
+
+    verify(listener).finished(true);
+    verifyNoMoreInteractions(listener);
+  }
+
+  @Test
+  public void execute_calls_listener_finished_method_even_if_a_step_throws_an_exception() {
+    RuntimeException toBeThrown = new RuntimeException("simulating failing execute Step method");
+    doThrow(toBeThrown)
+        .when(computationStep1)
+        .execute();
+
+    try {
+      new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2), listener)
+          .execute();
+      fail("exception toBeThrown should have been raised");
+    } catch (RuntimeException e) {
+      assertThat(e).isSameAs(toBeThrown);
+      verify(listener).finished(false);
+      verifyNoMoreInteractions(listener);
+    }
+
+  }
+
   private static ComputationSteps mockComputationSteps(ComputationStep... computationSteps) {
     ComputationSteps steps = mock(ComputationSteps.class);
     when(steps.instances()).thenReturn(Arrays.asList(computationSteps));