View Javadoc
1   package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.surefire.api.booter.Command;
23  import org.apache.maven.surefire.api.booter.MasterProcessCommand;
24  import org.apache.maven.surefire.booter.spi.LegacyMasterProcessChannelDecoder;
25  import org.apache.maven.surefire.api.booter.MasterProcessChannelDecoder;
26  import org.junit.Rule;
27  import org.junit.Test;
28  import org.junit.rules.ExpectedException;
29  
30  import java.io.IOException;
31  import java.io.InputStream;
32  import java.util.Iterator;
33  import java.util.NoSuchElementException;
34  
35  import static java.nio.channels.Channels.newChannel;
36  import static org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestLessInputStream.TestLessInputStreamBuilder;
37  import static org.apache.maven.surefire.api.booter.Command.SKIP_SINCE_NEXT_TEST;
38  import static org.apache.maven.surefire.api.booter.MasterProcessCommand.SHUTDOWN;
39  import static org.apache.maven.surefire.api.booter.Shutdown.EXIT;
40  import static org.apache.maven.surefire.api.booter.Shutdown.KILL;
41  import static org.apache.maven.plugin.surefire.extensions.StreamFeeder.encode;
42  import static org.hamcrest.MatcherAssert.assertThat;
43  import static org.hamcrest.Matchers.is;
44  import static org.hamcrest.Matchers.notNullValue;
45  import static org.junit.Assert.assertFalse;
46  import static org.junit.Assert.assertTrue;
47  
48  /**
49   * Testing cached and immediate commands in {@link TestLessInputStream}.
50   *
51   * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
52   * @since 2.19
53   */
54  public class TestLessInputStreamBuilderTest
55  {
56      @Rule
57      public final ExpectedException e = ExpectedException.none();
58  
59      @Test
60      public void cachableCommandsShouldBeIterableWithStillOpenIterator()
61      {
62          TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
63          TestLessInputStream is = builder.build();
64          Iterator<Command> iterator = builder.getIterableCachable().iterator();
65  
66          assertFalse( iterator.hasNext() );
67  
68          builder.getCachableCommands().skipSinceNextTest();
69          assertTrue( iterator.hasNext() );
70          assertThat( iterator.next(), is( SKIP_SINCE_NEXT_TEST ) );
71  
72          assertFalse( iterator.hasNext() );
73  
74          builder.getCachableCommands().shutdown( KILL );
75          assertTrue( iterator.hasNext() );
76          assertThat( iterator.next(), is( new Command( SHUTDOWN, "KILL" ) ) );
77  
78          builder.removeStream( is );
79      }
80  
81      @Test
82      public void immediateCommands()
83          throws IOException
84      {
85          TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
86          TestLessInputStream is = builder.build();
87          assertThat( is.availablePermits(), is( 0 ) );
88          is.noop();
89          assertThat( is.availablePermits(), is( 1 ) );
90          is.beforeNextCommand();
91          assertThat( is.availablePermits(), is( 0 ) );
92          assertThat( is.nextCommand(), is( Command.NOOP ) );
93          assertThat( is.availablePermits(), is( 0 ) );
94          e.expect( NoSuchElementException.class );
95          is.nextCommand();
96      }
97  
98      @Test
99      public void combinedCommands()
100         throws IOException
101     {
102         TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
103         TestLessInputStream is = builder.build();
104         assertThat( is.availablePermits(), is( 0 ) );
105         builder.getCachableCommands().skipSinceNextTest();
106         is.noop();
107         assertThat( is.availablePermits(), is( 2 ) );
108         is.beforeNextCommand();
109         assertThat( is.availablePermits(), is( 1 ) );
110         assertThat( is.nextCommand(), is( Command.NOOP ) );
111         assertThat( is.availablePermits(), is( 1 ) );
112         builder.getCachableCommands().skipSinceNextTest();
113         assertThat( is.availablePermits(), is( 1 ) );
114         builder.getImmediateCommands().shutdown( EXIT );
115         assertThat( is.availablePermits(), is( 2 ) );
116         is.beforeNextCommand();
117         assertThat( is.nextCommand().getCommandType(), is( SHUTDOWN ) );
118         assertThat( is.availablePermits(), is( 1 ) );
119         is.beforeNextCommand();
120         assertThat( is.nextCommand(), is( SKIP_SINCE_NEXT_TEST ) );
121         assertThat( is.availablePermits(), is( 0 ) );
122         builder.getImmediateCommands().noop();
123         assertThat( is.availablePermits(), is( 1 ) );
124         builder.getCachableCommands().shutdown( EXIT );
125         builder.getCachableCommands().shutdown( EXIT );
126         assertThat( is.availablePermits(), is( 2 ) );
127         is.beforeNextCommand();
128         assertThat( is.nextCommand(), is( Command.NOOP ) );
129         assertThat( is.availablePermits(), is( 1 ) );
130         is.beforeNextCommand();
131         assertThat( is.nextCommand().getCommandType(), is( SHUTDOWN ) );
132         assertThat( is.availablePermits(), is( 0 ) );
133         e.expect( NoSuchElementException.class );
134         is.nextCommand();
135     }
136 
137     @Test
138     public void shouldDecodeTwoCommands()
139             throws IOException
140     {
141         TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
142         final TestLessInputStream pluginIs = builder.build();
143         InputStream is = new InputStream()
144         {
145             private byte[] buffer;
146             private int idx;
147 
148             @Override
149             public int read() throws IOException
150             {
151                 if ( buffer == null )
152                 {
153                     idx = 0;
154                     Command cmd = pluginIs.readNextCommand();
155                     if ( cmd != null )
156                     {
157                         MasterProcessCommand cmdType = cmd.getCommandType();
158                         buffer = cmdType.hasDataType() ? encode( cmdType, cmd.getData() ) : encode( cmdType );
159                     }
160                 }
161 
162                 if ( buffer != null )
163                 {
164                     byte b = buffer[idx++];
165                     if ( idx == buffer.length )
166                     {
167                         buffer = null;
168                         idx = 0;
169                     }
170                     return b;
171                 }
172                 throw new IOException();
173             }
174         };
175         MasterProcessChannelDecoder decoder = new LegacyMasterProcessChannelDecoder( newChannel( is ) );
176         builder.getImmediateCommands().shutdown( KILL );
177         builder.getImmediateCommands().noop();
178         Command bye = decoder.decode();
179         assertThat( bye, is( notNullValue() ) );
180         assertThat( bye.getCommandType(), is( SHUTDOWN ) );
181         assertThat( bye.getData(), is( KILL.name() ) );
182         Command noop = decoder.decode();
183         assertThat( noop, is( notNullValue() ) );
184         assertThat( noop.getCommandType(), is( MasterProcessCommand.NOOP ) );
185     }
186 
187     @Test( expected = UnsupportedOperationException.class )
188     public void shouldThrowUnsupportedException1()
189     {
190         TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
191         builder.getImmediateCommands().provideNewTest();
192     }
193 
194     @Test( expected = UnsupportedOperationException.class )
195     public void shouldThrowUnsupportedException2()
196     {
197         TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
198         builder.getImmediateCommands().skipSinceNextTest();
199     }
200 
201     @Test( expected = UnsupportedOperationException.class )
202     public void shouldThrowUnsupportedException3()
203     {
204         TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
205         builder.getImmediateCommands().acknowledgeByeEventReceived();
206     }
207 
208     @Test( expected = UnsupportedOperationException.class )
209     public void shouldThrowUnsupportedException4()
210     {
211         TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
212         builder.getCachableCommands().acknowledgeByeEventReceived();
213     }
214 
215     @Test( expected = UnsupportedOperationException.class )
216     public void shouldThrowUnsupportedException5()
217     {
218         TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
219         builder.getCachableCommands().provideNewTest();
220     }
221 
222     @Test( expected = UnsupportedOperationException.class )
223     public void shouldThrowUnsupportedException6()
224     {
225         TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
226         builder.getCachableCommands().noop();
227     }
228 }