Coverage Report - org.jbehave.core.reporters.ConcurrentStoryReporter
 
Classes in this File Line Coverage Branch Coverage Complexity
ConcurrentStoryReporter
79%
141/178
60%
34/56
2.094
ConcurrentStoryReporter$DelayedMethod
53%
7/13
N/A
2.094
 
 1  
 package org.jbehave.core.reporters;
 2  
 
 3  
 import java.lang.reflect.InvocationTargetException;
 4  
 import java.lang.reflect.Method;
 5  
 import java.util.ArrayList;
 6  
 import java.util.Collections;
 7  
 import java.util.List;
 8  
 import java.util.Map;
 9  
 
 10  
 import org.jbehave.core.model.ExamplesTable;
 11  
 import org.jbehave.core.model.GivenStories;
 12  
 import org.jbehave.core.model.Lifecycle;
 13  
 import org.jbehave.core.model.Meta;
 14  
 import org.jbehave.core.model.Narrative;
 15  
 import org.jbehave.core.model.OutcomesTable;
 16  
 import org.jbehave.core.model.Scenario;
 17  
 import org.jbehave.core.model.Story;
 18  
 import org.jbehave.core.model.StoryDuration;
 19  
 
 20  
 /**
 21  
  * When running a multithreading mode, reports cannot be written concurrently but should 
 22  
  * be delayed and invoked only at the end of a story, ensuring synchronization on the delegate
 23  
  * responsible for the reporting.
 24  
  */
 25  
 public class ConcurrentStoryReporter implements StoryReporter {
 26  
 
 27  
     private static Method storyCancelled;
 28  
     private static Method storyNotAllowed;
 29  
     private static Method beforeStory;
 30  
     private static Method afterStory;
 31  
     private static Method narrative;
 32  
     private static Method lifecycle;
 33  
     private static Method scenarioNotAllowed;
 34  
     private static Method beforeScenario;
 35  
     private static Method scenarioMeta;
 36  
     private static Method afterScenario;
 37  
     private static Method givenStories;
 38  
     private static Method givenStoriesPaths;
 39  
     private static Method beforeExamples;
 40  
     private static Method example;
 41  
     private static Method afterExamples;
 42  
     private static Method beforeStep;
 43  
     private static Method successful;
 44  
     private static Method ignorable;
 45  
     private static Method pending;
 46  
     private static Method notPerformed;
 47  
     private static Method failed;
 48  
     private static Method failedOutcomes;
 49  
     private static Method dryRun;
 50  
     private static Method pendingMethods;
 51  
     private static Method restarted;
 52  
     private static Method restartedStory;
 53  
 
 54  
     static {
 55  
         try {
 56  1
             storyCancelled = StoryReporter.class.getMethod("storyCancelled", Story.class, StoryDuration.class);
 57  1
             storyNotAllowed = StoryReporter.class.getMethod("storyNotAllowed", Story.class, String.class);
 58  1
             beforeStory = StoryReporter.class.getMethod("beforeStory", Story.class, Boolean.TYPE);
 59  1
             afterStory = StoryReporter.class.getMethod("afterStory", Boolean.TYPE);
 60  1
             narrative = StoryReporter.class.getMethod("narrative", Narrative.class);
 61  1
             lifecycle = StoryReporter.class.getMethod("lifecyle", Lifecycle.class);
 62  1
             scenarioNotAllowed = StoryReporter.class.getMethod("scenarioNotAllowed", Scenario.class, String.class);
 63  1
             beforeScenario = StoryReporter.class.getMethod("beforeScenario", String.class);
 64  1
             scenarioMeta = StoryReporter.class.getMethod("scenarioMeta", Meta.class);
 65  1
             afterScenario = StoryReporter.class.getMethod("afterScenario");
 66  1
             givenStories = StoryReporter.class.getMethod("givenStories", GivenStories.class);
 67  1
             givenStoriesPaths = StoryReporter.class.getMethod("givenStories", List.class);
 68  1
             beforeExamples = StoryReporter.class.getMethod("beforeExamples", List.class, ExamplesTable.class);
 69  1
             example = StoryReporter.class.getMethod("example", Map.class);
 70  1
             afterExamples = StoryReporter.class.getMethod("afterExamples");
 71  1
             beforeStep = StoryReporter.class.getMethod("beforeStep", String.class);
 72  1
             successful = StoryReporter.class.getMethod("successful", String.class);
 73  1
             ignorable = StoryReporter.class.getMethod("ignorable", String.class);
 74  1
             pending = StoryReporter.class.getMethod("pending", String.class);
 75  1
             notPerformed = StoryReporter.class.getMethod("notPerformed", String.class);
 76  1
             failed = StoryReporter.class.getMethod("failed", String.class, Throwable.class);
 77  1
             failedOutcomes = StoryReporter.class.getMethod("failedOutcomes", String.class, OutcomesTable.class);
 78  1
             dryRun = StoryReporter.class.getMethod("dryRun");
 79  1
             pendingMethods = StoryReporter.class.getMethod("pendingMethods", List.class);
 80  1
             restarted = StoryReporter.class.getMethod("restarted", String.class, Throwable.class);
 81  1
             restartedStory = StoryReporter.class.getMethod("restartedStory", Story.class, Throwable.class);
 82  0
         } catch (NoSuchMethodException e) {
 83  0
             throw new RuntimeException(e);
 84  1
         }
 85  1
     }
 86  
 
 87  74
     private List<DelayedMethod> delayedMethods = new ArrayList<DelayedMethod>();
 88  
     private final StoryReporter crossReferencing;
 89  
     private final StoryReporter delegate;
 90  
     private final boolean multiThreading;
 91  74
     private boolean invoked = false;
 92  
 
 93  74
     public ConcurrentStoryReporter(StoryReporter crossReferencing, StoryReporter delegate, boolean multiThreading) {
 94  74
         this.crossReferencing = crossReferencing;
 95  74
         this.multiThreading = multiThreading;
 96  74
         this.delegate = delegate;
 97  74
     }
 98  
 
 99  
     public void storyNotAllowed(Story story, String filter) {
 100  0
         crossReferencing.storyNotAllowed(story, filter);
 101  0
         if (multiThreading) {
 102  0
             delayedMethods.add(new DelayedMethod(storyNotAllowed, story, filter));
 103  
         } else {
 104  0
             delegate.storyNotAllowed(story, filter);
 105  
         }
 106  0
     }
 107  
 
 108  
     public void beforeStory(Story story, boolean givenStory) {
 109  62
         crossReferencing.beforeStory(story, givenStory);
 110  62
         if (multiThreading) {
 111  6
             delayedMethods.add(new DelayedMethod(beforeStory, story, givenStory));
 112  
         } else {
 113  56
             delegate.beforeStory(story, givenStory);
 114  
         }
 115  62
     }
 116  
 
 117  
     public void afterStory(boolean givenStory) {
 118  62
         crossReferencing.afterStory(givenStory);
 119  62
         if (multiThreading) {
 120  6
             delayedMethods.add(new DelayedMethod(afterStory, givenStory));
 121  
         } else {
 122  56
             delegate.afterStory(givenStory);
 123  
         }
 124  62
     }
 125  
 
 126  
     public void narrative(Narrative aNarrative) {
 127  38
         crossReferencing.narrative(aNarrative);
 128  38
         if (multiThreading) {
 129  4
             delayedMethods.add(new DelayedMethod(narrative, aNarrative));
 130  
         } else {
 131  34
             delegate.narrative(aNarrative);
 132  
         }
 133  38
     }
 134  
     
 135  
     public void lifecyle(Lifecycle aLifecycle) {
 136  35
         crossReferencing.lifecyle(aLifecycle);
 137  35
         if (multiThreading) {
 138  4
             delayedMethods.add(new DelayedMethod(lifecycle, aLifecycle));
 139  
         } else {
 140  31
             delegate.lifecyle(aLifecycle);
 141  
         }
 142  35
     }
 143  
 
 144  
     public void scenarioNotAllowed(Scenario scenario, String filter) {
 145  0
         crossReferencing.scenarioNotAllowed(scenario, filter);
 146  0
         if (multiThreading) {
 147  0
             delayedMethods.add(new DelayedMethod(scenarioNotAllowed, scenario, filter));
 148  
         } else {
 149  0
             delegate.scenarioNotAllowed(scenario, filter);
 150  
         }
 151  0
     }
 152  
 
 153  
     public void beforeScenario(String scenarioTitle) {
 154  41
         crossReferencing.beforeScenario(scenarioTitle);
 155  41
         if (multiThreading) {
 156  4
             delayedMethods.add(new DelayedMethod(beforeScenario, scenarioTitle));
 157  
         } else {
 158  37
             delegate.beforeScenario(scenarioTitle);
 159  
         }
 160  41
     }
 161  
 
 162  
     public void scenarioMeta(Meta meta) {
 163  0
         crossReferencing.scenarioMeta(meta);
 164  0
         if (multiThreading) {
 165  0
             delayedMethods.add(new DelayedMethod(scenarioMeta, meta));
 166  
         } else {
 167  0
             delegate.scenarioMeta(meta);
 168  
         }
 169  0
     }
 170  
 
 171  
     public void afterScenario() {
 172  33
         crossReferencing.afterScenario();
 173  33
         if (multiThreading) {
 174  4
             delayedMethods.add(new DelayedMethod(afterScenario));
 175  
         } else {
 176  29
             delegate.afterScenario();
 177  
         }
 178  33
     }
 179  
 
 180  
     public void givenStories(GivenStories stories) {
 181  0
         crossReferencing.givenStories(stories);
 182  0
         if (multiThreading) {
 183  0
             delayedMethods.add(new DelayedMethod(givenStories, stories));
 184  
         } else {
 185  0
             delegate.givenStories(stories);
 186  
         }
 187  0
     }
 188  
 
 189  
     public void givenStories(List<String> storyPaths) {
 190  3
         crossReferencing.givenStories(storyPaths);
 191  3
         if (multiThreading) {
 192  0
             delayedMethods.add(new DelayedMethod(givenStoriesPaths, storyPaths));
 193  
         } else {
 194  3
             delegate.givenStories(storyPaths);
 195  
         }
 196  3
     }
 197  
 
 198  
     public void beforeExamples(List<String> steps, ExamplesTable table) {
 199  3
         crossReferencing.beforeExamples(steps, table);
 200  3
         if (multiThreading) {
 201  0
             delayedMethods.add(new DelayedMethod(beforeExamples, steps, table));
 202  
         } else {
 203  3
             delegate.beforeExamples(steps, table);
 204  
         }
 205  3
     }
 206  
 
 207  
     public void example(Map<String, String> tableRow) {
 208  6
         crossReferencing.example(tableRow);
 209  6
         if (multiThreading) {
 210  0
             delayedMethods.add(new DelayedMethod(example, tableRow));
 211  
         } else {
 212  6
             delegate.example(tableRow);
 213  
         }
 214  6
     }
 215  
 
 216  
     public void afterExamples() {
 217  3
         crossReferencing.afterExamples();
 218  3
         if (multiThreading) {
 219  0
             delayedMethods.add(new DelayedMethod(afterExamples));
 220  
         } else {
 221  3
             delegate.afterExamples();
 222  
         }
 223  3
     }
 224  
 
 225  
     public void beforeStep(String step) {
 226  36
         crossReferencing.beforeStep(step);
 227  36
         if (multiThreading) {
 228  5
             delayedMethods.add(new DelayedMethod(beforeStep, step));
 229  
         } else {
 230  31
             delegate.beforeStep(step);
 231  
         }
 232  36
     }
 233  
 
 234  
     public void successful(String step) {
 235  57
         crossReferencing.successful(step);
 236  57
         if (multiThreading) {
 237  4
             delayedMethods.add(new DelayedMethod(successful, step));
 238  
         } else {
 239  52
             delegate.successful(step);
 240  
         }
 241  57
     }
 242  
 
 243  
     public void ignorable(String step) {
 244  3
         crossReferencing.ignorable(step);
 245  3
         if (multiThreading) {
 246  0
             delayedMethods.add(new DelayedMethod(ignorable, step));
 247  
         } else {
 248  3
             delegate.ignorable(step);
 249  
         }
 250  3
     }
 251  
 
 252  
     public void pending(String step) {
 253  6
         crossReferencing.pending(step);
 254  6
         if (multiThreading) {
 255  0
             delayedMethods.add(new DelayedMethod(pending, step));
 256  
         } else {
 257  6
             delegate.pending(step);
 258  
         }
 259  6
     }
 260  
 
 261  
     public void notPerformed(String step) {
 262  5
         crossReferencing.notPerformed(step);
 263  5
         if (multiThreading) {
 264  0
             delayedMethods.add(new DelayedMethod(notPerformed, step));
 265  
         } else {
 266  5
             delegate.notPerformed(step);
 267  
         }
 268  5
     }
 269  
 
 270  
     public void failed(String step, Throwable cause) {
 271  13
         crossReferencing.failed(step, cause);
 272  13
         if (multiThreading) {
 273  0
             delayedMethods.add(new DelayedMethod(failed, step, cause));
 274  
         } else {
 275  13
             delegate.failed(step, cause);
 276  
         }
 277  13
     }
 278  
 
 279  
     public void failedOutcomes(String step, OutcomesTable table) {
 280  3
         crossReferencing.failedOutcomes(step, table);
 281  3
         if (multiThreading) {
 282  0
             delayedMethods.add(new DelayedMethod(failedOutcomes, step, table));
 283  
         } else {
 284  3
             delegate.failedOutcomes(step, table);
 285  
         }
 286  3
     }
 287  
 
 288  
     public void dryRun() {
 289  3
         crossReferencing.dryRun();
 290  3
         if (multiThreading) {
 291  0
             delayedMethods.add(new DelayedMethod(dryRun));
 292  
         } else {
 293  3
             delegate.dryRun();
 294  
         }
 295  3
     }
 296  
 
 297  
     public void pendingMethods(List<String> methods) {
 298  3
         crossReferencing.pendingMethods(methods);
 299  3
         if (multiThreading) {
 300  0
             delayedMethods.add(new DelayedMethod(pendingMethods, methods));
 301  
         } else {
 302  3
             delegate.pendingMethods(methods);
 303  
         }
 304  
         
 305  3
     }
 306  
     
 307  
     public void restarted(String step, Throwable cause) {
 308  3
         crossReferencing.restarted(step, cause);
 309  3
         if (multiThreading) {
 310  0
             delayedMethods.add(new DelayedMethod(restarted, step, cause));
 311  
         } else {
 312  3
             delegate.restarted(step, cause);
 313  
         }
 314  3
     }
 315  
     
 316  
     public void restartedStory(Story story, Throwable cause){
 317  3
         crossReferencing.restartedStory(story, cause);
 318  3
         if (multiThreading) {
 319  0
             delayedMethods.add(new DelayedMethod(restartedStory, story, cause));
 320  
         } else {
 321  3
             delegate.restartedStory(story, cause);
 322  
         }
 323  3
     }
 324  
 
 325  
     public void storyCancelled(Story story, StoryDuration storyDuration) {
 326  11
         crossReferencing.storyCancelled(story, storyDuration);
 327  11
         if (multiThreading) {
 328  0
             delayedMethods.add(new DelayedMethod(storyCancelled, story, storyDuration));
 329  
         } else {
 330  11
             delegate.storyCancelled(story, storyDuration);
 331  
         }
 332  11
     }
 333  
 
 334  
     public StoryReporter getDelegate() {
 335  6
         return delegate;
 336  
     }
 337  
 
 338  
     public boolean invoked(){
 339  0
             return invoked;
 340  
     }
 341  
     
 342  
     public void invokeDelayed() {
 343  62
         if ( !multiThreading ){
 344  56
             return;
 345  
         }
 346  6
         synchronized (delegate) {
 347  6
             for (DelayedMethod delayed : Collections.unmodifiableList(delayedMethods)) {
 348  33
                 delayed.invoke(delegate);
 349  33
             }
 350  6
         }
 351  6
         invoked = true;
 352  6
     }
 353  
 
 354  
     public static class DelayedMethod {
 355  
         private Method method;
 356  
         private Object[] args;
 357  
 
 358  38
         public DelayedMethod(Method method, Object... args) {
 359  38
             this.method = method;
 360  38
             this.args = args;
 361  37
         }
 362  
 
 363  
         public void invoke(StoryReporter delegate) {
 364  
             try {
 365  33
                 method.invoke(delegate, args);
 366  0
             } catch (IllegalAccessException e) {
 367  0
                 throw new RuntimeException(e);
 368  0
             } catch (InvocationTargetException e) {
 369  0
                 throw new RuntimeException(e);
 370  0
             } catch (IllegalArgumentException e) {
 371  0
                 throw new RuntimeException("" + method, e);
 372  33
             }
 373  33
         }
 374  
     }
 375  
 
 376  
 }