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.plugin.surefire.booterclient;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.Collections;
24  import java.util.List;
25  
26  import org.apache.maven.plugin.surefire.SurefireProperties;
27  import org.apache.maven.surefire.api.cli.CommandLineOption;
28  import org.apache.maven.surefire.api.report.ReporterConfiguration;
29  import org.apache.maven.surefire.api.testset.DirectoryScannerParameters;
30  import org.apache.maven.surefire.api.testset.RunOrderParameters;
31  import org.apache.maven.surefire.api.testset.TestArtifactInfo;
32  import org.apache.maven.surefire.api.testset.TestListResolver;
33  import org.apache.maven.surefire.api.testset.TestRequest;
34  import org.apache.maven.surefire.api.util.RunOrder;
35  import org.apache.maven.surefire.booter.AbstractPathConfiguration;
36  import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
37  import org.apache.maven.surefire.booter.KeyValueSource;
38  import org.apache.maven.surefire.booter.ProcessCheckerType;
39  import org.apache.maven.surefire.booter.ProviderConfiguration;
40  import org.apache.maven.surefire.booter.StartupConfiguration;
41  
42  import static org.apache.maven.plugin.surefire.SurefireHelper.replaceForkThreadsInPath;
43  import static org.apache.maven.surefire.booter.AbstractPathConfiguration.CHILD_DELEGATION;
44  import static org.apache.maven.surefire.booter.AbstractPathConfiguration.CLASSPATH;
45  import static org.apache.maven.surefire.booter.AbstractPathConfiguration.ENABLE_ASSERTIONS;
46  import static org.apache.maven.surefire.booter.AbstractPathConfiguration.SUREFIRE_CLASSPATH;
47  import static org.apache.maven.surefire.booter.BooterConstants.EXCLUDES_PROPERTY_PREFIX;
48  import static org.apache.maven.surefire.booter.BooterConstants.FAIL_FAST_COUNT;
49  import static org.apache.maven.surefire.booter.BooterConstants.FORKTESTSET;
50  import static org.apache.maven.surefire.booter.BooterConstants.FORKTESTSET_PREFER_TESTS_FROM_IN_STREAM;
51  import static org.apache.maven.surefire.booter.BooterConstants.FORK_NODE_CONNECTION_STRING;
52  import static org.apache.maven.surefire.booter.BooterConstants.FORK_NUMBER;
53  import static org.apache.maven.surefire.booter.BooterConstants.INCLUDES_PROPERTY_PREFIX;
54  import static org.apache.maven.surefire.booter.BooterConstants.ISTRIMSTACKTRACE;
55  import static org.apache.maven.surefire.booter.BooterConstants.MAIN_CLI_OPTIONS;
56  import static org.apache.maven.surefire.booter.BooterConstants.PLUGIN_PID;
57  import static org.apache.maven.surefire.booter.BooterConstants.PROCESS_CHECKER;
58  import static org.apache.maven.surefire.booter.BooterConstants.PROVIDER_CONFIGURATION;
59  import static org.apache.maven.surefire.booter.BooterConstants.REPORTSDIRECTORY;
60  import static org.apache.maven.surefire.booter.BooterConstants.REQUESTEDTEST;
61  import static org.apache.maven.surefire.booter.BooterConstants.RERUN_FAILING_TESTS_COUNT;
62  import static org.apache.maven.surefire.booter.BooterConstants.RUN_ORDER;
63  import static org.apache.maven.surefire.booter.BooterConstants.RUN_ORDER_RANDOM_SEED;
64  import static org.apache.maven.surefire.booter.BooterConstants.RUN_STATISTICS_FILE;
65  import static org.apache.maven.surefire.booter.BooterConstants.SHUTDOWN;
66  import static org.apache.maven.surefire.booter.BooterConstants.SOURCE_DIRECTORY;
67  import static org.apache.maven.surefire.booter.BooterConstants.SPECIFIC_TEST_PROPERTY_PREFIX;
68  import static org.apache.maven.surefire.booter.BooterConstants.SYSTEM_EXIT_TIMEOUT;
69  import static org.apache.maven.surefire.booter.BooterConstants.TESTARTIFACT_CLASSIFIER;
70  import static org.apache.maven.surefire.booter.BooterConstants.TESTARTIFACT_VERSION;
71  import static org.apache.maven.surefire.booter.BooterConstants.TEST_CLASSES_DIRECTORY;
72  import static org.apache.maven.surefire.booter.BooterConstants.TEST_SUITE_XML_FILES;
73  import static org.apache.maven.surefire.booter.BooterConstants.USEMANIFESTONLYJAR;
74  import static org.apache.maven.surefire.booter.BooterConstants.USESYSTEMCLASSLOADER;
75  import static org.apache.maven.surefire.booter.SystemPropertyManager.writePropertiesFile;
76  
77  /**
78   * Knows how to serialize and deserialize the booter configuration.
79   * <br>
80   * The internal serialization format is through a properties file. The long-term goal of this
81   * class is not to expose this implementation information to its clients. This still leaks somewhat,
82   * and there are some cases where properties are being accessed as "Properties" instead of
83   * more representative domain objects.
84   * <br>
85   *
86   * @author Jason van Zyl
87   * @author Emmanuel Venisse
88   * @author Brett Porter
89   * @author Dan Fabulich
90   * @author Kristian Rosenvold
91   */
92  class BooterSerializer {
93      private final ForkConfiguration forkConfiguration;
94  
95      BooterSerializer(ForkConfiguration forkConfiguration) {
96          this.forkConfiguration = forkConfiguration;
97      }
98  
99      /**
100      * Does not modify sourceProperties
101      */
102     File serialize(
103             KeyValueSource sourceProperties,
104             ProviderConfiguration providerConfiguration,
105             StartupConfiguration startupConfiguration,
106             Object testSet,
107             boolean readTestsFromInStream,
108             Long pid,
109             int forkNumber,
110             String forkNodeConnectionString)
111             throws IOException {
112         SurefireProperties properties = new SurefireProperties(sourceProperties);
113         properties.setNullableProperty(FORK_NODE_CONNECTION_STRING, forkNodeConnectionString);
114         properties.setProperty(PLUGIN_PID, pid);
115 
116         AbstractPathConfiguration cp = startupConfiguration.getClasspathConfiguration();
117         properties.setClasspath(CLASSPATH, cp.getTestClasspath());
118         properties.setClasspath(SUREFIRE_CLASSPATH, cp.getProviderClasspath());
119         properties.setProperty(ENABLE_ASSERTIONS, toString(cp.isEnableAssertions()));
120         properties.setProperty(CHILD_DELEGATION, toString(cp.isChildDelegation()));
121         ProcessCheckerType processChecker = startupConfiguration.getProcessChecker();
122         properties.setNullableProperty(PROCESS_CHECKER, processChecker == null ? null : processChecker.getType());
123 
124         TestArtifactInfo testNg = providerConfiguration.getTestArtifact();
125         if (testNg != null) {
126             properties.setProperty(TESTARTIFACT_VERSION, testNg.getVersion());
127             properties.setNullableProperty(TESTARTIFACT_CLASSIFIER, testNg.getClassifier());
128         }
129 
130         properties.setProperty(FORKTESTSET_PREFER_TESTS_FROM_IN_STREAM, readTestsFromInStream);
131         properties.setNullableProperty(FORKTESTSET, getTypeEncoded(testSet));
132 
133         TestRequest testSuiteDefinition = providerConfiguration.getTestSuiteDefinition();
134         if (testSuiteDefinition != null) {
135             properties.setProperty(SOURCE_DIRECTORY, testSuiteDefinition.getTestSourceDirectory());
136             if (testSet instanceof File) {
137                 properties.addList(Collections.singletonList((File) testSet), TEST_SUITE_XML_FILES);
138             } else {
139                 properties.addList(testSuiteDefinition.getSuiteXmlFiles(), TEST_SUITE_XML_FILES);
140             }
141             TestListResolver testFilter = testSuiteDefinition.getTestListResolver();
142             properties.setProperty(REQUESTEDTEST, testFilter == null ? "" : testFilter.getPluginParameterTest());
143             int rerunFailingTestsCount = testSuiteDefinition.getRerunFailingTestsCount();
144             properties.setNullableProperty(RERUN_FAILING_TESTS_COUNT, toString(rerunFailingTestsCount));
145         }
146 
147         DirectoryScannerParameters directoryScannerParameters = providerConfiguration.getDirScannerParams();
148         if (directoryScannerParameters != null) {
149             properties.addList(directoryScannerParameters.getIncludes(), INCLUDES_PROPERTY_PREFIX);
150             properties.addList(directoryScannerParameters.getExcludes(), EXCLUDES_PROPERTY_PREFIX);
151             properties.addList(directoryScannerParameters.getSpecificTests(), SPECIFIC_TEST_PROPERTY_PREFIX);
152             properties.setProperty(TEST_CLASSES_DIRECTORY, directoryScannerParameters.getTestClassesDirectory());
153         }
154 
155         final RunOrderParameters runOrderParameters = providerConfiguration.getRunOrderParameters();
156         if (runOrderParameters != null) {
157             properties.setProperty(RUN_ORDER, RunOrder.asString(runOrderParameters.getRunOrder()));
158             properties.setProperty(RUN_STATISTICS_FILE, runOrderParameters.getRunStatisticsFile());
159             properties.setProperty(RUN_ORDER_RANDOM_SEED, runOrderParameters.getRunOrderRandomSeed());
160         }
161 
162         ReporterConfiguration reporterConfiguration = providerConfiguration.getReporterConfiguration();
163         boolean rep = reporterConfiguration.isTrimStackTrace();
164         File reportsDirectory = replaceForkThreadsInPath(reporterConfiguration.getReportsDirectory(), forkNumber);
165         properties.setProperty(FORK_NUMBER, forkNumber);
166         properties.setProperty(ISTRIMSTACKTRACE, rep);
167         properties.setProperty(REPORTSDIRECTORY, reportsDirectory);
168         ClassLoaderConfiguration classLoaderConfig = startupConfiguration.getClassLoaderConfiguration();
169         properties.setProperty(USESYSTEMCLASSLOADER, toString(classLoaderConfig.isUseSystemClassLoader()));
170         properties.setProperty(USEMANIFESTONLYJAR, toString(classLoaderConfig.isUseManifestOnlyJar()));
171         properties.setProperty(PROVIDER_CONFIGURATION, startupConfiguration.getProviderClassName());
172         properties.setProperty(FAIL_FAST_COUNT, toString(providerConfiguration.getSkipAfterFailureCount()));
173         properties.setProperty(SHUTDOWN, providerConfiguration.getShutdown().name());
174         List<CommandLineOption> mainCliOptions = providerConfiguration.getMainCliOptions();
175         if (mainCliOptions != null) {
176             properties.addList(mainCliOptions, MAIN_CLI_OPTIONS);
177         }
178         properties.setNullableProperty(SYSTEM_EXIT_TIMEOUT, toString(providerConfiguration.getSystemExitTimeout()));
179 
180         File surefireTmpDir = forkConfiguration.getTempDirectory();
181         boolean debug = forkConfiguration.isDebug();
182         return writePropertiesFile(properties, surefireTmpDir, "surefire", debug);
183     }
184 
185     private static String getTypeEncoded(Object value) {
186         if (value == null) {
187             return null;
188         }
189         String valueToUse = value instanceof Class ? ((Class<?>) value).getName() : value.toString();
190         return value.getClass().getName() + "|" + valueToUse;
191     }
192 
193     private static String toString(Object o) {
194         return String.valueOf(o);
195     }
196 }