Compare commits
7 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8819189b45 | ||
|
|
d4ff5690a2 | ||
|
|
29722102e0 | ||
|
|
247445de1d | ||
|
|
31be190dad | ||
|
|
ed004ce7d9 | ||
|
|
0e175de82a |
3 changed files with 2 additions and 230 deletions
|
|
@ -4,6 +4,7 @@ import static io.kojan.runit.api.RUnit.*;
|
|||
import static io.kojan.runit.api.matcher.RUnitMatchers.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
|
||||
import io.kojan.javadeptools.rpm.*;
|
||||
|
|
@ -23,15 +24,10 @@ public class ApacheCommonsCheck {
|
|||
@PackageTest
|
||||
@IncludeBinary("apache-commons-[a-z][a-z0-9]+")
|
||||
@ExcludeBinary("apache-commons-parent") // Parent POM, no Java code
|
||||
@Disabled("JPMS provides are not generated for now")
|
||||
public void jpmsProvides(RpmInfo rpm) {
|
||||
String id = rpm.getName().substring("apache-commons-".length());
|
||||
assertThat("Apache Commons packages should have jpms provides", rpm,
|
||||
provides("jpms\\(org.apache.commons." + id + "\\)( = .*)?"));
|
||||
}
|
||||
|
||||
@PackageTest
|
||||
@IncludeBinary("apache-commons-.*")
|
||||
public void apacheLicense(RpmInfo rpm) {
|
||||
assertThat("Apache Commons packages license should be Apache-2.0", rpm.getLicense(), is("Apache-2.0"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
package tests;
|
||||
|
||||
import static io.kojan.runit.api.RUnit.*;
|
||||
import static io.kojan.runit.api.matcher.RUnitMatchers.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
|
||||
import io.kojan.javadeptools.rpm.RpmInfo;
|
||||
import io.kojan.runit.api.ExcludeFileName;
|
||||
import io.kojan.runit.api.ExcludeSource;
|
||||
import io.kojan.runit.api.ExcludeSymlink;
|
||||
import io.kojan.runit.api.FileTest;
|
||||
import io.kojan.runit.api.IncludeFileName;
|
||||
|
||||
@DisplayName("/jpackage_script")
|
||||
public class JPackageScriptCheck {
|
||||
@FileTest
|
||||
@IncludeFileName("/usr/bin/.*")
|
||||
@ExcludeSource
|
||||
@ExcludeSymlink
|
||||
@ExcludeFileName("/usr/bin/ant")
|
||||
public void testJPackageScript(RpmInfo rpm, byte[] bytes) {
|
||||
assumeThat("The binary is a script with a shebang", bytes.length, greaterThan(1));
|
||||
assumeThat("The binary is a script with a shebang", bytes[0], is((byte)'#'));
|
||||
assumeThat("The binary is a script with a shebang", bytes[1], is((byte)'!'));
|
||||
String content = new String(bytes, StandardCharsets.UTF_8);
|
||||
assumeThat("The script was generated with %jpackage_script", content,
|
||||
containsString(". /usr/share/java-utils/java-functions\n"));
|
||||
assertThat("The script explicitly sets JAVA_HOME to Java 21", content,
|
||||
containsString("\nJAVA_HOME=\"${JAVA_HOME:-/usr/lib/jvm/jre-21-openjdk}\"\n"));
|
||||
assertThat("Requires on java-21-openjdk-headless are present", rpm, requires("java-21-openjdk-headless"));
|
||||
assertThat("Requires on javapackages-tools are present", rpm, requires("javapackages-tools"));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
package tests;
|
||||
|
||||
import static io.kojan.runit.api.RUnit.*;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
|
||||
import io.kojan.javadeptools.rpm.*;
|
||||
import io.kojan.runit.api.*;
|
||||
|
||||
@DisplayName("/license")
|
||||
public class LicenseCheck {
|
||||
// General-purpose licenses that are approved for everything, including code.
|
||||
// See: https://docs.fedoraproject.org/en-US/legal/allowed-licenses/
|
||||
private static final Set<String> GLOBAL_ALLOWED_LICENSES = Set.of( //
|
||||
// General-purpose permissive licenses
|
||||
"0BSD", //
|
||||
"Apache-1.1", //
|
||||
"Apache-2.0", //
|
||||
"BSD-2-Clause", //
|
||||
"BSD-3-Clause", //
|
||||
"BSD-3-Clause-Sun", //
|
||||
"CPL-1.0", //
|
||||
"EPL-1.0", //
|
||||
"EPL-2.0", //
|
||||
"ISC", //
|
||||
"MIT", //
|
||||
"Plexus", //
|
||||
"SMLNJ", //
|
||||
"Saxpath", //
|
||||
"xpp", //
|
||||
"W3C", //
|
||||
// Very permissive licenses, close to public domain
|
||||
"ANTLR-PD", //
|
||||
"CC0-1.0", //
|
||||
"SAX-PD-2.0", //
|
||||
// GPL is only allowed with classpath exception,
|
||||
// and only as alternative to permissive licenses
|
||||
"EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", //
|
||||
"EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only WITH Classpath-exception-2.0", //
|
||||
// Likewise LGPL
|
||||
"LGPL-2.0-or-later OR Apache-2.0", //
|
||||
"Apache-2.0 OR LGPL-2.0-or-later" //
|
||||
);
|
||||
|
||||
// Public domain is valid only for packages that were reviewed by Fedora legal
|
||||
// and which were added to public-domain-text.txt at
|
||||
// https://gitlab.com/fedora/legal/fedora-license-data
|
||||
private static final Set<String> PUBLIC_DOMAIN_PACKAGES = Set.of( //
|
||||
"aopalliance", //
|
||||
"plexus-utils", //
|
||||
"xz-java", //
|
||||
"javapackages-bootstrap" // special case, as it it bundles all the above
|
||||
);
|
||||
|
||||
// Allowed content licenses, in addition to GLOBAL_ALLOWED_LICENSES
|
||||
private static final Set<String> CONTENT_ALLOWED_LICENSES = Set.of( //
|
||||
"GPL-2.0-or-later", //
|
||||
"LGPL-2.1-or-later", //
|
||||
"AFL-2.0", //
|
||||
"CC-BY-2.5" //
|
||||
);
|
||||
|
||||
@PackageTest
|
||||
@IncludeBinary
|
||||
public void testLicense(RpmInfo rpm) {
|
||||
// Licenses that are allowed for particular package. This may be a superset of
|
||||
// GLOBAL_ALLOWED_LICENSES, for example if the package is known to be docs-only,
|
||||
// content licenses may be allowed in addition to general-purpose licenses.
|
||||
Set<String> packageAllowedLicenses = new LinkedHashSet<String>(GLOBAL_ALLOWED_LICENSES);
|
||||
|
||||
if (PUBLIC_DOMAIN_PACKAGES.contains(rpm.getSourceName())) {
|
||||
packageAllowedLicenses.add("LicenseRef-Fedora-Public-Domain");
|
||||
}
|
||||
|
||||
if (rpm.getName().endsWith("-javadoc") || rpm.getName().endsWith("-manual")) {
|
||||
packageAllowedLicenses.addAll(CONTENT_ALLOWED_LICENSES);
|
||||
}
|
||||
|
||||
assertThat("License is allowed", rpm.getLicense(), new LicenseMatcher(packageAllowedLicenses));
|
||||
}
|
||||
}
|
||||
|
||||
class LicenseMatcher extends TypeSafeMatcher<String> {
|
||||
|
||||
private static final Pattern ID_REGEX = Pattern.compile("([a-zA-Z0-9.-]+).*");
|
||||
|
||||
private final Set<String> packageAllowedLicenses;
|
||||
|
||||
private String expression;
|
||||
private int parserPos;
|
||||
|
||||
public LicenseMatcher(Set<String> packageAllowedLicenses) {
|
||||
this.packageAllowedLicenses = packageAllowedLicenses;
|
||||
}
|
||||
|
||||
private void parseError(String msg) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Syntax error - " + msg + "\n");
|
||||
sb.append(" SPDX expression: \"" + expression + "\"\n");
|
||||
sb.append(" Location: here ---" + new String("-").repeat(parserPos) + "^");
|
||||
fail(sb.toString());
|
||||
}
|
||||
|
||||
private void parseEof() {
|
||||
if (parserPos != expression.length()) {
|
||||
parseError("Expected EOF");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matches(String op) {
|
||||
if (expression.substring(parserPos).startsWith(op)) {
|
||||
parserPos += op.length();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean allowed(int beginPos) {
|
||||
String expr = expression.substring(beginPos, parserPos);
|
||||
return packageAllowedLicenses.contains(expr);
|
||||
}
|
||||
|
||||
private void parseAtom() {
|
||||
Matcher matcher = ID_REGEX.matcher(expression.substring(parserPos));
|
||||
if (!matcher.matches()) {
|
||||
parseError("Expected identifier");
|
||||
}
|
||||
String tag = matcher.group(1);
|
||||
parserPos += tag.length();
|
||||
}
|
||||
|
||||
private boolean parsePrimary() {
|
||||
if (matches("(")) {
|
||||
boolean allowed = parseUnion();
|
||||
if (!matches(")")) {
|
||||
parseError("Unclosed parenthesis");
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
int beginPos = parserPos;
|
||||
parseAtom();
|
||||
if (matches(" WITH ")) {
|
||||
parseAtom();
|
||||
}
|
||||
return allowed(beginPos);
|
||||
}
|
||||
|
||||
private boolean parseIntersection() {
|
||||
int beginPos = parserPos;
|
||||
boolean allowed = parsePrimary();
|
||||
if (matches(" AND ")) {
|
||||
allowed &= parseIntersection();
|
||||
}
|
||||
return allowed || allowed(beginPos);
|
||||
}
|
||||
|
||||
private boolean parseUnion() {
|
||||
int beginPos = parserPos;
|
||||
boolean allowed = parseIntersection();
|
||||
if (matches(" OR ")) {
|
||||
allowed &= parseUnion();
|
||||
}
|
||||
return allowed || allowed(beginPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(String license) {
|
||||
expression = license;
|
||||
parserPos = 0;
|
||||
boolean allowed = parseUnion();
|
||||
parseEof();
|
||||
return allowed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("approved license");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue