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         
161         // Install the plugin in each product and start it
162         for (ProductExecution productExecution : productExecutions)
163         {
164             ProductHandler productHandler = productExecution.getProductHandler();
165             Product product = productExecution.getProduct();
166             if (product.isInstallPlugin() == null)
167             {
168                 product.setInstallPlugin(installPlugin);
169             }
170 
171             int actualHttpPort = 0;
172             if (!noWebapp)
173             {
174                 actualHttpPort = productHandler.start(product);
175             }
176 
177             if (productExecutions.size() == 1)
178             {
179                 systemProperties.put("http.port", String.valueOf(actualHttpPort));
180                 systemProperties.put("context.path", product.getContextPath());
181             }
182 
183             String baseUrl = MavenGoals.getBaseUrl(product.getServer(), actualHttpPort, product.getContextPath());
184             // hard coded system properties...
185             systemProperties.put("http." + product.getInstanceId() + ".port", String.valueOf(actualHttpPort));
186             systemProperties.put("context." + product.getInstanceId() + ".path", product.getContextPath());
187             systemProperties.put("http." + product.getInstanceId() + ".url", MavenGoals.getBaseUrl(product.getServer(), actualHttpPort, product.getContextPath()));
188 
189             systemProperties.put("baseurl." + product.getInstanceId(), baseUrl);
190             systemProperties.put("plugin.jar", pluginJar);
191 
192             // yes, this means you only get one base url if multiple products, but that is what selenium would expect
193             if (!systemProperties.containsKey("baseurl"))
194             {
195                 systemProperties.put("baseurl", baseUrl);
196             }
197 
198             systemProperties.put("homedir." + product.getInstanceId(), productHandler.getHomeDirectory(product).getAbsolutePath());
199             if (!systemProperties.containsKey("homedir"))
200             {
201                 systemProperties.put("homedir", productHandler.getHomeDirectory(product).getAbsolutePath());
202             }
203 
204             systemProperties.putAll(getProductFunctionalTestProperties(product));
205         }
206         systemProperties.put("testGroup", testGroupId);
207         systemProperties.putAll(getTestGroupSystemProperties(testGroupId));
208 
209         // Actually run the tests
210         goals.runTests("group-" + testGroupId, containerId, includes, excludes, systemProperties, targetDirectory);
211 
212         // Shut all products down
213         for (ProductExecution productExecution : productExecutions)
214         {
215             ProductHandler productHandler = productExecution.getProductHandler();
216             Product product = productExecution.getProduct();
217             if (!noWebapp)
218             {
219                 productHandler.stop(product);
220             }
221         }
222     }
223 
224     private Map<String, String> getTestGroupSystemProperties(String testGroupId)
225     {
226         if (NO_TEST_GROUP.equals(testGroupId))
227         {
228             return Collections.emptyMap();
229         }
230 
231         for (TestGroup group : getTestGroups())
232         {
233             if (group.getId().equals(testGroupId))
234             {
235                 return group.getSystemProperties();
236             }
237         }
238         return Collections.emptyMap();
239     }
240 
241     private List<String> getIncludesForTestGroup(String testGroupId)
242     {
243         if (NO_TEST_GROUP.equals(testGroupId))
244         {
245             return Collections.singletonList(functionalTestPattern);
246         }
247         else
248         {
249             for (TestGroup group : getTestGroups())
250             {
251                 if (group.getId().equals(testGroupId))
252                 {
253                     return group.getIncludes();
254                 }
255             }
256         }
257         return Collections.singletonList(functionalTestPattern);
258     }
259 
260 
261     private List<String> getExcludesForTestGroup(String testGroupId)
262     {
263         if (NO_TEST_GROUP.equals(testGroupId))
264         {
265             return Collections.emptyList();
266         }
267         else
268         {
269             for (TestGroup group : getTestGroups())
270             {
271                 if (group.getId().equals(testGroupId))
272                 {
273                     return group.getExcludes();
274                 }
275             }
276         }
277         return Collections.emptyList();
278     }
279 }