Compare commits
103 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
261e44c3fa | ||
|
|
0999df51b8 | ||
|
|
26792c770b | ||
|
|
13f9485252 | ||
|
|
d5d139af27 | ||
|
|
5db07614a8 | ||
|
|
4758ee4fda | ||
|
|
25bf954aac | ||
|
|
af194b6641 | ||
|
|
75adec844b | ||
|
|
0cd1370868 | ||
|
|
745343f757 | ||
|
|
50e2e10695 | ||
|
|
c9fe403c5e | ||
|
|
27b31452b9 | ||
|
|
1433c52224 | ||
|
|
4d05ece41c | ||
|
|
5f09737c33 | ||
|
|
cfa4787b3b | ||
|
|
d633634528 | ||
|
|
ed92ce4e3b | ||
|
|
b86f2bd711 | ||
|
|
ab6a8c544a | ||
|
|
f3f789d7c8 | ||
|
|
f36b1f9ec6 | ||
|
|
dfe9493ee7 | ||
|
|
da2f3b64d6 | ||
|
|
15f8f4398a | ||
|
|
dd3c24887d | ||
|
|
b0300a3876 | ||
|
|
abf645f388 | ||
|
|
9268133272 | ||
|
|
569590fe86 | ||
|
|
b94880fa5f | ||
|
|
4d53b55041 | ||
|
|
e329349409 | ||
|
|
ef3b34fa5d | ||
|
|
93d8b3ac06 | ||
|
|
4b485ba76d | ||
|
|
4ae5ee753f | ||
|
|
8ed9563d81 | ||
|
|
15381c38a6 | ||
|
|
6c83076bdf | ||
|
|
707483b8b5 | ||
|
|
36ba3a0a7d | ||
|
|
b5fc0e766e | ||
|
|
5e98b7b135 | ||
|
|
aa925a2124 | ||
|
|
a3f18d49bd | ||
|
|
e1a66d68e8 | ||
|
|
26be4efbd6 | ||
|
|
a59d4fec63 | ||
|
|
25ec6ea104 | ||
|
|
a726712ae6 | ||
|
|
a5d9cbdc3b | ||
|
|
a95157444d | ||
|
|
8ccf218367 | ||
|
|
b9e002af45 | ||
|
|
ed298de4a6 | ||
|
|
2a36967b05 | ||
|
|
e2fea19c9f | ||
|
|
d212186599 | ||
|
|
81e0d8e710 | ||
|
|
80629ccaac | ||
|
|
b2e1d2ad16 | ||
|
|
2fea375be4 | ||
|
|
c950749eaa | ||
|
|
f32125de3f | ||
|
|
145bf154c2 | ||
|
|
895145ddab | ||
|
|
b13dff6a47 | ||
|
|
250f5e78b7 | ||
|
|
11373015d0 | ||
|
|
1b70956120 | ||
|
|
4e37f2b106 | ||
|
|
7a2bd88447 | ||
|
|
9f8f906ef1 | ||
|
|
14b44cb6ec | ||
|
|
b2c991e859 | ||
|
|
dbcbaa2c0b | ||
|
|
2dfb4e9dcc | ||
|
|
fa344c07f6 | ||
|
|
cbf1b7c021 | ||
|
|
989b4038b8 | ||
|
|
f1de5523f0 | ||
|
|
e6508ea7ee | ||
|
|
b57074fd52 | ||
|
|
953b91c90c | ||
|
|
932e57ff98 | ||
|
|
bd21d85bf2 | ||
|
|
fa83b8fa59 | ||
|
|
fea4a270e6 | ||
|
|
afcee6c256 | ||
|
|
3e4d228486 | ||
|
|
cdd86f5765 | ||
|
|
2e4e9c77ef | ||
|
|
3527a2b904 | ||
|
|
a8c564b033 | ||
|
|
2e690c69b1 | ||
|
|
3635d041dc | ||
|
|
76b3e99286 | ||
|
|
7bf8bbb751 | ||
|
|
e6c7f32026 |
27 changed files with 848 additions and 328 deletions
47
README.md
47
README.md
|
|
@ -1,46 +1,5 @@
|
|||
# javapackages-validator-tests
|
||||
# Deprecated
|
||||
|
||||
This repository contains files used for testing Fedora Java packages using the
|
||||
tool `javapackages-validator` and to store configuration files for that tool.
|
||||
This repository is deprecated.
|
||||
|
||||
## Contents
|
||||
|
||||
* **`src/`** -- Configuration `.java` files, described later.
|
||||
* **`jp_validator.sh`** -- The script which calls the validator tool.
|
||||
* **`tests.fmf`** -- The main `.fmf` file containing metadata for all tests.
|
||||
|
||||
## How it works
|
||||
|
||||
The test uses an optional environment variable, `TEST_ARTIFACTS`, which can used
|
||||
to specify the path to RPMs. This allows local test execution.
|
||||
|
||||
The test analyzes the contents of `.rpm` files. The framework used by Fedora
|
||||
provides a standard location `/var/share/test-artifacts` which contains all the
|
||||
RPMs of the package that is being tested.
|
||||
|
||||
Unless overriden, tests obtain the image `javapckages-validator` from `quay.io`
|
||||
and execute it using `podman`. This is done in `jp_validator.sh`.
|
||||
|
||||
## Configuration
|
||||
|
||||
The behaviour of the tests is configured in 3 places:
|
||||
|
||||
1. The actual [source code](https://github.com/fedora-java/javapackages-validator/tree/master).
|
||||
We strive to keep it generic.
|
||||
2. The `.fmf` configuration files used in each package repository. We strive to
|
||||
keep them as small as possible.
|
||||
3. Most of the configuration should be done in this repository in the **src/**
|
||||
directory.
|
||||
|
||||
Custom test configuration is handled by using standard Java interfaces. The
|
||||
tests refer to interfaces and the actual implementations are compiled by
|
||||
validator.
|
||||
|
||||
Implementation is then obtained using reflection by constructing
|
||||
configuration classes using an empty constructor. Validator detects which
|
||||
interfaces the compiled classes implement and uses this information to configure
|
||||
checks.
|
||||
|
||||
It is possible to use multiple configurations for a simple check. In that case,
|
||||
the check is executed as many times as the number of configuration classes that
|
||||
resulted from compilation of the config sources.
|
||||
Javapackages tests were moved to https://gitlab.com/redhat/centos-stream/tests/javapackages
|
||||
|
|
|
|||
33
javapackages.sh
Executable file
33
javapackages.sh
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/bash
|
||||
|
||||
set -eux
|
||||
tmt_root="${TMT_TREE%/tree}"
|
||||
test_data="${TMT_TEST_DATA##"${tmt_root}"/}"
|
||||
|
||||
# Fails with CI which uses a local image
|
||||
if echo "${JP_VALIDATOR_IMAGE}" | grep -q '/'; then
|
||||
podman pull "${JP_VALIDATOR_IMAGE}" || sleep 10
|
||||
fi
|
||||
|
||||
command=(podman run --rm --security-opt='label=disable'
|
||||
--mount type=bind,source="${TEST_ARTIFACTS}",target='/mnt/test-artifacts/',readonly
|
||||
--mount type=bind,source="${tmt_root}",target='/mnt/tmt/'
|
||||
)
|
||||
[ -n "${JP_VALIDATOR_SOURCE_PATH}" ] && command+=(
|
||||
--mount type=bind,source="${JP_VALIDATOR_SOURCE_PATH}",target='/mnt/project/src',readonly
|
||||
)
|
||||
[ -n "${JP_VALIDATOR_OUTPUT_DIR}" ] && command+=(
|
||||
--mount type=bind,source="${JP_VALIDATOR_OUTPUT_DIR}",target='/mnt/project/classes'
|
||||
)
|
||||
command+=(
|
||||
--env TMT_TEST_DATA="/mnt/tmt/${test_data}"
|
||||
--env TMT_TREE="/mnt/tmt/tree"
|
||||
"${JP_VALIDATOR_IMAGE}" org.fedoraproject.javapackages.validator.MainTmt -x
|
||||
-f '/mnt/test-artifacts/'
|
||||
)
|
||||
[ -n "${JP_VALIDATOR_SOURCE_PATH}" ] && command+=(
|
||||
-sp '/mnt/project/src' -d '/mnt/project/classes'
|
||||
)
|
||||
command+=(${JP_VALIDATOR_ARGS})
|
||||
|
||||
exec "${command[@]}"
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
# /mnt/envroot required by SymlinkConfig
|
||||
|
||||
exec podman run --rm --security-opt='label=disable'\
|
||||
--mount type=bind,source="${TEST_ARTIFACTS}",target='/mnt/test_artifacts/',readonly\
|
||||
--mount type=bind,source='src/',target='/mnt/config/',readonly\
|
||||
--mount type=bind,source="${ENVROOT}",target='/mnt/envroot',readonly\
|
||||
"${JP_VALIDATOR_IMAGE}" ${@} '/mnt/test_artifacts/'\
|
||||
;
|
||||
31
main.fmf
Normal file
31
main.fmf
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
summary: Javapackages-validator tests
|
||||
contact:
|
||||
- Marian Koncek <mkoncek@redhat.com>
|
||||
- Mikolaj Izdebski <mizdebsk@redhat.com>
|
||||
description: |
|
||||
This test executes a series of tests checking for various aspects of the Java package.
|
||||
This includes packaging guidelines compliance, package sanity and various regressions.
|
||||
tier: 0
|
||||
framework: shell
|
||||
require:
|
||||
- bash
|
||||
- podman
|
||||
environment:
|
||||
TEST_ARTIFACTS: /var/share/test-artifacts
|
||||
JP_VALIDATOR_IMAGE: quay.io/fedora-java/javapackages-validator:2
|
||||
JP_VALIDATOR_SOURCE_PATH: src
|
||||
JP_VALIDATOR_OUTPUT_DIR: ""
|
||||
JP_VALIDATOR_ARGS: |
|
||||
org.fedoraproject.javapackages.validator.validators.jp.ValidatorFactoryGeneric
|
||||
org.fedoraproject.javapackages.validator.validators.jp.ValidatorFactoryJP
|
||||
io.kojan.runit.validator.RunitValidatorFactory
|
||||
result: custom
|
||||
test: exec ./javapackages.sh
|
||||
|
||||
/javapackages-validator:
|
||||
adjust:
|
||||
# Generic flavor. Run selected upstream validators as well certain downstream ones.
|
||||
- when: jpv_flavor == generic
|
||||
environment+:
|
||||
JP_VALIDATOR_ARGS: |
|
||||
org.fedoraproject.javapackages.validator.validators.jp.ValidatorFactoryGeneric
|
||||
17
src/.project
17
src/.project
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>config</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
package org.fedoraproject.javapackages.validator.config;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.fedoraproject.javadeptools.rpm.RpmInfo;
|
||||
import org.fedoraproject.javapackages.validator.Common;
|
||||
import org.fedoraproject.javapackages.validator.config.BytecodeVersionConfig;
|
||||
|
||||
public class BytecodeVersionConfigJP implements BytecodeVersionConfig {
|
||||
private Set<String> packagesReqVersion8 = Set.of(new String[] {
|
||||
"maven",
|
||||
"apache-commons-cli",
|
||||
"apache-commons-codec",
|
||||
"apache-commons-io",
|
||||
"apache-commons-lang3",
|
||||
"atinject",
|
||||
"cdi-api",
|
||||
"google-guice",
|
||||
"guava",
|
||||
"httpcomponents-client",
|
||||
"httpcomponents-core",
|
||||
"jakarta-annotations",
|
||||
"jansi",
|
||||
"jsr-305",
|
||||
"maven-resolver",
|
||||
"maven-shared-utils",
|
||||
"maven-wagon",
|
||||
"plexus-cipher",
|
||||
"plexus-classworlds",
|
||||
"plexus-containers",
|
||||
"plexus-interpolation",
|
||||
"plexus-sec-dispatcher",
|
||||
"plexus-utils",
|
||||
"sisu",
|
||||
"slf4j",
|
||||
|
||||
"ant",
|
||||
"antlr",
|
||||
"apache-commons-net",
|
||||
"bcel",
|
||||
"bsf",
|
||||
"jakarta-activation1",
|
||||
"jakarta-mail",
|
||||
"jakarta-oro",
|
||||
"jdepend",
|
||||
"jsch",
|
||||
"jzlib",
|
||||
"regexp",
|
||||
"xalan-j2",
|
||||
"xerces-j2",
|
||||
"xml-commons-apis",
|
||||
"xml-commons-resolver",
|
||||
});
|
||||
|
||||
@Override
|
||||
public boolean allowedVersion(RpmInfo rpm, String jarName, String className, int version) {
|
||||
// JEP 238: Multi-Release JAR Files
|
||||
// https://openjdk.org/jeps/238
|
||||
if (className.startsWith("META-INF/versions/")) {
|
||||
return version <= 44 + Integer.parseInt(className.substring(18, className.indexOf('/', 18)));
|
||||
}
|
||||
|
||||
if (className.equals("module-info.class") || className.equals("package-info.class")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (packagesReqVersion8.contains(rpm.getPackageName())) {
|
||||
return version <= 44 + 8;
|
||||
}
|
||||
|
||||
return version <= 44 + 17;
|
||||
}
|
||||
}
|
||||
115
src/BytecodeVersionJarValidatorJP.java
Normal file
115
src/BytecodeVersionJarValidatorJP.java
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
package org.fedoraproject.javapackages.validator.validators.jp;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.fedoraproject.javapackages.validator.spi.Decorated;
|
||||
import org.fedoraproject.javapackages.validator.util.BytecodeVersionJarValidator;
|
||||
import org.fedoraproject.javapackages.validator.util.Common;
|
||||
|
||||
import io.kojan.javadeptools.rpm.RpmPackage;
|
||||
|
||||
public class BytecodeVersionJarValidatorJP extends BytecodeVersionJarValidator {
|
||||
@Override
|
||||
public String getTestName() {
|
||||
return "/java/jp/bytecode_version";
|
||||
}
|
||||
|
||||
private Set<String> packagesReqVersion8 = Set.of(new String[] {
|
||||
"maven",
|
||||
"apache-commons-cli",
|
||||
"apache-commons-codec",
|
||||
"apache-commons-io",
|
||||
"apache-commons-lang3",
|
||||
"atinject",
|
||||
"cdi-api",
|
||||
"google-guice",
|
||||
"guava",
|
||||
"httpcomponents-client",
|
||||
"httpcomponents-core",
|
||||
"jakarta-annotations",
|
||||
"jansi",
|
||||
"jsr-305",
|
||||
"maven-resolver",
|
||||
"maven-shared-utils",
|
||||
"maven-wagon",
|
||||
"plexus-cipher",
|
||||
"plexus-classworlds",
|
||||
"plexus-containers",
|
||||
"plexus-interpolation",
|
||||
"plexus-sec-dispatcher",
|
||||
"plexus-utils",
|
||||
"sisu",
|
||||
"slf4j",
|
||||
|
||||
"ant",
|
||||
"antlr",
|
||||
"apache-commons-net",
|
||||
"bcel",
|
||||
"bsf",
|
||||
"jakarta-activation1",
|
||||
"jakarta-mail",
|
||||
"jakarta-oro",
|
||||
"jdepend",
|
||||
"jsch",
|
||||
"jzlib",
|
||||
"regexp",
|
||||
"xalan-j2",
|
||||
"xerces-j2",
|
||||
"xml-commons-apis",
|
||||
"xml-commons-resolver",
|
||||
});
|
||||
|
||||
@Override
|
||||
public void validate(RpmPackage rpm, Path jarPath, Map<Path, Version> classVersions) {
|
||||
for (var entry : classVersions.entrySet()) {
|
||||
Path classPath = entry.getKey();
|
||||
int version = entry.getValue().major();
|
||||
int maxAllowedVersion = 21;
|
||||
int expected;
|
||||
|
||||
if (classPath.endsWith("module-info.class") || classPath.endsWith("package-info.class")) {
|
||||
// pass
|
||||
} else if (classPath.startsWith("META-INF/versions")) {
|
||||
// JEP 238: Multi-Release JAR Files
|
||||
// https://openjdk.org/jeps/238
|
||||
|
||||
if (version > 44 + (expected = Short.parseShort(classPath.getName(2).toString()))) {
|
||||
fail("{0}: {1}: {2}: class bytecode version is {3} which is larger than {4}",
|
||||
Decorated.rpm(rpm),
|
||||
Decorated.custom(jarPath, DECORATION_JAR),
|
||||
Decorated.struct(classPath),
|
||||
Decorated.actual(version),
|
||||
Decorated.expected(expected));
|
||||
continue;
|
||||
} else {
|
||||
// pass
|
||||
}
|
||||
} else if (packagesReqVersion8.contains(Common.getPackageName(rpm.getInfo())) && version > 44 + 8) {
|
||||
fail("{0}: {1}: {2}: class bytecode version is {3} which is larger than {4} (package is required to have a bytecode version compatible with JVM 8)",
|
||||
Decorated.rpm(rpm),
|
||||
Decorated.custom(jarPath, DECORATION_JAR),
|
||||
Decorated.struct(classPath),
|
||||
Decorated.actual(version),
|
||||
Decorated.expected(44 + 8));
|
||||
continue;
|
||||
} else if (version > 44 + maxAllowedVersion) {
|
||||
fail("{0}: {1}: {2}: class bytecode version is {3} which is larger than {4} (all packages should have bytecode version compatible with JVM {5})",
|
||||
Decorated.rpm(rpm),
|
||||
Decorated.custom(jarPath, DECORATION_JAR),
|
||||
Decorated.struct(classPath),
|
||||
Decorated.actual(version),
|
||||
Decorated.expected(44 + maxAllowedVersion),
|
||||
Decorated.plain(maxAllowedVersion));
|
||||
continue;
|
||||
}
|
||||
|
||||
pass("{0}: {1}: {2}: class bytecode version: {3}",
|
||||
Decorated.rpm(rpm),
|
||||
Decorated.custom(jarPath, DECORATION_JAR),
|
||||
Decorated.struct(classPath),
|
||||
Decorated.actual(version));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
package org.fedoraproject.javapackages.validator.config;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.fedoraproject.javadeptools.rpm.RpmInfo;
|
||||
import org.fedoraproject.javapackages.validator.Common;
|
||||
|
||||
public class DuplicateFileConfigJP implements DuplicateFileConfig {
|
||||
@Override
|
||||
public boolean allowedDuplicateFile(Path path, Collection<? extends RpmInfo> providerRpms) {
|
||||
if (path.toString().startsWith("/usr/share/licenses/")) {
|
||||
return providerRpms.stream().map(RpmInfo::getPackageName).distinct().count() == 1;
|
||||
}
|
||||
|
||||
if (providerRpms.stream().allMatch(rpm -> rpm.getName().startsWith("maven-openjdk"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (providerRpms.stream().allMatch(rpm -> rpm.getName().startsWith("maven-local-openjdk"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
30
src/DuplicateFileValidatorJP.java
Normal file
30
src/DuplicateFileValidatorJP.java
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package org.fedoraproject.javapackages.validator.validators.jp;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.fedoraproject.javapackages.validator.util.Common;
|
||||
import org.fedoraproject.javapackages.validator.util.DuplicateFileValidator.DefaultDuplicateFileValidator;
|
||||
|
||||
import io.kojan.javadeptools.rpm.RpmInfo;
|
||||
|
||||
public class DuplicateFileValidatorJP extends DefaultDuplicateFileValidator {
|
||||
@Override
|
||||
public String getTestName() {
|
||||
return "/jp/duplicate_files";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowedDuplicateFile(Path path, Collection<? extends RpmInfo> providerRpms) throws Exception {
|
||||
if (path.getParent().equals(Path.of("/usr/share/jpbinding"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME we want to get rid of these duplicates
|
||||
if (path.toString().startsWith("/usr/share/licenses/")) {
|
||||
return providerRpms.stream().map(Common::getPackageName).distinct().count() == 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +1,51 @@
|
|||
package org.fedoraproject.javapackages.validator.config;
|
||||
package org.fedoraproject.javapackages.validator.validators.jp;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.fedoraproject.javadeptools.rpm.RpmInfo;
|
||||
import org.fedoraproject.javapackages.validator.spi.Decorated;
|
||||
import org.fedoraproject.javapackages.validator.util.Common;
|
||||
import org.fedoraproject.javapackages.validator.util.FilesValidator;
|
||||
|
||||
import io.kojan.javadeptools.rpm.RpmInfo;
|
||||
import io.kojan.javadeptools.rpm.RpmPackage;
|
||||
|
||||
public class FilesValidatorJP extends FilesValidator {
|
||||
@Override
|
||||
public String getTestName() {
|
||||
return "/jp/files";
|
||||
}
|
||||
|
||||
public class FilesConfigJP implements FilesConfig {
|
||||
private Map<String, Pattern> patternsCache = new TreeMap<>();
|
||||
|
||||
private static String substitute(RpmInfo rpm, String text) {
|
||||
return text
|
||||
.replace("${package}", rpm.getPackageName())
|
||||
.replace("${package}", Common.getPackageName(rpm))
|
||||
.replace("${rpm.name}", rpm.getName())
|
||||
;
|
||||
}
|
||||
|
||||
private static class Prefix {
|
||||
static final String ETC = "/etc/${package}";
|
||||
static final String JPBINDING = "/usr/share/jpbinding";
|
||||
static final String ETC_PKG = "/etc/${package}";
|
||||
static final String ETC_JAVA = "/etc/java";
|
||||
static final String USR_BIN = "/usr/bin/";
|
||||
static final String USR_LIB_BUILD_ID = "/usr/lib/.build-id";
|
||||
}
|
||||
|
||||
private static Set<String> ignoredComponents = new LinkedHashSet<>();
|
||||
static {
|
||||
ignoredComponents.add("javapackages-bootstrap");
|
||||
ignoredComponents.add("javapackages-tools");
|
||||
}
|
||||
|
||||
private static Map<String, List<String>> nameAliases = new TreeMap<>();
|
||||
static {
|
||||
nameAliases.put("maven-resolver", List.of("aether"));
|
||||
|
|
@ -40,30 +60,33 @@ public class FilesConfigJP implements FilesConfig {
|
|||
|
||||
private static Map<String, List<String>> prefixes = new TreeMap<>();
|
||||
static {
|
||||
prefixes.put("ant", List.of(Prefix.ETC, Prefix.USR_BIN));
|
||||
prefixes.put("ant", List.of(Prefix.ETC_PKG, Prefix.ETC_JAVA, Prefix.JPBINDING, Prefix.USR_BIN));
|
||||
prefixes.put("antlr", List.of(Prefix.USR_BIN));
|
||||
prefixes.put("aqute-bnd", List.of(Prefix.USR_BIN));
|
||||
prefixes.put("byaccj", List.of(Prefix.USR_BIN, Prefix.USR_LIB_BUILD_ID));
|
||||
prefixes.put("jansi", List.of(Prefix.USR_LIB_BUILD_ID));
|
||||
prefixes.put("javacc", List.of(Prefix.USR_BIN));
|
||||
prefixes.put("java_cup", List.of(Prefix.USR_BIN));
|
||||
prefixes.put("javapackages-bootstrap", List.of("/usr/lib/java/javapackages-bootstrap", "/usr/lib/rpm", "/etc/rpm", "/usr/libexec/javapackages-bootstrap"));
|
||||
prefixes.put("javapackages-tools", List.of(Prefix.USR_BIN, "/usr/share/xmvn/conf", "/usr/lib/rpm", "/usr/share/java-utils/", "/usr/lib/eclipse", "/usr/share/eclipse", "/etc/java", "/etc/jvm", "/usr/lib/java", "/usr/lib/jvm", "/etc/ivy", "/etc/ant.d"));
|
||||
prefixes.put("jflex", List.of(Prefix.USR_BIN));
|
||||
prefixes.put("maven", List.of(Prefix.ETC));
|
||||
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));
|
||||
prefixes.put("xml-commons-resolver", List.of(Prefix.USR_BIN));
|
||||
prefixes.put("xmvn", List.of(Prefix.USR_BIN));
|
||||
prefixes.put("xmvn", List.of(Prefix.JPBINDING, Prefix.USR_BIN));
|
||||
prefixes.put("xmvn-generator", List.of("/usr/lib/rpm", "/etc/rpm"));
|
||||
}
|
||||
|
||||
private static Map<String, List<String>> exceptionalFiles = new TreeMap<>();
|
||||
static {
|
||||
exceptionalFiles.put("aqute-bnd", List.of("/etc/ant.d/aqute-bnd"));
|
||||
exceptionalFiles.put("maven", List.of("/etc/m2.conf", "/etc/java/maven.conf"));
|
||||
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("javapackages-tools", List.of("/usr/share/java-utils", "/usr/share/xmvn", "/usr/share/ivy-xmls", "/usr/share/java", "/usr/share/javadoc", "/usr/share/jvm", "/usr/share/jvm-common", "/usr/share/maven-metadata", "/usr/share/maven-poms"));
|
||||
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) {
|
||||
|
|
@ -105,13 +128,13 @@ public class FilesConfigJP implements FilesConfig {
|
|||
private static final Pattern DOC_LICENSE_PATTERN = Pattern.compile("/usr/share/(doc|licenses)/([^/]*)(.*)");
|
||||
|
||||
private boolean allowedAnyFile(RpmInfo rpm, String filename) {
|
||||
for (String prefix : prefixes.getOrDefault(rpm.getPackageName(), Collections.emptyList())) {
|
||||
for (String prefix : prefixes.getOrDefault(Common.getPackageName(rpm), Collections.emptyList())) {
|
||||
if (filename.startsWith(substitute(rpm, prefix))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (String filepath : exceptionalFiles.getOrDefault(rpm.getPackageName(), Collections.emptyList())) {
|
||||
for (String filepath : exceptionalFiles.getOrDefault(Common.getPackageName(rpm), Collections.emptyList())) {
|
||||
if (filename.equals(filepath)) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -145,8 +168,8 @@ public class FilesConfigJP implements FilesConfig {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (patternsCache.computeIfAbsent(rpm.getPackageName() + "/javadoc",
|
||||
p -> Pattern.compile("/usr/share/javadoc/" + rpm.getPackageName() + "(:?/.*)?"))
|
||||
if (patternsCache.computeIfAbsent(Common.getPackageName(rpm) + "/javadoc",
|
||||
_ -> Pattern.compile("/usr/share/javadoc/" + Common.getPackageName(rpm) + "(:?/.*)?"))
|
||||
.matcher(filename).matches()) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -221,7 +244,7 @@ public class FilesConfigJP implements FilesConfig {
|
|||
}
|
||||
|
||||
if (namesRelated(rpm.getName(), rpmEntryPrefix)
|
||||
|| namesRelated(rpm.getPackageName(), rpmEntryPrefix)
|
||||
|| namesRelated(Common.getPackageName(rpm), rpmEntryPrefix)
|
||||
|| isAlias(rpm.getName(), rpmEntryPrefix)) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -240,7 +263,7 @@ public class FilesConfigJP implements FilesConfig {
|
|||
}
|
||||
|
||||
if (namesRelated(rpm.getName(), rpmEntryPrefix)
|
||||
|| namesRelated(rpm.getPackageName(), rpmEntryPrefix)
|
||||
|| namesRelated(Common.getPackageName(rpm), rpmEntryPrefix)
|
||||
|| isAlias(rpm.getName(), rpmEntryPrefix)) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -258,7 +281,7 @@ public class FilesConfigJP implements FilesConfig {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (filename.startsWith("/usr/bin/" + rpm.getPackageName() + "/")) {
|
||||
if (filename.startsWith("/usr/bin/" + Common.getPackageName(rpm) + "/")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -308,6 +331,16 @@ public class FilesConfigJP implements FilesConfig {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(RpmPackage rpm) throws Exception {
|
||||
if (ignoredComponents.contains(rpm.getInfo().getSourceName())) {
|
||||
skip("{0}: the component {1} is ignored", Decorated.rpm(rpm),
|
||||
Decorated.actual(rpm.getInfo().getSourceName()));
|
||||
} else {
|
||||
super.validate(rpm);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowedFile(RpmInfo rpm, Path path) {
|
||||
if (rpm.isSourcePackage()) {
|
||||
|
|
@ -315,21 +348,20 @@ public class FilesConfigJP implements FilesConfig {
|
|||
return true;
|
||||
}
|
||||
|
||||
// TODO
|
||||
String filename = path.toString();
|
||||
|
||||
if (rpm.getName().equals(rpm.getPackageName() + "-javadoc") || rpm.getName().equals(rpm.getPackageName() + "-javadocs")) {
|
||||
if (rpm.getName().equals(Common.getPackageName(rpm) + "-javadoc") || rpm.getName().equals(Common.getPackageName(rpm) + "-javadocs")) {
|
||||
return allowedJavadocFile(rpm, filename);
|
||||
} else if (rpm.getName().equals(rpm.getPackageName() + "-debuginfo")) {
|
||||
} else if (rpm.getName().equals(Common.getPackageName(rpm) + "-debuginfo")) {
|
||||
return allowedDebuginfoFile(rpm, filename);
|
||||
} else if (rpm.getName().equals(rpm.getPackageName() + "-debugsource")) {
|
||||
} else if (rpm.getName().equals(Common.getPackageName(rpm) + "-debugsource")) {
|
||||
return allowedDebugsourceFile(rpm, filename);
|
||||
} else if (rpm.getName().startsWith("python3-javapackages")) {
|
||||
return allowedPythonLibraryFile(rpm, filename);
|
||||
} else if (rpm.getName().startsWith("antlr-C++")) {
|
||||
return allowedCLibraryFile(rpm, filename);
|
||||
} else {
|
||||
// TODO differentiate Java applications ad libraries
|
||||
// TODO differentiate Java applications ad libraries
|
||||
return allowedJavaApplicationFile(rpm, filename);
|
||||
}
|
||||
}
|
||||
27
src/JavaExclusiveArchValidatorJP.java
Normal file
27
src/JavaExclusiveArchValidatorJP.java
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package org.fedoraproject.javapackages.validator.validators.jp;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.fedoraproject.javapackages.validator.spi.Decorated;
|
||||
import org.fedoraproject.javapackages.validator.validators.JavaExclusiveArchValidator;
|
||||
|
||||
import io.kojan.javadeptools.rpm.RpmPackage;
|
||||
|
||||
public class JavaExclusiveArchValidatorJP extends JavaExclusiveArchValidator {
|
||||
@Override
|
||||
public String getTestName() {
|
||||
return "/java/jp/exclusive_arch";
|
||||
}
|
||||
|
||||
private static final Set<String> SKIPPED = Set.of("javapackages-tools", "byaccj", "jurand");
|
||||
|
||||
@Override
|
||||
public void validate(RpmPackage rpm) throws Exception {
|
||||
String component = rpm.getInfo().getSourceName();
|
||||
if (SKIPPED.contains(component)) {
|
||||
skip("Skipping rpm {0}", Decorated.rpm(rpm));
|
||||
return;
|
||||
}
|
||||
super.validate(rpm);
|
||||
}
|
||||
}
|
||||
23
src/JpmsProvidesValidatorJP.java
Normal file
23
src/JpmsProvidesValidatorJP.java
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
package org.fedoraproject.javapackages.validator.validators.jp;
|
||||
|
||||
import org.apache.commons.compress.archivers.cpio.CpioArchiveEntry;
|
||||
import org.fedoraproject.javapackages.validator.spi.Decorated;
|
||||
import org.fedoraproject.javapackages.validator.validators.JpmsProvidesValidator;
|
||||
|
||||
import io.kojan.javadeptools.rpm.RpmPackage;
|
||||
|
||||
public class JpmsProvidesValidatorJP extends JpmsProvidesValidator {
|
||||
@Override
|
||||
public String getTestName() {
|
||||
return "/java/jp/jpms-provides";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptJarEntry(RpmPackage rpm, CpioArchiveEntry cpio, byte[] bytes) throws Exception {
|
||||
if (rpm.getInfo().getSourceName().equals("javapackages-bootstrap")) {
|
||||
skip("Skipping rpm {0}", Decorated.rpm(rpm));
|
||||
return;
|
||||
}
|
||||
super.acceptJarEntry(rpm, cpio, bytes);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
package org.fedoraproject.javapackages.validator.config;
|
||||
|
||||
import org.fedoraproject.javadeptools.rpm.RpmInfo;
|
||||
import org.fedoraproject.javapackages.validator.Common;
|
||||
|
||||
public class RpmFilesizeConfigJP implements RpmFilesizeConfig {
|
||||
@Override
|
||||
public boolean allowedFilesize(RpmInfo rpm, long sizeBytes) {
|
||||
if (rpm.isSourcePackage()) {
|
||||
return sizeBytes <= 1_000_000_000;
|
||||
}
|
||||
|
||||
if (rpm.getPackageName().equals("javapackages-bootstrap")) {
|
||||
return sizeBytes <= 40_000_000;
|
||||
}
|
||||
|
||||
// javadoc rpms
|
||||
if (rpm.getName().equals(rpm.getPackageName() + "-javadoc")) {
|
||||
return sizeBytes <= 4_000_000;
|
||||
}
|
||||
|
||||
// maven-lib and xmvn-minimal bundle dependencies during bootstrap
|
||||
if (rpm.getRelease().endsWith("~bootstrap")) {
|
||||
if (rpm.getName().equals("maven-lib") || rpm.getName().equals("xmvn-minimal")) {
|
||||
return sizeBytes <= 10_000_000;
|
||||
}
|
||||
}
|
||||
|
||||
return sizeBytes <= 3_500_000;
|
||||
}
|
||||
}
|
||||
38
src/RpmFilesizeValidatorJP.java
Normal file
38
src/RpmFilesizeValidatorJP.java
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package org.fedoraproject.javapackages.validator.validators.jp;
|
||||
|
||||
import org.fedoraproject.javapackages.validator.util.Common;
|
||||
import org.fedoraproject.javapackages.validator.util.RpmFilesizeValidator;
|
||||
|
||||
import io.kojan.javadeptools.rpm.RpmInfo;
|
||||
|
||||
public class RpmFilesizeValidatorJP extends RpmFilesizeValidator {
|
||||
@Override
|
||||
public String getTestName() {
|
||||
return "/jp/rpm_filesize";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowedFilesize(RpmInfo rpm, long sizeBytes) {
|
||||
if (rpm.isSourcePackage()) {
|
||||
return sizeBytes <= 1_000_000_000;
|
||||
}
|
||||
|
||||
if (Common.getPackageName(rpm).equals("javapackages-bootstrap")) {
|
||||
return sizeBytes <= 60_000_000;
|
||||
}
|
||||
|
||||
// javadoc rpms
|
||||
if (rpm.getName().equals(Common.getPackageName(rpm) + "-javadoc")) {
|
||||
return sizeBytes <= 4_000_000;
|
||||
}
|
||||
|
||||
// maven-lib and xmvn-minimal bundle dependencies during bootstrap
|
||||
if (rpm.getRelease().endsWith("~bootstrap")) {
|
||||
if (rpm.getName().equals("maven-lib") || rpm.getName().equals("xmvn-minimal")) {
|
||||
return sizeBytes <= 10_000_000;
|
||||
}
|
||||
}
|
||||
|
||||
return sizeBytes <= 4_000_000;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
package org.fedoraproject.javapackages.validator.config;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class SymlinkConfigJP extends SymlinkConfig.EnvrootImpl {
|
||||
public SymlinkConfigJP() {
|
||||
super(Paths.get("/mnt/envroot"));
|
||||
}
|
||||
}
|
||||
20
src/ValidatorFactoryGeneric.java
Normal file
20
src/ValidatorFactoryGeneric.java
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package org.fedoraproject.javapackages.validator.validators.jp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.fedoraproject.javapackages.validator.spi.Validator;
|
||||
import org.fedoraproject.javapackages.validator.spi.ValidatorFactory;
|
||||
import org.fedoraproject.javapackages.validator.validators.*;
|
||||
|
||||
public class ValidatorFactoryGeneric implements ValidatorFactory {
|
||||
@Override
|
||||
public List<Validator> getValidators() {
|
||||
return List.of(new Validator[] {
|
||||
new AttributeProvidesValidator(),
|
||||
new JavadocNoarchValidator(),
|
||||
new JavaExclusiveArchValidatorJP(),
|
||||
new MavenMetadataValidator(),
|
||||
new NoBootstrapValidator(),
|
||||
});
|
||||
}
|
||||
}
|
||||
18
src/ValidatorFactoryJP.java
Normal file
18
src/ValidatorFactoryJP.java
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package org.fedoraproject.javapackages.validator.validators.jp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.fedoraproject.javapackages.validator.spi.Validator;
|
||||
import org.fedoraproject.javapackages.validator.spi.ValidatorFactory;
|
||||
|
||||
public class ValidatorFactoryJP implements ValidatorFactory {
|
||||
@Override
|
||||
public List<Validator> getValidators() {
|
||||
return List.of(new Validator[] {
|
||||
new BytecodeVersionJarValidatorJP(),
|
||||
new DuplicateFileValidatorJP(),
|
||||
new FilesValidatorJP(),
|
||||
new RpmFilesizeValidatorJP(),
|
||||
});
|
||||
}
|
||||
}
|
||||
13
src/javapackages-validator.properties
Normal file
13
src/javapackages-validator.properties
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
compiler.release=22
|
||||
#repositories=https://s01.oss.sonatype.org/content/repositories/snapshots
|
||||
dependencies=\
|
||||
io.kojan:runit-api:1.0.0 \
|
||||
io.kojan:runit-validator:1.0.0 \
|
||||
org.apiguardian:apiguardian-api:1.1.2 \
|
||||
org.hamcrest:hamcrest:3.0 \
|
||||
org.junit.jupiter:junit-jupiter-api:5.11.3 \
|
||||
org.junit.jupiter:junit-jupiter-engine:5.11.3 \
|
||||
org.junit.platform:junit-platform-commons:1.11.3 \
|
||||
org.junit.platform:junit-platform-engine:1.11.3 \
|
||||
org.junit.platform:junit-platform-launcher:1.11.3 \
|
||||
org.opentest4j:opentest4j:1.3.0 \
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
org.fedoraproject.javapackages.validator.validators.jp.ValidatorFactoryGeneric
|
||||
org.fedoraproject.javapackages.validator.validators.jp.ValidatorFactoryJP
|
||||
37
src/runit/ApacheCommonsCheck.java
Normal file
37
src/runit/ApacheCommonsCheck.java
Normal 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 org.junit.jupiter.api.DisplayName;
|
||||
|
||||
import io.kojan.javadeptools.rpm.*;
|
||||
import io.kojan.runit.api.*;
|
||||
|
||||
@DisplayName("/apache-commons")
|
||||
public class ApacheCommonsCheck {
|
||||
|
||||
@PackageTest
|
||||
@IncludeSource("apache-commons-.*")
|
||||
@IncludeBinary("apache-commons-.*")
|
||||
@ExcludeBinary("apache-commons-collections-testframework")
|
||||
public void saneName(RpmInfo rpm) {
|
||||
assertThat("Package name is sane", rpm.getName(), matchesRegex("apache-commons-[a-z][a-z0-9]+(-javadoc)?"));
|
||||
}
|
||||
|
||||
@PackageTest
|
||||
@IncludeBinary("apache-commons-[a-z][a-z0-9]+")
|
||||
@ExcludeBinary("apache-commons-parent") // Parent POM, no Java code
|
||||
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"));
|
||||
}
|
||||
}
|
||||
57
src/runit/BasicCheck.java
Normal file
57
src/runit/BasicCheck.java
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package tests;
|
||||
|
||||
import static io.kojan.runit.api.RUnit.*;
|
||||
import static io.kojan.runit.api.matcher.RUnitMatchers.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
|
||||
import io.kojan.javadeptools.rpm.*;
|
||||
import io.kojan.runit.api.*;
|
||||
|
||||
@DisplayName("/basic")
|
||||
public class BasicCheck {
|
||||
|
||||
@PackageTest
|
||||
public void noBootstrapRelease(RpmInfo rpm) {
|
||||
assertThat("No ~bootstrap in release", rpm.getRelease(), not(endsWith("~bootstrap")));
|
||||
}
|
||||
|
||||
@PackageTest
|
||||
@ExcludeSource("java_cup")
|
||||
@ExcludeBinary("java_cup")
|
||||
@ExcludeBinary("java_cup-javadoc")
|
||||
@ExcludeBinary("java_cup-manual")
|
||||
@ExcludeBinary("antlr-C\\+\\+")
|
||||
public void saneName(RpmInfo rpm) {
|
||||
assertThat("Package name is sane", rpm.getName(), matchesRegex("[a-z][a-z0-9.-]+[a-z0-9]"));
|
||||
}
|
||||
|
||||
@PackageTest
|
||||
@ExcludeBinary("maven-lib")
|
||||
@ExcludeBinary("sisu")
|
||||
@ExcludeBinary("javapackages-bootstrap")
|
||||
public void bundledProvides(RpmInfo rpm) {
|
||||
assertThat("No bundled(*) provides", rpm, not(provides("bundled\\(.*\\)")));
|
||||
}
|
||||
|
||||
@PackageTest
|
||||
@IncludeBinary
|
||||
public void binaryVersionMatchesSourceVersion(RpmInfo rpm) {
|
||||
Pattern srpmPattern = Pattern.compile("^(.+)-([^-]+)-([^-]+).src.rpm$");
|
||||
Matcher matcher = srpmPattern.matcher(rpm.getSourceRPM());
|
||||
assertThat("SRPM name matches regex", matcher.matches(), is(true));
|
||||
assertThat("Binary package Version matches SRPM Version", rpm.getVersion(), is(matcher.group(2)));
|
||||
assertThat("Binary package Release matches SRPM Release", rpm.getRelease(), is(matcher.group(3)));
|
||||
}
|
||||
|
||||
@PackageTest
|
||||
@IncludeBinary
|
||||
public void noConflicts(RpmInfo rpm) {
|
||||
assertThat("Packages have no explicit Conflicts", rpm, not(conflicts(".*")));
|
||||
}
|
||||
|
||||
}
|
||||
49
src/runit/FileCheck.java
Normal file
49
src/runit/FileCheck.java
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package tests;
|
||||
|
||||
import static io.kojan.runit.api.RUnit.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
|
||||
import io.kojan.javadeptools.rpm.*;
|
||||
import io.kojan.runit.api.*;
|
||||
|
||||
@DisplayName("/file")
|
||||
public class FileCheck {
|
||||
|
||||
@FileTest
|
||||
@IncludeRegularFile
|
||||
@ExcludeBinary(".*-debuginfo")
|
||||
public void elvesLiveInUserLib(RpmInfo rpm, Path path, byte[] data, RpmFile entry) {
|
||||
assumeThat("File is not too small to be ELF", entry.getSize(), is(greaterThanOrEqualTo(4L)));
|
||||
assumeThat("ELF magic is present", Arrays.copyOfRange(data, 0, 4), is(new byte[] { 0x7f, 'E', 'L', 'F' }));
|
||||
assertThat("ELF files must be under /usr/lib", path.toString(), startsWith("/usr/lib/"));
|
||||
assertThat("Noarch packages must not contain ELF files", rpm.getArch(), is(not("noarch")));
|
||||
}
|
||||
|
||||
@FileTest
|
||||
@IncludeBinary
|
||||
@ExcludeBinary(".*-debuginfo")
|
||||
public void modeTest(RpmInfo rpm, Path path, byte[] data, RpmFile entry) throws Exception {
|
||||
String mode = Integer.toOctalString((int) entry.getMode() & 07777);
|
||||
if (entry.isRegularFile()) {
|
||||
if (entry.getSize() >= 4 && data[0] == 0x7f && data[1] == 'E' && data[2] == 'L' && data[3] == 'F') {
|
||||
assertThat("ELF files must have mode 755", mode, is("755"));
|
||||
} else if (entry.getSize() >= 2 && data[0] == '#' && data[1] == '!') {
|
||||
assertThat("Files with shebang must have mode 755", mode, is("755"));
|
||||
} else if (entry.getSize() == 0) {
|
||||
assertThat("Empty files must have mode 644 or 0", mode, either(is("644")).or(is("0")));
|
||||
} else {
|
||||
assertThat("Other regular files must have mode 644", mode, is("644"));
|
||||
}
|
||||
} else if (entry.isDirectory()) {
|
||||
assertThat("Directories must have mode 755", mode, is("755"));
|
||||
} else if (!entry.isSymbolicLink()) {
|
||||
assertThat("Not a regular file, not a symlink and not a directory", false, is(true));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
37
src/runit/JPackageScriptCheck.java
Normal file
37
src/runit/JPackageScriptCheck.java
Normal 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"));
|
||||
}
|
||||
}
|
||||
43
src/runit/JarCheck.java
Normal file
43
src/runit/JarCheck.java
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
package tests;
|
||||
|
||||
import static io.kojan.runit.api.RUnit.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
|
||||
import io.kojan.javadeptools.rpm.*;
|
||||
import io.kojan.runit.api.*;
|
||||
|
||||
@DisplayName("/jar")
|
||||
public class JarCheck {
|
||||
|
||||
@FileTest
|
||||
@IncludeFileName("/usr/(share|lib)/java/.*\\.jar")
|
||||
@ExcludeSource
|
||||
@ExcludeSymlink
|
||||
public void testJarSanity(RpmInfo rpm, Path path, byte[] content, RpmFile entry) throws Exception {
|
||||
assertThat("JAR file must be a regular file", entry.isRegularFile(), is(true));
|
||||
assertThat("JAR file mode must be 644", Integer.toOctalString((int) entry.getMode() & 07777), is("644"));
|
||||
assertThat("JAR file must not be empty", entry.getSize(), greaterThan(10L));
|
||||
assertThat("JAR file has PKZIP magic number", (char) content[0], is('P'));
|
||||
assertThat("JAR file has PKZIP magic number", (char) content[1], is('K'));
|
||||
try (JarInputStream jis = new JarInputStream(new ByteArrayInputStream(content))) {
|
||||
Manifest mf = jis.getManifest();
|
||||
assertThat("JAR must have manifest", mf, not(nullValue()));
|
||||
Attributes attrs = mf.getMainAttributes();
|
||||
assertThat("JAR must have main attritutes", attrs, not(nullValue()));
|
||||
for (String attr : Arrays.asList("Javapackages-GroupId", "Javapackages-ArtifactId",
|
||||
"Javapackages-Version")) {
|
||||
String val = attrs.getValue(attr);
|
||||
assertThat("JAR must have " + attr + " manifest attribute", val, not(nullValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/runit/JavadocCheck.java
Normal file
28
src/runit/JavadocCheck.java
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package tests;
|
||||
|
||||
import static io.kojan.runit.api.RUnit.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
|
||||
import io.kojan.javadeptools.rpm.*;
|
||||
import io.kojan.runit.api.*;
|
||||
|
||||
@DisplayName("/javadoc")
|
||||
public class JavadocCheck {
|
||||
|
||||
@PackageTest
|
||||
@IncludeBinary(".*-javadoc")
|
||||
public void testJavadocNoarch(RpmInfo rpm) {
|
||||
assertThat("Javadoc package is noarch", rpm.getArch(), is("noarch"));
|
||||
}
|
||||
|
||||
@FileTest
|
||||
@IncludeBinary(".*-javadoc")
|
||||
public void javadocFiles(RpmInfo rpm, Path path) {
|
||||
assertThat("Javadoc package contains only javadoc content", path.toString(),
|
||||
anyOf(startsWith("/usr/share/javadoc/"), startsWith("/usr/share/licenses/")));
|
||||
}
|
||||
}
|
||||
188
src/runit/LicenseCheck.java
Normal file
188
src/runit/LicenseCheck.java
Normal 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");
|
||||
}
|
||||
}
|
||||
92
tests.fmf
92
tests.fmf
|
|
@ -1,92 +0,0 @@
|
|||
contact:
|
||||
- Marian Koncek <mkoncek@redhat.com>
|
||||
require:
|
||||
- bash
|
||||
- findutils
|
||||
- podman
|
||||
environment:
|
||||
TEST_ARTIFACTS: /var/share/test-artifacts
|
||||
JP_VALIDATOR_IMAGE: quay.io/mizdebsk/javapackages-validator
|
||||
ENVROOT: /
|
||||
|
||||
/symlink:
|
||||
description: >
|
||||
Check for files inside RPMs. This test checks for dangling symlinks.
|
||||
(configurable)
|
||||
test: ./jp_validator.sh SymlinkCheck -c /mnt/config/SymlinkConfigJP.java
|
||||
adjust:
|
||||
- enabled: false
|
||||
when: trigger == MBICI
|
||||
|
||||
/duplicate_file:
|
||||
description: >
|
||||
Check for files inside RPMs. This test checks multiple RPMs at once and
|
||||
tests for duplicate files.
|
||||
(configurable)
|
||||
test: ./jp_validator.sh DuplicateFileCheck -c /mnt/config/DuplicateFileConfigJP.java
|
||||
|
||||
/rpm_filesize:
|
||||
description: >
|
||||
Check whether the RPM file has allowed size in bytes.
|
||||
(configurable)
|
||||
test: ./jp_validator.sh RpmFilesizeCheck -c /mnt/config/RpmFilesizeConfigJP.java
|
||||
|
||||
/files:
|
||||
description: >
|
||||
Check RPM and test whether it contains allowed / disallowed files inside.
|
||||
(configurable)
|
||||
test: ./jp_validator.sh FilesCheck -c /mnt/config/FilesConfigJP.java
|
||||
|
||||
/attributes:
|
||||
description: >
|
||||
Set of tests to check for RPM attributes.
|
||||
(configurable)
|
||||
|
||||
/conflicts:
|
||||
test: ./jp_validator.sh attribute.ConflictsCheck
|
||||
|
||||
/enhances:
|
||||
test: ./jp_validator.sh attribute.EnhancesCheck
|
||||
|
||||
/obsoletes:
|
||||
test: ./jp_validator.sh attribute.ObsoletesCheck
|
||||
|
||||
/order_with_requires:
|
||||
test: ./jp_validator.sh attribute.OrderWithRequiresCheck
|
||||
|
||||
/provides:
|
||||
test: ./jp_validator.sh attribute.ProvidesCheck
|
||||
|
||||
/recommends:
|
||||
test: ./jp_validator.sh attribute.RecommendsCheck
|
||||
|
||||
/requires:
|
||||
test: ./jp_validator.sh attribute.RequiresCheck
|
||||
|
||||
/suggests:
|
||||
test: ./jp_validator.sh attribute.SuggestsCheck
|
||||
|
||||
/supplements:
|
||||
test: ./jp_validator.sh attribute.SupplementsCheck
|
||||
|
||||
/java_specific:
|
||||
description: >
|
||||
Set of tests used for packages that contain Java code.
|
||||
|
||||
/bytecode_version:
|
||||
description: >
|
||||
Check each .class file present inside each .jar archive inside the RPM
|
||||
and test whether its bytecode version is in valid range.
|
||||
(configurable)
|
||||
test: ./jp_validator.sh BytecodeVersionCheck -c /mnt/config/BytecodeVersionConfigJP.java
|
||||
|
||||
/javadoc_noarch:
|
||||
description: >
|
||||
Check whether javadoc packages have architecture noarch
|
||||
test: ./jp_validator.sh JavadocNoarchCheck
|
||||
|
||||
/java_exclusive_arch:
|
||||
description: >
|
||||
Check whether java packages have the ExclusiveArch field set correctly
|
||||
according to this change https://fedoraproject.org/wiki/Changes/Drop_i686_JDKs
|
||||
test: ./jp_validator.sh JavaExclusiveArchCheck
|
||||
Loading…
Add table
Add a link
Reference in a new issue