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.its.jiras;
20  
21  import java.util.Iterator;
22  
23  import org.apache.maven.surefire.its.fixture.OutputValidator;
24  import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
25  import org.apache.maven.surefire.its.fixture.SurefireLauncher;
26  import org.junit.jupiter.params.ParameterizedTest;
27  import org.junit.jupiter.params.provider.MethodSource;
28  
29  import static java.util.Arrays.asList;
30  import static java.util.concurrent.TimeUnit.SECONDS;
31  import static org.apache.maven.surefire.its.jiras.Surefire1295AttributeJvmCrashesToTestsIT.ForkMode.DEFAULT;
32  import static org.apache.maven.surefire.its.jiras.Surefire1295AttributeJvmCrashesToTestsIT.ForkMode.ONE_FORK_NO_REUSE;
33  import static org.apache.maven.surefire.its.jiras.Surefire1295AttributeJvmCrashesToTestsIT.ForkMode.ONE_FORK_REUSE;
34  import static org.assertj.core.api.Assertions.assertThat;
35  import static org.junit.jupiter.api.Assertions.fail;
36  import static org.junit.jupiter.api.Assumptions.assumeTrue;
37  
38  /**
39   * https://issues.apache.org/jira/browse/SUREFIRE-1295
40   * https://github.com/apache/maven-surefire/pull/136
41   *
42   * @author michaeltandy
43   * @since 2.20
44   */
45  public class Surefire1295AttributeJvmCrashesToTestsIT extends SurefireJUnit4IntegrationTestCase {
46      private static final int ONE_FORK_REUSE_THREAD_COUNT = 1;
47  
48      /**
49       *
50       */
51      public enum ForkMode {
52          DEFAULT,
53          ONE_FORK_NO_REUSE,
54          ONE_FORK_REUSE
55      }
56  
57      static Iterable<Object[]> parameters() {
58          return asList(new Object[][] {
59              //                exit() does not stop all Threads immediately,
60              //                see https://github.com/michaeltandy/crashjvm/issues/1
61              {"exit", DEFAULT},
62              {"exit", ONE_FORK_NO_REUSE},
63              {"exit", ONE_FORK_REUSE},
64              {"abort", DEFAULT},
65              {"abort", ONE_FORK_NO_REUSE},
66              {"abort", ONE_FORK_REUSE},
67              {"segfault", DEFAULT},
68              {"segfault", ONE_FORK_NO_REUSE},
69              {"segfault", ONE_FORK_REUSE}
70          });
71      }
72  
73      @ParameterizedTest
74      @MethodSource("parameters")
75      void test(String crashStyle, ForkMode forkStyle) throws Exception {
76          SurefireLauncher launcher = unpack("crash-during-test", "_" + crashStyle + "_" + forkStyle.ordinal())
77                  .setForkJvm();
78  
79          switch (forkStyle) {
80              case DEFAULT:
81                  break;
82              case ONE_FORK_NO_REUSE:
83                  launcher.forkCount(1).reuseForks(false);
84                  break;
85              case ONE_FORK_REUSE:
86                  launcher.forkPerThread(ONE_FORK_REUSE_THREAD_COUNT).threadCount(ONE_FORK_REUSE_THREAD_COUNT);
87                  break;
88              default:
89                  fail();
90          }
91  
92          checkCrash(launcher.addGoal("-DcrashType=" + crashStyle));
93      }
94  
95      private static void checkCrash(SurefireLauncher launcher) throws Exception {
96          OutputValidator validator = launcher.maven().withFailure().executeTest();
97  
98          boolean osAndArchSupported = true;
99          for (Iterator<String> it = validator.loadLogLines().iterator(); it.hasNext(); ) {
100             String line = it.next();
101             if (line.contains("java.lang.RuntimeException: Unrecognised OS")
102                     || line.contains("java.lang.RuntimeException: Unrecognised arch")) {
103                 osAndArchSupported = false;
104                 break;
105             }
106         }
107 
108         assumeTrue(
109                 osAndArchSupported,
110                 "crashjvm does not support " + System.getProperty("os.name") + "/" + System.getProperty("os.arch"));
111 
112         validator
113                 .verifyTextInLog("The forked VM terminated without properly saying "
114                         + "goodbye. VM crash or System.exit called?")
115                 .verifyTextInLog("Crashed tests:");
116 
117         // Cannot flush log.txt stream because it is consumed internally by Verifier.
118         // Waiting for the stream to become flushed on disk.
119         SECONDS.sleep(1L);
120 
121         for (Iterator<String> it = validator.loadLogLines().iterator(); it.hasNext(); ) {
122             String line = it.next();
123             if (line.contains("Crashed tests:")) {
124                 line = it.next();
125                 if (it.hasNext()) {
126                     assertThat(line).contains("junit44.environment.Test1CrashedTest");
127                 } else {
128                     fail("Could not find any line after 'Crashed tests:'.");
129                 }
130             }
131         }
132     }
133 }