View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.surefire.booter.spi;
20  
21  import java.io.ByteArrayOutputStream;
22  import java.io.IOException;
23  import java.io.PrintStream;
24  import java.nio.Buffer;
25  import java.nio.ByteBuffer;
26  import java.util.Map;
27  import java.util.Map.Entry;
28  
29  import org.apache.maven.plugin.surefire.log.api.ConsoleLoggerUtils;
30  import org.apache.maven.surefire.api.report.ReportEntry;
31  import org.apache.maven.surefire.api.report.SafeThrowable;
32  import org.apache.maven.surefire.api.report.StackTraceWriter;
33  import org.apache.maven.surefire.api.report.TestOutputReportEntry;
34  import org.apache.maven.surefire.api.report.TestSetReportEntry;
35  import org.apache.maven.surefire.api.util.internal.ObjectUtils;
36  import org.apache.maven.surefire.api.util.internal.WritableBufferedByteChannel;
37  import org.junit.Test;
38  
39  import static java.nio.charset.StandardCharsets.UTF_8;
40  import static java.util.Arrays.copyOfRange;
41  import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_TEST_ERROR;
42  import static org.apache.maven.surefire.api.report.RunMode.NORMAL_RUN;
43  import static org.apache.maven.surefire.api.report.TestOutputReportEntry.stdErr;
44  import static org.apache.maven.surefire.api.report.TestOutputReportEntry.stdErrln;
45  import static org.apache.maven.surefire.api.report.TestOutputReportEntry.stdOut;
46  import static org.apache.maven.surefire.api.report.TestOutputReportEntry.stdOutln;
47  import static org.apache.maven.surefire.api.util.internal.Channels.newBufferedChannel;
48  import static org.apache.maven.surefire.api.util.internal.ObjectUtils.systemProps;
49  import static org.assertj.core.api.Assertions.assertThat;
50  import static org.mockito.Mockito.mock;
51  import static org.mockito.Mockito.when;
52  
53  /**
54   * Test for {@link EventChannelEncoder}.
55   *
56   * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
57   * @since 3.0.0-M4
58   */
59  @SuppressWarnings({"checkstyle:linelength", "checkstyle:magicnumber"})
60  public class EventChannelEncoderTest {
61      private static final int ELAPSED_TIME = 102;
62      private static final byte[] ELAPSED_TIME_HEXA = new byte[] {0, 0, 0, 0x66};
63  
64      @Test
65      public void reportEntry() throws IOException {
66          final String exceptionMessage = "msg";
67          final String smartStackTrace = "MyTest:86 >> Error";
68          final String stackTrace = "trace line 1\ntrace line 2";
69          final String trimmedStackTrace = "trace line 1\ntrace line 2";
70  
71          SafeThrowable safeThrowable = new SafeThrowable(new Exception(exceptionMessage));
72          StackTraceWriter stackTraceWriter = mock(StackTraceWriter.class);
73          when(stackTraceWriter.getThrowable()).thenReturn(safeThrowable);
74          when(stackTraceWriter.smartTrimmedStackTrace()).thenReturn(smartStackTrace);
75          when(stackTraceWriter.writeTrimmedTraceToString()).thenReturn(trimmedStackTrace);
76          when(stackTraceWriter.writeTraceToString()).thenReturn(stackTrace);
77  
78          TestSetReportEntry reportEntry = mock(TestSetReportEntry.class);
79          when(reportEntry.getRunMode()).thenReturn(NORMAL_RUN);
80          when(reportEntry.getTestRunId()).thenReturn(1L);
81          when(reportEntry.getElapsed()).thenReturn(ELAPSED_TIME);
82          when(reportEntry.getGroup()).thenReturn("this group");
83          when(reportEntry.getMessage()).thenReturn("skipped test");
84          when(reportEntry.getName()).thenReturn("my test");
85          when(reportEntry.getNameWithGroup()).thenReturn("name with group");
86          when(reportEntry.getSourceName()).thenReturn("pkg.MyTest");
87          when(reportEntry.getStackTraceWriter()).thenReturn(stackTraceWriter);
88  
89          Stream out = Stream.newStream();
90          EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
91          ByteBuffer encoded = encoder.encode(BOOTERCODE_TEST_ERROR, reportEntry, false);
92          ByteArrayOutputStream expectedFrame = new ByteArrayOutputStream();
93          expectedFrame.write(":maven-surefire-event:".getBytes(UTF_8));
94          expectedFrame.write((byte) 10);
95          expectedFrame.write(":test-error:".getBytes(UTF_8));
96          expectedFrame.write((byte) 10);
97          expectedFrame.write(":normal-run:".getBytes(UTF_8));
98          expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
99          expectedFrame.write(':');
100         expectedFrame.write((byte) 5);
101         expectedFrame.write(":UTF-8:".getBytes(UTF_8));
102         expectedFrame.write(new byte[] {0, 0, 0, 10});
103         expectedFrame.write(':');
104         expectedFrame.write(reportEntry.getSourceName().getBytes(UTF_8));
105         expectedFrame.write(':');
106         expectedFrame.write(new byte[] {0, 0, 0, 1});
107         expectedFrame.write(':');
108         expectedFrame.write(0);
109         expectedFrame.write(':');
110         expectedFrame.write(new byte[] {0, 0, 0, 7});
111         expectedFrame.write(':');
112         expectedFrame.write(reportEntry.getName().getBytes(UTF_8));
113         expectedFrame.write(':');
114         expectedFrame.write(new byte[] {0, 0, 0, 1});
115         expectedFrame.write(':');
116         expectedFrame.write(0);
117         expectedFrame.write(':');
118         expectedFrame.write(new byte[] {0, 0, 0, 10});
119         expectedFrame.write(':');
120         expectedFrame.write(reportEntry.getGroup().getBytes(UTF_8));
121         expectedFrame.write(':');
122         expectedFrame.write(new byte[] {0, 0, 0, 12});
123         expectedFrame.write(':');
124         expectedFrame.write(reportEntry.getMessage().getBytes(UTF_8));
125         expectedFrame.write(':');
126         expectedFrame.write(0xff);
127         expectedFrame.write(ELAPSED_TIME_HEXA);
128         expectedFrame.write(':');
129         expectedFrame.write(new byte[] {0, 0, 0, 3});
130         expectedFrame.write(':');
131         expectedFrame.write(exceptionMessage.getBytes(UTF_8));
132         expectedFrame.write(':');
133         expectedFrame.write(new byte[] {0, 0, 0, 18});
134         expectedFrame.write(':');
135         expectedFrame.write(
136                 reportEntry.getStackTraceWriter().smartTrimmedStackTrace().getBytes(UTF_8));
137         expectedFrame.write(':');
138         expectedFrame.write(new byte[] {0, 0, 0, 25});
139         expectedFrame.write(':');
140         expectedFrame.write(stackTrace.getBytes(UTF_8));
141         expectedFrame.write(':');
142         ((Buffer) encoded).flip();
143 
144         assertThat(toArray(encoded)).isEqualTo(expectedFrame.toByteArray());
145 
146         out = Stream.newStream();
147         encoder = new EventChannelEncoder(newBufferedChannel(out));
148         encoded = encoder.encode(BOOTERCODE_TEST_ERROR, reportEntry, true);
149         expectedFrame = new ByteArrayOutputStream();
150         expectedFrame.write(":maven-surefire-event:".getBytes(UTF_8));
151         expectedFrame.write((byte) 10);
152         expectedFrame.write(":test-error:".getBytes(UTF_8));
153         expectedFrame.write((byte) 10);
154         expectedFrame.write(":normal-run:".getBytes(UTF_8));
155         expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
156         expectedFrame.write(':');
157         expectedFrame.write((byte) 5);
158         expectedFrame.write(":UTF-8:".getBytes(UTF_8));
159         expectedFrame.write(new byte[] {0, 0, 0, 10});
160         expectedFrame.write(':');
161         expectedFrame.write(reportEntry.getSourceName().getBytes(UTF_8));
162         expectedFrame.write(':');
163         expectedFrame.write(new byte[] {0, 0, 0, 1});
164         expectedFrame.write(':');
165         expectedFrame.write(0);
166         expectedFrame.write(':');
167         expectedFrame.write(new byte[] {0, 0, 0, 7});
168         expectedFrame.write(':');
169         expectedFrame.write(reportEntry.getName().getBytes(UTF_8));
170         expectedFrame.write(':');
171         expectedFrame.write(new byte[] {0, 0, 0, 1});
172         expectedFrame.write(':');
173         expectedFrame.write(0);
174         expectedFrame.write(':');
175         expectedFrame.write(new byte[] {0, 0, 0, 10});
176         expectedFrame.write(':');
177         expectedFrame.write(reportEntry.getGroup().getBytes(UTF_8));
178         expectedFrame.write(':');
179         expectedFrame.write(new byte[] {0, 0, 0, 12});
180         expectedFrame.write(':');
181         expectedFrame.write(reportEntry.getMessage().getBytes(UTF_8));
182         expectedFrame.write(':');
183         expectedFrame.write(0xff);
184         expectedFrame.write(ELAPSED_TIME_HEXA);
185         expectedFrame.write(':');
186         expectedFrame.write(new byte[] {0, 0, 0, 3});
187         expectedFrame.write(':');
188         expectedFrame.write(exceptionMessage.getBytes(UTF_8));
189         expectedFrame.write(':');
190         expectedFrame.write(new byte[] {0, 0, 0, 18});
191         expectedFrame.write(':');
192         expectedFrame.write(
193                 reportEntry.getStackTraceWriter().smartTrimmedStackTrace().getBytes(UTF_8));
194         expectedFrame.write(':');
195         expectedFrame.write(new byte[] {0, 0, 0, 25});
196         expectedFrame.write(':');
197         expectedFrame.write(trimmedStackTrace.getBytes(UTF_8));
198         expectedFrame.write(':');
199         ((Buffer) encoded).flip();
200 
201         assertThat(toArray(encoded)).isEqualTo(expectedFrame.toByteArray());
202 
203         out = Stream.newStream();
204         encoder = new EventChannelEncoder(newBufferedChannel(out));
205         encoder.testSetStarting(reportEntry, true);
206         expectedFrame = new ByteArrayOutputStream();
207         expectedFrame.write(":maven-surefire-event:".getBytes(UTF_8));
208         expectedFrame.write((byte) 16);
209         expectedFrame.write(":testset-starting:".getBytes(UTF_8));
210         expectedFrame.write((byte) 10);
211         expectedFrame.write(":normal-run:".getBytes(UTF_8));
212         expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
213         expectedFrame.write(':');
214         expectedFrame.write((byte) 5);
215         expectedFrame.write(":UTF-8:".getBytes(UTF_8));
216         expectedFrame.write(new byte[] {0, 0, 0, 10});
217         expectedFrame.write(':');
218         expectedFrame.write(reportEntry.getSourceName().getBytes(UTF_8));
219         expectedFrame.write(':');
220         expectedFrame.write(new byte[] {0, 0, 0, 1});
221         expectedFrame.write(':');
222         expectedFrame.write(0);
223         expectedFrame.write(':');
224         expectedFrame.write(new byte[] {0, 0, 0, 7});
225         expectedFrame.write(':');
226         expectedFrame.write(reportEntry.getName().getBytes(UTF_8));
227         expectedFrame.write(':');
228         expectedFrame.write(new byte[] {0, 0, 0, 1});
229         expectedFrame.write(':');
230         expectedFrame.write(0);
231         expectedFrame.write(':');
232         expectedFrame.write(new byte[] {0, 0, 0, 10});
233         expectedFrame.write(':');
234         expectedFrame.write(reportEntry.getGroup().getBytes(UTF_8));
235         expectedFrame.write(':');
236         expectedFrame.write(new byte[] {0, 0, 0, 12});
237         expectedFrame.write(':');
238         expectedFrame.write(reportEntry.getMessage().getBytes(UTF_8));
239         expectedFrame.write(':');
240         expectedFrame.write(0xff);
241         expectedFrame.write(ELAPSED_TIME_HEXA);
242         expectedFrame.write(':');
243         expectedFrame.write(new byte[] {0, 0, 0, 3});
244         expectedFrame.write(':');
245         expectedFrame.write(exceptionMessage.getBytes(UTF_8));
246         expectedFrame.write(':');
247         expectedFrame.write(new byte[] {0, 0, 0, 18});
248         expectedFrame.write(':');
249         expectedFrame.write(
250                 reportEntry.getStackTraceWriter().smartTrimmedStackTrace().getBytes(UTF_8));
251         expectedFrame.write(':');
252         expectedFrame.write(new byte[] {0, 0, 0, 25});
253         expectedFrame.write(':');
254         expectedFrame.write(trimmedStackTrace.getBytes(UTF_8));
255         expectedFrame.write(':');
256         assertThat(out.toByteArray()).isEqualTo(expectedFrame.toByteArray());
257 
258         out = Stream.newStream();
259         encoder = new EventChannelEncoder(newBufferedChannel(out));
260 
261         encoder.testSetStarting(reportEntry, false);
262         expectedFrame = new ByteArrayOutputStream();
263         expectedFrame.write(":maven-surefire-event:".getBytes(UTF_8));
264         expectedFrame.write((byte) 16);
265         expectedFrame.write(":testset-starting:".getBytes(UTF_8));
266         expectedFrame.write((byte) 10);
267         expectedFrame.write(":normal-run:".getBytes(UTF_8));
268         expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
269         expectedFrame.write(':');
270         expectedFrame.write((byte) 5);
271         expectedFrame.write(":UTF-8:".getBytes(UTF_8));
272         expectedFrame.write(new byte[] {0, 0, 0, 10});
273         expectedFrame.write(':');
274         expectedFrame.write(reportEntry.getSourceName().getBytes(UTF_8));
275         expectedFrame.write(':');
276         expectedFrame.write(new byte[] {0, 0, 0, 1});
277         expectedFrame.write(':');
278         expectedFrame.write(0);
279         expectedFrame.write(':');
280         expectedFrame.write(new byte[] {0, 0, 0, 7});
281         expectedFrame.write(':');
282         expectedFrame.write(reportEntry.getName().getBytes(UTF_8));
283         expectedFrame.write(':');
284         expectedFrame.write(new byte[] {0, 0, 0, 1});
285         expectedFrame.write(':');
286         expectedFrame.write(0);
287         expectedFrame.write(':');
288         expectedFrame.write(new byte[] {0, 0, 0, 10});
289         expectedFrame.write(':');
290         expectedFrame.write(reportEntry.getGroup().getBytes(UTF_8));
291         expectedFrame.write(':');
292         expectedFrame.write(new byte[] {0, 0, 0, 12});
293         expectedFrame.write(':');
294         expectedFrame.write(reportEntry.getMessage().getBytes(UTF_8));
295         expectedFrame.write(':');
296         expectedFrame.write(0xff);
297         expectedFrame.write(ELAPSED_TIME_HEXA);
298         expectedFrame.write(':');
299         expectedFrame.write(new byte[] {0, 0, 0, 3});
300         expectedFrame.write(':');
301         expectedFrame.write(exceptionMessage.getBytes(UTF_8));
302         expectedFrame.write(':');
303         expectedFrame.write(new byte[] {0, 0, 0, 18});
304         expectedFrame.write(':');
305         expectedFrame.write(
306                 reportEntry.getStackTraceWriter().smartTrimmedStackTrace().getBytes(UTF_8));
307         expectedFrame.write(':');
308         expectedFrame.write(new byte[] {0, 0, 0, 25});
309         expectedFrame.write(':');
310         expectedFrame.write(stackTrace.getBytes(UTF_8));
311         expectedFrame.write(':');
312         assertThat(out.toByteArray()).isEqualTo(expectedFrame.toByteArray());
313     }
314 
315     @Test
316     public void testSetCompleted() throws IOException {
317         String exceptionMessage = "msg";
318         String smartStackTrace = "MyTest:86 >> Error";
319         String stackTrace = "trace line 1\ntrace line 2";
320         String trimmedStackTrace = "trace line 1\ntrace line 2";
321 
322         SafeThrowable safeThrowable = new SafeThrowable(new Exception(exceptionMessage));
323         StackTraceWriter stackTraceWriter = mock(StackTraceWriter.class);
324         when(stackTraceWriter.getThrowable()).thenReturn(safeThrowable);
325         when(stackTraceWriter.smartTrimmedStackTrace()).thenReturn(smartStackTrace);
326         when(stackTraceWriter.writeTrimmedTraceToString()).thenReturn(trimmedStackTrace);
327         when(stackTraceWriter.writeTraceToString()).thenReturn(stackTrace);
328 
329         Map<String, String> props = systemProps();
330 
331         TestSetReportEntry reportEntry = mock(TestSetReportEntry.class);
332         when(reportEntry.getRunMode()).thenReturn(NORMAL_RUN);
333         when(reportEntry.getTestRunId()).thenReturn(1L);
334         when(reportEntry.getElapsed()).thenReturn(ELAPSED_TIME);
335         when(reportEntry.getGroup()).thenReturn("this group");
336         when(reportEntry.getMessage()).thenReturn("skipped test");
337         when(reportEntry.getName()).thenReturn("my test");
338         when(reportEntry.getNameWithGroup()).thenReturn("name with group");
339         when(reportEntry.getSourceName()).thenReturn("pkg.MyTest");
340         when(reportEntry.getStackTraceWriter()).thenReturn(stackTraceWriter);
341         when(reportEntry.getSystemProperties()).thenReturn(props);
342 
343         Stream out = Stream.newStream();
344         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
345 
346         encoder.testSetCompleted(reportEntry, false);
347 
348         ByteArrayOutputStream expectedFrame = new ByteArrayOutputStream();
349         for (Entry<String, String> entry : props.entrySet()) {
350             expectedFrame.write(":maven-surefire-event:".getBytes());
351             expectedFrame.write(8);
352             expectedFrame.write(":sys-prop:".getBytes());
353             expectedFrame.write(10);
354             expectedFrame.write(":normal-run:".getBytes());
355             expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
356             expectedFrame.write(":".getBytes());
357             expectedFrame.write(5);
358             expectedFrame.write(":UTF-8:".getBytes());
359             int[] k = toBytes(entry.getKey().length());
360             expectedFrame.write(k[0]);
361             expectedFrame.write(k[1]);
362             expectedFrame.write(k[2]);
363             expectedFrame.write(k[3]);
364             expectedFrame.write(':');
365             expectedFrame.write(entry.getKey().getBytes(UTF_8));
366             expectedFrame.write(':');
367             int[] v = toBytes(entry.getValue() == null ? 1 : entry.getValue().getBytes(UTF_8).length);
368             expectedFrame.write(v[0]);
369             expectedFrame.write(v[1]);
370             expectedFrame.write(v[2]);
371             expectedFrame.write(v[3]);
372             expectedFrame.write(':');
373             expectedFrame.write((entry.getValue() == null ? "\u0000" : entry.getValue()).getBytes(UTF_8));
374             expectedFrame.write(':');
375         }
376 
377         expectedFrame.write(":maven-surefire-event:".getBytes(UTF_8));
378         expectedFrame.write((byte) 17);
379         expectedFrame.write(":testset-completed:".getBytes(UTF_8));
380         expectedFrame.write((byte) 10);
381         expectedFrame.write(":normal-run:".getBytes(UTF_8));
382         expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
383         expectedFrame.write(':');
384         expectedFrame.write((byte) 5);
385         expectedFrame.write(":UTF-8:".getBytes(UTF_8));
386         expectedFrame.write(new byte[] {0, 0, 0, 10});
387         expectedFrame.write(':');
388         expectedFrame.write(reportEntry.getSourceName().getBytes(UTF_8));
389         expectedFrame.write(':');
390         expectedFrame.write(new byte[] {0, 0, 0, 1});
391         expectedFrame.write(':');
392         expectedFrame.write(0);
393         expectedFrame.write(':');
394         expectedFrame.write(new byte[] {0, 0, 0, 7});
395         expectedFrame.write(':');
396         expectedFrame.write(reportEntry.getName().getBytes(UTF_8));
397         expectedFrame.write(':');
398         expectedFrame.write(new byte[] {0, 0, 0, 1});
399         expectedFrame.write(':');
400         expectedFrame.write(0);
401         expectedFrame.write(':');
402         expectedFrame.write(new byte[] {0, 0, 0, 10});
403         expectedFrame.write(':');
404         expectedFrame.write(reportEntry.getGroup().getBytes(UTF_8));
405         expectedFrame.write(':');
406         expectedFrame.write(new byte[] {0, 0, 0, 12});
407         expectedFrame.write(':');
408         expectedFrame.write(reportEntry.getMessage().getBytes(UTF_8));
409         expectedFrame.write(':');
410         expectedFrame.write(0xff);
411         expectedFrame.write(ELAPSED_TIME_HEXA);
412         expectedFrame.write(':');
413         expectedFrame.write(new byte[] {0, 0, 0, 3});
414         expectedFrame.write(':');
415         expectedFrame.write(exceptionMessage.getBytes(UTF_8));
416         expectedFrame.write(':');
417         expectedFrame.write(new byte[] {0, 0, 0, 18});
418         expectedFrame.write(':');
419         expectedFrame.write(
420                 reportEntry.getStackTraceWriter().smartTrimmedStackTrace().getBytes(UTF_8));
421         expectedFrame.write(':');
422         expectedFrame.write(new byte[] {0, 0, 0, 25});
423         expectedFrame.write(':');
424         expectedFrame.write(stackTrace.getBytes(UTF_8));
425         expectedFrame.write(':');
426 
427         assertThat(out.toByteArray()).isEqualTo(expectedFrame.toByteArray());
428     }
429 
430     @Test
431     public void testStarting() throws IOException {
432         String exceptionMessage = "msg";
433         String smartStackTrace = "MyTest:86 >> Error";
434         String stackTrace = "trace line 1\ntrace line 2";
435         String trimmedStackTrace = "trace line 1\ntrace line 2";
436 
437         SafeThrowable safeThrowable = new SafeThrowable(new Exception(exceptionMessage));
438         StackTraceWriter stackTraceWriter = mock(StackTraceWriter.class);
439         when(stackTraceWriter.getThrowable()).thenReturn(safeThrowable);
440         when(stackTraceWriter.smartTrimmedStackTrace()).thenReturn(smartStackTrace);
441         when(stackTraceWriter.writeTrimmedTraceToString()).thenReturn(trimmedStackTrace);
442         when(stackTraceWriter.writeTraceToString()).thenReturn(stackTrace);
443 
444         ReportEntry reportEntry = mock(ReportEntry.class);
445         when(reportEntry.getRunMode()).thenReturn(NORMAL_RUN);
446         when(reportEntry.getTestRunId()).thenReturn(1L);
447         when(reportEntry.getElapsed()).thenReturn(ELAPSED_TIME);
448         when(reportEntry.getGroup()).thenReturn("this group");
449         when(reportEntry.getMessage()).thenReturn("skipped test");
450         when(reportEntry.getName()).thenReturn("my test");
451         when(reportEntry.getNameWithGroup()).thenReturn("name with group");
452         when(reportEntry.getSourceName()).thenReturn("pkg.MyTest");
453         when(reportEntry.getStackTraceWriter()).thenReturn(stackTraceWriter);
454 
455         Stream out = Stream.newStream();
456         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
457 
458         encoder.testStarting(reportEntry, true);
459 
460         ByteArrayOutputStream expectedFrame = new ByteArrayOutputStream();
461         expectedFrame.write(":maven-surefire-event:".getBytes(UTF_8));
462         expectedFrame.write((byte) 13);
463         expectedFrame.write(":test-starting:".getBytes(UTF_8));
464         expectedFrame.write((byte) 10);
465         expectedFrame.write(":normal-run:".getBytes(UTF_8));
466         expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
467         expectedFrame.write(':');
468         expectedFrame.write((byte) 5);
469         expectedFrame.write(":UTF-8:".getBytes(UTF_8));
470         expectedFrame.write(new byte[] {0, 0, 0, 10});
471         expectedFrame.write(':');
472         expectedFrame.write(reportEntry.getSourceName().getBytes(UTF_8));
473         expectedFrame.write(':');
474         expectedFrame.write(new byte[] {0, 0, 0, 1});
475         expectedFrame.write(':');
476         expectedFrame.write(0);
477         expectedFrame.write(':');
478         expectedFrame.write(new byte[] {0, 0, 0, 7});
479         expectedFrame.write(':');
480         expectedFrame.write(reportEntry.getName().getBytes(UTF_8));
481         expectedFrame.write(':');
482         expectedFrame.write(new byte[] {0, 0, 0, 1});
483         expectedFrame.write(':');
484         expectedFrame.write(0);
485         expectedFrame.write(':');
486         expectedFrame.write(new byte[] {0, 0, 0, 10});
487         expectedFrame.write(':');
488         expectedFrame.write(reportEntry.getGroup().getBytes(UTF_8));
489         expectedFrame.write(':');
490         expectedFrame.write(new byte[] {0, 0, 0, 12});
491         expectedFrame.write(':');
492         expectedFrame.write(reportEntry.getMessage().getBytes(UTF_8));
493         expectedFrame.write(':');
494         expectedFrame.write(0xff);
495         expectedFrame.write(ELAPSED_TIME_HEXA);
496         expectedFrame.write(':');
497         expectedFrame.write(new byte[] {0, 0, 0, 3});
498         expectedFrame.write(':');
499         expectedFrame.write(exceptionMessage.getBytes(UTF_8));
500         expectedFrame.write(':');
501         expectedFrame.write(new byte[] {0, 0, 0, 18});
502         expectedFrame.write(':');
503         expectedFrame.write(
504                 reportEntry.getStackTraceWriter().smartTrimmedStackTrace().getBytes(UTF_8));
505         expectedFrame.write(':');
506         expectedFrame.write(new byte[] {0, 0, 0, 25});
507         expectedFrame.write(':');
508         expectedFrame.write(stackTrace.getBytes(UTF_8));
509         expectedFrame.write(':');
510         assertThat(out.toByteArray()).isEqualTo(expectedFrame.toByteArray());
511     }
512 
513     @Test
514     public void testSuccess() throws IOException {
515         String exceptionMessage = "msg";
516         String smartStackTrace = "MyTest:86 >> Error";
517         String stackTrace = "trace line 1\ntrace line 2";
518         String trimmedStackTrace = "trace line 1\ntrace line 2";
519 
520         SafeThrowable safeThrowable = new SafeThrowable(new Exception(exceptionMessage));
521         StackTraceWriter stackTraceWriter = mock(StackTraceWriter.class);
522         when(stackTraceWriter.getThrowable()).thenReturn(safeThrowable);
523         when(stackTraceWriter.smartTrimmedStackTrace()).thenReturn(smartStackTrace);
524         when(stackTraceWriter.writeTrimmedTraceToString()).thenReturn(trimmedStackTrace);
525         when(stackTraceWriter.writeTraceToString()).thenReturn(stackTrace);
526 
527         ReportEntry reportEntry = mock(ReportEntry.class);
528         when(reportEntry.getRunMode()).thenReturn(NORMAL_RUN);
529         when(reportEntry.getTestRunId()).thenReturn(1L);
530         when(reportEntry.getElapsed()).thenReturn(ELAPSED_TIME);
531         when(reportEntry.getGroup()).thenReturn("this group");
532         when(reportEntry.getMessage()).thenReturn("skipped test");
533         when(reportEntry.getName()).thenReturn("my test");
534         when(reportEntry.getNameWithGroup()).thenReturn("name with group");
535         when(reportEntry.getSourceName()).thenReturn("pkg.MyTest");
536         when(reportEntry.getStackTraceWriter()).thenReturn(stackTraceWriter);
537 
538         Stream out = Stream.newStream();
539         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
540 
541         encoder.testSucceeded(reportEntry, true);
542         ByteArrayOutputStream expectedFrame = new ByteArrayOutputStream();
543         expectedFrame.write(":maven-surefire-event:".getBytes(UTF_8));
544         expectedFrame.write((byte) 14);
545         expectedFrame.write(":test-succeeded:".getBytes(UTF_8));
546         expectedFrame.write((byte) 10);
547         expectedFrame.write(":normal-run:".getBytes(UTF_8));
548         expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
549         expectedFrame.write(':');
550         expectedFrame.write((byte) 5);
551         expectedFrame.write(":UTF-8:".getBytes(UTF_8));
552         expectedFrame.write(new byte[] {0, 0, 0, 10});
553         expectedFrame.write(':');
554         expectedFrame.write(reportEntry.getSourceName().getBytes(UTF_8));
555         expectedFrame.write(':');
556         expectedFrame.write(new byte[] {0, 0, 0, 1});
557         expectedFrame.write(':');
558         expectedFrame.write(0);
559         expectedFrame.write(':');
560         expectedFrame.write(new byte[] {0, 0, 0, 7});
561         expectedFrame.write(':');
562         expectedFrame.write(reportEntry.getName().getBytes(UTF_8));
563         expectedFrame.write(':');
564         expectedFrame.write(new byte[] {0, 0, 0, 1});
565         expectedFrame.write(':');
566         expectedFrame.write(0);
567         expectedFrame.write(':');
568         expectedFrame.write(new byte[] {0, 0, 0, 10});
569         expectedFrame.write(':');
570         expectedFrame.write(reportEntry.getGroup().getBytes(UTF_8));
571         expectedFrame.write(':');
572         expectedFrame.write(new byte[] {0, 0, 0, 12});
573         expectedFrame.write(':');
574         expectedFrame.write(reportEntry.getMessage().getBytes(UTF_8));
575         expectedFrame.write(':');
576         expectedFrame.write(0xff);
577         expectedFrame.write(ELAPSED_TIME_HEXA);
578         expectedFrame.write(':');
579         expectedFrame.write(new byte[] {0, 0, 0, 3});
580         expectedFrame.write(':');
581         expectedFrame.write(exceptionMessage.getBytes(UTF_8));
582         expectedFrame.write(':');
583         expectedFrame.write(new byte[] {0, 0, 0, 18});
584         expectedFrame.write(':');
585         expectedFrame.write(
586                 reportEntry.getStackTraceWriter().smartTrimmedStackTrace().getBytes(UTF_8));
587         expectedFrame.write(':');
588         expectedFrame.write(new byte[] {0, 0, 0, 25});
589         expectedFrame.write(':');
590         expectedFrame.write(stackTrace.getBytes(UTF_8));
591         expectedFrame.write(':');
592         assertThat(out.toByteArray()).isEqualTo(expectedFrame.toByteArray());
593     }
594 
595     @Test
596     public void testFailed() throws IOException {
597         String exceptionMessage = "msg";
598         String smartStackTrace = "MyTest:86 >> Error";
599         String stackTrace = "trace line 1\ntrace line 2";
600         String trimmedStackTrace = "trace line 1\ntrace line 2";
601 
602         SafeThrowable safeThrowable = new SafeThrowable(new Exception(exceptionMessage));
603         StackTraceWriter stackTraceWriter = mock(StackTraceWriter.class);
604         when(stackTraceWriter.getThrowable()).thenReturn(safeThrowable);
605         when(stackTraceWriter.smartTrimmedStackTrace()).thenReturn(smartStackTrace);
606         when(stackTraceWriter.writeTrimmedTraceToString()).thenReturn(trimmedStackTrace);
607         when(stackTraceWriter.writeTraceToString()).thenReturn(stackTrace);
608 
609         ReportEntry reportEntry = mock(ReportEntry.class);
610         when(reportEntry.getRunMode()).thenReturn(NORMAL_RUN);
611         when(reportEntry.getTestRunId()).thenReturn(1L);
612         when(reportEntry.getElapsed()).thenReturn(ELAPSED_TIME);
613         when(reportEntry.getGroup()).thenReturn("this group");
614         when(reportEntry.getMessage()).thenReturn("skipped test");
615         when(reportEntry.getName()).thenReturn("my test");
616         when(reportEntry.getNameWithGroup()).thenReturn("name with group");
617         when(reportEntry.getSourceName()).thenReturn("pkg.MyTest");
618         when(reportEntry.getStackTraceWriter()).thenReturn(stackTraceWriter);
619 
620         Stream out = Stream.newStream();
621         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
622 
623         encoder.testFailed(reportEntry, false);
624         ByteArrayOutputStream expectedFrame = new ByteArrayOutputStream();
625         expectedFrame.write(":maven-surefire-event:".getBytes(UTF_8));
626         expectedFrame.write((byte) 11);
627         expectedFrame.write(":test-failed:".getBytes(UTF_8));
628         expectedFrame.write((byte) 10);
629         expectedFrame.write(":normal-run:".getBytes(UTF_8));
630         expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
631         expectedFrame.write(':');
632         expectedFrame.write((byte) 5);
633         expectedFrame.write(":UTF-8:".getBytes(UTF_8));
634         expectedFrame.write(new byte[] {0, 0, 0, 10});
635         expectedFrame.write(':');
636         expectedFrame.write(reportEntry.getSourceName().getBytes(UTF_8));
637         expectedFrame.write(':');
638         expectedFrame.write(new byte[] {0, 0, 0, 1});
639         expectedFrame.write(':');
640         expectedFrame.write(0);
641         expectedFrame.write(':');
642         expectedFrame.write(new byte[] {0, 0, 0, 7});
643         expectedFrame.write(':');
644         expectedFrame.write(reportEntry.getName().getBytes(UTF_8));
645         expectedFrame.write(':');
646         expectedFrame.write(new byte[] {0, 0, 0, 1});
647         expectedFrame.write(':');
648         expectedFrame.write(0);
649         expectedFrame.write(':');
650         expectedFrame.write(new byte[] {0, 0, 0, 10});
651         expectedFrame.write(':');
652         expectedFrame.write(reportEntry.getGroup().getBytes(UTF_8));
653         expectedFrame.write(':');
654         expectedFrame.write(new byte[] {0, 0, 0, 12});
655         expectedFrame.write(':');
656         expectedFrame.write(reportEntry.getMessage().getBytes(UTF_8));
657         expectedFrame.write(':');
658         expectedFrame.write(0xff);
659         expectedFrame.write(ELAPSED_TIME_HEXA);
660         expectedFrame.write(':');
661         expectedFrame.write(new byte[] {0, 0, 0, 3});
662         expectedFrame.write(':');
663         expectedFrame.write(exceptionMessage.getBytes(UTF_8));
664         expectedFrame.write(':');
665         expectedFrame.write(new byte[] {0, 0, 0, 18});
666         expectedFrame.write(':');
667         expectedFrame.write(
668                 reportEntry.getStackTraceWriter().smartTrimmedStackTrace().getBytes(UTF_8));
669         expectedFrame.write(':');
670         expectedFrame.write(new byte[] {0, 0, 0, 25});
671         expectedFrame.write(':');
672         expectedFrame.write(stackTrace.getBytes(UTF_8));
673         expectedFrame.write(':');
674         assertThat(out.toByteArray()).isEqualTo(expectedFrame.toByteArray());
675     }
676 
677     @Test
678     public void testSkipped() throws IOException {
679         String smartStackTrace = "MyTest:86 >> Error";
680         String stackTrace = "trace line 1\ntrace line 2";
681         String trimmedStackTrace = "trace line 1\ntrace line 2";
682 
683         SafeThrowable safeThrowable = new SafeThrowable(new Exception());
684         StackTraceWriter stackTraceWriter = mock(StackTraceWriter.class);
685         when(stackTraceWriter.getThrowable()).thenReturn(safeThrowable);
686         when(stackTraceWriter.smartTrimmedStackTrace()).thenReturn(smartStackTrace);
687         when(stackTraceWriter.writeTrimmedTraceToString()).thenReturn(trimmedStackTrace);
688         when(stackTraceWriter.writeTraceToString()).thenReturn(stackTrace);
689 
690         ReportEntry reportEntry = mock(ReportEntry.class);
691         when(reportEntry.getRunMode()).thenReturn(NORMAL_RUN);
692         when(reportEntry.getTestRunId()).thenReturn(1L);
693         when(reportEntry.getElapsed()).thenReturn(ELAPSED_TIME);
694         when(reportEntry.getGroup()).thenReturn("this group");
695         when(reportEntry.getMessage()).thenReturn("skipped test");
696         when(reportEntry.getName()).thenReturn("my test");
697         when(reportEntry.getNameWithGroup()).thenReturn("name with group");
698         when(reportEntry.getSourceName()).thenReturn("pkg.MyTest");
699         when(reportEntry.getStackTraceWriter()).thenReturn(stackTraceWriter);
700 
701         Stream out = Stream.newStream();
702         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
703 
704         encoder.testSkipped(reportEntry, false);
705         ByteArrayOutputStream expectedFrame = new ByteArrayOutputStream();
706         expectedFrame.write(":maven-surefire-event:".getBytes(UTF_8));
707         expectedFrame.write((byte) 12);
708         expectedFrame.write(":test-skipped:".getBytes(UTF_8));
709         expectedFrame.write((byte) 10);
710         expectedFrame.write(":normal-run:".getBytes(UTF_8));
711         expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
712         expectedFrame.write(':');
713         expectedFrame.write((byte) 5);
714         expectedFrame.write(":UTF-8:".getBytes(UTF_8));
715         expectedFrame.write(new byte[] {0, 0, 0, 10});
716         expectedFrame.write(':');
717         expectedFrame.write(reportEntry.getSourceName().getBytes(UTF_8));
718         expectedFrame.write(':');
719         expectedFrame.write(new byte[] {0, 0, 0, 1});
720         expectedFrame.write(':');
721         expectedFrame.write(0);
722         expectedFrame.write(':');
723         expectedFrame.write(new byte[] {0, 0, 0, 7});
724         expectedFrame.write(':');
725         expectedFrame.write(reportEntry.getName().getBytes(UTF_8));
726         expectedFrame.write(':');
727         expectedFrame.write(new byte[] {0, 0, 0, 1});
728         expectedFrame.write(':');
729         expectedFrame.write(0);
730         expectedFrame.write(':');
731         expectedFrame.write(new byte[] {0, 0, 0, 10});
732         expectedFrame.write(':');
733         expectedFrame.write(reportEntry.getGroup().getBytes(UTF_8));
734         expectedFrame.write(':');
735         expectedFrame.write(new byte[] {0, 0, 0, 12});
736         expectedFrame.write(':');
737         expectedFrame.write(reportEntry.getMessage().getBytes(UTF_8));
738         expectedFrame.write(':');
739         expectedFrame.write(0xFF);
740         expectedFrame.write(ELAPSED_TIME_HEXA);
741         expectedFrame.write(':');
742         expectedFrame.write(new byte[] {0, 0, 0, 1});
743         expectedFrame.write(':');
744         expectedFrame.write(0);
745         expectedFrame.write(':');
746         expectedFrame.write(new byte[] {0, 0, 0, 18});
747         expectedFrame.write(':');
748         expectedFrame.write(
749                 reportEntry.getStackTraceWriter().smartTrimmedStackTrace().getBytes(UTF_8));
750         expectedFrame.write(':');
751         expectedFrame.write(new byte[] {0, 0, 0, 25});
752         expectedFrame.write(':');
753         expectedFrame.write(stackTrace.getBytes(UTF_8));
754         expectedFrame.write(':');
755         assertThat(out.toByteArray()).isEqualTo(expectedFrame.toByteArray());
756     }
757 
758     @Test
759     public void testError() throws IOException {
760         String stackTrace = "trace line 1\ntrace line 2";
761 
762         String trimmedStackTrace = "trace line 1";
763 
764         SafeThrowable safeThrowable = new SafeThrowable(new Exception());
765         StackTraceWriter stackTraceWriter = mock(StackTraceWriter.class);
766         when(stackTraceWriter.getThrowable()).thenReturn(safeThrowable);
767         when(stackTraceWriter.smartTrimmedStackTrace()).thenReturn(null);
768         when(stackTraceWriter.writeTrimmedTraceToString()).thenReturn(trimmedStackTrace);
769         when(stackTraceWriter.writeTraceToString()).thenReturn(stackTrace);
770 
771         ReportEntry reportEntry = mock(ReportEntry.class);
772         when(reportEntry.getRunMode()).thenReturn(NORMAL_RUN);
773         when(reportEntry.getTestRunId()).thenReturn(1L);
774         when(reportEntry.getElapsed()).thenReturn(ELAPSED_TIME);
775         when(reportEntry.getGroup()).thenReturn("this group");
776         when(reportEntry.getMessage()).thenReturn("skipped test");
777         when(reportEntry.getName()).thenReturn("my test");
778         when(reportEntry.getNameWithGroup()).thenReturn("name with group");
779         when(reportEntry.getSourceName()).thenReturn("pkg.MyTest");
780         when(reportEntry.getStackTraceWriter()).thenReturn(stackTraceWriter);
781 
782         Stream out = Stream.newStream();
783         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
784         encoder.testError(reportEntry, false);
785         ByteArrayOutputStream expectedFrame = new ByteArrayOutputStream();
786         expectedFrame.write(":maven-surefire-event:".getBytes(UTF_8));
787         expectedFrame.write((byte) 10);
788         expectedFrame.write(":test-error:".getBytes(UTF_8));
789         expectedFrame.write((byte) 10);
790         expectedFrame.write(":normal-run:".getBytes(UTF_8));
791         expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
792         expectedFrame.write(':');
793         expectedFrame.write((byte) 5);
794         expectedFrame.write(":UTF-8:".getBytes(UTF_8));
795         expectedFrame.write(new byte[] {0, 0, 0, 10});
796         expectedFrame.write(':');
797         expectedFrame.write(reportEntry.getSourceName().getBytes(UTF_8));
798         expectedFrame.write(':');
799         expectedFrame.write(new byte[] {0, 0, 0, 1});
800         expectedFrame.write(':');
801         expectedFrame.write(0);
802         expectedFrame.write(':');
803         expectedFrame.write(new byte[] {0, 0, 0, 7});
804         expectedFrame.write(':');
805         expectedFrame.write(reportEntry.getName().getBytes(UTF_8));
806         expectedFrame.write(':');
807         expectedFrame.write(new byte[] {0, 0, 0, 1});
808         expectedFrame.write(':');
809         expectedFrame.write(0);
810         expectedFrame.write(':');
811         expectedFrame.write(new byte[] {0, 0, 0, 10});
812         expectedFrame.write(':');
813         expectedFrame.write(reportEntry.getGroup().getBytes(UTF_8));
814         expectedFrame.write(':');
815         expectedFrame.write(new byte[] {0, 0, 0, 12});
816         expectedFrame.write(':');
817         expectedFrame.write(reportEntry.getMessage().getBytes(UTF_8));
818         expectedFrame.write(':');
819         expectedFrame.write(0xff);
820         expectedFrame.write(ELAPSED_TIME_HEXA);
821         expectedFrame.write(':');
822         expectedFrame.write(new byte[] {0, 0, 0, 1});
823         expectedFrame.write(':');
824         expectedFrame.write(0);
825         expectedFrame.write(':');
826         expectedFrame.write(new byte[] {0, 0, 0, 1});
827         expectedFrame.write(':');
828         expectedFrame.write(0);
829         expectedFrame.write(':');
830         expectedFrame.write(new byte[] {0, 0, 0, 25});
831         expectedFrame.write(':');
832         expectedFrame.write(stackTrace.getBytes(UTF_8));
833         expectedFrame.write(':');
834         assertThat(out.toByteArray()).isEqualTo(expectedFrame.toByteArray());
835     }
836 
837     @Test
838     public void testAssumptionFailure() throws IOException {
839         String exceptionMessage = "msg";
840 
841         String smartStackTrace = "MyTest:86 >> Error";
842 
843         SafeThrowable safeThrowable = new SafeThrowable(new Exception(exceptionMessage));
844         StackTraceWriter stackTraceWriter = mock(StackTraceWriter.class);
845         when(stackTraceWriter.getThrowable()).thenReturn(safeThrowable);
846         when(stackTraceWriter.smartTrimmedStackTrace()).thenReturn(smartStackTrace);
847         when(stackTraceWriter.writeTrimmedTraceToString()).thenReturn(null);
848         when(stackTraceWriter.writeTraceToString()).thenReturn(null);
849 
850         ReportEntry reportEntry = mock(ReportEntry.class);
851         when(reportEntry.getRunMode()).thenReturn(NORMAL_RUN);
852         when(reportEntry.getTestRunId()).thenReturn(1L);
853         when(reportEntry.getElapsed()).thenReturn(null);
854         when(reportEntry.getGroup()).thenReturn("this group");
855         when(reportEntry.getMessage()).thenReturn("skipped test");
856         when(reportEntry.getName()).thenReturn("my test");
857         when(reportEntry.getNameWithGroup()).thenReturn("name with group");
858         when(reportEntry.getSourceName()).thenReturn("pkg.MyTest");
859         when(reportEntry.getStackTraceWriter()).thenReturn(stackTraceWriter);
860 
861         Stream out = Stream.newStream();
862         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
863 
864         encoder.testAssumptionFailure(reportEntry, false);
865         ByteArrayOutputStream expectedFrame = new ByteArrayOutputStream();
866         expectedFrame.write(":maven-surefire-event:".getBytes(UTF_8));
867         expectedFrame.write((byte) 23);
868         expectedFrame.write(":test-assumption-failure:".getBytes(UTF_8));
869         expectedFrame.write((byte) 10);
870         expectedFrame.write(":normal-run:".getBytes(UTF_8));
871         expectedFrame.write("\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001".getBytes());
872         expectedFrame.write(':');
873         expectedFrame.write((byte) 5);
874         expectedFrame.write(":UTF-8:".getBytes(UTF_8));
875         expectedFrame.write(new byte[] {0, 0, 0, 10});
876         expectedFrame.write(':');
877         expectedFrame.write(reportEntry.getSourceName().getBytes(UTF_8));
878         expectedFrame.write(':');
879         expectedFrame.write(new byte[] {0, 0, 0, 1});
880         expectedFrame.write(':');
881         expectedFrame.write(0);
882         expectedFrame.write(':');
883         expectedFrame.write(new byte[] {0, 0, 0, 7});
884         expectedFrame.write(':');
885         expectedFrame.write(reportEntry.getName().getBytes(UTF_8));
886         expectedFrame.write(':');
887         expectedFrame.write(new byte[] {0, 0, 0, 1});
888         expectedFrame.write(':');
889         expectedFrame.write(0);
890         expectedFrame.write(':');
891         expectedFrame.write(new byte[] {0, 0, 0, 10});
892         expectedFrame.write(':');
893         expectedFrame.write(reportEntry.getGroup().getBytes(UTF_8));
894         expectedFrame.write(':');
895         expectedFrame.write(new byte[] {0, 0, 0, 12});
896         expectedFrame.write(':');
897         expectedFrame.write(reportEntry.getMessage().getBytes(UTF_8));
898         expectedFrame.write(':');
899         expectedFrame.write(0);
900         expectedFrame.write(':');
901         expectedFrame.write(new byte[] {0, 0, 0, 3});
902         expectedFrame.write(':');
903         expectedFrame.write(exceptionMessage.getBytes(UTF_8));
904         expectedFrame.write(':');
905         expectedFrame.write(new byte[] {0, 0, 0, 18});
906         expectedFrame.write(':');
907         expectedFrame.write(smartStackTrace.getBytes(UTF_8));
908         expectedFrame.write(':');
909         expectedFrame.write(new byte[] {0, 0, 0, 1});
910         expectedFrame.write(':');
911         expectedFrame.write(0);
912         expectedFrame.write(':');
913         assertThat(out.toByteArray()).isEqualTo(expectedFrame.toByteArray());
914     }
915 
916     @Test
917     public void testBye() {
918         Stream out = Stream.newStream();
919         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
920 
921         encoder.bye();
922 
923         String encoded = new String(out.toByteArray(), UTF_8);
924 
925         assertThat(encoded).isEqualTo(":maven-surefire-event:\u0003:bye:");
926     }
927 
928     @Test
929     public void testStopOnNextTest() {
930         Stream out = Stream.newStream();
931         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
932 
933         encoder.stopOnNextTest();
934 
935         String encoded = new String(out.toByteArray(), UTF_8);
936         assertThat(encoded).isEqualTo(":maven-surefire-event:\u0011:stop-on-next-test:");
937     }
938 
939     @Test
940     public void testAcquireNextTest() {
941         Stream out = Stream.newStream();
942         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
943 
944         encoder.acquireNextTest();
945 
946         String encoded = new String(out.toByteArray(), UTF_8);
947         assertThat(encoded).isEqualTo(":maven-surefire-event:\u0009:next-test:");
948     }
949 
950     @Test
951     public void testSendOpcode() {
952         Channel channel = new Channel();
953         new EventChannelEncoder(channel).testOutput(new TestOutputReportEntry(stdOut("msg"), NORMAL_RUN, 1L));
954         assertThat(toString(channel.src))
955                 .isEqualTo(":maven-surefire-event:" + (char) 14 + ":std-out-stream:" + (char) 10 + ":normal-run:"
956                         + "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
957                         + (char) 5 + ":UTF-8:\u0000\u0000\u0000\u0003:msg:");
958 
959         channel = new Channel();
960         new EventChannelEncoder(channel).testOutput(new TestOutputReportEntry(stdErr(null), NORMAL_RUN, 1L));
961         assertThat(toString(channel.src))
962                 .isEqualTo(":maven-surefire-event:" + (char) 14 + ":std-err-stream:" + (char) 10 + ":normal-run:"
963                         + "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
964                         + (char) 5 + ":UTF-8:\u0000\u0000\u0000\u0001:\u0000:");
965 
966         ByteBuffer result =
967                 new EventChannelEncoder(new Channel()).encodeMessage(BOOTERCODE_TEST_ERROR, NORMAL_RUN, 1L, "msg");
968         assertThat(toString(result))
969                 .isEqualTo(":maven-surefire-event:" + (char) 10 + ":test-error:" + (char) 10 + ":normal-run:"
970                         + "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
971                         + (char) 5 + ":UTF-8:\u0000\u0000\u0000\u0003:msg:");
972     }
973 
974     @Test
975     public void testConsoleInfo() {
976         Stream out = Stream.newStream();
977         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
978 
979         encoder.consoleInfoLog("msg");
980 
981         String encoded = new String(out.toByteArray(), UTF_8);
982 
983         String expected = ":maven-surefire-event:\u0010:console-info-log:\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:";
984 
985         assertThat(encoded).isEqualTo(expected);
986     }
987 
988     @Test
989     public void testConsoleError() {
990         Stream out = Stream.newStream();
991         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
992 
993         encoder.consoleErrorLog("msg");
994 
995         String encoded = new String(out.toByteArray(), UTF_8);
996 
997         String expected = ":maven-surefire-event:\u0011:console-error-log:\u0005:UTF-8:"
998                 + "\u0000\u0000\u0000\u0003:msg:"
999                 + "\u0000\u0000\u0000\u0001:\u0000:"
1000                 + "\u0000\u0000\u0000\u0001:\u0000:";
1001 
1002         assertThat(encoded).isEqualTo(expected);
1003     }
1004 
1005     @Test
1006     public void testConsoleErrorLog1() throws IOException {
1007         Stream out = Stream.newStream();
1008         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
1009 
1010         Exception e = new Exception("msg");
1011         encoder.consoleErrorLog(e);
1012         String stackTrace = ConsoleLoggerUtils.toString(e);
1013         ByteArrayOutputStream expectedFrame = new ByteArrayOutputStream();
1014         expectedFrame.write(":maven-surefire-event:\u0011:console-error-log:\u0005:UTF-8:".getBytes(UTF_8));
1015         expectedFrame.write(0);
1016         expectedFrame.write(0);
1017         expectedFrame.write(0);
1018         expectedFrame.write(3);
1019         expectedFrame.write(':');
1020         expectedFrame.write("msg".getBytes(UTF_8));
1021         expectedFrame.write(':');
1022         expectedFrame.write(0);
1023         expectedFrame.write(0);
1024         expectedFrame.write(0);
1025         expectedFrame.write(1);
1026         expectedFrame.write(':');
1027         expectedFrame.write(0);
1028         expectedFrame.write(':');
1029         byte[] stackTraceBytes = stackTrace.getBytes(UTF_8);
1030         int[] stackTraceLength = toBytes(stackTraceBytes.length);
1031         expectedFrame.write(stackTraceLength[0]);
1032         expectedFrame.write(stackTraceLength[1]);
1033         expectedFrame.write(stackTraceLength[2]);
1034         expectedFrame.write(stackTraceLength[3]);
1035         expectedFrame.write(':');
1036         expectedFrame.write(stackTraceBytes);
1037         expectedFrame.write(':');
1038         assertThat(out.toByteArray()).isEqualTo(expectedFrame.toByteArray());
1039     }
1040 
1041     @Test
1042     public void testConsoleErrorLog2() throws IOException {
1043         Stream out = Stream.newStream();
1044         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
1045 
1046         Exception e = new Exception("msg");
1047         encoder.consoleErrorLog("msg2", e);
1048         String stackTrace = ConsoleLoggerUtils.toString(e);
1049         ByteArrayOutputStream expectedFrame = new ByteArrayOutputStream();
1050         expectedFrame.write(":maven-surefire-event:\u0011:console-error-log:\u0005:UTF-8:".getBytes(UTF_8));
1051         expectedFrame.write(0);
1052         expectedFrame.write(0);
1053         expectedFrame.write(0);
1054         expectedFrame.write(4);
1055         expectedFrame.write(':');
1056         expectedFrame.write("msg2".getBytes(UTF_8));
1057         expectedFrame.write(':');
1058         expectedFrame.write(0);
1059         expectedFrame.write(0);
1060         expectedFrame.write(0);
1061         expectedFrame.write(1);
1062         expectedFrame.write(':');
1063         expectedFrame.write(0);
1064         expectedFrame.write(':');
1065         byte[] stackTraceBytes = stackTrace.getBytes(UTF_8);
1066         int[] stackTraceLength = toBytes(stackTraceBytes.length);
1067         expectedFrame.write(stackTraceLength[0]);
1068         expectedFrame.write(stackTraceLength[1]);
1069         expectedFrame.write(stackTraceLength[2]);
1070         expectedFrame.write(stackTraceLength[3]);
1071         expectedFrame.write(':');
1072         expectedFrame.write(stackTraceBytes);
1073         expectedFrame.write(':');
1074         assertThat(out.toByteArray()).isEqualTo(expectedFrame.toByteArray());
1075     }
1076 
1077     @Test
1078     public void testConsoleErrorLog3() {
1079         Stream out = Stream.newStream();
1080         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
1081 
1082         StackTraceWriter stackTraceWriter = mock(StackTraceWriter.class);
1083         when(stackTraceWriter.getThrowable()).thenReturn(new SafeThrowable("1"));
1084         when(stackTraceWriter.smartTrimmedStackTrace()).thenReturn("2");
1085         when(stackTraceWriter.writeTraceToString()).thenReturn("3");
1086         when(stackTraceWriter.writeTrimmedTraceToString()).thenReturn("4");
1087 
1088         encoder.consoleErrorLog(stackTraceWriter, true);
1089         String encoded = new String(out.toByteArray(), UTF_8);
1090         assertThat(encoded)
1091                 .startsWith(
1092                         ":maven-surefire-event:\u0011:console-error-log:\u0005:UTF-8:\u0000\u0000\u0000\u0001:1:\u0000\u0000\u0000\u0001:2:\u0000\u0000\u0000\u0001:4:");
1093     }
1094 
1095     @Test
1096     public void testConsoleDebug() {
1097         Stream out = Stream.newStream();
1098         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
1099 
1100         encoder.consoleDebugLog("msg");
1101 
1102         String encoded = new String(out.toByteArray(), UTF_8);
1103 
1104         String expected = ":maven-surefire-event:\u0011:console-debug-log:\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:";
1105 
1106         assertThat(encoded).isEqualTo(expected);
1107     }
1108 
1109     @Test
1110     public void testConsoleWarning() {
1111         Stream out = Stream.newStream();
1112         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
1113 
1114         encoder.consoleWarningLog("msg");
1115 
1116         String encoded = new String(out.toByteArray(), UTF_8);
1117 
1118         String expected = ":maven-surefire-event:\u0013:console-warning-log:\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:";
1119 
1120         assertThat(encoded).isEqualTo(expected);
1121     }
1122 
1123     @Test
1124     public void testStdOutStream() throws IOException {
1125         Stream out = Stream.newStream();
1126         WritableBufferedByteChannel channel = newBufferedChannel(out);
1127         EventChannelEncoder encoder = new EventChannelEncoder(channel);
1128 
1129         encoder.testOutput(new TestOutputReportEntry(stdOut("msg"), NORMAL_RUN, 1L));
1130         channel.close();
1131 
1132         String expected = ":maven-surefire-event:\u000e:std-out-stream:"
1133                 + (char) 10 + ":normal-run:\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
1134                 + "\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:";
1135 
1136         assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
1137     }
1138 
1139     @Test
1140     public void testStdOutStreamLn() throws IOException {
1141         Stream out = Stream.newStream();
1142         WritableBufferedByteChannel channel = newBufferedChannel(out);
1143         EventChannelEncoder encoder = new EventChannelEncoder(channel);
1144 
1145         encoder.testOutput(new TestOutputReportEntry(stdOutln("msg"), NORMAL_RUN, 1L));
1146         channel.close();
1147 
1148         String expected = ":maven-surefire-event:\u0017:std-out-stream-new-line:"
1149                 + (char) 10 + ":normal-run:\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
1150                 + "\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:";
1151 
1152         assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
1153     }
1154 
1155     @Test
1156     public void testStdErrStream() throws IOException {
1157         Stream out = Stream.newStream();
1158         WritableBufferedByteChannel channel = newBufferedChannel(out);
1159         EventChannelEncoder encoder = new EventChannelEncoder(channel);
1160 
1161         encoder.testOutput(new TestOutputReportEntry(stdErr("msg"), NORMAL_RUN, 1L));
1162         channel.close();
1163 
1164         String expected = ":maven-surefire-event:\u000e:std-err-stream:"
1165                 + (char) 10 + ":normal-run:\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
1166                 + "\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:";
1167 
1168         assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
1169     }
1170 
1171     @Test
1172     public void testStdErrStreamLn() throws IOException {
1173         Stream out = Stream.newStream();
1174         WritableBufferedByteChannel channel = newBufferedChannel(out);
1175         EventChannelEncoder encoder = new EventChannelEncoder(channel);
1176 
1177         encoder.testOutput(new TestOutputReportEntry(stdErrln("msg"), NORMAL_RUN, 1L));
1178         channel.close();
1179 
1180         String expected = ":maven-surefire-event:\u0017:std-err-stream-new-line:"
1181                 + (char) 10 + ":normal-run:\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
1182                 + "\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:";
1183 
1184         assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
1185     }
1186 
1187     @Test
1188     public void testStdErrStreamEmptyMessageNullTestId() throws IOException {
1189         Stream out = Stream.newStream();
1190         WritableBufferedByteChannel channel = newBufferedChannel(out);
1191         EventChannelEncoder encoder = new EventChannelEncoder(channel);
1192 
1193         // This used to produce a BufferOverflowException; see SUREFIRE-2056.
1194         // In essence, we used to under-allocate for the encoding of a null test ID
1195         // (we used to allocate 0 byte instead of 1 byte).
1196         // The message needs to be empty in order to reproduce the bug,
1197         // otherwise we over-allocate for the test message
1198         // (for safety, due to unpredictability of the size of encoded text)
1199         // and this over-allocation ends up compensating the under-allocation for the null test id.
1200         encoder.testOutput(new TestOutputReportEntry(stdErr(""), NORMAL_RUN, null));
1201         channel.close();
1202 
1203         String expected = ":maven-surefire-event:\u000e:std-err-stream:"
1204                 + (char) 10 + ":normal-run:\u0000:"
1205                 + "\u0005:UTF-8:\u0000\u0000\u0000\u0000::";
1206 
1207         assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
1208     }
1209 
1210     @Test
1211     public void testStdErrStreamEmptyMessageNullRunMode() throws IOException {
1212         Stream out = Stream.newStream();
1213         WritableBufferedByteChannel channel = newBufferedChannel(out);
1214         EventChannelEncoder encoder = new EventChannelEncoder(channel);
1215 
1216         // This used to produce a BufferOverflowException; see SUREFIRE-2076.
1217         encoder.testOutput(new TestOutputReportEntry(stdErr(""), null, 1L));
1218         channel.close();
1219 
1220         String expected = ":maven-surefire-event:\u000e:std-err-stream:"
1221                 + (char) 0 + "::" // One byte for length and 1+1 bytes for the 2 delimiters (0 bytes for null runMode)
1222                 + "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
1223                 + "\u0005:UTF-8:\u0000\u0000\u0000\u0000::";
1224 
1225         assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
1226     }
1227 
1228     @Test
1229     @SuppressWarnings("checkstyle:innerassignment")
1230     public void shouldCountSameNumberOfSystemProperties() throws IOException {
1231         Stream stream = Stream.newStream();
1232         WritableBufferedByteChannel channel = newBufferedChannel(stream);
1233         EventChannelEncoder encoder = new EventChannelEncoder(channel);
1234 
1235         Map<String, String> sysProps = ObjectUtils.systemProps();
1236         encoder.encodeSystemProperties(sysProps, NORMAL_RUN, 1L);
1237         channel.close();
1238 
1239         for (Entry<String, String> entry : sysProps.entrySet()) {
1240             int[] k = toBytes(entry.getKey().length());
1241             int[] v = toBytes(entry.getValue() == null ? 1 : entry.getValue().getBytes(UTF_8).length);
1242             ByteArrayOutputStream expectedFrame = new ByteArrayOutputStream();
1243             expectedFrame.write(":maven-surefire-event:sys-prop:normal-run:UTF-8:".getBytes(UTF_8));
1244             expectedFrame.write(k[0]);
1245             expectedFrame.write(k[1]);
1246             expectedFrame.write(k[2]);
1247             expectedFrame.write(k[3]);
1248             expectedFrame.write(':');
1249             expectedFrame.write(v[0]);
1250             expectedFrame.write(v[1]);
1251             expectedFrame.write(v[2]);
1252             expectedFrame.write(v[3]);
1253             expectedFrame.write(':');
1254             expectedFrame.write((entry.getValue() == null ? "\u0000" : entry.getValue()).getBytes(UTF_8));
1255             expectedFrame.write(':');
1256             assertThat(stream.toByteArray()).contains(expectedFrame.toByteArray());
1257         }
1258     }
1259 
1260     @Test
1261     public void shouldHandleExit() {
1262         Stream out = Stream.newStream();
1263 
1264         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
1265         StackTraceWriter stackTraceWriter = mock(StackTraceWriter.class);
1266         when(stackTraceWriter.getThrowable()).thenReturn(new SafeThrowable("1"));
1267         when(stackTraceWriter.smartTrimmedStackTrace()).thenReturn("2");
1268         when(stackTraceWriter.writeTraceToString()).thenReturn("3");
1269         when(stackTraceWriter.writeTrimmedTraceToString()).thenReturn("4");
1270         encoder.sendExitError(stackTraceWriter, false);
1271 
1272         assertThat(new String(out.toByteArray(), UTF_8))
1273                 .startsWith(
1274                         ":maven-surefire-event:\u000e:jvm-exit-error:\u0005:UTF-8:\u0000\u0000\u0000\u0001:1:\u0000\u0000\u0000\u0001:2:\u0000\u0000\u0000\u0001:3:");
1275     }
1276 
1277     @Test
1278     public void shouldHandleExitWithTrimmedTrace() {
1279         Stream out = Stream.newStream();
1280 
1281         EventChannelEncoder encoder = new EventChannelEncoder(newBufferedChannel(out));
1282         StackTraceWriter stackTraceWriter = mock(StackTraceWriter.class);
1283         when(stackTraceWriter.getThrowable()).thenReturn(new SafeThrowable("1"));
1284         when(stackTraceWriter.smartTrimmedStackTrace()).thenReturn("2");
1285         when(stackTraceWriter.writeTraceToString()).thenReturn("3");
1286         when(stackTraceWriter.writeTrimmedTraceToString()).thenReturn("4");
1287         encoder.sendExitError(stackTraceWriter, true);
1288 
1289         assertThat(new String(out.toByteArray(), UTF_8))
1290                 .startsWith(
1291                         ":maven-surefire-event:\u000e:jvm-exit-error:\u0005:UTF-8:\u0000\u0000\u0000\u0001:1:\u0000\u0000\u0000\u0001:2:\u0000\u0000\u0000\u0001:4:");
1292     }
1293 
1294     @Test
1295     public void testInterruptHandling() throws IOException {
1296         Stream out = Stream.newStream();
1297         WritableBufferedByteChannel channel = newBufferedChannel(out);
1298         EventChannelEncoder encoder = new EventChannelEncoder(channel);
1299 
1300         Thread.currentThread().interrupt();
1301         try {
1302             encoder.testOutput(new TestOutputReportEntry(stdOut("msg"), NORMAL_RUN, 2L));
1303             channel.close();
1304         } finally {
1305             // Clear the interrupt and make sure it survived the invocation
1306             assertThat(Thread.interrupted()).isTrue();
1307         }
1308 
1309         assertThat(new String(out.toByteArray(), UTF_8))
1310                 .isEqualTo(":maven-surefire-event:\u000e:std-out-stream:"
1311                         + (char) 10 + ":normal-run:\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002"
1312                         + ":\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:");
1313     }
1314 
1315     private static class Stream extends PrintStream {
1316         private final ByteArrayOutputStream out;
1317 
1318         Stream(ByteArrayOutputStream out) {
1319             super(out, true);
1320             this.out = out;
1321         }
1322 
1323         byte[] toByteArray() {
1324             return out.toByteArray();
1325         }
1326 
1327         static Stream newStream() {
1328             return new Stream(new ByteArrayOutputStream());
1329         }
1330     }
1331 
1332     private static byte[] toArray(ByteBuffer buffer) {
1333         return copyOfRange(buffer.array(), buffer.arrayOffset(), buffer.arrayOffset() + buffer.remaining());
1334     }
1335 
1336     private static String toString(ByteBuffer frame) {
1337         ByteArrayOutputStream os = new ByteArrayOutputStream();
1338         ((Buffer) frame).flip();
1339         os.write(frame.array(), frame.arrayOffset() + ((Buffer) frame).position(), frame.remaining());
1340         return new String(os.toByteArray(), UTF_8);
1341     }
1342 
1343     private static int[] toBytes(int i) {
1344         int[] result = new int[4];
1345         result[0] = 0xff & (i >> 24);
1346         result[1] = 0xff & (i >> 16);
1347         result[2] = 0xff & (i >> 8);
1348         result[3] = 0xff & i;
1349         return result;
1350     }
1351 
1352     private static final class Channel implements WritableBufferedByteChannel {
1353         ByteBuffer src;
1354 
1355         @Override
1356         public void writeBuffered(ByteBuffer src) {
1357             this.src = src;
1358         }
1359 
1360         @Override
1361         public long countBufferOverflows() {
1362             return 0;
1363         }
1364 
1365         @Override
1366         public int write(ByteBuffer src) {
1367             this.src = src;
1368             return 0;
1369         }
1370 
1371         @Override
1372         public boolean isOpen() {
1373             return false;
1374         }
1375 
1376         @Override
1377         public void close() {}
1378     }
1379 }