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