Option to performance profile SingleFeatureTest
[odlparent.git] / features-test / src / main / java / org / opendaylight / odlparent / featuretest / SingleFeatureTest.java
index 9d60d096a166ca051c223f33c688ea84165f426d..54e4726eda74919212c76bc3fb7fff3fb0fc2d51 100644 (file)
@@ -5,27 +5,38 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
+
 package org.opendaylight.odlparent.featuretest;
 
 import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP;
 import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP;
 import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP;
 import static org.ops4j.pax.exam.CoreOptions.maven;
+import static org.ops4j.pax.exam.CoreOptions.when;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
-//import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel;
 
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
 import javax.inject.Inject;
+
 import org.apache.karaf.features.Feature;
 import org.apache.karaf.features.FeaturesService;
 import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.internal.model.Features;
+import org.apache.karaf.features.internal.model.JaxbUtil;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -34,17 +45,23 @@ import org.ops4j.pax.exam.Configuration;
 import org.ops4j.pax.exam.CoreOptions;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
+import org.ops4j.pax.exam.options.extra.VMOption;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 @RunWith(PerRepoTestRunner.class)
 public class SingleFeatureTest {
+
     private static final String MAVEN_REPO_LOCAL = "maven.repo.local";
     private static final String ORG_OPS4J_PAX_URL_MVN_LOCAL_REPOSITORY = "org.ops4j.pax.url.mvn.localRepository";
     private static final String ORG_OPS4J_PAX_URL_MVN_REPOSITORIES = "org.ops4j.pax.url.mvn.repositories";
     private static final String ETC_ORG_OPS4J_PAX_URL_MVN_CFG = "etc/org.ops4j.pax.url.mvn.cfg";
-    private static final String LOG4J_LOGGER_ORG_OPENDAYLIGHT_YANGTOOLS_FEATURETEST = "log4j.logger.org.opendaylight.odlparent.featuretest";
+    private static final String ETC_ORG_OPS4J_PAX_LOGGING_CFG = "etc/org.ops4j.pax.logging.cfg";
+    private static final String KEEP_UNPACK_DIRECTORY_PROP = "karaf.keep.unpack";
+    private static final String PROFILE_PROP = "karaf.featureTest.profile";
+
+    private static final String LOG4J_LOGGER_ORG_OPENDAYLIGHT_YANGTOOLS_FEATURETEST =
+            "log4j.logger.org.opendaylight.odlparent.featuretest";
     private static final Logger LOG = LoggerFactory.getLogger(SingleFeatureTest.class);
 
     /*
@@ -53,9 +70,8 @@ public class SingleFeatureTest {
     private static final String ORG_OPS4J_PAX_LOGGING_CFG = "etc/org.ops4j.pax.logging.cfg";
 
     /*
-     * Default values for karaf distro version, type, groupId, and artifactId
+     * Default values for karaf distro type, groupId, and artifactId
      */
-    private static final String KARAF_DISTRO_VERSION = "3.0.2";
     private static final String KARAF_DISTRO_TYPE = "zip";
     private static final String KARAF_DISTRO_ARTIFACTID = "apache-karaf";
     private static final String KARAF_DISTRO_GROUPID = "org.apache.karaf";
@@ -68,34 +84,58 @@ public class SingleFeatureTest {
     private static final String KARAF_DISTRO_ARTIFACTID_PROP = "karaf.distro.artifactId";
     private static final String KARAF_DISTRO_GROUPID_PROP = "karaf.distro.groupId";
 
+    /**
+     * Property file used to store the Karaf distribution version.
+     */
+    private static final String PROPERTIES_FILENAME = "singlefeaturetest.properties";
 
     /**
-     * List of karaf 3.0.2 default maven repositories with snapshot repositories excluded.
-     *
-     * Unfortunately this must be hard-coded since declarative model which uses Options,
+     * <p>List of Karaf 3.0.4 default maven repositories with snapshot repositories excluded.</p>
+     * <p>Unfortunately this must be hard-coded since declarative model which uses Options,
      * does not allow us to read value, parse it (properties has allways
      * problems with lists) and construct replacement string which does
-     * not contains snapshots.
-     *
+     * not contains snapshots.</p>
+     * <p>When updating Karaf, check this against org.ops4j.pax.url.mvn.cfg in the Karaf distribution.</p>
      */
-    private static final String EXTERNAL_DEFAULT_REPOSITORIES = "http://repo1.maven.org/maven2@id=central, " +
-    "http://repository.springsource.com/maven/bundles/release@id=spring.ebr.release, " +
-    "http://repository.springsource.com/maven/bundles/external@id=spring.ebr.external, " +
-    "http://zodiac.springsource.com/maven/bundles/release@id=gemini ";
+    private static final String EXTERNAL_DEFAULT_REPOSITORIES = "http://repo1.maven.org/maven2@id=central, "
+            + "http://repository.springsource.com/maven/bundles/release@id=spring.ebr.release, "
+            + "http://repository.springsource.com/maven/bundles/external@id=spring.ebr.external, "
+            + "http://zodiac.springsource.com/maven/bundles/release@id=gemini ";
 
 
-   @Inject
-   private FeaturesService featuresService;
+    @Inject
+    private FeaturesService featuresService;
 
+    private String karafVersion;
+    private String karafDistroVersion;
+
+    /**
+     * Returns the required configuration.
+     *
+     * @return The Pax Exam configuration.
+     * @throws IOException if an error occurs.
+     */
     @Configuration
     public Option[] config() throws IOException {
-       return new Option[] {
-             getKarafDistroOption(),
-             keepRuntimeFolder(),
-             configureConsole().ignoreLocalConsole(),
-             logLevel(LogLevel.WARN),
-             mvnLocalRepoOption(),
-             editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,LOG4J_LOGGER_ORG_OPENDAYLIGHT_YANGTOOLS_FEATURETEST,LogLevel.INFO.name()),
+        return new Option[] {
+            // TODO: Find a way to inherit memory limits from Maven options.
+            new VMOption("-Xmx2g"),
+            new VMOption("-XX:MaxPermSize=512m"),
+            when(Boolean.getBoolean(PROFILE_PROP)).useOptions(
+                new VMOption("-XX:+UnlockCommercialFeatures"),
+                new VMOption("-XX:+FlightRecorder"),
+                new VMOption("-XX:FlightRecorderOptions=defaultrecording=true,dumponexit=true,dumponexitpath="
+                               + getNewJFRFile())
+            ),
+            getKarafDistroOption(),
+            when(Boolean.getBoolean(KEEP_UNPACK_DIRECTORY_PROP)).useOptions(keepRuntimeFolder()),
+            configureConsole().ignoreLocalConsole(),
+            logLevel(LogLevel.WARN),
+            mvnLocalRepoOption(),
+            standardKarafFeatures(),
+            editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG, LOG4J_LOGGER_ORG_OPENDAYLIGHT_YANGTOOLS_FEATURETEST,
+                    LogLevel.INFO.name()),
+            editConfigurationFilePut(ETC_ORG_OPS4J_PAX_LOGGING_CFG, "log4j.rootLogger", "INFO, stdout, osgi:*"),
              /*
               *
               * Disables external snapshot repositories.
@@ -119,56 +159,110 @@ public class SingleFeatureTest {
               *
               *
               */
-             disableExternalSnapshotRepositories(),
-             CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP).value(System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP)),
-             CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP).value(System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP)),
-             CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP).value(System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP)),
-       };
+            disableExternalSnapshotRepositories(),
+            CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP).value(
+                    System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP)),
+            CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP).value(
+                    System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP)),
+            CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP).value(
+                    System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP)),
+        };
+    }
+
+    private String getNewJFRFile() throws IOException {
+        return File.createTempFile("SingleFeatureTest-Karaf-JavaFlightRecorder", ".jfr").getAbsolutePath();
+    }
+
+    private Option standardKarafFeatures() throws IOException {
+        String url = maven().groupId("org.apache.karaf.features").artifactId("standard").classifier("features").type(
+                "xml").version(getKarafVersion()).getURL();
+        try {
+            Features features = JaxbUtil.unmarshal(new URL(url).openStream(), false);
+            List<String> featureNames = new ArrayList<>();
+            for (Feature f : features.getFeature()) {
+                featureNames.add(f.getName());
+            }
+
+            return features(url, featureNames.toArray(new String[featureNames.size()]));
+        } catch (IOException e) {
+            throw new IOException("Could not obtain features from URL: " + url, e);
+        }
+    }
+
+    private String getKarafVersion() {
+        if (karafVersion == null) {
+            // We use a properties file to retrieve ${karaf.version}, instead of .versionAsInProject()
+            // This avoids forcing all users to depend on Karaf in their POMs
+            Properties singleFeatureTestProps = new Properties();
+            try (InputStream singleFeatureTestInputStream = Thread.currentThread().getContextClassLoader()
+                    .getResourceAsStream(PROPERTIES_FILENAME)) {
+                singleFeatureTestProps.load(singleFeatureTestInputStream);
+            } catch (IOException e) {
+                LOG.error("Unable to load {} to determine the Karaf version", PROPERTIES_FILENAME, e);
+            }
+            karafVersion = singleFeatureTestProps.getProperty(KARAF_DISTRO_VERSION_PROP);
+
+            LOG.info("Retrieved karafVersion {} from properties file {}", karafVersion, PROPERTIES_FILENAME);
+        } else {
+            LOG.info("Retrieved karafVersion {} from system property {}", karafVersion, KARAF_DISTRO_VERSION_PROP);
+        }
+
+        return karafVersion;
+    }
+
+    private String getKarafDistroVersion() {
+        if (karafDistroVersion == null) {
+            karafDistroVersion = System.getProperty(KARAF_DISTRO_VERSION_PROP);
+            if (karafDistroVersion == null) {
+                karafDistroVersion = getKarafVersion();
+            } else {
+                LOG.info("Retrieved karafDistroVersion {} from system property {}", karafVersion,
+                        KARAF_DISTRO_VERSION_PROP);
+            }
+        }
+
+        return karafDistroVersion;
     }
 
     /**
-     *
      * Disables snapshot repositories, which are enabled by default in karaf distribution.
      *
-     *
-     *
      * @return Edit Configuration option which removes external snapshot repositories.
      */
     private static Option disableExternalSnapshotRepositories() {
-        return editConfigurationFilePut(ETC_ORG_OPS4J_PAX_URL_MVN_CFG, ORG_OPS4J_PAX_URL_MVN_REPOSITORIES,EXTERNAL_DEFAULT_REPOSITORIES);
+        return editConfigurationFilePut(ETC_ORG_OPS4J_PAX_URL_MVN_CFG, ORG_OPS4J_PAX_URL_MVN_REPOSITORIES,
+                EXTERNAL_DEFAULT_REPOSITORIES);
     }
 
     protected Option mvnLocalRepoOption() {
         String mvnRepoLocal = System.getProperty(MAVEN_REPO_LOCAL, "");
-        LOG.info("mvnLocalRepo \"{}\"",mvnRepoLocal);
-        Option option =
-                editConfigurationFilePut(ETC_ORG_OPS4J_PAX_URL_MVN_CFG,ORG_OPS4J_PAX_URL_MVN_LOCAL_REPOSITORY,mvnRepoLocal);
-        return option;
+        LOG.info("mvnLocalRepo \"{}\"", mvnRepoLocal);
+        return editConfigurationFilePut(ETC_ORG_OPS4J_PAX_URL_MVN_CFG, ORG_OPS4J_PAX_URL_MVN_LOCAL_REPOSITORY,
+                mvnRepoLocal);
     }
 
     protected Option getKarafDistroOption() {
-        String groupId = System.getProperty(KARAF_DISTRO_GROUPID_PROP,KARAF_DISTRO_GROUPID);
-        String artifactId = System.getProperty(KARAF_DISTRO_ARTIFACTID_PROP,KARAF_DISTRO_ARTIFACTID);
-        String version = System.getProperty(KARAF_DISTRO_VERSION_PROP,KARAF_DISTRO_VERSION);
-        String type = System.getProperty(KARAF_DISTRO_TYPE_PROP,KARAF_DISTRO_TYPE);
-        LOG.info("Using karaf distro {} {} {} {}",groupId,artifactId,version,type);
+        String groupId = System.getProperty(KARAF_DISTRO_GROUPID_PROP, KARAF_DISTRO_GROUPID);
+        String artifactId = System.getProperty(KARAF_DISTRO_ARTIFACTID_PROP, KARAF_DISTRO_ARTIFACTID);
+        String type = System.getProperty(KARAF_DISTRO_TYPE_PROP, KARAF_DISTRO_TYPE);
+        LOG.info("Using karaf distro {} {} {} {}", groupId, artifactId, getKarafDistroVersion(), type);
         return karafDistributionConfiguration()
                 .frameworkUrl(
                         maven()
                                 .groupId(groupId)
                                 .artifactId(artifactId)
                                 .type(type)
-                                .version(version))
-               .name("OpenDaylight")
-               .unpackDirectory(new File("target/pax"))
-               .useDeployFolder(false);
+                                .version(getKarafDistroVersion()))
+                .name("OpenDaylight")
+                .unpackDirectory(new File("target/pax"))
+                .useDeployFolder(false);
     }
 
