1 package org.apache.maven.surefire.booter;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.surefire.testset.TestSetFailedException;
23 import org.junit.After;
24 import org.junit.Before;
25 import org.junit.Test;
26 import org.junit.runner.RunWith;
27
28 import java.io.ByteArrayOutputStream;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.PrintStream;
32 import java.nio.ByteBuffer;
33 import java.util.Iterator;
34 import java.util.NoSuchElementException;
35 import java.util.concurrent.BlockingQueue;
36 import java.util.concurrent.CountDownLatch;
37 import java.util.concurrent.ExecutionException;
38 import java.util.concurrent.FutureTask;
39 import java.util.concurrent.LinkedBlockingQueue;
40 import java.util.concurrent.TimeUnit;
41
42 import static java.nio.charset.StandardCharsets.ISO_8859_1;
43
44 import static org.junit.Assert.assertFalse;
45 import static org.junit.Assert.assertTrue;
46 import static org.junit.Assert.fail;
47 import static org.hamcrest.MatcherAssert.assertThat;
48 import static org.hamcrest.Matchers.is;
49 import static org.fest.assertions.Assertions.assertThat;
50
51
52
53
54
55
56
57 @RunWith( NewClassLoaderRunner.class )
58 public class CommandReaderTest
59 {
60 private final BlockingQueue<Byte> blockingStream = new LinkedBlockingQueue<>();
61 private InputStream realInputStream;
62 private CommandReader reader;
63
64 static class A {
65 }
66
67 static class B {
68 }
69
70 static class C {
71 }
72
73 static class D {
74 }
75
76 @Before
77 public void init()
78 {
79 Thread.interrupted();
80 realInputStream = System.in;
81 addTestToPipeline( getClass().getName() );
82 System.setIn( new SystemInputStream() );
83 reader = CommandReader.getReader();
84 }
85
86 @After
87 public void deinit()
88 {
89 reader.stop();
90 System.setIn( realInputStream );
91 }
92
93 @Test
94 public void readJustOneClass()
95 {
96 Iterator<String> it = reader.getIterableClasses( nul() ).iterator();
97 assertTrue( it.hasNext() );
98 assertThat( it.next(), is( getClass().getName() ) );
99 reader.stop();
100 assertFalse( it.hasNext() );
101 try
102 {
103 it.next();
104 fail();
105 }
106 catch ( NoSuchElementException e )
107 {
108
109 }
110 }
111
112 @Test
113 public void manyClasses()
114 {
115 Iterator<String> it1 = reader.getIterableClasses( nul() ).iterator();
116 assertThat( it1.next(), is( getClass().getName() ) );
117 addTestToPipeline( A.class.getName() );
118 assertThat( it1.next(), is( A.class.getName() ) );
119 addTestToPipeline( B.class.getName() );
120 assertThat( it1.next(), is( B.class.getName() ) );
121 addTestToPipeline( C.class.getName() );
122 assertThat( it1.next(), is( C.class.getName() ) );
123 addEndOfPipeline();
124 addTestToPipeline( D.class.getName() );
125 assertFalse( it1.hasNext() );
126 }
127
128 @Test
129 public void twoIterators() throws Exception
130 {
131 Iterator<String> it1 = reader.getIterableClasses( nul() ).iterator();
132
133 assertThat( it1.next(), is( getClass().getName() ) );
134 addTestToPipeline( A.class.getName() );
135 assertThat( it1.next(), is( A.class.getName() ) );
136 addTestToPipeline( B.class.getName() );
137
138 TimeUnit.MILLISECONDS.sleep( 200 );
139
140 Iterator<String> it2 = reader.iterated();
141
142 assertThat( it1.next(), is( B.class.getName() ) );
143 addTestToPipeline( C.class.getName() );
144
145 assertThat( it2.hasNext(), is( true ) );
146 assertThat( it2.next(), is( getClass().getName() ) );
147 assertThat( it2.hasNext(), is( true ) );
148 assertThat( it2.next(), is( A.class.getName() ) );
149 assertThat( it2 ).isEmpty();
150
151 assertThat( it1.next(), is( C.class.getName() ) );
152 addEndOfPipeline();
153 assertThat( it1 ).isEmpty();
154 }
155
156 @Test( expected = NoSuchElementException.class )
157 public void stopBeforeReadInThread()
158 throws Throwable
159 {
160 Runnable runnable = new Runnable()
161 {
162 @Override
163 public void run()
164 {
165 Iterator<String> it = reader.getIterableClasses( nul() ).iterator();
166 assertThat( it.next(), is( CommandReaderTest.class.getName() ) );
167 }
168 };
169 FutureTask<Object> futureTask = new FutureTask<>( runnable, null );
170 Thread t = new Thread( futureTask );
171 reader.stop();
172 t.start();
173 try
174 {
175 futureTask.get();
176 }
177 catch ( ExecutionException e )
178 {
179 throw e.getCause();
180 }
181 }
182
183 @Test
184 public void readTwoClassesInThread()
185 throws Throwable
186 {
187 final CountDownLatch counter = new CountDownLatch( 1 );
188 Runnable runnable = new Runnable()
189 {
190 @Override
191 public void run()
192 {
193 Iterator<String> it = reader.getIterableClasses( nul() ).iterator();
194 assertThat( it.next(), is( CommandReaderTest.class.getName() ) );
195 counter.countDown();
196 assertThat( it.next(), is( PropertiesWrapperTest.class.getName() ) );
197 }
198 };
199 FutureTask<Object> futureTask = new FutureTask<>( runnable, null );
200 Thread t = new Thread( futureTask );
201 t.start();
202 counter.await();
203 addTestToPipeline( PropertiesWrapperTest.class.getName() );
204 try
205 {
206 futureTask.get();
207 }
208 catch ( ExecutionException e )
209 {
210 throw e.getCause();
211 }
212 }
213
214 @Test( timeout = 15000 )
215 public void shouldAwaitReaderUp()
216 throws TestSetFailedException
217 {
218 assertTrue( reader.awaitStarted() );
219 reader.stop();
220 assertFalse( reader.awaitStarted() );
221 }
222
223 private class SystemInputStream
224 extends InputStream
225 {
226 @Override
227 public int read()
228 throws IOException
229 {
230 try
231 {
232 return CommandReaderTest.this.blockingStream.take();
233 }
234 catch ( InterruptedException e )
235 {
236 throw new IOException( e );
237 }
238 }
239 }
240
241 private void addTestToPipeline( String cls )
242 {
243 byte[] clazz = cls.getBytes( ISO_8859_1 );
244 ByteBuffer buffer = ByteBuffer.allocate( 8 + clazz.length )
245 .putInt( MasterProcessCommand.RUN_CLASS.getId() )
246 .putInt( clazz.length )
247 .put( clazz );
248 buffer.rewind();
249 for ( ; buffer.hasRemaining(); )
250 {
251 blockingStream.add( buffer.get() );
252 }
253 }
254
255 private void addEndOfPipeline()
256 {
257 ByteBuffer buffer = ByteBuffer.allocate( 8 )
258 .putInt( MasterProcessCommand.TEST_SET_FINISHED.getId() )
259 .putInt( 0 );
260 buffer.rewind();
261 for ( ; buffer.hasRemaining(); )
262 {
263 blockingStream.add( buffer.get() );
264 }
265 }
266
267 private static PrintStream nul()
268 {
269 return new PrintStream( new ByteArrayOutputStream() );
270 }
271 }