##### Coverage Report - org.jbehave.core.reporters.ConcurrentStoryReporter

Classes in this File | Line Coverage | Branch Coverage | Complexity
ConcurrentStoryReporter |
72% | 120/166
40% | 22/54
| 2.206896551724138;2.207
ConcurrentStoryReporter$DelayedMethod |
0% | 0/13
N/A | N/A
| 2.206896551724138;2.207

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