-    private URI getRepoURI() throws URISyntaxException {
+    private static URI getRepoUri() throws URISyntaxException {
         return new URI(getProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP));
     }
 
-    private String getFeatureName() {
+    private static String getFeatureName() {
         return getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP);
     }
 
@@ -176,38 +270,47 @@ public class SingleFeatureTest {
         return getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP);
     }
 
-    private String getProperty(final String propName) {
+    private static String getProperty(final String propName) {
         String prop = System.getProperty(propName);
-        Assert.assertTrue("Missing property :" +propName, prop!=null);
+        Assert.assertTrue("Missing property :" + propName, prop != null);
         return prop;
     }
 
-    private void checkRepository(final URI repoURI) {
+    private void checkRepository(final URI repoUri) {
         Repository repo = null;
-        for(Repository r: featuresService.listRepositories()) {
-            if(r.getURI().equals(repoURI)){
+        for (Repository r : featuresService.listRepositories()) {
+            if (r.getURI().equals(repoUri)) {
                 repo = r;
                 break;
             }
         }
-        Assert.assertNotNull("Repository not found: " + repoURI,repo);
+        Assert.assertNotNull("Repository not found: " + repoUri, repo);
     }
 
+    /**
+     * Sets the repository up.
+     *
+     * @throws Exception if an error occurs.
+     */
     @Before
     public void installRepo() throws Exception {
-        LOG.info("Attempting to add repository {}", getRepoURI());
-        featuresService.addRepository(getRepoURI());
-        checkRepository(getRepoURI());
-        LOG.info("Successfully loaded repository {}", getRepoURI());
+        final URI repoUri = getRepoUri();
+        LOG.info("Attempting to add repository {}", repoUri);
+        featuresService.addRepository(repoUri);
+        checkRepository(repoUri);
+        LOG.info("Successfully loaded repository {}", repoUri);
     }
 
-    @Test
+    // Give it 10 minutes max as we've seen feature install hang on jenkins.
+    @Test(timeout = 600000)
     public void installFeature() throws Exception {
-      LOG.info("Attempting to install feature {} {}", getFeatureName(),getFeatureVersion());
-      featuresService.installFeature(getFeatureName(), getFeatureVersion());
-      Feature f = featuresService.getFeature(getFeatureName(), getFeatureVersion());
-      Assert.assertNotNull("Attempt to get feature "+ getFeatureName() + " " + getFeatureVersion() + "resulted in null" , f);
-      Assert.assertTrue("Failed to install Feature: " + getFeatureName() + " " + getFeatureVersion(),featuresService.isInstalled(f));
-      LOG.info("Successfull installed feature {} {}", getFeatureName(),getFeatureVersion());
+        LOG.info("Attempting to install feature {} {}", getFeatureName(), getFeatureVersion());
+        featuresService.installFeature(getFeatureName(), getFeatureVersion());
+        Feature feature = featuresService.getFeature(getFeatureName(), getFeatureVersion());
+        Assert.assertNotNull(
+                "Attempt to get feature " + getFeatureName() + " " + getFeatureVersion() + "resulted in null", feature);
+        Assert.assertTrue("Failed to install Feature: " + getFeatureName() + " " + getFeatureVersion(),
+                featuresService.isInstalled(feature));
+        LOG.info("Successfull installed feature {} {}", getFeatureName(), getFeatureVersion());
     }
 }