blob: 25f26dd9bd6c8f5c15b4ef92bb8c989c20130b85 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2017 IBM Corporation and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which accompanies this distribution,
* and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors: IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.pde.build.internal.tests.p2;
import static org.junit.Assert.*;
import java.io.File;
import java.util.*;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.equinox.internal.p2.metadata.License;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.IFileArtifactRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.pde.build.internal.tests.Utils;
import org.eclipse.pde.build.tests.BuildConfiguration;
import org.eclipse.pde.internal.build.site.BuildTimeFeature;
import org.eclipse.pde.internal.build.site.BuildTimeFeatureFactory;
import org.junit.Test;
public class LicenseTests extends P2TestCase {
private static final int URL_EMPTY = 1;
private static final int URL_NON_EMPTY = 2;
private static final int URL_NONE = 0;
private static final int DESC_EMPTY = 100;
private static final int DESC_NON_EMPTY = 101;
@Test
public void testLicenseFeatureOldP2() throws Exception {
IFolder buildFolder = newTest("testLicenseFeatureOldP2", "licenseFeature1");
IFolder repo = Utils.createFolder(buildFolder, "repo");
String repoLocation = "file:" + repo.getLocation().toOSString();
Properties properties = BuildConfiguration.getBuilderProperties(buildFolder);
properties.put("topLevelElementId", "F1");
properties.put("generate.p2.metadata", "true");
properties.put("p2.metadata.repo", repoLocation);
properties.put("p2.artifact.repo", repoLocation);
properties.put("p2.publish.artifacts", "true");
Utils.storeBuildProperties(buildFolder, properties);
runBuild(buildFolder);
IMetadataRepository metadata = loadMetadataRepository(repoLocation);
IArtifactRepository artifacts = loadArtifactRepository(repoLocation);
IInstallableUnit iu = getIU(metadata, "F1.feature.group");
License actualLicense = (License) iu.getLicenses().toArray()[0];
// Check that root file ends up as an artifact
IInstallableUnit rootFileIU = getIU(metadata, "org.eclipse.rootfiles.ANY.ANY.ANY");
IArtifactKey rootFileKey = (IArtifactKey) rootFileIU.getArtifacts().toArray()[0];
File actualRootFile = ((IFileArtifactRepository) artifacts).getArtifactFile(rootFileKey);
Set<String> entries = new HashSet<>();
entries.add("root.html");
assertZipContents(actualRootFile, entries);
// Check that all expected files are in zip
entries = new HashSet<>();
entries.add("feature.properties");
entries.add("feature.xml");
entries.add("feature_fr.properties");
entries.add("license.html");
entries.add("license_fr.html");
assertZipContents(buildFolder, "repo/features/F1_1.0.0.jar", entries);
// Check that feature.properties contains all original properties PLUS
// properties from license
IFile licensePropertyFile = buildFolder.getFile("features/L1/feature.properties");
Properties licenseProperties = Utils.loadProperties(licensePropertyFile);
IFile originalPropertyFile = buildFolder.getFile("features/F1/feature.properties");
Properties originalProperties = Utils.loadProperties(originalPropertyFile);
IFile actualPropertiesFile = buildFolder.getFile("checkProperties");
Utils.extractFromZip(buildFolder, "I.TestBuild/F1-TestBuild.zip",
"eclipse/features/F1_1.0.0/feature.properties", actualPropertiesFile);
Properties actualProperties = Utils.loadProperties(actualPropertiesFile);
assertEquals("Result feature.properties has incorrect number of properties", originalProperties.size() + 2,
actualProperties.size());
Enumeration<Object> keys = originalProperties.keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
assertEquals(originalProperties.getProperty(key, "originalMissing"), actualProperties.getProperty(key));
}
keys = licenseProperties.keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
assertEquals(licenseProperties.getProperty(key, "originalMissing"), actualProperties.getProperty(key));
}
// Check that license from L1 ends up int he meta data for the feature
BuildTimeFeatureFactory factory = new BuildTimeFeatureFactory();
IFile licenseFeatureFile = buildFolder.getFile("features/L1/feature.xml");
BuildTimeFeature licenseFeature = factory.parseBuildFeature(licenseFeatureFile.getLocationURI().toURL());
IFile originalFeatureFile = buildFolder.getFile("features/F1/feature.xml");
BuildTimeFeature originalFeature = factory.parseBuildFeature(originalFeatureFile.getLocationURI().toURL());
assertEquals(licenseFeature.getLicenseURL(), URIUtil.toUnencodedString(actualLicense.getLocation()));
assertEquals(licenseFeature.getLicense(), actualLicense.getBody());
// Check that license elements in feature.xml where changed.
IFile actualFeatureFile = buildFolder.getFile("checkFeature.xml");
Utils.extractFromZip(buildFolder, "I.TestBuild/F1-TestBuild.zip", "eclipse/features/F1_1.0.0/feature.xml",
actualFeatureFile);
BuildTimeFeature actualFeature = factory.parseBuildFeature(actualFeatureFile.getLocationURI().toURL());
assertNotNull(actualFeature.getLicense());
assertEquals(licenseFeature.getLicense(), actualFeature.getLicense());
assertNotNull(actualFeature.getLicenseURL());
assertEquals(licenseFeature.getLicenseURL(), actualFeature.getLicenseURL());
assertEquals(originalFeature.getId(), actualFeature.getId());
assertEquals(originalFeature.getDescription(), actualFeature.getDescription());
assertEquals(originalFeature.getCopyright(), actualFeature.getCopyright());
}
// Test various combinations of empty and non-empty license and payload values
@Test
public void testEmptyCombosPDE() throws Exception {
// Prepare
IFolder buildFolder = newTest("testEmptyCombosPDE", "emptyLicenseTests");
Properties properties = BuildConfiguration.getBuilderProperties(buildFolder);
properties.put("topLevelElementId", "F1");
properties.put("baseLocation", "");
Utils.storeBuildProperties(buildFolder, properties);
// Test URL combinations
for (int licenseState = 0; licenseState < 3; licenseState++) {
for (int payloadState = 0; payloadState < 3; payloadState++) {
copyFeature(buildFolder, "L1", licenseState);
copyFeature(buildFolder, "F1", payloadState);
runBuild(buildFolder);
checkBuiltFeature(buildFolder, getStateMessage(licenseState, payloadState));
new File(buildFolder.getLocation().toFile(), "I.TestBuild/F1-TestBuild.zip").delete();
}
}
// Test Description combinations
for (int licenseState = 100; licenseState < 102; licenseState++) {
for (int payloadState = 0; payloadState < 3; payloadState++) {
copyFeature(buildFolder, "L1", licenseState);
copyFeature(buildFolder, "F1", payloadState);
runBuild(buildFolder);
checkBuiltFeature(buildFolder, getStateMessage(licenseState, payloadState));
new File(buildFolder.getLocation().toFile(), "I.TestBuild/F1-TestBuild.zip").delete();
}
}
}
@Test
public void testRootUsedWithNoLicenseRefPDE() throws Exception {
boolean expectedExceptionCaught = false;
IFolder buildFolder = newTest("testRootUsedWithNoLicenseRefPDE", "rootNoRef");
Properties properties = BuildConfiguration.getBuilderProperties(buildFolder);
properties.put("topLevelElementId", "F1");
Utils.storeBuildProperties(buildFolder, properties);
try {
runBuild(buildFolder);
} catch (Exception e) {
assertTrue("Build throws wrong exception", e.getMessage()
.indexOf("uses 'license:' root keyword but does not reference a license feature") != -1);
expectedExceptionCaught = true;
}
assertTrue("Build should have failed", expectedExceptionCaught);
}
@Test
public void testLicenseFeaturePDE() throws Exception {
IFolder buildFolder = newTest("testLicenseFeaturePDE", "licenseFeature1");
Properties properties = BuildConfiguration.getBuilderProperties(buildFolder);
properties.put("topLevelElementId", "F1");
Utils.storeBuildProperties(buildFolder, properties);
runBuild(buildFolder);
// Check that all expected files are in zip
Set<String> entries = new HashSet<>();
entries.add("eclipse/features/F1_1.0.0/feature.properties");
entries.add("eclipse/features/F1_1.0.0/feature.xml");
entries.add("eclipse/features/F1_1.0.0/feature_fr.properties");
entries.add("eclipse/features/F1_1.0.0/license.html");
entries.add("eclipse/features/F1_1.0.0/license_fr.html");
entries.add("eclipse/root.html");
assertZipContents(buildFolder, "I.TestBuild/F1-TestBuild.zip", entries);
// Check that feature.properties contains all original properties PLUS
// properties from license
IFile licensePropertyFile = buildFolder.getFile("features/L1/feature.properties");
Properties licenseProperties = Utils.loadProperties(licensePropertyFile);
IFile originalPropertyFile = buildFolder.getFile("features/F1/feature.properties");
Properties originalProperties = Utils.loadProperties(originalPropertyFile);
IFile actualPropertiesFile = buildFolder.getFile("checkProperties");
Utils.extractFromZip(buildFolder, "I.TestBuild/F1-TestBuild.zip",
"eclipse/features/F1_1.0.0/feature.properties", actualPropertiesFile);
Properties actualProperties = Utils.loadProperties(actualPropertiesFile);
assertEquals("Result feature.properties has incorrect number of properties", originalProperties.size() + 2,
actualProperties.size());
Enumeration<Object> keys = originalProperties.keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
assertEquals(originalProperties.getProperty(key, "originalMissing"), actualProperties.getProperty(key));
}
keys = licenseProperties.keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
assertEquals(licenseProperties.getProperty(key, "originalMissing"), actualProperties.getProperty(key));
}
checkBuiltFeature(buildFolder, "");
}
@Test
public void testP2Gathering() throws Exception {
IFolder buildFolder = newTest("licenseP2Gathering", "licenseFeature1");
Utils.writeBuffer(buildFolder.getFile("features/L1/license.html"), new StringBuffer("I'm a license\n"));
Properties properties = new Properties();
properties.put("bin.includes", "feature.xml,feature.properties,license.html");
Utils.storeBuildProperties(buildFolder.getFolder("features/L1"), properties);
properties = BuildConfiguration.getBuilderProperties(buildFolder);
properties.put("topLevelElementId", "F1");
properties.put("baseLocation", "");
properties.put("p2.gathering", "true");
Utils.storeBuildProperties(buildFolder, properties);
runBuild(buildFolder);
Set<String> entries = new HashSet<>();
entries.add("license.html");
assertZipContents(buildFolder, "buildRepo/features/F1_1.0.0.jar", entries);
// also try using the gather task directly
IFile testXML = buildFolder.getFile("test.xml");
IFolder repo2 = Utils.createFolder(buildFolder, "repo2");
StringBuffer test = new StringBuffer();
test.append(
"<project default=\"publish\"> \n");
test.append(
" <target name=\"publish\"> \n");
test.append(
" <eclipse.gatherFeature metadataRepository=\"${repo}\" artifactRepository=\"${repo}\" \n");
test.append(
" buildResultFolder=\"${folder}\" baseDirectory=\"${folder}\" \n");
test.append(
" licenseDirectory=\"${license}\" /> \n");
test.append(
" </target> \n");
test.append(
"</project> \n");
Utils.writeBuffer(testXML, test);
properties = new Properties();
properties.put("repo", URIUtil.toUnencodedString(repo2.getLocationURI()));
properties.put("folder", buildFolder.getFolder("features/F1").getLocation().toString());
properties.put("license", buildFolder.getFolder("features/L1").getLocation().toString());
runAntScript(testXML.getLocation().toOSString(), new String[] { "publish" },
buildFolder.getLocation().toOSString(), properties);
entries = new HashSet<>();
entries.add("license.html");
assertZipContents(repo2, "features/F1_1.0.0.jar", entries);
}
@Test
public void testP2Gathering_Custom() throws Exception {
IFolder buildFolder = newTest("licenseP2GatheringCustom", "licenseFeature1");
Utils.writeBuffer(buildFolder.getFile("features/L1/rootFile.html"), new StringBuffer("I'm a license\n"));
Utils.writeBuffer(buildFolder.getFile("features/L1/sub/license.html"), new StringBuffer("I'm a license\n"));
Properties properties = new Properties();
properties.put("bin.includes", "feature.xml,feature.properties,sub/license.html");
Utils.storeBuildProperties(buildFolder.getFolder("features/L1"), properties);
IFolder f = buildFolder.getFolder("features/F1");
properties = new Properties();
properties.put("bin.includes", "feature.xml");
properties.put("customBuildCallbacks", "true");
properties.put("root", "license:file:rootFile.html");
Utils.storeBuildProperties(f, properties);
StringBuffer buffer = new StringBuffer();
buffer.append("<project name=\"customGather\" default=\"noDefault\"> \n");
buffer.append(" <target name=\"pre.gather.bin.parts\"> \n");
buffer.append(" <concat destfile=\"${feature.directory}/a.txt\"> \n");
buffer.append(" Mary had a little lamb. \n");
buffer.append(" </concat> \n");
buffer.append(" </target> \n");
buffer.append("</project> \n");
Utils.writeBuffer(f.getFile("customBuildCallbacks.xml"), buffer);
properties = BuildConfiguration.getBuilderProperties(buildFolder);
properties.put("topLevelElementId", "F1");
properties.put("baseLocation", "");
properties.put("p2.gathering", "true");
Utils.storeBuildProperties(buildFolder, properties);
runBuild(buildFolder);
Set<String> entries = new HashSet<>();
entries.add("sub/license.html");
entries.add("a.txt");
assertZipContents(buildFolder, "buildRepo/features/F1_1.0.0.jar", entries);
entries = new HashSet<>();
entries.add("rootFile.html");
assertZipContents(buildFolder, "buildRepo/binary/F1_root_1.0.0", entries);
}
@Test
public void testBinaryLicense() throws Exception {
IFolder buildFolder = newTest("binaryLicense", "licenseFeature1");
Utils.writeBuffer(buildFolder.getFile("features/L1/META-INF/MANIFEST.MF"), new StringBuffer("manifest\n"));
Utils.writeBuffer(buildFolder.getFile("features/L1/META-INF/ECLIPSEF.RSA"), new StringBuffer("rsa\n"));
Utils.writeBuffer(buildFolder.getFile("features/L1/sub/license.html"), new StringBuffer("I'm a license\n"));
Properties properties = new Properties();
properties.put("bin.includes", "feature.xml,feature.properties,sub/license.html, META-INF/");
Utils.storeBuildProperties(buildFolder.getFolder("features/L1"), properties);
properties = BuildConfiguration.getBuilderProperties(buildFolder);
properties.put("topLevelElementId", "L1");
properties.put("baseLocation", "");
properties.put("archivesFormat", "*,*,*-folder");
Utils.storeBuildProperties(buildFolder, properties);
runBuild(buildFolder);
IFolder build2 = Utils.createFolder(buildFolder, "build2");
Utils.copy(buildFolder.getFolder("features/F1").getLocation().toFile(),
build2.getFolder("features/F1").getLocation().toFile());
properties = BuildConfiguration.getBuilderProperties(build2);
properties.put("topLevelElementId", "F1");
properties.put("baseLocation", "");
properties.put("pluginPath", buildFolder.getFolder("tmp/eclipse").getLocation().toString());
properties.put("archivesFormat", "*,*,*-folder");
Utils.storeBuildProperties(build2, properties);
runBuild(build2);
assertResourceFile(build2, "tmp/eclipse/features/F1_1.0.0/sub/license.html");
assertFalse(build2.getFolder("tmp/eclipse/features/F1_1.0.0/META-INF").exists());
IFolder build3 = Utils.createFolder(buildFolder, "build3");
Utils.copy(buildFolder.getFolder("features/F1").getLocation().toFile(),
build3.getFolder("features/F1").getLocation().toFile());
properties = BuildConfiguration.getBuilderProperties(build3);
properties.put("topLevelElementId", "F1");
properties.put("baseLocation", "");
properties.put("pluginPath", buildFolder.getFolder("tmp/eclipse").getLocation().toString());
properties.put("p2.gathering", "true");
Utils.storeBuildProperties(build3, properties);
runBuild(build3);
Set<String> entries = new HashSet<>();
entries.add("sub/license.html");
assertZipContents(build3, "buildRepo/features/F1_1.0.0.jar", entries);
assertResourceFile(build2, "tmp/eclipse/features/F1_1.0.0/sub/license.html");
assertFalse(build2.getFolder("tmp/eclipse/features/F1_1.0.0/META-INF").exists());
assertResourceFile(build3, "buildRepo/features/F1_1.0.0.jar");
assertFalse(Utils.extractFromZip(build3, "buildRepo/features/F1_1.0.0.jar", "META-INF/ECLIPSEF.RSA",
build3.getFile("rsa.txt")));
}
private String getStateMessage(int state) {
switch (state) {
case URL_NONE:
return "No URL";
case URL_EMPTY:
return "URL Empty";
case URL_NON_EMPTY:
return "URL Not Empty";
case DESC_EMPTY:
return "Description Empty";
case DESC_NON_EMPTY:
return "Description Not Empty";
default:
return "unknown";
}
}
private String getStateMessage(int licenseState, int payloadState) {
String lState = getStateMessage(licenseState);
String pState = getStateMessage(payloadState);
return "License State: " + lState + " Payload State: " + pState + ": ";
}
private void checkBuiltFeature(IFolder buildFolder, String errorMessage) throws Exception {
// Check that license elements in feature.xml where changed.
BuildTimeFeatureFactory factory = new BuildTimeFeatureFactory();
// IFile actualFeatureFile =
// buildFolder.getFile("tmp/eclipse/features/F1_1.0.0/feature.xml");//buildFolder.getFile("checkFeature.xml");
IFile actualFeatureFile = buildFolder.getFile("checkFeature.xml");
assertTrue(Utils.extractFromZip(buildFolder, "I.TestBuild/F1-TestBuild.zip",
"eclipse/features/F1_1.0.0/feature.xml", actualFeatureFile));
BuildTimeFeature actualFeature = factory.parseBuildFeature(actualFeatureFile.getLocationURI().toURL());
IFile licenseFeatureFile = buildFolder.getFile("features/L1/feature.xml");
BuildTimeFeature licenseFeature = factory.parseBuildFeature(licenseFeatureFile.getLocationURI().toURL());
IFile originalFeatureFile = buildFolder.getFile("features/F1/feature.xml");
BuildTimeFeature originalFeature = factory.parseBuildFeature(originalFeatureFile.getLocationURI().toURL());
assertNotNull(errorMessage + "license was null", actualFeature.getLicense());
assertEquals(errorMessage + "license text not equal", licenseFeature.getLicense(), actualFeature.getLicense());
assertNotNull(errorMessage + "license url was null", actualFeature.getLicenseURL());
assertEquals(errorMessage + "license url not equal", licenseFeature.getLicenseURL(),
actualFeature.getLicenseURL());
assertEquals(errorMessage + "feature ID corrupted", originalFeature.getId(), actualFeature.getId());
assertEquals(errorMessage + "feature description corrupted", originalFeature.getDescription(),
actualFeature.getDescription());
assertEquals(errorMessage + "feature copyright corrupted", originalFeature.getCopyright(),
actualFeature.getCopyright());
}
private void copyFeature(IFolder buildFolder, String featureID, int state) throws CoreException {
String sourceFileName = null;
switch (state) {
case URL_EMPTY:
sourceFileName = "emptyLicenseURLFeature.xml";
break;
case URL_NON_EMPTY:
sourceFileName = "nonEmptyLicenseURLFeature.xml";
break;
case URL_NONE:
sourceFileName = "noLicenseURLFeature.xml";
break;
case DESC_EMPTY:
sourceFileName = "emptyLicenseDescFeature.xml";
break;
case DESC_NON_EMPTY:
sourceFileName = "nonEmptyLicenseDescFeature.xml";
break;
}
IFile source = buildFolder.getFile("features/" + featureID + "/" + sourceFileName);
IFile dest = buildFolder.getFile("features/" + featureID + "/feature.xml");
if (dest.exists()) {
dest.delete(true, null);
}
source.copy(dest.getFullPath(), true, null);
}
@Test
public void testBug338835_MissingLicenseSection() throws Exception {
IFolder buildFolder = newTest("338835");
IFolder featureFolder = Utils.createFolder(buildFolder, "feature");
IFolder licenseFolder = Utils.createFolder(buildFolder, "license");
StringBuffer buffer = new StringBuffer();
buffer.append("<feature id=\"org.eclipse.ptp\" version=\"5.0.0.qualifier\" \n");
buffer.append(" license-feature=\"org.eclipse.ptp.license\" license-feature-version=\"1.0.0.qualifier\">\n");
buffer.append(" <description url=\"http://eclipse.org/ptp\">%description</description> \n");
buffer.append(" <copyright>%copyright</copyright> \n");
buffer.append(" <url> \n");
buffer.append(" <update label=\"%updateSiteName\" url=\"https://download.eclipse.org/updates\"/> \n");
buffer.append(" </url> \n");
buffer.append("</feature> \n");
Utils.writeBuffer(featureFolder.getFile("feature.xml"), buffer);
buffer.append("<feature id=\"license\" version=\"5.0.0.qualifier\" >\n");
buffer.append(" <license url=\"http://eclipse.org/license.html\"> \n");
buffer.append(" This is legal stuff \n");
buffer.append(" </license> \n");
buffer.append("</feature> \n");
Utils.writeBuffer(licenseFolder.getFile("feature.xml"), buffer);
buffer = new StringBuffer();
buffer.append(
"<project name=\"build\" basedir=\".\" > \n");
buffer.append(
" <target name=\"test\"> \n");
buffer.append(" <eclipse.licenseReplacer featureFilePath=\"" + featureFolder.getLocation().toOSString()
+ "\" \n");
buffer.append(" licenseFilePath=\"" + licenseFolder.getLocation().toOSString()
+ "\" /> \n");
buffer.append(
" </target> \n");
buffer.append(
"</project> \n");
IFile buildXml = buildFolder.getFile("build.xml");
Utils.writeBuffer(buildXml, buffer);
runAntScript(buildXml.getLocation().toOSString(), new String[] { "test" },
buildFolder.getLocation().toOSString(), null);
BuildTimeFeature feature = new BuildTimeFeatureFactory()
.parseBuildFeature(featureFolder.getFile("feature.xml").getLocationURI().toURL());
assertEquals(feature.getLicense().trim(), "This is legal stuff");
}
}