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;
20  
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.InputStream;
24  import java.lang.management.ManagementFactory;
25  import java.lang.management.ThreadInfo;
26  import java.lang.management.ThreadMXBean;
27  import java.nio.charset.StandardCharsets;
28  import java.nio.file.Files;
29  import java.util.ArrayList;
30  import java.util.Collection;
31  import java.util.concurrent.ScheduledExecutorService;
32  import java.util.concurrent.ScheduledThreadPoolExecutor;
33  import java.util.concurrent.Semaphore;
34  
35  import org.apache.maven.surefire.api.util.SureFireFileManager;
36  import org.apache.maven.surefire.shared.io.FileUtils;
37  import org.junit.Test;
38  
39  import static java.nio.charset.StandardCharsets.UTF_8;
40  import static org.assertj.core.api.Assertions.assertThat;
41  import static org.powermock.reflect.Whitebox.invokeMethod;
42  
43  /**
44   * Tests for {@link ForkedBooter}.
45   */
46  @SuppressWarnings("checkstyle:magicnumber")
47  public class ForkedBooterTest {
48      @Test
49      public void shouldGenerateThreadDump() throws Exception {
50          Collection<String> threadNames = new ArrayList<>();
51          ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
52          for (ThreadInfo threadInfo : threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds(), 100)) {
53              threadNames.add(threadInfo.getThreadName());
54          }
55  
56          String dump = invokeMethod(ForkedBooter.class, "generateThreadDump");
57  
58          for (String threadName : threadNames) {
59              assertThat(dump).contains("\"" + threadName + "\"");
60          }
61  
62          assertThat(dump).contains("   java.lang.Thread.State: ").contains("        at ");
63      }
64  
65      @Test
66      public void shouldFindCurrentProcessName() throws Exception {
67          String process = ManagementFactory.getRuntimeMXBean().getName();
68          String expected = invokeMethod(ForkedBooter.class, "getProcessName");
69          assertThat(process).isEqualTo(expected);
70      }
71  
72      @Test
73      public void shouldNotBeDebugMode() throws Exception {
74          boolean expected = invokeMethod(ForkedBooter.class, "isDebugging");
75          assertThat(expected).isFalse();
76      }
77  
78      @Test
79      public void shouldReadSurefireProperties() throws Exception {
80          File tmpDir = Files.createTempDirectory("ForkedBooterTest.1.").toFile();
81  
82          try {
83              try (InputStream is = invokeMethod(
84                      ForkedBooter.class,
85                      "createSurefirePropertiesIfFileExists",
86                      tmpDir.getCanonicalPath(),
87                      "surefire.properties")) {
88                  assertThat(is).isNull();
89              }
90  
91              File props = new File(tmpDir, "surefire.properties");
92  
93              assertThat(props.createNewFile()).isTrue();
94  
95              FileUtils.write(props, "key=value", UTF_8);
96  
97              try (InputStream is2 = invokeMethod(
98                      ForkedBooter.class,
99                      "createSurefirePropertiesIfFileExists",
100                     tmpDir.getCanonicalPath(),
101                     "surefire.properties")) {
102                 assertThat(is2).isNotNull().isInstanceOf(FileInputStream.class);
103 
104                 byte[] propsContent = new byte[20];
105                 int length = is2.read(propsContent);
106 
107                 assertThat(new String(propsContent, 0, length)).isEqualTo("key=value");
108             }
109         } finally {
110             FileUtils.deleteDirectory(tmpDir);
111         }
112     }
113 
114     @Test
115     public void shouldCreateScheduler() throws Exception {
116         ScheduledExecutorService scheduler = null;
117         try {
118             scheduler = invokeMethod(ForkedBooter.class, "createScheduler", "thread name");
119             assertThat(scheduler).isNotNull();
120         } finally {
121             if (scheduler != null) {
122                 scheduler.shutdownNow();
123             }
124         }
125     }
126 
127     @Test(timeout = 10_000)
128     public void testBarrier1() throws Exception {
129         Semaphore semaphore = new Semaphore(2);
130         boolean acquiredOnePermit = invokeMethod(ForkedBooter.class, "acquireOnePermit", semaphore);
131 
132         assertThat(acquiredOnePermit).isTrue();
133         assertThat(semaphore.availablePermits()).isEqualTo(1);
134     }
135 
136     @Test
137     public void testBarrier2() throws Exception {
138         Semaphore semaphore = new Semaphore(0);
139         Thread.currentThread().interrupt();
140         try {
141             boolean acquiredOnePermit = invokeMethod(ForkedBooter.class, "acquireOnePermit", semaphore);
142 
143             assertThat(acquiredOnePermit).isFalse();
144             assertThat(semaphore.availablePermits()).isEqualTo(0);
145         } finally {
146             assertThat(Thread.interrupted()).isFalse();
147         }
148     }
149 
150     @Test
151     public void testScheduler() throws Exception {
152         ScheduledThreadPoolExecutor executor = invokeMethod(ForkedBooter.class, "createScheduler", "thread name");
153         executor.shutdown();
154         assertThat(executor.getCorePoolSize()).isEqualTo(1);
155         assertThat(executor.getMaximumPoolSize()).isEqualTo(1);
156     }
157 
158     @Test
159     public void testIsDebug() throws Exception {
160         boolean isDebug = invokeMethod(ForkedBooter.class, "isDebugging");
161         assertThat(isDebug).isFalse();
162     }
163 
164     @Test
165     public void testPropsNotExist() throws Exception {
166         String target = System.getProperty("user.dir");
167         String file = "not exists";
168         InputStream is = invokeMethod(ForkedBooter.class, "createSurefirePropertiesIfFileExists", target, file);
169         assertThat(is).isNull();
170     }
171 
172     @Test
173     public void testPropsExist() throws Exception {
174         File props = SureFireFileManager.createTempFile("surefire", ".properties");
175         String target = props.getParent();
176         String file = props.getName();
177         FileUtils.write(props, "Hi", StandardCharsets.US_ASCII);
178         try (InputStream is = invokeMethod(ForkedBooter.class, "createSurefirePropertiesIfFileExists", target, file)) {
179             assertThat(is).isNotNull();
180             byte[] data = new byte[5];
181             int bytes = is.read(data);
182             assertThat(bytes).isEqualTo(2);
183             assertThat(data[0]).isEqualTo((byte) 'H');
184             assertThat(data[1]).isEqualTo((byte) 'i');
185         }
186     }
187 
188     @Test
189     public void testThreadDump() throws Exception {
190         String threads = invokeMethod(ForkedBooter.class, "generateThreadDump");
191         assertThat(threads).isNotNull();
192         assertThat(threads).contains("\"main\"").contains("java.lang.Thread.State: RUNNABLE");
193     }
194 }