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