Compare commits

..

8 commits

Author SHA1 Message Date
Mikolaj Izdebski
261e44c3fa Add deprecation notice to README.md 2025-03-24 08:47:41 +01:00
Mikolaj Izdebski
0999df51b8 Fix a typo in maven4 package name 2025-02-26 23:24:09 +01:00
Mikolaj Izdebski
26792c770b Increase generic package size limit 2025-02-26 23:09:58 +01:00
Mikolaj Izdebski
13f9485252 Configure files for maven4 2025-02-26 23:06:06 +01:00
Mikolaj Izdebski
d5d139af27 Increase allowed size for javapackages-bootstrap 2025-02-26 20:43:17 +01:00
Mikolaj Izdebski
5db07614a8 Add files whiletists for jline 2025-02-26 20:41:03 +01:00
Marian Koncek
4758ee4fda Allow junit5 to install executables 2025-02-25 10:48:31 +01:00
Mikolaj Izdebski
25bf954aac Allow public domain for plexus-utils4 2025-02-16 18:06:31 +01:00
6 changed files with 241 additions and 25 deletions

View file

@ -1,23 +1,5 @@
# javapackages-validator-tests
# Deprecated
This repository contains the `.fmf` test files referenced by packages that are tested by _javapackages-validator_ tool.
This repository is deprecated.
## Versioning
The version scheme is based on Fedora versions (`f<NUM>`).
Changes made to a single branch must be backwards compatible or fix a bug.
Breaking changes can be made to a branch that corresponds to the Rawhide branch at the time of submission.
Packages then explicitly update their git reference and new versions of the package will be tested with the new tests.
This approach ensures that changes to old versions of packages will not be tested with possibly incompatible tests.
## Forking
If you wish to fork this project and add your own tests, you should follow these steps:
1. Add a source directory (e.g. `src`) with your own validators.
2. Add a text [service file](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ServiceLoader.html) named `org.fedoraproject.javapackages.validator.Validator` into the same directory.
This file contains fully-qualified class names of validators which you want to use, one name per line.
Javapackages-validator will run all the validators listed in the service file, unless they have been explicitly filtered using per-package configuration.
This is explained in the project documentation.
Javapackages tests were moved to https://gitlab.com/redhat/centos-stream/tests/javapackages

View file

@ -68,7 +68,10 @@ public class FilesValidatorJP extends FilesValidator {
prefixes.put("javacc", List.of(Prefix.USR_BIN));
prefixes.put("java_cup", List.of(Prefix.USR_BIN));
prefixes.put("jflex", List.of(Prefix.USR_BIN));
prefixes.put("jline", List.of(Prefix.USR_LIB_BUILD_ID));
prefixes.put("junit5", List.of(Prefix.USR_BIN));
prefixes.put("maven", List.of(Prefix.ETC_PKG, Prefix.ETC_JAVA, Prefix.JPBINDING, Prefix.USR_BIN));
prefixes.put("maven4", List.of(Prefix.ETC_PKG, Prefix.ETC_JAVA, Prefix.JPBINDING, Prefix.USR_BIN));
prefixes.put("modello", List.of(Prefix.USR_BIN));
prefixes.put("objectweb-asm", List.of(Prefix.USR_BIN));
prefixes.put("xerces-j2", List.of(Prefix.USR_BIN));
@ -81,7 +84,9 @@ public class FilesValidatorJP extends FilesValidator {
static {
exceptionalFiles.put("aqute-bnd", List.of("/etc/ant.d/aqute-bnd"));
exceptionalFiles.put("maven", List.of("/etc/m2.conf"));
exceptionalFiles.put("maven4", List.of("/etc/m24.conf"));
exceptionalFiles.put("jansi", List.of("/usr/lib/jansi", "/usr/lib/jansi/libjansi.so", "/usr/lib/java/jansi"));
exceptionalFiles.put("jline", List.of("/usr/lib/jline", "/usr/lib/jline/libjlinenative.so", "/usr/lib/java/jline"));
}
private static boolean namesRelated(String lhs, String rhs) {

View file

@ -18,7 +18,7 @@ public class RpmFilesizeValidatorJP extends RpmFilesizeValidator {
}
if (Common.getPackageName(rpm).equals("javapackages-bootstrap")) {
return sizeBytes <= 40_000_000;
return sizeBytes <= 60_000_000;
}
// javadoc rpms
@ -33,6 +33,6 @@ public class RpmFilesizeValidatorJP extends RpmFilesizeValidator {
}
}
return sizeBytes <= 3_500_000;
return sizeBytes <= 4_000_000;
}
}

View file

@ -4,7 +4,6 @@ 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.*;
@ -24,10 +23,15 @@ 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"));
}
}

View file

@ -0,0 +1,37 @@
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"));
}
}

188
src/runit/LicenseCheck.java Normal file
View file

@ -0,0 +1,188 @@
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", //
"plexus-utils4", //
"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");
}
}