1   package com.atlassian.maven.plugins.amps;
2   
3   import java.io.File;
4   import java.util.Collections;
5   import java.util.HashMap;
6   import java.util.HashSet;
7   import java.util.List;
8   import java.util.Map;
9   import java.util.Set;
10  
11  import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
12  import org.apache.maven.plugin.MojoExecutionException;
13  import org.apache.maven.project.MavenProject;
14  import org.jfrog.maven.annomojo.annotations.MojoComponent;
15  import org.jfrog.maven.annomojo.annotations.MojoGoal;
16  import org.jfrog.maven.annomojo.annotations.MojoParameter;
17  import org.jfrog.maven.annomojo.annotations.MojoRequiresDependencyResolution;
18  
19  import com.atlassian.maven.plugins.amps.product.ProductHandler;
20  
21  /**
22   * Run the integration tests against the webapp
23   */
24  @MojoGoal("integration-test")
25  @MojoRequiresDependencyResolution("test")
26  public class IntegrationTestMojo extends AbstractTestGroupsHandlerMojo
27  {
28      /**
29       * Pattern for to use to find integration tests.  Only used if no test groups are defined.
30       */
31      @MojoParameter(expression = "${functional.test.pattern}")
32      private String functionalTestPattern = "it/**";
33  
34      /**
35       * The directory containing generated test classes of the project being tested.
36       */
37      @MojoParameter(expression = "${project.build.testOutputDirectory}", required = true)
38      private File testClassesDirectory;
39  
40      /**
41       * A comma separated list of test groups to run.  If not specified, all
42       * test groups are run.
43       */
44      @MojoParameter(expression = "${testGroups}")
45      private String configuredTestGroupsToRun;
46  
47      /**
48       * Whether the reference application will not be started or not
49       */
50      @MojoParameter(expression = "${no.webapp}", defaultValue = "false")
51      private boolean noWebapp = false;
52  
53      @MojoComponent
54      private ArtifactHandlerManager artifactHandlerManager;
55  
56      @MojoParameter(expression="${maven.test.skip}", defaultValue = "false")
57      private boolean testsSkip = false;
58  
59      @MojoParameter(expression="${skipTests}", defaultValue = "false")
60      private boolean skipTests = false;
61  
62      /**
63       * Skip the integration tests along with any product startups
64       */
65      @MojoParameter(expression="${skipITs}", defaultValue = "false")
66      private boolean skipITs = false;
67  
68      protected void doExecute() throws MojoExecutionException
69      {
70          final MavenProject project = getMavenContext().getProject();
71  
72          // workaround for MNG-1682/MNG-2426: force maven to install artifact using the "jar" handler
73          project.getArtifact().setArtifactHandler(artifactHandlerManager.getArtifactHandler("jar"));
74  
75          if (!new File(testClassesDirectory, "it").exists())
76          {
77              getLog().info("No integration tests found");
78              return;
79          }
80  
81          if (skipTests || testsSkip || skipITs)
82          {
83              getLog().info("Integration tests skipped");
84              return;
85          }
86  
87          final MavenGoals goals = getMavenGoals();
88          final String pluginJar = targetDirectory.getAbsolutePath() + "/" + finalName + ".jar";
89  
90          final Set<String> configuredTestGroupIds = getTestGroupIds();
91          if (configuredTestGroupIds.isEmpty())
92          {
93              runTestsForTestGroup(NO_TEST_GROUP, goals, pluginJar, copy(systemPropertyVariables));
94          }
95          else if (configuredTestGroupsToRun != null)
96          {
97              String[] testGroupIdsToRun = configuredTestGroupsToRun.split(",");
98  
99              // now run the tests
100             for (String testGroupId : testGroupIdsToRun)
101             {
102                 if (!configuredTestGroupIds.contains(testGroupId))
103                 {
104                     getLog().warn("Test group " + testGroupId + " does not exist");
105                 }
106                 else
107                 {
108                     runTestsForTestGroup(testGroupId, goals, pluginJar, copy(systemPropertyVariables));
109                 }
110             }
111         }
112         else
113         {
114             for (String testGroupId : configuredTestGroupIds)
115             {
116                 runTestsForTestGroup(testGroupId, goals, pluginJar, copy(systemPropertyVariables));
117             }
118         }
119     }
120 
121     private Map<String,Object> copy(Map<String,Object> systemPropertyVariables)
122     {
123         return new HashMap<String,Object>(systemPropertyVariables);
124     }
125 
126     /**
127      * Returns product-specific properties to pass to the container during
128      * integration testing. Default implementation does nothing.
129      * @param product the {@code Product} object to use
130      * @return a {@code Map} of properties to add to the system properties passed
131      * to the container
132      */
133     protected Map<String, String> getProductFunctionalTestProperties(Product product)
134     {
135         return Collections.emptyMap();
136     }
137 
138     private Set<String> getTestGroupIds() throws MojoExecutionException
139     {
140         Set<String> ids = new HashSet<String>();
141 
142         //ids.addAll(ProductHandlerFactory.getIds());
143         for (TestGroup group : getTestGroups())
144         {
145             ids.add(group.getId());
146         }
147 
148         return ids;
149     }
150 
151 
152 
153     private void runTestsForTestGroup(String testGroupId, MavenGoals goals, String pluginJar, Map<String,Object> systemProperties) throws MojoExecutionException
154     {
155         List<String> includes = getIncludesForTestGroup(testGroupId);
156         List<String> excludes = getExcludesForTestGroup(testGroupId);
157 
158         List<ProductExecution> executionsDeclaredInPom = getTestGroupProductExecutions(testGroupId);
159         List<ProductExecution> productExecutions = includeStudioDependentProducts(executionsDeclaredInPom, goals);
160         setParallelMode(productExecutions);
161 
162         // Install the plugin in each product and start it
163         for (ProductExecution productExecution : productExecutions)
164         {
165             ProductHandler productHandler = productExecution.getProductHandler();
166             Product product = productExecution.getProduct();
167             if (product.isInstallPlugin() == null)
168             {
169                 product.setInstallPlugin(installPlugin);
170             }
171 
172             int actualHttpPort = 0;
173             if (!noWebapp)
174             {
175                 actualHttpPort = productHandler.start(product);
176             }
177 
178             if (productExecutions.size() == 1)
179             {
180                 systemProperties.put("http.port", String.valueOf(actualHttpPort));
181                 systemProperties.put("context.path", product.getContextPath());
182             }
183 
184             String baseUrl = MavenGoals.getBaseUrl(product.getServer(), actualHttpPort, product.getContextPath());
185             // hard coded system properties...
186             systemProperties.put("http." + product.getInstanceId() + ".port", String.valueOf(actualHttpPort));
187             systemProperties.put("context." + product.getInstanceId() + ".path", product.getContextPath());
188             systemProperties.put("http." + product.getInstanceId() + ".url", MavenGoals.getBaseUrl(product.getServer(), actualHttpPort, product.getContextPath()));
189 
190             systemProperties.put("baseurl." + product.getInstanceId(), baseUrl);
191             systemProperties.put("plugin.jar", pluginJar);
192 
193             // yes, this means you only get one base url if multiple products, but that is what selenium would expect
194             if (!systemProperties.containsKey("baseurl"))
195             {
196                 systemProperties.put("baseurl", baseUrl);
197             }
198 
199             systemProperties.put("homedir." + product.getInstanceId(), productHandler.getHomeDirectory(product).getAbsolutePath());
200             if (!systemProperties.containsKey("homedir"))
201             {
202                 systemProperties.put("homedir", productHandler.getHomeDirectory(product).getAbsolutePath());
203             }
204 
205             systemProperties.putAll(getProductFunctionalTestProperties(product));
206         }
207         systemProperties.put("testGroup", testGroupId);
208         systemProperties.putAll(getTestGroupSystemProperties(testGroupId));
209 
210         if (parallel)
211         {
212             waitForProducts(productExecutions, true);
213         }
214 
215         // Actually run the tests
216         goals.runTests("group-" + testGroupId, getClassifier(testGroupId), includes, excludes, systemProperties, targetDirectory);
217 
218         // Shut all products down
219         if (!noWebapp)
220         {
221             stopProducts(productExecutions);
222         }
223     }
224 
225     /**
226      * Returns the classifier of the test group. Unless specified, this is "tomcat6x", the default container.
227      */
228     private String getClassifier(String testGroupId)
229     {
230         for (TestGroup group : getTestGroups())
231         {
232             if (group.getId().equals(testGroupId))
233             {
234                 if (group.getClassifier() != null)
235                 {
236                     return group.getClassifier();
237                 }
238                 else
239                 {
240                     return DEFAULT_CONTAINER;
241                 }
242             }
243         }
244         return DEFAULT_CONTAINER;
245     }
246 
247 
248     private Map<String, String> getTestGroupSystemProperties(String testGroupId)
249     {
250         if (NO_TEST_GROUP.equals(testGroupId))
251         {
252             return Collections.emptyMap();
253         }
254 
255         for (TestGroup group : getTestGroups())
256         {
257             if (group.getId().equals(testGroupId))
258             {
259                 return group.getSystemProperties();
260             }
261         }
262         return Collections.emptyMap();
263     }
264 
265     private List<String> getIncludesForTestGroup(String testGroupId)
266     {
267         if (NO_TEST_GROUP.equals(testGroupId))
268         {
269             return Collections.singletonList(functionalTestPattern);
270         }
271         else
272         {
273             for (TestGroup group : getTestGroups())
274             {
275                 if (group.getId().equals(testGroupId))
276                 {
277                     return group.getIncludes();
278                 }
279             }
280         }
281         return Collections.singletonList(functionalTestPattern);
282     }
283 
284 
285     private List<String> getExcludesForTestGroup(String testGroupId)
286     {
287         if (NO_TEST_GROUP.equals(testGroupId))
288         {
289             return Collections.emptyList();
290         }
291         else
292         {
293             for (TestGroup group : getTestGroups())
294             {
295                 if (group.getId().equals(testGroupId))
296                 {
297                     return group.getExcludes();
298                 }
299             }
300         }
301         return Collections.emptyList();
302     }
303 }