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.plugin.surefire.extensions;
20  
21  import java.io.ByteArrayOutputStream;
22  import java.io.IOException;
23  import java.nio.Buffer;
24  import java.nio.ByteBuffer;
25  import java.nio.channels.WritableByteChannel;
26  import java.util.Iterator;
27  
28  import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
29  import org.apache.maven.surefire.api.booter.Command;
30  import org.apache.maven.surefire.extensions.CommandReader;
31  import org.junit.After;
32  import org.junit.Before;
33  import org.junit.Test;
34  import org.mockito.invocation.InvocationOnMock;
35  import org.mockito.stubbing.Answer;
36  
37  import static java.util.Arrays.asList;
38  import static org.apache.maven.surefire.api.booter.Command.TEST_SET_FINISHED;
39  import static org.apache.maven.surefire.api.booter.MasterProcessCommand.RUN_CLASS;
40  import static org.assertj.core.api.Assertions.assertThat;
41  import static org.mockito.ArgumentMatchers.any;
42  import static org.mockito.Mockito.mock;
43  import static org.mockito.Mockito.times;
44  import static org.mockito.Mockito.verify;
45  import static org.mockito.Mockito.verifyZeroInteractions;
46  import static org.mockito.Mockito.when;
47  
48  /**
49   * Tests for {@link StreamFeeder}.
50   */
51  public class StreamFeederTest {
52      private final ByteArrayOutputStream out = new ByteArrayOutputStream();
53      private final WritableByteChannel channel = mock(WritableByteChannel.class);
54      private final CommandReader commandReader = mock(CommandReader.class);
55      private StreamFeeder streamFeeder;
56  
57      @Before
58      public void setup() throws IOException {
59          final Iterator<Command> it =
60                  asList(new Command(RUN_CLASS, "pkg.ATest"), TEST_SET_FINISHED).iterator();
61          when(commandReader.readNextCommand()).thenAnswer(new Answer<Command>() {
62              @Override
63              public Command answer(InvocationOnMock invocation) {
64                  return it.hasNext() ? it.next() : null;
65              }
66          });
67      }
68  
69      @After
70      public void close() throws IOException {
71          if (streamFeeder != null) {
72              streamFeeder.disable();
73              streamFeeder.close();
74          }
75      }
76  
77      @Test
78      public void shouldEncodeCommandToStream() throws Exception {
79          when(channel.write(any(ByteBuffer.class))).thenAnswer(new Answer<Object>() {
80              @Override
81              public Object answer(InvocationOnMock invocation) throws IOException {
82                  ByteBuffer bb = invocation.getArgument(0);
83                  ((Buffer) bb).flip();
84                  out.write(bb.array(), 0, ((Buffer) bb).limit());
85                  return ((Buffer) bb).limit();
86              }
87          });
88  
89          ConsoleLogger logger = mock(ConsoleLogger.class);
90          streamFeeder = new StreamFeeder("t", channel, commandReader, logger);
91          streamFeeder.start();
92  
93          streamFeeder.join();
94          String commands = out.toString();
95  
96          String expected = new StringBuilder()
97                  .append(":maven-surefire-command:")
98                  .append((char) 13)
99                  .append(":run-testclass:")
100                 .append((char) 5)
101                 .append(":UTF-8:")
102                 .append((char) 0)
103                 .append((char) 0)
104                 .append((char) 0)
105                 .append((char) 9)
106                 .append(":")
107                 .append("pkg.ATest")
108                 .append(":")
109                 .append(":maven-surefire-command:")
110                 .append((char) 16)
111                 .append(":testset-finished:")
112                 .toString();
113 
114         assertThat(commands).isEqualTo(expected);
115 
116         verify(channel, times(1)).close();
117 
118         assertThat(streamFeeder.getException()).isNull();
119 
120         verifyZeroInteractions(logger);
121     }
122 
123     @Test
124     public void shouldFailThread() throws Exception {
125         when(channel.write(any(ByteBuffer.class))).thenAnswer(new Answer<Object>() {
126             @Override
127             public Object answer(InvocationOnMock invocation) throws IOException {
128                 throw new IOException();
129             }
130         });
131 
132         ConsoleLogger logger = mock(ConsoleLogger.class);
133         streamFeeder = new StreamFeeder("t", channel, commandReader, logger);
134         streamFeeder.start();
135 
136         streamFeeder.join();
137 
138         assertThat(out.size()).isZero();
139 
140         verify(channel, times(1)).close();
141 
142         assertThat(streamFeeder.getException()).isNotNull().isInstanceOf(IOException.class);
143 
144         verifyZeroInteractions(logger);
145     }
146 }