View Javadoc
1   package org.apache.maven.surefire.booter;
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.junit.Rule;
23  import org.junit.Test;
24  import org.junit.rules.ExpectedException;
25  
26  import java.io.File;
27  import java.lang.management.ManagementFactory;
28  import java.util.regex.Matcher;
29  
30  import static java.util.concurrent.TimeUnit.SECONDS;
31  import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_UNIX;
32  import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
33  import static org.apache.maven.surefire.booter.ProcessInfo.unixProcessInfo;
34  import static org.apache.maven.surefire.booter.ProcessInfo.windowsProcessInfo;
35  import static org.fest.assertions.Assertions.assertThat;
36  import static org.hamcrest.CoreMatchers.is;
37  import static org.hamcrest.CoreMatchers.not;
38  import static org.hamcrest.CoreMatchers.notNullValue;
39  import static org.junit.Assert.fail;
40  import static org.junit.Assume.assumeThat;
41  import static org.junit.Assume.assumeTrue;
42  import static org.powermock.reflect.Whitebox.invokeMethod;
43  import static org.powermock.reflect.Whitebox.setInternalState;
44  
45  /**
46   * Testing {@link PpidChecker} on a platform.
47   *
48   * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
49   * @since 2.20.1
50   */
51  @SuppressWarnings( "checkstyle:magicnumber" )
52  public class PpidCheckerTest
53  {
54      @Rule
55      public final ExpectedException exceptions = ExpectedException.none();
56  
57      @Test
58      public void canExecuteUnixPs()
59      {
60          assumeTrue( IS_OS_UNIX );
61          assertThat( PpidChecker.canExecuteUnixPs() )
62                  .as( "Surefire should be tested on real box OS, e.g. Ubuntu or FreeBSD." )
63                  .isTrue();
64      }
65  
66      @Test
67      public void shouldHavePidAtBegin()
68      {
69          String expectedPid = ManagementFactory.getRuntimeMXBean().getName().split( "@" )[0].trim();
70  
71          PpidChecker checker = new PpidChecker( expectedPid );
72          ProcessInfo processInfo = IS_OS_UNIX ? checker.unix() : checker.windows();
73  
74          assertThat( processInfo )
75                  .isNotNull();
76  
77          assertThat( checker.canUse() )
78                  .isTrue();
79  
80          assertThat( checker.isProcessAlive() )
81                  .isTrue();
82  
83          assertThat( processInfo.getPID() )
84                  .isEqualTo( expectedPid );
85  
86          assertThat( processInfo.getTime() )
87                  .isNotNull();
88      }
89  
90      @Test
91      public void shouldHavePid() throws Exception
92      {
93          String expectedPid = ManagementFactory.getRuntimeMXBean().getName().split( "@" )[0].trim();
94          System.out.println( "java version " + System.getProperty( "java.version" ) + " expectedPid=" + expectedPid );
95  
96          PpidChecker checker = new PpidChecker( expectedPid );
97          setInternalState( checker, "parentProcessInfo",
98                  IS_OS_UNIX
99                          ? unixProcessInfo( expectedPid, 0L )
100                         : windowsProcessInfo( expectedPid, windowsProcessStartTime( checker ) ) );
101 
102         // the etime in Unix is measured in seconds. So let's wait 1s at least.
103         SECONDS.sleep( 1L );
104 
105         ProcessInfo processInfo = IS_OS_UNIX ? checker.unix() : checker.windows();
106 
107         assertThat( processInfo )
108                 .isNotNull();
109 
110         assertThat( checker.canUse() )
111                 .isTrue();
112 
113         assertThat( checker.isProcessAlive() )
114                 .isTrue();
115 
116         assertThat( processInfo.getPID() )
117                 .isEqualTo( expectedPid );
118 
119         assertThat( processInfo.getTime() )
120                 .isNotNull();
121 
122         assertThat( checker.toString() )
123                 .contains( "ppid=" + expectedPid )
124                 .contains( "stopped=false" )
125                 .contains( "invalid=false" )
126                 .contains( "error=false" );
127 
128         checker.destroyActiveCommands();
129         assertThat( checker.canUse() )
130                 .isFalse();
131         assertThat( (boolean) invokeMethod( checker, "isStopped" ) )
132                 .isTrue();
133     }
134 
135     @Test
136     public void shouldBeStopped()
137     {
138         PpidChecker checker = new PpidChecker( "0" );
139         checker.stop();
140 
141         assertThat( checker.canUse() )
142                 .isFalse();
143 
144         exceptions.expect( IllegalStateException.class );
145         exceptions.expectMessage( "irrelevant to call isProcessAlive()" );
146 
147         checker.isProcessAlive();
148 
149         fail( "this test should throw exception" );
150     }
151 
152     @Test
153     public void shouldNotFindSuchPID()
154     {
155         PpidChecker checker = new PpidChecker( "1000000" );
156         setInternalState( checker, "parentProcessInfo", ProcessInfo.ERR_PROCESS_INFO );
157 
158         assertThat( checker.canUse() )
159                 .isFalse();
160 
161         exceptions.expect( IllegalStateException.class );
162         exceptions.expectMessage( "irrelevant to call isProcessAlive()" );
163 
164         checker.isProcessAlive();
165 
166         fail( "this test should throw exception" );
167     }
168 
169     @Test
170     public void shouldNotBeAlive()
171     {
172         PpidChecker checker = new PpidChecker( "1000000" );
173 
174         assertThat( checker.canUse() )
175                 .isTrue();
176 
177         assertThat( checker.isProcessAlive() )
178                 .isFalse();
179     }
180 
181     @Test
182     public void shouldParseEtime()
183     {
184         Matcher m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "38 1234567890" );
185         assertThat( m.matches() )
186                 .isFalse();
187 
188         m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "05:38 1234567890" );
189         assertThat( m.matches() )
190                 .isTrue();
191         assertThat( PpidChecker.fromDays( m ) ).isEqualTo( 0L );
192         assertThat( PpidChecker.fromHours( m ) ).isEqualTo( 0L );
193         assertThat( PpidChecker.fromMinutes( m ) ).isEqualTo( 300L );
194         assertThat( PpidChecker.fromSeconds( m ) ).isEqualTo( 38L );
195         assertThat( PpidChecker.fromPID( m ) ).isEqualTo( "1234567890" );
196 
197         m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "00:05:38 1234567890" );
198         assertThat( m.matches() )
199                 .isTrue();
200         assertThat( PpidChecker.fromDays( m ) ).isEqualTo( 0L );
201         assertThat( PpidChecker.fromHours( m ) ).isEqualTo( 0L );
202         assertThat( PpidChecker.fromMinutes( m ) ).isEqualTo( 300L );
203         assertThat( PpidChecker.fromSeconds( m ) ).isEqualTo( 38L );
204         assertThat( PpidChecker.fromPID( m ) ).isEqualTo( "1234567890" );
205 
206         m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "01:05:38 1234567890" );
207         assertThat( m.matches() )
208                 .isTrue();
209         assertThat( PpidChecker.fromDays( m ) ).isEqualTo( 0L );
210         assertThat( PpidChecker.fromHours( m ) ).isEqualTo( 3600L );
211         assertThat( PpidChecker.fromMinutes( m ) ).isEqualTo( 300L );
212         assertThat( PpidChecker.fromSeconds( m ) ).isEqualTo( 38L );
213         assertThat( PpidChecker.fromPID( m ) ).isEqualTo( "1234567890" );
214 
215         m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "02-01:05:38 1234567890" );
216         assertThat( m.matches() )
217                 .isTrue();
218         assertThat( PpidChecker.fromDays( m ) ).isEqualTo( 2 * 24 * 3600L );
219         assertThat( PpidChecker.fromHours( m ) ).isEqualTo( 3600L );
220         assertThat( PpidChecker.fromMinutes( m ) ).isEqualTo( 300L );
221         assertThat( PpidChecker.fromSeconds( m ) ).isEqualTo( 38L );
222         assertThat( PpidChecker.fromPID( m ) ).isEqualTo( "1234567890" );
223 
224         m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "02-1:5:3 1234567890" );
225         assertThat( m.matches() )
226                 .isTrue();
227         assertThat( PpidChecker.fromDays( m ) ).isEqualTo( 2 * 24 * 3600L );
228         assertThat( PpidChecker.fromHours( m ) ).isEqualTo( 3600L );
229         assertThat( PpidChecker.fromMinutes( m ) ).isEqualTo( 300L );
230         assertThat( PpidChecker.fromSeconds( m ) ).isEqualTo( 3L );
231         assertThat( PpidChecker.fromPID( m ) ).isEqualTo( "1234567890" );
232     }
233 
234     @Test
235     public void shouldParseBusyboxHoursEtime()
236     {
237         Matcher m = PpidChecker.BUSYBOX_CMD_OUT_PATTERN.matcher( "38 1234567890" );
238         assertThat( m.matches() )
239                 .isFalse();
240 
241         m = PpidChecker.BUSYBOX_CMD_OUT_PATTERN.matcher( "05h38 1234567890" );
242         assertThat( m.matches() )
243                 .isTrue();
244         assertThat( PpidChecker.fromBusyboxHours( m ) ).isEqualTo( 3600 * 5L );
245         assertThat( PpidChecker.fromBusyboxMinutes( m ) ).isEqualTo( 60 * 38L );
246         assertThat( PpidChecker.fromBusyboxPID( m ) ).isEqualTo( "1234567890" );
247     }
248 
249     @Test
250     public void shouldHaveSystemPathToWmicOnWindows() throws Exception
251     {
252         assumeTrue( IS_OS_WINDOWS );
253         assumeThat( System.getenv( "SystemRoot" ), is( notNullValue() ) );
254         assumeThat( System.getenv( "SystemRoot" ), is( not( "" ) ) );
255         assumeTrue( new File( System.getenv( "SystemRoot" ), "System32\\Wbem" ).isDirectory() );
256         assumeTrue( new File( System.getenv( "SystemRoot" ), "System32\\Wbem\\wmic.exe" ).isFile() );
257         assertThat( (Boolean) invokeMethod( PpidChecker.class, "hasWmicStandardSystemPath" ) ).isTrue();
258         assertThat( new File( System.getenv( "SystemRoot" ), "System32\\Wbem\\wmic.exe" ) ).isFile();
259     }
260 
261     @Test
262     public void shouldBeTypeNull()
263     {
264         assertThat( ProcessCheckerType.toEnum( null ) )
265                 .isNull();
266 
267         assertThat( ProcessCheckerType.toEnum( "   " ) )
268                 .isNull();
269 
270         assertThat( ProcessCheckerType.isValid( null ) )
271                 .isTrue();
272     }
273 
274     @Test
275     public void shouldBeException()
276     {
277         exceptions.expect( IllegalArgumentException.class );
278         exceptions.expectMessage( "unknown process checker" );
279 
280         assertThat( ProcessCheckerType.toEnum( "anything else" ) )
281                 .isNull();
282     }
283 
284     @Test
285     public void shouldNotBeValid()
286     {
287         assertThat( ProcessCheckerType.isValid( "anything" ) )
288                 .isFalse();
289     }
290 
291     @Test
292     public void shouldBeTypePing()
293     {
294         assertThat( ProcessCheckerType.toEnum( "ping" ) )
295                 .isEqualTo( ProcessCheckerType.PING );
296 
297         assertThat( ProcessCheckerType.isValid( "ping" ) )
298                 .isTrue();
299 
300         assertThat( ProcessCheckerType.PING.getType() )
301                 .isEqualTo( "ping" );
302     }
303 
304     @Test
305     public void shouldBeTypeNative()
306     {
307         assertThat( ProcessCheckerType.toEnum( "native" ) )
308                 .isEqualTo( ProcessCheckerType.NATIVE );
309 
310         assertThat( ProcessCheckerType.isValid( "native" ) )
311                 .isTrue();
312 
313         assertThat( ProcessCheckerType.NATIVE.getType() )
314                 .isEqualTo( "native" );
315     }
316 
317     @Test
318     public void shouldBeTypeAll()
319     {
320         assertThat( ProcessCheckerType.toEnum( "all" ) )
321                 .isEqualTo( ProcessCheckerType.ALL );
322 
323         assertThat( ProcessCheckerType.isValid( "all" ) )
324                 .isTrue();
325 
326         assertThat( ProcessCheckerType.ALL.getType() )
327                 .isEqualTo( "all" );
328     }
329 
330     private static long windowsProcessStartTime( PpidChecker checker )
331     {
332         return (long) checker.windows().getTime();
333     }
334 }