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