2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.odlparent.featuretest;
11 import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP;
12 import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP;
13 import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP;
14 import static org.ops4j.pax.exam.CoreOptions.maven;
15 import static org.ops4j.pax.exam.CoreOptions.when;
16 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
17 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
18 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
19 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
20 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
21 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel;
24 import java.io.InputStream;
25 import java.io.IOException;
27 import java.net.URISyntaxException;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Properties;
33 import javax.inject.Inject;
35 import org.apache.karaf.features.Feature;
36 import org.apache.karaf.features.FeaturesService;
37 import org.apache.karaf.features.Repository;
38 import org.apache.karaf.features.internal.model.Features;
39 import org.apache.karaf.features.internal.model.JaxbUtil;
40 import org.junit.Assert;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.ops4j.pax.exam.Configuration;
45 import org.ops4j.pax.exam.CoreOptions;
46 import org.ops4j.pax.exam.Option;
47 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
48 import org.ops4j.pax.exam.options.extra.VMOption;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 @RunWith(PerRepoTestRunner.class)
53 public class SingleFeatureTest {
54 private static final String MAVEN_REPO_LOCAL = "maven.repo.local";
55 private static final String ORG_OPS4J_PAX_URL_MVN_LOCAL_REPOSITORY = "org.ops4j.pax.url.mvn.localRepository";
56 private static final String ORG_OPS4J_PAX_URL_MVN_REPOSITORIES = "org.ops4j.pax.url.mvn.repositories";
57 private static final String ETC_ORG_OPS4J_PAX_URL_MVN_CFG = "etc/org.ops4j.pax.url.mvn.cfg";
58 private static final String ETC_ORG_OPS4J_PAX_LOGGING_CFG = "etc/org.ops4j.pax.logging.cfg";
59 private static final String KEEP_UNPACK_DIRECTORY_PROP = "karaf.keep.unpack";
60 private static final String LOG4J_LOGGER_ORG_OPENDAYLIGHT_YANGTOOLS_FEATURETEST =
61 "log4j.logger.org.opendaylight.odlparent.featuretest";
62 private static final Logger LOG = LoggerFactory.getLogger(SingleFeatureTest.class);
65 * File name to add our logging config property too.
67 private static final String ORG_OPS4J_PAX_LOGGING_CFG = "etc/org.ops4j.pax.logging.cfg";
70 * Default values for karaf distro type, groupId, and artifactId
72 private static final String KARAF_DISTRO_TYPE = "zip";
73 private static final String KARAF_DISTRO_ARTIFACTID = "apache-karaf";
74 private static final String KARAF_DISTRO_GROUPID = "org.apache.karaf";
77 * Property names to override defaults for karaf distro artifactId, groupId, version, and type
79 private static final String KARAF_DISTRO_VERSION_PROP = "karaf.distro.version";
80 private static final String KARAF_DISTRO_TYPE_PROP = "karaf.distro.type";
81 private static final String KARAF_DISTRO_ARTIFACTID_PROP = "karaf.distro.artifactId";
82 private static final String KARAF_DISTRO_GROUPID_PROP = "karaf.distro.groupId";
85 * Property file used to store the Karaf distribution version.
87 private static final String PROPERTIES_FILENAME = "singlefeaturetest.properties";
90 * <p>List of Karaf 3.0.4 default maven repositories with snapshot repositories excluded.</p>
91 * <p>Unfortunately this must be hard-coded since declarative model which uses Options,
92 * does not allow us to read value, parse it (properties has allways
93 * problems with lists) and construct replacement string which does
94 * not contains snapshots.</p>
95 * <p>When updating Karaf, check this against org.ops4j.pax.url.mvn.cfg in the Karaf distribution.</p>
97 private static final String EXTERNAL_DEFAULT_REPOSITORIES = "http://repo1.maven.org/maven2@id=central, "
98 + "http://repository.springsource.com/maven/bundles/release@id=spring.ebr.release, "
99 + "http://repository.springsource.com/maven/bundles/external@id=spring.ebr.external, "
100 + "http://zodiac.springsource.com/maven/bundles/release@id=gemini ";
104 private FeaturesService featuresService;
106 private String karafVersion;
107 private String karafDistroVersion;
110 * Returns the required configuration.
112 * @return The Pax Exam configuration.
113 * @throws IOException if an error occurs.
116 public Option[] config() throws IOException {
117 return new Option[] {
118 // TODO: Find a way to inherit memory limits from Maven options.
119 new VMOption("-Xmx2g"),
120 new VMOption("-XX:MaxPermSize=512m"),
121 getKarafDistroOption(),
122 when(Boolean.getBoolean(KEEP_UNPACK_DIRECTORY_PROP)).useOptions(keepRuntimeFolder()),
123 configureConsole().ignoreLocalConsole(),
124 logLevel(LogLevel.WARN),
125 mvnLocalRepoOption(),
126 standardKarafFeatures(),
127 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG, LOG4J_LOGGER_ORG_OPENDAYLIGHT_YANGTOOLS_FEATURETEST,
128 LogLevel.INFO.name()),
129 editConfigurationFilePut(ETC_ORG_OPS4J_PAX_LOGGING_CFG, "log4j.rootLogger", "INFO, stdout, osgi:*"),
132 * Disables external snapshot repositories.
134 * Pax URL and Karaf by default always search for new version of snapshots
135 * in all snapshots repository, even if that snapshots does not belong to that
136 * repository and maven is invoked even with -nsu (no snapshot update)
139 * This is also true for OpenDaylight snapshot artefacts - pax url tries
140 * to resolve them from third-party repositories, even if they are not present
141 * there - this increases time which takes for features to install.
143 * For more complex projects this actually means several HTTP GETs for each
144 * snapshot bundle referenced, even if the bundle is already present
145 * in local maven repository.
147 * In order to speed-up installation and remove unnecessary network traffic,
148 * which fails for obvious reasons, external snapshot repositories are
153 disableExternalSnapshotRepositories(),
154 CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP).value(
155 System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP)),
156 CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP).value(
157 System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP)),
158 CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP).value(
159 System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP)),
163 private Option standardKarafFeatures() {
164 String url = maven().groupId("org.apache.karaf.features").artifactId("standard").classifier("features").type(
165 "xml").version(getKarafVersion()).getURL();
167 Features features = JaxbUtil.unmarshal(new URL(url).openStream(), false);
168 List<String> featureNames = new ArrayList<>();
169 for (Feature f : features.getFeature()) {
170 featureNames.add(f.getName());
173 return features(url, featureNames.toArray(new String[featureNames.size()]));
174 } catch (Exception e) {
175 throw new RuntimeException("Could not obtain features from URL " + url, e);
179 private String getKarafVersion() {
180 if (karafVersion == null) {
181 // We use a properties file to retrieve ${karaf.version}, instead of .versionAsInProject()
182 // This avoids forcing all users to depend on Karaf in their POMs
183 Properties singleFeatureTestProps = new Properties();
184 try (InputStream singleFeatureTestInputStream = Thread.currentThread().getContextClassLoader()
185 .getResourceAsStream(PROPERTIES_FILENAME)) {
186 singleFeatureTestProps.load(singleFeatureTestInputStream);
187 } catch (IOException e) {
188 LOG.error("Unable to load {} to determine the Karaf version", PROPERTIES_FILENAME, e);
190 karafVersion = singleFeatureTestProps.getProperty(KARAF_DISTRO_VERSION_PROP);
192 LOG.info("Retrieved karafVersion {} from properties file {}", karafVersion, PROPERTIES_FILENAME);
194 LOG.info("Retrieved karafVersion {} from system property {}", karafVersion, KARAF_DISTRO_VERSION_PROP);
200 private String getKarafDistroVersion() {
201 if (karafDistroVersion == null) {
202 karafDistroVersion = System.getProperty(KARAF_DISTRO_VERSION_PROP);
203 if (karafDistroVersion == null) {
204 karafDistroVersion = getKarafVersion();
206 LOG.info("Retrieved karafDistroVersion {} from system property {}", karafVersion,
207 KARAF_DISTRO_VERSION_PROP);
211 return karafDistroVersion;
215 * Disables snapshot repositories, which are enabled by default in karaf distribution.
217 * @return Edit Configuration option which removes external snapshot repositories.
219 private static Option disableExternalSnapshotRepositories() {
220 return editConfigurationFilePut(ETC_ORG_OPS4J_PAX_URL_MVN_CFG, ORG_OPS4J_PAX_URL_MVN_REPOSITORIES,
221 EXTERNAL_DEFAULT_REPOSITORIES);
224 protected Option mvnLocalRepoOption() {
225 String mvnRepoLocal = System.getProperty(MAVEN_REPO_LOCAL, "");
226 LOG.info("mvnLocalRepo \"{}\"", mvnRepoLocal);
227 return editConfigurationFilePut(ETC_ORG_OPS4J_PAX_URL_MVN_CFG, ORG_OPS4J_PAX_URL_MVN_LOCAL_REPOSITORY,
231 protected Option getKarafDistroOption() {
232 String groupId = System.getProperty(KARAF_DISTRO_GROUPID_PROP, KARAF_DISTRO_GROUPID);
233 String artifactId = System.getProperty(KARAF_DISTRO_ARTIFACTID_PROP, KARAF_DISTRO_ARTIFACTID);
234 String type = System.getProperty(KARAF_DISTRO_TYPE_PROP, KARAF_DISTRO_TYPE);
235 LOG.info("Using karaf distro {} {} {} {}", groupId, artifactId, getKarafDistroVersion(), type);
236 return karafDistributionConfiguration()
240 .artifactId(artifactId)
242 .version(getKarafDistroVersion()))
243 .name("OpenDaylight")
244 .unpackDirectory(new File("target/pax"))
245 .useDeployFolder(false);
248 private static URI getRepoUri() throws URISyntaxException {
249 return new URI(getProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP));
252 private static String getFeatureName() {
253 return getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP);
256 public String getFeatureVersion() {
257 return getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP);
260 private static String getProperty(final String propName) {
261 String prop = System.getProperty(propName);
262 Assert.assertTrue("Missing property :" + propName, prop != null);
266 private void checkRepository(final URI repoUri) {
267 Repository repo = null;
268 for (Repository r : featuresService.listRepositories()) {
269 if (r.getURI().equals(repoUri)) {
274 Assert.assertNotNull("Repository not found: " + repoUri, repo);
278 * Sets the repository up.
280 * @throws Exception if an error occurs.
283 public void installRepo() throws Exception {
284 final URI repoUri = getRepoUri();
285 LOG.info("Attempting to add repository {}", repoUri);
286 featuresService.addRepository(repoUri);
287 checkRepository(repoUri);
288 LOG.info("Successfully loaded repository {}", repoUri);
291 // Give it 5 minutes max as we've seen feature install hang on jenkins.
292 @Test(timeout = 300000)
293 public void installFeature() throws Exception {
294 LOG.info("Attempting to install feature {} {}", getFeatureName(), getFeatureVersion());
295 featuresService.installFeature(getFeatureName(), getFeatureVersion());
296 Feature feature = featuresService.getFeature(getFeatureName(), getFeatureVersion());
297 Assert.assertNotNull(
298 "Attempt to get feature " + getFeatureName() + " " + getFeatureVersion() + "resulted in null", feature);
299 Assert.assertTrue("Failed to install Feature: " + getFeatureName() + " " + getFeatureVersion(),
300 featuresService.isInstalled(feature));
301 LOG.info("Successfull installed feature {} {}", getFeatureName(), getFeatureVersion());