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