You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by us...@apache.org on 2022/01/06 18:09:50 UTC
[lucene] 01/03: LUCENE-10328: Module path for compiling and running tests is wrong (#571)
This is an automated email from the ASF dual-hosted git repository.
uschindler pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/lucene.git
commit bc6aa00c5fd7fca586ae93379bbabda60dd8273c
Author: Dawid Weiss <da...@carrotsearch.com>
AuthorDate: Wed Jan 5 20:42:02 2022 +0100
LUCENE-10328: Module path for compiling and running tests is wrong (#571)
---
gradle/documentation/render-javadoc.gradle | 29 +-
gradle/java/modules.gradle | 585 +++++++++++++++------
gradle/maven/publications.gradle | 4 +-
gradle/validation/check-environment.gradle | 10 +-
gradle/validation/ecj-lint.gradle | 49 +-
gradle/validation/validate-source-patterns.gradle | 14 +-
lucene/analysis/common/build.gradle | 2 +-
lucene/analysis/icu/build.gradle | 2 +-
lucene/analysis/kuromoji/build.gradle | 2 +-
lucene/analysis/morfologik.tests/build.gradle | 5 +-
.../morfologik.tests/src/test/module-info.java | 2 +-
.../morfologik/tests/TestMorfologikAnalyzer.java | 8 +-
lucene/analysis/morfologik/build.gradle | 2 +-
lucene/analysis/nori/build.gradle | 4 +-
lucene/analysis/opennlp/build.gradle | 2 +-
lucene/analysis/phonetic/build.gradle | 2 +-
lucene/analysis/smartcn/build.gradle | 2 +-
lucene/analysis/stempel/build.gradle | 2 +-
lucene/backward-codecs/build.gradle | 2 +-
lucene/benchmark/build.gradle | 9 +-
lucene/classification/build.gradle | 6 +-
lucene/codecs/build.gradle | 2 +-
.../lucene90/{ => tests}/MockTermStateFactory.java | 13 +-
.../codecs/uniformsplit/TestBlockWriter.java | 2 +-
.../sharedterms/TestSTBlockReader.java | 2 +-
lucene/core.tests/build.gradle | 5 +-
.../src/java/module-info.java} | 14 +-
.../lucene/core/tests/main/EmptyReference.java} | 13 +-
.../lucene/core/tests/main/package-info.java} | 10 +-
lucene/core.tests/src/java/overview.html | 26 +
lucene/core.tests/src/test/module-info.java | 3 +-
.../org/apache/lucene/core/tests/TestMMap.java | 7 +-
.../core/tests/TestModuleResourceLoader.java | 9 +-
.../core/tests/TestRuntimeDependenciesSane.java | 58 ++
lucene/core/build.gradle | 4 +-
lucene/demo/build.gradle | 2 +-
lucene/expressions/build.gradle | 2 +-
lucene/facet/build.gradle | 7 +-
lucene/grouping/build.gradle | 2 +-
lucene/highlighter/build.gradle | 6 +-
lucene/join/build.gradle | 2 +-
lucene/luke/build.gradle | 2 +-
lucene/memory/build.gradle | 4 +-
lucene/misc/build.gradle | 2 +-
lucene/monitor/build.gradle | 4 +-
lucene/queries/build.gradle | 4 +-
lucene/queryparser/build.gradle | 2 +-
lucene/replicator/build.gradle | 10 +-
lucene/sandbox/build.gradle | 2 +-
lucene/spatial-extras/build.gradle | 20 +-
.../lucene/spatial/spatial4j/TestGeo3dRpt.java | 2 +-
.../build.gradle | 7 +-
.../tests}/RandomGeo3dShapeGenerator.java | 56 +-
.../lucene/spatial3d/tests/package-info.java} | 10 +-
.../spatial-test-fixtures/src/java/overview.html | 24 +
lucene/spatial3d/build.gradle | 10 +-
.../spatial3d/geom/GeoBaseCompositeShape.java | 6 +
.../lucene/spatial3d/geom/TestGeoExactCircle.java | 3 +-
.../spatial3d/geom/TestRandomBinaryCodec.java | 2 +-
.../spatial3d/geom/TestRandomGeoPolygon.java | 2 +-
.../geom/TestRandomGeoShapeRelationship.java | 2 +-
.../lucene/spatial3d/geom/TestRandomPlane.java | 2 +-
lucene/suggest/build.gradle | 2 +-
lucene/test-framework/src/java/module-info.java | 6 +-
settings.gradle | 1 +
versions.lock | 2 +-
66 files changed, 753 insertions(+), 366 deletions(-)
diff --git a/gradle/documentation/render-javadoc.gradle b/gradle/documentation/render-javadoc.gradle
index 63cfbf3..0863aab 100644
--- a/gradle/documentation/render-javadoc.gradle
+++ b/gradle/documentation/render-javadoc.gradle
@@ -59,7 +59,7 @@ allprojects {
outputDir = project.javadoc.destinationDir
}
- if (project.path == ':lucene:luke' || project.path.endsWith(".tests")) {
+ if (project.path == ':lucene:luke' || !(project in rootProject.ext.mavenProjects)) {
// These projects are not part of the public API so we don't render their javadocs
// as part of the site's creation. A side-effect of this is that javadocs would not
// be linted for these projects. To avoid this, we connect the regular javadoc task
@@ -167,26 +167,6 @@ configure(project(":lucene:test-framework")) {
project.tasks.withType(RenderJavadocTask) {
// TODO: fix missing javadocs
javadocMissingLevel = "class"
- // TODO: clean up split packages
- javadocMissingIgnore = [
- "org.apache.lucene.analysis",
- "org.apache.lucene.analysis.standard",
- "org.apache.lucene.codecs",
- "org.apache.lucene.codecs.blockterms",
- "org.apache.lucene.codecs.bloom",
- "org.apache.lucene.codecs.compressing",
- "org.apache.lucene.codecs.uniformsplit",
- "org.apache.lucene.codecs.uniformsplit.sharedterms",
- "org.apache.lucene.geo",
- "org.apache.lucene.index",
- "org.apache.lucene.search",
- "org.apache.lucene.search.similarities",
- "org.apache.lucene.search.spans",
- "org.apache.lucene.store",
- "org.apache.lucene.util",
- "org.apache.lucene.util.automaton",
- "org.apache.lucene.util.fst"
- ]
}
}
@@ -197,6 +177,13 @@ configure(project(":lucene:sandbox")) {
}
}
+configure(project(":lucene:spatial-test-fixtures")) {
+ project.tasks.withType(RenderJavadocTask) {
+ // TODO: fix missing javadocs
+ javadocMissingLevel = "class"
+ }
+}
+
configure(project(":lucene:misc")) {
project.tasks.withType(RenderJavadocTask) {
// TODO: fix missing javadocs
diff --git a/gradle/java/modules.gradle b/gradle/java/modules.gradle
index 5e334ab..fa75116 100644
--- a/gradle/java/modules.gradle
+++ b/gradle/java/modules.gradle
@@ -15,6 +15,8 @@
* limitations under the License.
*/
+import java.nio.file.Path
+
// Configure miscellaneous aspects required for supporting the java module system layer.
// Debugging utilities.
@@ -27,189 +29,162 @@ allprojects {
modularity.inferModulePath.set(false)
}
- // Map convention configuration names to "modular" corresponding configurations.
- Closure<String> moduleConfigurationNameFor = { String configurationName ->
- return "module" + configurationName.capitalize().replace("Classpath", "Path")
- }
-
- //
- // For each source set, create explicit configurations for declaring modular dependencies.
- // These "modular" configurations correspond 1:1 to Gradle's conventions but have a 'module' prefix
- // and a capitalized remaining part of the conventional name. For example, an 'api' configuration in
- // the main source set would have a corresponding 'moduleApi' configuration for declaring modular
- // dependencies.
- //
- // Gradle's java plugin "convention" configurations extend from their modular counterparts
- // so all dependencies end up on classpath by default for backward compatibility with other
- // tasks and gradle infrastructure.
//
- // At the same time, we also know which dependencies (and their transitive graph of dependencies!)
- // should be placed on module-path only.
- //
- // Note that an explicit configuration of modular dependencies also opens up the possibility of automatically
- // validating whether the dependency configuration for a gradle project is consistent with the information in
- // the module-info descriptor because there is a (nearly?) direct correspondence between the two:
- //
- // moduleApi - 'requires transitive'
- // moduleImplementation - 'requires'
- // moduleCompileOnly - 'requires static'
+ // Configure modular extensions for each source set.
//
project.sourceSets.all { SourceSet sourceSet ->
- ConfigurationContainer configurations = project.configurations
-
- // Create modular configurations for convention configurations.
- Closure<Configuration> createModuleConfigurationForConvention = { String configurationName ->
- Configuration conventionConfiguration = configurations.maybeCreate(configurationName)
- Configuration moduleConfiguration = configurations.maybeCreate(moduleConfigurationNameFor(configurationName))
- moduleConfiguration.canBeConsumed(false)
- moduleConfiguration.canBeResolved(false)
- conventionConfiguration.extendsFrom(moduleConfiguration)
-
- project.logger.info("Created module configuration for '${conventionConfiguration.name}': ${moduleConfiguration.name}")
- return moduleConfiguration
- }
-
- Configuration moduleApi = createModuleConfigurationForConvention(sourceSet.apiConfigurationName)
- Configuration moduleImplementation = createModuleConfigurationForConvention(sourceSet.implementationConfigurationName)
- moduleImplementation.extendsFrom(moduleApi)
- Configuration moduleRuntimeOnly = createModuleConfigurationForConvention(sourceSet.runtimeOnlyConfigurationName)
- Configuration moduleCompileOnly = createModuleConfigurationForConvention(sourceSet.compileOnlyConfigurationName)
- // sourceSet.compileOnlyApiConfigurationName // This seems like a very esoteric use case, leave out.
-
- // Set up compilation module path configuration combining corresponding convention configurations.
- Closure<Configuration> createResolvableModuleConfiguration = { String configurationName ->
- Configuration conventionConfiguration = configurations.maybeCreate(configurationName)
- Configuration moduleConfiguration = configurations.maybeCreate(
- moduleConfigurationNameFor(conventionConfiguration.name))
- moduleConfiguration.canBeConsumed(false)
- moduleConfiguration.canBeResolved(true)
- moduleConfiguration.attributes {
- // Prefer class folders over JARs. The exception is made for tests projects which require a composition
- // of classes and resources, otherwise split into two folders.
- if (project.name.endsWith(".tests")) {
- attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, LibraryElements.JAR))
- } else {
- attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, LibraryElements.CLASSES))
- }
- }
-
- project.logger.info("Created resolvable module configuration for '${conventionConfiguration.name}': ${moduleConfiguration.name}")
- return moduleConfiguration
- }
-
- Configuration compileModulePathConfiguration = createResolvableModuleConfiguration(sourceSet.compileClasspathConfigurationName)
- compileModulePathConfiguration.extendsFrom(moduleCompileOnly, moduleImplementation)
-
- Configuration runtimeModulePathConfiguration = createResolvableModuleConfiguration(sourceSet.runtimeClasspathConfigurationName)
- runtimeModulePathConfiguration.extendsFrom(moduleRuntimeOnly, moduleImplementation)
-
// Create and register a source set extension for manipulating classpath/ module-path
- ModularPathsExtension modularPaths = new ModularPathsExtension(project, sourceSet,
- compileModulePathConfiguration,
- runtimeModulePathConfiguration)
+ ModularPathsExtension modularPaths = new ModularPathsExtension(project, sourceSet)
sourceSet.extensions.add("modularPaths", modularPaths)
- // Customized the JavaCompile for this source set so that it has proper module path.
+ // LUCENE-10344: We have to provide a special-case extension for ECJ because it does not
+ // support all of the module-specific javac options.
+ ModularPathsExtension modularPathsForEcj = modularPaths
+ if (sourceSet.name == SourceSet.TEST_SOURCE_SET_NAME && project.path in [
+ ":lucene:spatial-extras",
+ ":lucene:spatial3d",
+ ]) {
+ modularPathsForEcj = modularPaths.cloneWithMode(ModularPathsExtension.Mode.CLASSPATH_ONLY)
+ }
+ sourceSet.extensions.add("modularPathsForEcj", modularPathsForEcj)
+
+ // TODO: the tests of these projects currently don't compile or work in
+ // module-path mode. Make the modular paths extension use class path only.
+ if (sourceSet.name == SourceSet.TEST_SOURCE_SET_NAME && project.path in [
+ // Circular dependency between artifacts or source set outputs,
+ // causing package split issues at runtime.
+ ":lucene:core",
+ ":lucene:codecs",
+ ":lucene:test-framework",
+ ]) {
+ modularPaths.mode = ModularPathsExtension.Mode.CLASSPATH_ONLY
+ }
+
+ // Configure the JavaCompile task associated with this source set.
tasks.named(sourceSet.getCompileJavaTaskName()).configure({ JavaCompile task ->
task.dependsOn modularPaths.compileModulePathConfiguration
- // LUCENE-10327: don't allow gradle to emit an empty sourcepath as it would break compilation.
+ // LUCENE-10327: don't allow gradle to emit an empty sourcepath as it would break
+ // compilation of modules.
task.options.setSourcepath(sourceSet.java.sourceDirectories)
// Add modular dependencies and their transitive dependencies to module path.
- task.options.compilerArgumentProviders.add((CommandLineArgumentProvider) {
- def modularPathFiles = modularPaths.compileModulePathConfiguration.files
- def extraArgs = []
- if (!modularPathFiles.isEmpty()) {
- if (!modularPaths.hasModuleDescriptor()) {
- // We're compiling a non-module so we'll bring everything on module path in
- // otherwise things wouldn't be part of the resolved module graph.
- extraArgs += ["--add-modules", "ALL-MODULE-PATH"]
- }
-
- extraArgs += ["--module-path", modularPathFiles.join(File.pathSeparator)]
- }
-
- task.logger.info("Module path for ${task.path}:\n " + modularPathFiles.sort().join("\n "))
-
- return extraArgs
- })
+ task.options.compilerArgumentProviders.add(modularPaths.compilationArguments)
// LUCENE-10304: if we modify the classpath here, IntelliJ no longer sees the dependencies as compile-time
// dependencies, don't know why.
if (!rootProject.ext.isIdea) {
- // Modify the default classpath by removing anything already placed on module path.
- // This could be done in a fancier way but a set difference is just fine for us here. Use a lazy
- // provider to delay computation of the actual path.
- task.classpath = files({ ->
- def trimmedClasspath = sourceSet.compileClasspath - modularPaths.compileModulePathConfiguration
- task.logger.info("Class path for ${task.path}:\n " + trimmedClasspath.files.sort().join("\n "))
- return trimmedClasspath
- })
+ task.classpath = modularPaths.compilationClasspath
+ }
+
+ doFirst {
+ modularPaths.logCompilationPaths(logger)
}
})
+
+ // For source sets that contain a module descriptor, configure a jar task that combines
+ // classes and resources into a single module.
+ if (sourceSet.name != SourceSet.MAIN_SOURCE_SET_NAME) {
+ tasks.maybeCreate(sourceSet.getJarTaskName(), org.gradle.jvm.tasks.Jar).configure({
+ archiveClassifier = sourceSet.name
+ from(sourceSet.output)
+ })
+ }
+ }
+
+ // Connect modular configurations between their "test" and "main" source sets, this reflects
+ // the conventions set by the Java plugin.
+ project.configurations {
+ moduleTestApi.extendsFrom moduleApi
+ moduleTestImplementation.extendsFrom moduleImplementation
+ moduleTestRuntimeOnly.extendsFrom moduleRuntimeOnly
+ moduleTestCompileOnly.extendsFrom moduleCompileOnly
}
+ // Gradle's java plugin sets the compile and runtime classpath to be a combination
+ // of configuration dependencies and source set's outputs. For source sets with modules,
+ // this leads to split class and resource folders.
//
- // Configure the (default) test task to use module paths.
+ // We tweak the default source set path configurations here by assembling jar task outputs
+ // of the respective source set, instead of their source set output folders. We also attach
+ // the main source set's jar to the modular test implementation configuration.
+ SourceSet mainSourceSet = project.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME)
+ boolean mainIsModular = mainSourceSet.modularPaths.hasModuleDescriptor()
+ boolean mainIsEmpty = mainSourceSet.allJava.isEmpty()
+ SourceSet testSourceSet = project.sourceSets.getByName(SourceSet.TEST_SOURCE_SET_NAME)
+ boolean testIsModular = testSourceSet.modularPaths.hasModuleDescriptor()
+
+ // LUCENE-10304: if we modify the classpath here, IntelliJ no longer sees the dependencies as compile-time
+ // dependencies, don't know why.
+ if (!rootProject.ext.isIdea) {
+ def jarTask = project.tasks.getByName(mainSourceSet.getJarTaskName())
+ def testJarTask = project.tasks.getByName(testSourceSet.getJarTaskName())
+
+ // Consider various combinations of module/classpath configuration between the main and test source set.
+ if (testIsModular) {
+ if (mainIsModular || mainIsEmpty) {
+ // If the main source set is empty, skip the jar task.
+ def jarTaskOutputs = mainIsEmpty ? [] : jarTask.outputs
+
+ // Fully modular tests - must have no split packages, proper access, etc.
+ // Work around the split classes/resources problem by adjusting classpaths to
+ // rely on JARs rather than source set output folders.
+ testSourceSet.compileClasspath = project.objects.fileCollection().from(
+ jarTaskOutputs,
+ project.configurations.getByName(testSourceSet.getCompileClasspathConfigurationName()),
+ )
+ testSourceSet.runtimeClasspath = project.objects.fileCollection().from(
+ jarTaskOutputs,
+ testJarTask.outputs,
+ project.configurations.getByName(testSourceSet.getRuntimeClasspathConfigurationName()),
+ )
+
+ project.dependencies {
+ moduleTestImplementation files(jarTaskOutputs)
+ moduleTestRuntimeOnly files(testJarTask.outputs)
+ }
+ } else {
+ // This combination simply does not make any sense (in my opinion).
+ throw GradleException("Test source set is modular and main source set is class-based, this makes no sense: " + project.path)
+ }
+ } else {
+ if (mainIsModular) {
+ // This combination is a potential candidate for patching the main sourceset's module with test classes. I could
+ // not resolve all the difficulties that arise when you try to do it though:
+ // - either a separate module descriptor is needed that opens test packages, adds dependencies via requires clauses
+ // or a series of jvm arguments (--add-reads, --add-opens, etc.) has to be generated and maintained. This is
+ // very low-level (ECJ doesn't support a full set of these instructions, for example).
+ //
+ // Fall back to classpath mode.
+ } else {
+ // This is the 'plain old classpath' mode: neither the main source set nor the test set are modular.
+ }
+ }
+ }
+
+ //
+ // Configures a Test task associated with the provided source set to use module paths.
//
// There is no explicit connection between source sets and test tasks so there is no way (?)
// to do this automatically, convention-style.
-
+ //
// This closure can be used to configure a different task, with a different source set, should we
// have the need for it.
Closure<Void> configureTestTaskForSourceSet = { Test task, SourceSet sourceSet ->
task.configure {
- Configuration modulePath = task.project.configurations.maybeCreate(
- moduleConfigurationNameFor(sourceSet.getRuntimeClasspathConfigurationName()))
+ ModularPathsExtension modularPaths = sourceSet.modularPaths
- task.dependsOn modulePath
+ dependsOn modularPaths
// Add modular dependencies and their transitive dependencies to module path.
- task.jvmArgumentProviders.add((CommandLineArgumentProvider) {
- def extraArgs = []
-
- // Determine whether the source set classes themselves should be appended
- // to classpath or module path.
- boolean sourceSetIsAModule = sourceSet.modularPaths.hasModuleDescriptor()
-
- if (!modulePath.isEmpty() || sourceSetIsAModule) {
- if (sourceSetIsAModule) {
- // Add source set outputs to module path.
- extraArgs += ["--module-path", (modulePath + sourceSet.output.classesDirs).files.join(File.pathSeparator)]
- // Ideally, we should only add the sourceset's module here, everything else would be resolved via the
- // module descriptor. But this would require parsing the module descriptor and may cause JVM version conflicts
- // so keeping it simple.
- extraArgs += ["--add-modules", "ALL-MODULE-PATH"]
- } else {
- extraArgs += ["--module-path", modulePath.files.join(File.pathSeparator)]
- // In this case we're running a non-module against things on the module path so let's bring in
- // everything on module path into the resolution graph.
- extraArgs += ["--add-modules", "ALL-MODULE-PATH"]
- }
- }
+ jvmArgumentProviders.add(modularPaths.runtimeArguments)
- task.logger.info("Module path for ${task.path}:\n " + modulePath.files.sort().join("\n "))
-
- return extraArgs
- })
+ // Modify the default classpath.
+ classpath = modularPaths.runtimeClasspath
-
- // Modify the default classpath by removing anything already placed on module path.
- // This could be done in a fancier way but a set difference is just fine for us here. Use a lazy
- // provider to delay computation of the actual path.
- task.classpath = files({ ->
- def trimmedClasspath = sourceSet.runtimeClasspath - modulePath
-
- boolean sourceSetIsAModule = sourceSet.modularPaths.hasModuleDescriptor()
- if (sourceSetIsAModule) {
- // also subtract the sourceSet's output directories.
- trimmedClasspath = trimmedClasspath - sourceSet.output.classesDirs
- }
-
- task.logger.info("Class path for ${task.path}:\n " + trimmedClasspath.files.sort().join("\n "))
- return trimmedClasspath
- })
+ doFirst {
+ modularPaths.logRuntimePaths(logger)
+ }
}
}
@@ -237,19 +212,233 @@ allprojects {
}
-class ModularPathsExtension {
+//
+// For a source set, create explicit configurations for declaring modular dependencies.
+//
+// These "modular" configurations correspond 1:1 to Gradle's conventions but have a 'module' prefix
+// and a capitalized remaining part of the conventional name. For example, an 'api' configuration in
+// the main source set would have a corresponding 'moduleApi' configuration for declaring modular
+// dependencies.
+//
+// Gradle's java plugin "convention" configurations extend from their modular counterparts
+// so all dependencies end up on classpath by default for backward compatibility with other
+// tasks and gradle infrastructure.
+//
+// At the same time, we also know which dependencies (and their transitive graph of dependencies!)
+// should be placed on module-path only.
+//
+// Note that an explicit configuration of modular dependencies also opens up the possibility of automatically
+// validating whether the dependency configuration for a gradle project is consistent with the information in
+// the module-info descriptor because there is a (nearly?) direct correspondence between the two:
+//
+// moduleApi - 'requires transitive'
+// moduleImplementation - 'requires'
+// moduleCompileOnly - 'requires static'
+//
+class ModularPathsExtension implements Cloneable, Iterable<Object> {
+ /**
+ * Determines how paths are split between module path and classpath.
+ */
+ enum Mode {
+ /**
+ * Dependencies and source set outputs are placed on classpath, even if declared on modular
+ * configurations. This would be the 'default' backward-compatible mode.
+ */
+ CLASSPATH_ONLY,
+
+ /**
+ * Dependencies from modular configurations are placed on module path. Source set outputs
+ * are placed on classpath.
+ */
+ DEPENDENCIES_ON_MODULE_PATH
+ }
+
Project project
SourceSet sourceSet
Configuration compileModulePathConfiguration
Configuration runtimeModulePathConfiguration
+ Configuration modulePatchOnlyConfiguration
- ModularPathsExtension(Project project, SourceSet sourceSet,
- Configuration compileModulePathConfiguration,
- Configuration runtimeModulePathConfiguration) {
- this.project = project
+ // The mode of splitting paths for this source set.
+ Mode mode = Mode.DEPENDENCIES_ON_MODULE_PATH
+
+ // More verbose debugging for paths.
+ private boolean debugPaths
+
+ /**
+ * A list of module name - path provider entries that will be converted
+ * into {@code --patch-module} options.
+ */
+ private List<Map.Entry<String, Provider<Path>>> modulePatches = new ArrayList<>()
+
+ ModularPathsExtension(Project project, SourceSet sourceSet) {
+ this.project = project
this.sourceSet = sourceSet
- this.compileModulePathConfiguration = compileModulePathConfiguration
- this.runtimeModulePathConfiguration = runtimeModulePathConfiguration
+
+ debugPaths = Boolean.parseBoolean(project.propertyOrDefault('build.debug.paths', 'false'))
+
+ ConfigurationContainer configurations = project.configurations
+
+ // Create modular configurations for gradle's java plugin convention configurations.
+ Configuration moduleApi = createModuleConfigurationForConvention(sourceSet.apiConfigurationName)
+ Configuration moduleImplementation = createModuleConfigurationForConvention(sourceSet.implementationConfigurationName)
+ Configuration moduleRuntimeOnly = createModuleConfigurationForConvention(sourceSet.runtimeOnlyConfigurationName)
+ Configuration moduleCompileOnly = createModuleConfigurationForConvention(sourceSet.compileOnlyConfigurationName)
+
+
+ // Apply hierarchy relationships to modular configurations.
+ moduleImplementation.extendsFrom(moduleApi)
+
+ // Patched modules have to end up in the implementation configuration for IDEs, which
+ // otherwise get terribly confused.
+ Configuration modulePatchOnly = createModuleConfigurationForConvention(
+ SourceSet.isMain(sourceSet) ? "patchOnly" : sourceSet.name + "PatchOnly")
+ modulePatchOnly.canBeResolved(true)
+ moduleImplementation.extendsFrom(modulePatchOnly)
+ this.modulePatchOnlyConfiguration = modulePatchOnly
+
+ // This part of convention configurations seems like a very esoteric use case, leave out for now.
+ // sourceSet.compileOnlyApiConfigurationName
+
+ // We have to ensure configurations are using assembled resources and classes (jar variant) as a single
+ // module can't be expanded into multiple folders.
+ Closure<Void> ensureJarVariant = { Configuration c ->
+ c.attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements, LibraryElements.JAR))
+ }
+
+ // Set up compilation module path configuration combining corresponding convention configurations.
+ Closure<Configuration> createResolvableModuleConfiguration = { String configurationName ->
+ Configuration conventionConfiguration = configurations.maybeCreate(configurationName)
+ Configuration moduleConfiguration = configurations.maybeCreate(moduleConfigurationNameFor(conventionConfiguration.name))
+ moduleConfiguration.canBeConsumed(false)
+ moduleConfiguration.canBeResolved(true)
+ ensureJarVariant(moduleConfiguration)
+
+ project.logger.info("Created resolvable module configuration for '${conventionConfiguration.name}': ${moduleConfiguration.name}")
+ return moduleConfiguration
+ }
+
+ ensureJarVariant(configurations.maybeCreate(sourceSet.compileClasspathConfigurationName))
+ ensureJarVariant(configurations.maybeCreate(sourceSet.runtimeClasspathConfigurationName))
+
+ this.compileModulePathConfiguration = createResolvableModuleConfiguration(sourceSet.compileClasspathConfigurationName)
+ compileModulePathConfiguration.extendsFrom(moduleCompileOnly, moduleImplementation)
+
+ this.runtimeModulePathConfiguration = createResolvableModuleConfiguration(sourceSet.runtimeClasspathConfigurationName)
+ runtimeModulePathConfiguration.extendsFrom(moduleRuntimeOnly, moduleImplementation)
+ }
+
+ /**
+ * Adds {@code --patch-module} option for the provided module name and the provider of a
+ * folder or JAR file.
+ *
+ * @param moduleName
+ * @param pathProvider
+ */
+ void patchModule(String moduleName, Provider<Path> pathProvider) {
+ modulePatches.add(Map.entry(moduleName, pathProvider));
+ }
+
+ private FileCollection getCompilationModulePath() {
+ if (mode == Mode.CLASSPATH_ONLY) {
+ return project.files()
+ }
+ return compileModulePathConfiguration - modulePatchOnlyConfiguration
+ }
+
+ private FileCollection getRuntimeModulePath() {
+ if (mode == Mode.CLASSPATH_ONLY) {
+ if (hasModuleDescriptor()) {
+ // The source set is itself a module.
+ throw new GradleException("Source set contains a module but classpath-only" +
+ " dependencies requested: ${project.path}, source set '${sourceSet.name}'")
+ }
+
+ return project.files()
+ }
+
+ return runtimeModulePathConfiguration - modulePatchOnlyConfiguration
+ }
+
+ FileCollection getCompilationClasspath() {
+ if (mode == Mode.CLASSPATH_ONLY) {
+ return sourceSet.compileClasspath
+ }
+
+ // Modify the default classpath by removing anything already placed on module path.
+ // Use a lazy provider to delay computation.
+ project.files({ ->
+ return sourceSet.compileClasspath - compileModulePathConfiguration - modulePatchOnlyConfiguration
+ })
+ }
+
+ CommandLineArgumentProvider getCompilationArguments() {
+ return new CommandLineArgumentProvider() {
+ @Override
+ Iterable<String> asArguments() {
+ FileCollection modulePath = ModularPathsExtension.this.compilationModulePath
+
+ if (modulePath.isEmpty()) {
+ return []
+ }
+
+ ArrayList<String> extraArgs = []
+ extraArgs += ["--module-path", modulePath.join(File.pathSeparator)]
+
+ if (!hasModuleDescriptor()) {
+ // We're compiling what appears to be a non-module source set so we'll
+ // bring everything on module path in the resolution graph,
+ // otherwise modular dependencies wouldn't be part of the resolved module graph and this
+ // would result in class-not-found compilation problems.
+ extraArgs += ["--add-modules", "ALL-MODULE-PATH"]
+ }
+
+ // Add module-patching.
+ extraArgs += getPatchModuleArguments(modulePatches)
+
+ return extraArgs
+ }
+ }
+ }
+
+ FileCollection getRuntimeClasspath() {
+ if (mode == Mode.CLASSPATH_ONLY) {
+ return sourceSet.runtimeClasspath
+ }
+
+ // Modify the default classpath by removing anything already placed on module path.
+ // Use a lazy provider to delay computation.
+ project.files({ ->
+ return sourceSet.runtimeClasspath - runtimeModulePath - modulePatchOnlyConfiguration
+ })
+ }
+
+ CommandLineArgumentProvider getRuntimeArguments() {
+ return new CommandLineArgumentProvider() {
+ @Override
+ Iterable<String> asArguments() {
+ FileCollection modulePath = ModularPathsExtension.this.runtimeModulePath
+
+ if (modulePath.isEmpty()) {
+ return []
+ }
+
+ def extraArgs = []
+
+ // Add source set outputs to module path.
+ extraArgs += ["--module-path", modulePath.files.join(File.pathSeparator)]
+
+ // Ideally, we should only add the sourceset's module here, everything else would be resolved via the
+ // module descriptor. But this would require parsing the module descriptor and may cause JVM version conflicts
+ // so keeping it simple.
+ extraArgs += ["--add-modules", "ALL-MODULE-PATH"]
+
+ // Add module-patching.
+ extraArgs += getPatchModuleArguments(modulePatches)
+
+ return extraArgs
+ }
+ }
}
boolean hasModuleDescriptor() {
@@ -257,4 +446,86 @@ class ModularPathsExtension {
.map(dir -> new File(dir, "module-info.java"))
.anyMatch(file -> file.exists())
}
+
+ private List<String> getPatchModuleArguments(List<Map.Entry<String, Provider<Path>>> patches) {
+ def args = []
+ patches.each {
+ args.add("--patch-module");
+ args.add(it.key + "=" + it.value.get())
+ }
+ return args
+ }
+
+ private static String toList(FileCollection files) {
+ return files.isEmpty() ? " [empty]" : ("\n " + files.sort().join("\n "))
+ }
+
+ private static String toList(List<Map.Entry<String, Provider<Path>>> patches) {
+ return patches.isEmpty() ? " [empty]" : ("\n " + patches.collect {"${it.key}=${it.value.get()}"}.join("\n "))
+ }
+
+ public void logCompilationPaths(Logger logger) {
+ def value = "Modular extension, compilation paths, source set=${sourceSet.name}${hasModuleDescriptor() ? " (module)" : ""}, mode=${mode}:\n" +
+ " Module path:${toList(compilationModulePath)}\n" +
+ " Class path: ${toList(compilationClasspath)}\n" +
+ " Patches: ${toList(modulePatches)}"
+
+ if (debugPaths) {
+ logger.lifecycle(value)
+ } else {
+ logger.info(value)
+ }
+ }
+
+ public void logRuntimePaths(Logger logger) {
+ def value = "Modular extension, runtime paths, source set=${sourceSet.name}${hasModuleDescriptor() ? " (module)" : ""}, mode=${mode}:\n" +
+ " Module path:${toList(runtimeModulePath)}\n" +
+ " Class path: ${toList(runtimeClasspath)}\n" +
+ " Patches : ${toList(modulePatches)}"
+
+ if (debugPaths) {
+ logger.lifecycle(value)
+ } else {
+ logger.info(value)
+ }
+ }
+
+ public ModularPathsExtension clone() {
+ return (ModularPathsExtension) super.clone()
+ }
+
+ ModularPathsExtension cloneWithMode(Mode newMode) {
+ def cloned = this.clone()
+ cloned.mode = newMode
+ return cloned
+ }
+
+ // Map convention configuration names to "modular" corresponding configurations.
+ static String moduleConfigurationNameFor(String configurationName) {
+ return "module" + configurationName.capitalize().replace("Classpath", "Path")
+ }
+
+ // Create module configuration for the corresponding convention configuration.
+ private Configuration createModuleConfigurationForConvention(String configurationName) {
+ ConfigurationContainer configurations = project.configurations
+ Configuration conventionConfiguration = configurations.maybeCreate(configurationName)
+ Configuration moduleConfiguration = configurations.maybeCreate(moduleConfigurationNameFor(configurationName))
+ moduleConfiguration.canBeConsumed(false)
+ moduleConfiguration.canBeResolved(false)
+ conventionConfiguration.extendsFrom(moduleConfiguration)
+
+ project.logger.info("Created module configuration for '${conventionConfiguration.name}': ${moduleConfiguration.name}")
+ return moduleConfiguration
+ }
+
+ /**
+ * Provide internal dependencies for tasks willing to depend on this modular paths object.
+ */
+ @Override
+ Iterator<Object> iterator() {
+ return [
+ compileModulePathConfiguration,
+ runtimeModulePathConfiguration
+ ].iterator()
+ }
}
\ No newline at end of file
diff --git a/gradle/maven/publications.gradle b/gradle/maven/publications.gradle
index cc9bc96..17b444b 100644
--- a/gradle/maven/publications.gradle
+++ b/gradle/maven/publications.gradle
@@ -38,7 +38,9 @@ configure(rootProject) {
// Exclude the parent container project for analysis modules (no artifacts).
":lucene:analysis",
// Exclude the native module.
- ":lucene:misc:native"
+ ":lucene:misc:native",
+ // Exclude test fixtures.
+ ":lucene:spatial-test-fixtures"
]
// Exclude all subprojects that are modular test projects and those explicitly
diff --git a/gradle/validation/check-environment.gradle b/gradle/validation/check-environment.gradle
index 7694f8d..00912c4 100644
--- a/gradle/validation/check-environment.gradle
+++ b/gradle/validation/check-environment.gradle
@@ -33,14 +33,20 @@ configure(rootProject) {
def currentJavaVersion = JavaVersion.current()
if (currentJavaVersion < minJavaVersion) {
throw new GradleException("At least Java ${minJavaVersion} is required, you are running Java ${currentJavaVersion} "
- + "[${System.getProperty('java.vm.name')} ${System.getProperty('java.vm.version')}]")
+ + "[${System.getProperty('java.vm.name')} ${System.getProperty('java.vm.version')}]")
}
// If we're regenerating the wrapper, skip the check.
if (!gradle.startParameter.taskNames.contains("wrapper")) {
def currentGradleVersion = GradleVersion.current()
if (currentGradleVersion != GradleVersion.version(expectedGradleVersion)) {
- throw new GradleException("Gradle ${expectedGradleVersion} is required (hint: use the gradlew script): this gradle is ${currentGradleVersion}")
+ if (currentGradleVersion.baseVersion == GradleVersion.version(expectedGradleVersion).baseVersion) {
+ logger.warn("Gradle ${expectedGradleVersion} is required but base version of this gradle matches, proceeding (" +
+ "this gradle is ${currentGradleVersion})")
+ } else {
+ throw new GradleException("Gradle ${expectedGradleVersion} is required (hint: use the gradlew script): " +
+ "this gradle is ${currentGradleVersion}")
+ }
}
}
}
diff --git a/gradle/validation/ecj-lint.gradle b/gradle/validation/ecj-lint.gradle
index 0d99d2c..33b79ca 100644
--- a/gradle/validation/ecj-lint.gradle
+++ b/gradle/validation/ecj-lint.gradle
@@ -74,42 +74,36 @@ allprojects {
args += [ "-properties", file("${resources}/ecj.javadocs.prefs").absolutePath ]
// We depend on modular paths.
- def modularPaths = sourceSet.modularPaths
- dependsOn modularPaths.compileModulePathConfiguration
+ def modularPaths = sourceSet.modularPathsForEcj
+ dependsOn modularPaths
- // Place input files in an external file to dodge command line argument
- // limits. We could pass a directory but ecj seems to be buggy: when it
- // encounters a module-info.java file it no longer compiles other source files.
- def inputsFile = file("${tmpDst}/ecj-inputs.txt")
+ // Add modular dependencies and their transitive dependencies to module path.
+ task.argumentProviders.add(modularPaths.compilationArguments)
+ // Add classpath, if needed.
task.argumentProviders.add((CommandLineArgumentProvider) {
- // Add modular dependencies and their transitive dependencies to module path.
- def modularPathFiles = modularPaths.compileModulePathConfiguration.files
- def extraArgs = []
- if (!modularPathFiles.isEmpty()) {
- if (!modularPaths.hasModuleDescriptor()) {
- // We're compiling a non-module so we'll bring everything on module path in
- // otherwise things wouldn't be part of the resolved module graph.
- extraArgs += ["--add-modules", "ALL-MODULE-PATH"]
- }
-
- extraArgs += ["--module-path", modularPathFiles.join(File.pathSeparator)]
- }
-
// Add classpath locations in a lazy provider (can't resolve the
// configuration at evaluation time). Filter out non-existing entries
// (output folders for non-existing input source dirs like resources).
- def cpath = sourceSet.compileClasspath.filter { p -> p.exists() }
- cpath = cpath - modularPathFiles
+ FileCollection cpath = modularPaths.compilationClasspath.filter { p -> p.exists() }
if (!cpath.isEmpty()) {
- extraArgs += ["-classpath", cpath.join(File.pathSeparator)]
+ return ["-classpath", cpath.join(File.pathSeparator)]
+ } else {
+ return []
}
+ })
- extraArgs += ["@" + inputsFile.absolutePath]
- return extraArgs
+ // Place input files in an external file to dodge command line argument
+ // limits. We could pass a directory but ecj seems to be buggy: when it
+ // encounters a module-info.java file it no longer compiles other source files.
+ def inputsFile = file("${tmpDst}/ecj-inputs.txt")
+ task.argumentProviders.add((CommandLineArgumentProvider) {
+ return ["@" + inputsFile.absolutePath]
})
doFirst {
+ modularPaths.logCompilationPaths(logger)
+
tmpDst.mkdirs()
// escape filename accoring to ECJ's rules:
@@ -118,7 +112,12 @@ allprojects {
def escapeFileName = { String s -> s.replaceAll(/ +/, /"$0"/) }
inputsFile.setText(
srcDirs.collectMany { dir ->
- project.fileTree(dir: dir, include: "**/*.java" ).files
+ project.fileTree(
+ dir: dir,
+ include: "**/*.java",
+ // Exclude the benchmark class with dependencies on nekohtml, which causes module-classpath conflicts and breaks ecj.
+ exclude: "**/DemoHTMLParser.java"
+ ).files
}
// Try to sort all input files; a side-effect of this should be that module-info.java
// is placed first on the list, which works around ECJ bug:
diff --git a/gradle/validation/validate-source-patterns.gradle b/gradle/validation/validate-source-patterns.gradle
index 3c5cf71..a82ce95 100644
--- a/gradle/validation/validate-source-patterns.gradle
+++ b/gradle/validation/validate-source-patterns.gradle
@@ -150,12 +150,11 @@ class ValidateSourcePatternsTask extends DefaultTask {
(~$/\n\s*var\s+.*=.*<>.*/$) : 'Diamond operators should not be used with var'
]
- def found = 0;
def violations = new TreeSet();
def reportViolation = { f, name ->
- logger.error('{}: {}', name, f);
- violations.add(name);
- found++;
+ String msg = String.format(Locale.ROOT, "%s: %s", f, name)
+ logger.error(msg)
+ violations.add(msg)
}
def javadocsPattern = ~$/(?sm)^\Q/**\E(.*?)\Q*/\E/$;
@@ -254,9 +253,10 @@ class ValidateSourcePatternsTask extends DefaultTask {
}
progress.completed()
- if (found) {
- throw new GradleException(String.format(Locale.ENGLISH, 'Found %d violations in source files (%s).',
- found, violations.join(', ')));
+ if (!violations.isEmpty()) {
+ throw new GradleException(String.format(Locale.ENGLISH, 'Found %d source violation(s):\n %s',
+ violations.size(),
+ violations.join('\n ')))
}
}
}
diff --git a/lucene/analysis/common/build.gradle b/lucene/analysis/common/build.gradle
index 1815041..6530ac6 100644
--- a/lucene/analysis/common/build.gradle
+++ b/lucene/analysis/common/build.gradle
@@ -21,7 +21,7 @@ description = 'Analyzers for indexing content in different languages and domains
dependencies {
moduleApi project(':lucene:core')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
// Fetch the data and enable regression tests against woorm/ libreoffice dictionaries.
diff --git a/lucene/analysis/icu/build.gradle b/lucene/analysis/icu/build.gradle
index e76b327..aba455f 100644
--- a/lucene/analysis/icu/build.gradle
+++ b/lucene/analysis/icu/build.gradle
@@ -25,5 +25,5 @@ dependencies {
moduleApi 'com.ibm.icu:icu4j'
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/analysis/kuromoji/build.gradle b/lucene/analysis/kuromoji/build.gradle
index 07fc0b0..fd8aedb 100644
--- a/lucene/analysis/kuromoji/build.gradle
+++ b/lucene/analysis/kuromoji/build.gradle
@@ -23,5 +23,5 @@ dependencies {
moduleApi project(':lucene:core')
moduleApi project(':lucene:analysis:common')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/analysis/morfologik.tests/build.gradle b/lucene/analysis/morfologik.tests/build.gradle
index 9cd6720..d2f94dd 100644
--- a/lucene/analysis/morfologik.tests/build.gradle
+++ b/lucene/analysis/morfologik.tests/build.gradle
@@ -21,8 +21,5 @@ description = 'Module tests for :lucene:analysis:morfologik'
dependencies {
moduleTestImplementation project(':lucene:analysis:morfologik')
- moduleTestImplementation("junit:junit", {
- exclude group: "org.hamcrest"
- })
- moduleTestImplementation "org.hamcrest:hamcrest"
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/analysis/morfologik.tests/src/test/module-info.java b/lucene/analysis/morfologik.tests/src/test/module-info.java
index 15642a9..b6f869f 100644
--- a/lucene/analysis/morfologik.tests/src/test/module-info.java
+++ b/lucene/analysis/morfologik.tests/src/test/module-info.java
@@ -21,7 +21,7 @@ module org.apache.lucene.analysis.morfologik.tests {
requires org.apache.lucene.core;
requires org.apache.lucene.analysis.common;
requires org.apache.lucene.analysis.morfologik;
- requires junit;
+ requires org.apache.lucene.test_framework;
exports org.apache.lucene.analysis.morfologik.tests;
}
diff --git a/lucene/analysis/morfologik.tests/src/test/org/apache/lucene/analysis/morfologik/tests/TestMorfologikAnalyzer.java b/lucene/analysis/morfologik.tests/src/test/org/apache/lucene/analysis/morfologik/tests/TestMorfologikAnalyzer.java
index c2933fc..b1607d9 100644
--- a/lucene/analysis/morfologik.tests/src/test/org/apache/lucene/analysis/morfologik/tests/TestMorfologikAnalyzer.java
+++ b/lucene/analysis/morfologik.tests/src/test/org/apache/lucene/analysis/morfologik/tests/TestMorfologikAnalyzer.java
@@ -19,28 +19,24 @@ package org.apache.lucene.analysis.morfologik.tests;
import org.apache.lucene.analysis.morfologik.MorfologikAnalyzer;
import org.apache.lucene.analysis.uk.UkrainianMorfologikAnalyzer;
import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.tests.util.LuceneTestCase;
import org.junit.Assert;
-import org.junit.Test;
-public class TestMorfologikAnalyzer {
- @Test
+public class TestMorfologikAnalyzer extends LuceneTestCase {
public void testMorfologikAnalyzerLoads() {
var analyzer = new MorfologikAnalyzer();
Assert.assertNotNull(analyzer);
}
- @Test
public void testUkrainianMorfologikAnalyzerLoads() {
var analyzer = new UkrainianMorfologikAnalyzer();
Assert.assertNotNull(analyzer);
}
- @Test
public void testWeAreModule() {
Assert.assertTrue(this.getClass().getModule().isNamed());
}
- @Test
public void testLuceneIsAModule() {
Assert.assertTrue(IndexWriter.class.getModule().isNamed());
}
diff --git a/lucene/analysis/morfologik/build.gradle b/lucene/analysis/morfologik/build.gradle
index 03d7c09..4faee5d 100644
--- a/lucene/analysis/morfologik/build.gradle
+++ b/lucene/analysis/morfologik/build.gradle
@@ -27,5 +27,5 @@ dependencies {
moduleImplementation 'org.carrot2:morfologik-polish'
moduleImplementation 'ua.net.nlp:morfologik-ukrainian-search'
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/analysis/nori/build.gradle b/lucene/analysis/nori/build.gradle
index 079cf50..c84ade8 100644
--- a/lucene/analysis/nori/build.gradle
+++ b/lucene/analysis/nori/build.gradle
@@ -22,7 +22,7 @@ description = 'Korean Morphological Analyzer'
dependencies {
moduleApi project(':lucene:core')
moduleApi project(':lucene:analysis:common')
-
- testImplementation project(':lucene:test-framework')
+
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/analysis/opennlp/build.gradle b/lucene/analysis/opennlp/build.gradle
index 3fee61a..2964e88 100644
--- a/lucene/analysis/opennlp/build.gradle
+++ b/lucene/analysis/opennlp/build.gradle
@@ -24,5 +24,5 @@ dependencies {
moduleApi project(':lucene:analysis:common')
moduleApi 'org.apache.opennlp:opennlp-tools'
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/analysis/phonetic/build.gradle b/lucene/analysis/phonetic/build.gradle
index 2297af5..1b8eee8 100644
--- a/lucene/analysis/phonetic/build.gradle
+++ b/lucene/analysis/phonetic/build.gradle
@@ -25,6 +25,6 @@ dependencies {
moduleApi 'commons-codec:commons-codec'
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/analysis/smartcn/build.gradle b/lucene/analysis/smartcn/build.gradle
index 960be70..87aafc9 100644
--- a/lucene/analysis/smartcn/build.gradle
+++ b/lucene/analysis/smartcn/build.gradle
@@ -23,5 +23,5 @@ dependencies {
moduleApi project(':lucene:core')
moduleApi project(':lucene:analysis:common')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/analysis/stempel/build.gradle b/lucene/analysis/stempel/build.gradle
index 3299159..52d1b81 100644
--- a/lucene/analysis/stempel/build.gradle
+++ b/lucene/analysis/stempel/build.gradle
@@ -23,5 +23,5 @@ dependencies {
moduleApi project(':lucene:core')
moduleApi project(':lucene:analysis:common')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/backward-codecs/build.gradle b/lucene/backward-codecs/build.gradle
index d5e25d9..528c1a5 100644
--- a/lucene/backward-codecs/build.gradle
+++ b/lucene/backward-codecs/build.gradle
@@ -22,5 +22,5 @@ description = 'Codecs for older versions of Lucene'
dependencies {
moduleApi project(':lucene:core')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/benchmark/build.gradle b/lucene/benchmark/build.gradle
index 9da51c3..97f17bd 100644
--- a/lucene/benchmark/build.gradle
+++ b/lucene/benchmark/build.gradle
@@ -36,11 +36,18 @@ dependencies {
moduleImplementation "org.locationtech.spatial4j:spatial4j"
moduleImplementation ("net.sourceforge.nekohtml:nekohtml", {
exclude module: "xml-apis"
+ // LUCENE-10337: Exclude xercesImpl from module path because it has split packages with the JDK (!)
+ exclude module: "xercesImpl"
+ })
+
+ // LUCENE-10337: Include xercesImpl on regular classpath where it won't cause conflicts.
+ implementation ("xerces:xercesImpl", {
+ exclude module: "xml-apis"
})
moduleRuntimeOnly project(':lucene:analysis:icu')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
// We add 'conf' to resources because we validate *.alg script correctness in one of the tests.
diff --git a/lucene/classification/build.gradle b/lucene/classification/build.gradle
index 8566cdb..1b8a1bd 100644
--- a/lucene/classification/build.gradle
+++ b/lucene/classification/build.gradle
@@ -25,7 +25,7 @@ dependencies {
moduleImplementation project(':lucene:queries')
moduleImplementation project(':lucene:grouping')
- testImplementation project(':lucene:test-framework')
- testImplementation project(':lucene:analysis:common')
- testImplementation project(':lucene:codecs')
+ moduleTestImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:analysis:common')
+ moduleTestImplementation project(':lucene:codecs')
}
diff --git a/lucene/codecs/build.gradle b/lucene/codecs/build.gradle
index 92e0782..1de66fe 100644
--- a/lucene/codecs/build.gradle
+++ b/lucene/codecs/build.gradle
@@ -21,5 +21,5 @@ description = 'Lucene codecs and postings formats'
dependencies {
moduleImplementation project(':lucene:core')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/codecs/src/test/org/apache/lucene/codecs/lucene90/MockTermStateFactory.java b/lucene/codecs/src/test/org/apache/lucene/codecs/lucene90/tests/MockTermStateFactory.java
similarity index 71%
rename from lucene/codecs/src/test/org/apache/lucene/codecs/lucene90/MockTermStateFactory.java
rename to lucene/codecs/src/test/org/apache/lucene/codecs/lucene90/tests/MockTermStateFactory.java
index 17ee5ef..69c36e7 100644
--- a/lucene/codecs/src/test/org/apache/lucene/codecs/lucene90/MockTermStateFactory.java
+++ b/lucene/codecs/src/test/org/apache/lucene/codecs/lucene90/tests/MockTermStateFactory.java
@@ -15,13 +15,14 @@
* limitations under the License.
*/
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene90.tests;
-/** Test utility class to create mock {@link Lucene90PostingsFormat.IntBlockTermState}. */
-public class MockTermStateFactory {
+import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.IntBlockTermState;
- /** Creates an empty {@link Lucene90PostingsFormat.IntBlockTermState}. */
- public static Lucene90PostingsFormat.IntBlockTermState create() {
- return new Lucene90PostingsFormat.IntBlockTermState();
+/** Test utility class to create mock {@link IntBlockTermState}. */
+public class MockTermStateFactory {
+ /** Creates an empty {@link IntBlockTermState}. */
+ public static IntBlockTermState create() {
+ return new IntBlockTermState();
}
}
diff --git a/lucene/codecs/src/test/org/apache/lucene/codecs/uniformsplit/TestBlockWriter.java b/lucene/codecs/src/test/org/apache/lucene/codecs/uniformsplit/TestBlockWriter.java
index 5d74e7b..5f05cb0 100644
--- a/lucene/codecs/src/test/org/apache/lucene/codecs/uniformsplit/TestBlockWriter.java
+++ b/lucene/codecs/src/test/org/apache/lucene/codecs/uniformsplit/TestBlockWriter.java
@@ -19,7 +19,7 @@ package org.apache.lucene.codecs.uniformsplit;
import java.io.IOException;
import java.util.Collections;
-import org.apache.lucene.codecs.lucene90.MockTermStateFactory;
+import org.apache.lucene.codecs.lucene90.tests.MockTermStateFactory;
import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.IndexOptions;
diff --git a/lucene/codecs/src/test/org/apache/lucene/codecs/uniformsplit/sharedterms/TestSTBlockReader.java b/lucene/codecs/src/test/org/apache/lucene/codecs/uniformsplit/sharedterms/TestSTBlockReader.java
index 2a5e912..dc5a4c2 100644
--- a/lucene/codecs/src/test/org/apache/lucene/codecs/uniformsplit/sharedterms/TestSTBlockReader.java
+++ b/lucene/codecs/src/test/org/apache/lucene/codecs/uniformsplit/sharedterms/TestSTBlockReader.java
@@ -27,7 +27,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.lucene.codecs.BlockTermState;
import org.apache.lucene.codecs.PostingsReaderBase;
-import org.apache.lucene.codecs.lucene90.MockTermStateFactory;
+import org.apache.lucene.codecs.lucene90.tests.MockTermStateFactory;
import org.apache.lucene.codecs.uniformsplit.BlockHeader;
import org.apache.lucene.codecs.uniformsplit.BlockLine;
import org.apache.lucene.codecs.uniformsplit.FSTDictionary;
diff --git a/lucene/core.tests/build.gradle b/lucene/core.tests/build.gradle
index 9ada300..4bc8bf5 100644
--- a/lucene/core.tests/build.gradle
+++ b/lucene/core.tests/build.gradle
@@ -21,8 +21,5 @@ description = 'Module tests for :lucene:core'
dependencies {
moduleTestImplementation project(':lucene:core')
- moduleTestImplementation("junit:junit", {
- exclude group: "org.hamcrest"
- })
- moduleTestImplementation "org.hamcrest:hamcrest"
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/backward-codecs/build.gradle b/lucene/core.tests/src/java/module-info.java
similarity index 78%
copy from lucene/backward-codecs/build.gradle
copy to lucene/core.tests/src/java/module-info.java
index d5e25d9..28f8806 100644
--- a/lucene/backward-codecs/build.gradle
+++ b/lucene/core.tests/src/java/module-info.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-
-apply plugin: 'java-library'
-
-description = 'Codecs for older versions of Lucene'
-
-dependencies {
- moduleApi project(':lucene:core')
- testImplementation project(':lucene:test-framework')
+/**
+ * A placeholder module descriptor just so that we can check whether referencing it from the actual
+ * test module works.
+ */
+module org.apache.lucene.core.tests.main {
+ exports org.apache.lucene.core.tests.main;
}
diff --git a/lucene/backward-codecs/build.gradle b/lucene/core.tests/src/java/org/apache/lucene/core/tests/main/EmptyReference.java
similarity index 80%
copy from lucene/backward-codecs/build.gradle
copy to lucene/core.tests/src/java/org/apache/lucene/core/tests/main/EmptyReference.java
index d5e25d9..55c367b 100644
--- a/lucene/backward-codecs/build.gradle
+++ b/lucene/core.tests/src/java/org/apache/lucene/core/tests/main/EmptyReference.java
@@ -14,13 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.lucene.core.tests.main;
-
-apply plugin: 'java-library'
-
-description = 'Codecs for older versions of Lucene'
-
-dependencies {
- moduleApi project(':lucene:core')
- testImplementation project(':lucene:test-framework')
+/** Just an empty class to reference from the actual tests. */
+public class EmptyReference {
+ /** No instantiation. */
+ private EmptyReference() {}
}
diff --git a/lucene/core/build.gradle b/lucene/core.tests/src/java/org/apache/lucene/core/tests/main/package-info.java
similarity index 81%
copy from lucene/core/build.gradle
copy to lucene/core.tests/src/java/org/apache/lucene/core/tests/main/package-info.java
index 989c57f..5b9241b 100644
--- a/lucene/core/build.gradle
+++ b/lucene/core.tests/src/java/org/apache/lucene/core/tests/main/package-info.java
@@ -15,11 +15,5 @@
* limitations under the License.
*/
-apply plugin: 'java-library'
-
-description = 'Lucene core library'
-
-dependencies {
- testImplementation project(':lucene:codecs')
- testImplementation project(':lucene:test-framework')
-}
+/** Contains a placeholder class for referencing in tests. */
+package org.apache.lucene.core.tests.main;
diff --git a/lucene/core.tests/src/java/overview.html b/lucene/core.tests/src/java/overview.html
new file mode 100644
index 0000000..e71200a
--- /dev/null
+++ b/lucene/core.tests/src/java/overview.html
@@ -0,0 +1,26 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+<head>
+ <title>Apache Lucene Core Tests</title>
+</head>
+ <body>
+
+ <p>A placeholder module descriptor just so that we can check whether
+ referencing it from the actual test module works.</p>
+ </body>
+</html>
diff --git a/lucene/core.tests/src/test/module-info.java b/lucene/core.tests/src/test/module-info.java
index 21fb271..26fa595 100644
--- a/lucene/core.tests/src/test/module-info.java
+++ b/lucene/core.tests/src/test/module-info.java
@@ -19,7 +19,8 @@
@SuppressWarnings({"requires-automatic"})
module org.apache.lucene.core.tests {
requires org.apache.lucene.core;
- requires junit;
+ requires org.apache.lucene.test_framework;
+ requires org.apache.lucene.core.tests.main;
exports org.apache.lucene.core.tests;
diff --git a/lucene/core.tests/src/test/org/apache/lucene/core/tests/TestMMap.java b/lucene/core.tests/src/test/org/apache/lucene/core/tests/TestMMap.java
index 2324846..fcaae01 100644
--- a/lucene/core.tests/src/test/org/apache/lucene/core/tests/TestMMap.java
+++ b/lucene/core.tests/src/test/org/apache/lucene/core/tests/TestMMap.java
@@ -17,12 +17,11 @@
package org.apache.lucene.core.tests;
import org.apache.lucene.store.MMapDirectory;
+import org.apache.lucene.tests.util.LuceneTestCase;
import org.junit.Assert;
-import org.junit.Test;
-public class TestMMap {
- @Test
- public void testUnmapSupported() throws Exception {
+public class TestMMap extends LuceneTestCase {
+ public void testUnmapSupported() {
final Module module = MMapDirectory.class.getModule();
Assert.assertTrue("Lucene Core is not loaded as module", module.isNamed());
Assert.assertTrue(
diff --git a/lucene/core.tests/src/test/org/apache/lucene/core/tests/TestModuleResourceLoader.java b/lucene/core.tests/src/test/org/apache/lucene/core/tests/TestModuleResourceLoader.java
index ac111e6..edbd705 100644
--- a/lucene/core.tests/src/test/org/apache/lucene/core/tests/TestModuleResourceLoader.java
+++ b/lucene/core.tests/src/test/org/apache/lucene/core/tests/TestModuleResourceLoader.java
@@ -17,13 +17,12 @@
package org.apache.lucene.core.tests;
import java.io.IOException;
+import org.apache.lucene.tests.util.LuceneTestCase;
import org.apache.lucene.util.ModuleResourceLoader;
import org.apache.lucene.util.ResourceLoader;
-import org.junit.Assert;
import org.junit.BeforeClass;
-import org.junit.Test;
-public class TestModuleResourceLoader extends Assert {
+public class TestModuleResourceLoader extends LuceneTestCase {
private static final Module MODULE = TestModuleResourceLoader.class.getModule();
private final ResourceLoader loader = new ModuleResourceLoader(MODULE);
@@ -33,7 +32,6 @@ public class TestModuleResourceLoader extends Assert {
assertTrue("Test class must be in a named module", MODULE.isNamed());
}
- @Test
public void testModuleResources() throws Exception {
try (var stream = loader.openResource("org/apache/lucene/core/testresources/accessible.txt")) {
stream.available();
@@ -51,8 +49,7 @@ public class TestModuleResourceLoader extends Assert {
}
}
- @Test
- public void testModuleClassloading() throws Exception {
+ public void testModuleClassloading() {
assertSame(
TestModuleResourceLoader.class,
loader.findClass(TestModuleResourceLoader.class.getName(), Object.class));
diff --git a/lucene/core.tests/src/test/org/apache/lucene/core/tests/TestRuntimeDependenciesSane.java b/lucene/core.tests/src/test/org/apache/lucene/core/tests/TestRuntimeDependenciesSane.java
new file mode 100644
index 0000000..2a07d4b
--- /dev/null
+++ b/lucene/core.tests/src/test/org/apache/lucene/core/tests/TestRuntimeDependenciesSane.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.core.tests;
+
+import org.apache.lucene.core.tests.main.EmptyReference;
+import org.apache.lucene.index.IndexWriter;
+import org.junit.Test;
+
+/** Intentionally not a subclass of {@code LuceneTestCase}. */
+public class TestRuntimeDependenciesSane {
+ @Test
+ public void testExternalDependenciesAreModules() {
+ isModule(org.junit.Test.class);
+ }
+
+ @Test
+ public void testInterProjectDependenciesAreModules() {
+ // The core Lucene should be a modular dependency.
+ isModule(IndexWriter.class);
+ }
+
+ @Test
+ public void testTestSourceSetIsAModule() {
+ // The test source set itself should be loaded as a module.
+ isModule(getClass());
+ }
+
+ @Test
+ public void testMainSourceSetIsAModule() {
+ // The test source set itself should be loaded as a module.
+ isModule(EmptyReference.class);
+ }
+
+ private static void isModule(Class<?> clazz) {
+ var module = clazz.getModule();
+ if (!module.isNamed()) {
+ throw new AssertionError(
+ "Class should be loaded from a named module: "
+ + clazz.getName()
+ + " but is instead part of: "
+ + module);
+ }
+ }
+}
diff --git a/lucene/core/build.gradle b/lucene/core/build.gradle
index 989c57f..e55c085 100644
--- a/lucene/core/build.gradle
+++ b/lucene/core/build.gradle
@@ -20,6 +20,6 @@ apply plugin: 'java-library'
description = 'Lucene core library'
dependencies {
- testImplementation project(':lucene:codecs')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:codecs')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/demo/build.gradle b/lucene/demo/build.gradle
index 70fd1df..a5c9469 100644
--- a/lucene/demo/build.gradle
+++ b/lucene/demo/build.gradle
@@ -27,5 +27,5 @@ dependencies {
moduleImplementation project(':lucene:queryparser')
moduleImplementation project(':lucene:expressions')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/expressions/build.gradle b/lucene/expressions/build.gradle
index 6823ae6..f9fcee6 100644
--- a/lucene/expressions/build.gradle
+++ b/lucene/expressions/build.gradle
@@ -29,5 +29,5 @@ dependencies {
moduleImplementation 'org.ow2.asm:asm'
moduleImplementation 'org.ow2.asm:asm-commons'
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/facet/build.gradle b/lucene/facet/build.gradle
index 1b16f94..87b1950 100644
--- a/lucene/facet/build.gradle
+++ b/lucene/facet/build.gradle
@@ -22,11 +22,10 @@ description = 'Faceted indexing and search capabilities'
dependencies {
moduleApi project(':lucene:core')
-
moduleImplementation 'com.carrotsearch:hppc'
- testImplementation project(':lucene:test-framework')
- testImplementation project(':lucene:queries')
+ moduleTestImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:queries')
// Required for opening older indexes for backward compatibility tests
- testImplementation project(':lucene:backward-codecs')
+ moduleTestImplementation project(':lucene:backward-codecs')
}
diff --git a/lucene/grouping/build.gradle b/lucene/grouping/build.gradle
index 7035a11..5915c78 100644
--- a/lucene/grouping/build.gradle
+++ b/lucene/grouping/build.gradle
@@ -25,5 +25,5 @@ dependencies {
moduleImplementation project(':lucene:queries')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/highlighter/build.gradle b/lucene/highlighter/build.gradle
index 105f1de..d2e7baf 100644
--- a/lucene/highlighter/build.gradle
+++ b/lucene/highlighter/build.gradle
@@ -26,7 +26,7 @@ dependencies {
moduleImplementation project(':lucene:queries')
moduleImplementation project(':lucene:memory')
- testImplementation project(':lucene:test-framework')
- testImplementation project(':lucene:analysis:common')
- testImplementation project(':lucene:queryparser')
+ moduleTestImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:analysis:common')
+ moduleTestImplementation project(':lucene:queryparser')
}
diff --git a/lucene/join/build.gradle b/lucene/join/build.gradle
index d8c2eab..840b3bc 100644
--- a/lucene/join/build.gradle
+++ b/lucene/join/build.gradle
@@ -21,5 +21,5 @@ description = 'Index-time and Query-time joins for normalized content'
dependencies {
moduleApi project(':lucene:core')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
\ No newline at end of file
diff --git a/lucene/luke/build.gradle b/lucene/luke/build.gradle
index 6def3e6..1504240 100644
--- a/lucene/luke/build.gradle
+++ b/lucene/luke/build.gradle
@@ -45,7 +45,7 @@ dependencies {
moduleImplementation project(':lucene:analysis:stempel')
moduleImplementation project(':lucene:suggest')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
// Configure main class name for all JARs.
diff --git a/lucene/memory/build.gradle b/lucene/memory/build.gradle
index eb6626e..789070f 100644
--- a/lucene/memory/build.gradle
+++ b/lucene/memory/build.gradle
@@ -23,6 +23,6 @@ description = 'Single-document in-memory index implementation'
dependencies {
moduleApi project(':lucene:core')
- testImplementation project(':lucene:test-framework')
- testImplementation project(':lucene:queryparser')
+ moduleTestImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:queryparser')
}
\ No newline at end of file
diff --git a/lucene/misc/build.gradle b/lucene/misc/build.gradle
index b9d7626..1c4468a 100644
--- a/lucene/misc/build.gradle
+++ b/lucene/misc/build.gradle
@@ -21,7 +21,7 @@ description = 'Index tools and other miscellaneous code'
dependencies {
moduleApi project(':lucene:core')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
nativeDeps project(":lucene:misc:native")
}
\ No newline at end of file
diff --git a/lucene/monitor/build.gradle b/lucene/monitor/build.gradle
index ff6677f..83d6759 100644
--- a/lucene/monitor/build.gradle
+++ b/lucene/monitor/build.gradle
@@ -25,6 +25,6 @@ dependencies {
moduleImplementation project(':lucene:memory')
moduleImplementation project(':lucene:analysis:common')
- testImplementation project(':lucene:queryparser')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:queryparser')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/queries/build.gradle b/lucene/queries/build.gradle
index d0cc010..560365c 100644
--- a/lucene/queries/build.gradle
+++ b/lucene/queries/build.gradle
@@ -22,7 +22,7 @@ description = 'Filters and Queries that add to core Lucene'
dependencies {
moduleApi project(':lucene:core')
- testImplementation project(':lucene:test-framework')
- testImplementation project(':lucene:expressions')
+ moduleTestImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:expressions')
}
diff --git a/lucene/queryparser/build.gradle b/lucene/queryparser/build.gradle
index b50b565..2390cfe 100644
--- a/lucene/queryparser/build.gradle
+++ b/lucene/queryparser/build.gradle
@@ -24,5 +24,5 @@ dependencies {
moduleApi project(':lucene:queries')
moduleApi project(':lucene:sandbox')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/replicator/build.gradle b/lucene/replicator/build.gradle
index d3dfc07..2058502 100644
--- a/lucene/replicator/build.gradle
+++ b/lucene/replicator/build.gradle
@@ -30,12 +30,12 @@ dependencies {
moduleImplementation 'javax.servlet:javax.servlet-api'
- testImplementation 'org.eclipse.jetty:jetty-server'
- testImplementation('org.eclipse.jetty:jetty-servlet', {
+ moduleTestImplementation project(':lucene:test-framework')
+
+ moduleTestImplementation 'org.eclipse.jetty:jetty-server'
+ moduleTestImplementation('org.eclipse.jetty:jetty-servlet', {
exclude group: "org.eclipse.jetty", module: "jetty-security"
})
- testImplementation 'org.eclipse.jetty:jetty-continuation'
-
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation 'org.eclipse.jetty:jetty-continuation'
}
diff --git a/lucene/sandbox/build.gradle b/lucene/sandbox/build.gradle
index b7e8018..93f01e3 100644
--- a/lucene/sandbox/build.gradle
+++ b/lucene/sandbox/build.gradle
@@ -22,5 +22,5 @@ description = 'Various third party contributions and new ideas'
dependencies {
moduleApi project(':lucene:core')
moduleApi project(':lucene:queries')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/spatial-extras/build.gradle b/lucene/spatial-extras/build.gradle
index 34fa10e..baa772f 100644
--- a/lucene/spatial-extras/build.gradle
+++ b/lucene/spatial-extras/build.gradle
@@ -19,6 +19,10 @@ apply plugin: 'java-library'
description = 'Geospatial search'
+configurations {
+ spatial4jTestPatch
+}
+
dependencies {
moduleApi project(':lucene:core')
moduleApi project(':lucene:spatial3d')
@@ -26,11 +30,17 @@ dependencies {
moduleApi 'org.locationtech.spatial4j:spatial4j'
moduleApi 'io.sgr:s2-geometry-library-java'
- testImplementation project(':lucene:test-framework')
- testImplementation testFixtures(project(':lucene:spatial3d'))
-
+ moduleTestImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:spatial-test-fixtures')
moduleTestImplementation 'org.locationtech.jts:jts-core'
- testImplementation 'org.locationtech.spatial4j:spatial4j::tests'
-}
+ // We add patched modules to this configuration because otherwise IDEs would not see the
+ // dependency at all, even in classpath mode (they don't see --patch-module commands we
+ // add to the compiler and test tasks).
+ moduleTestPatchOnly 'org.locationtech.spatial4j:spatial4j::tests'
+ spatial4jTestPatch 'org.locationtech.spatial4j:spatial4j::tests'
+}
+sourceSets.test.extensions.configure("modularPaths", {
+ it.patchModule("spatial4j", project.providers.provider({ configurations.spatial4jTestPatch.singleFile }))
+})
\ No newline at end of file
diff --git a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/TestGeo3dRpt.java b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/TestGeo3dRpt.java
index 425142e..0d3e812 100644
--- a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/TestGeo3dRpt.java
+++ b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/TestGeo3dRpt.java
@@ -16,7 +16,7 @@
*/
package org.apache.lucene.spatial.spatial4j;
-import static org.apache.lucene.spatial3d.geom.RandomGeo3dShapeGenerator.*;
+import static org.apache.lucene.spatial3d.tests.RandomGeo3dShapeGenerator.*;
import static org.locationtech.spatial4j.distance.DistanceUtils.DEGREES_TO_RADIANS;
import java.io.IOException;
diff --git a/lucene/backward-codecs/build.gradle b/lucene/spatial-test-fixtures/build.gradle
similarity index 83%
copy from lucene/backward-codecs/build.gradle
copy to lucene/spatial-test-fixtures/build.gradle
index d5e25d9..983416d 100644
--- a/lucene/backward-codecs/build.gradle
+++ b/lucene/spatial-test-fixtures/build.gradle
@@ -15,12 +15,11 @@
* limitations under the License.
*/
-
apply plugin: 'java-library'
-description = 'Codecs for older versions of Lucene'
+description = '3D spatial planar geometry test fixtures'
dependencies {
- moduleApi project(':lucene:core')
- testImplementation project(':lucene:test-framework')
+ moduleImplementation project(':lucene:test-framework')
+ moduleImplementation project(':lucene:spatial3d')
}
diff --git a/lucene/spatial3d/src/testFixtures/java/org/apache/lucene/spatial3d/geom/RandomGeo3dShapeGenerator.java b/lucene/spatial-test-fixtures/src/java/org/apache/lucene/spatial3d/tests/RandomGeo3dShapeGenerator.java
similarity index 95%
rename from lucene/spatial3d/src/testFixtures/java/org/apache/lucene/spatial3d/geom/RandomGeo3dShapeGenerator.java
rename to lucene/spatial-test-fixtures/src/java/org/apache/lucene/spatial3d/tests/RandomGeo3dShapeGenerator.java
index da4ac89..d3ddb3f 100644
--- a/lucene/spatial3d/src/testFixtures/java/org/apache/lucene/spatial3d/geom/RandomGeo3dShapeGenerator.java
+++ b/lucene/spatial-test-fixtures/src/java/org/apache/lucene/spatial3d/tests/RandomGeo3dShapeGenerator.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.lucene.spatial3d.geom;
+package org.apache.lucene.spatial3d.tests;
import com.carrotsearch.randomizedtesting.RandomizedContext;
import com.carrotsearch.randomizedtesting.RandomizedTest;
@@ -25,6 +25,23 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
+import org.apache.lucene.spatial3d.geom.GeoArea;
+import org.apache.lucene.spatial3d.geom.GeoAreaShape;
+import org.apache.lucene.spatial3d.geom.GeoBBox;
+import org.apache.lucene.spatial3d.geom.GeoBBoxFactory;
+import org.apache.lucene.spatial3d.geom.GeoCircle;
+import org.apache.lucene.spatial3d.geom.GeoCircleFactory;
+import org.apache.lucene.spatial3d.geom.GeoCompositeAreaShape;
+import org.apache.lucene.spatial3d.geom.GeoCompositeMembershipShape;
+import org.apache.lucene.spatial3d.geom.GeoPath;
+import org.apache.lucene.spatial3d.geom.GeoPathFactory;
+import org.apache.lucene.spatial3d.geom.GeoPoint;
+import org.apache.lucene.spatial3d.geom.GeoPointShape;
+import org.apache.lucene.spatial3d.geom.GeoPointShapeFactory;
+import org.apache.lucene.spatial3d.geom.GeoPolygon;
+import org.apache.lucene.spatial3d.geom.GeoPolygonFactory;
+import org.apache.lucene.spatial3d.geom.GeoShape;
+import org.apache.lucene.spatial3d.geom.PlanetModel;
/**
* Class for generating random Geo3dShapes. They can be generated under given constraints which are
@@ -42,22 +59,22 @@ public final class RandomGeo3dShapeGenerator {
private static final int MAX_POINT_ITERATIONS = 1000;
/* Supported shapes */
- protected static final int CONVEX_POLYGON = 0;
- protected static final int CONVEX_POLYGON_WITH_HOLES = 1;
- protected static final int CONCAVE_POLYGON = 2;
- protected static final int CONCAVE_POLYGON_WITH_HOLES = 3;
- protected static final int COMPLEX_POLYGON = 4;
- protected static final int CIRCLE = 5;
- protected static final int RECTANGLE = 6;
- protected static final int PATH = 7;
- protected static final int COLLECTION = 8;
- protected static final int POINT = 9;
- protected static final int LINE = 10;
- protected static final int EXACT_CIRCLE = 11;
+ public static final int CONVEX_POLYGON = 0;
+ public static final int CONVEX_POLYGON_WITH_HOLES = 1;
+ public static final int CONCAVE_POLYGON = 2;
+ public static final int CONCAVE_POLYGON_WITH_HOLES = 3;
+ public static final int COMPLEX_POLYGON = 4;
+ public static final int CIRCLE = 5;
+ public static final int RECTANGLE = 6;
+ public static final int PATH = 7;
+ public static final int COLLECTION = 8;
+ public static final int POINT = 9;
+ public static final int LINE = 10;
+ public static final int EXACT_CIRCLE = 11;
/* Helper shapes for generating constraints whch are just three sided polygons */
- protected static final int CONVEX_SIMPLE_POLYGON = 500;
- protected static final int CONCAVE_SIMPLE_POLYGON = 501;
+ public static final int CONVEX_SIMPLE_POLYGON = 500;
+ public static final int CONCAVE_SIMPLE_POLYGON = 501;
/** Static methods only. */
private RandomGeo3dShapeGenerator() {}
@@ -550,7 +567,7 @@ public final class RandomGeo3dShapeGenerator {
collection.addShape(member);
}
}
- if (collection.shapes.size() == 0) {
+ if (collection.size() == 0) {
continue;
}
return collection;
@@ -963,7 +980,7 @@ public final class RandomGeo3dShapeGenerator {
* @param points The points to order.
* @return The list of ordered points anti-clockwise.
*/
- protected static List<GeoPoint> orderPoints(List<GeoPoint> points) {
+ public static List<GeoPoint> orderPoints(List<GeoPoint> points) {
double x = 0;
double y = 0;
double z = 0;
@@ -1005,8 +1022,7 @@ public final class RandomGeo3dShapeGenerator {
* Class that holds the constraints that are given to build shapes. It consists in a list of
* GeoAreaShapes and relationships the new shape needs to satisfy.
*/
- static class Constraints extends HashMap<GeoAreaShape, Integer> {
-
+ public static class Constraints extends HashMap<GeoAreaShape, Integer> {
/**
* Check if the shape is valid under the constraints.
*
@@ -1052,7 +1068,7 @@ public final class RandomGeo3dShapeGenerator {
// For GeoCompositeMembershipShape we only consider the first shape to help
// converging
if (relationship == GeoArea.WITHIN && shape instanceof GeoCompositeMembershipShape) {
- shape = (((GeoCompositeMembershipShape) shape).shapes.get(0));
+ shape = (((GeoCompositeMembershipShape) shape).getShapes().get(0));
}
switch (relationship) {
case GeoArea.DISJOINT:
diff --git a/lucene/core/build.gradle b/lucene/spatial-test-fixtures/src/java/org/apache/lucene/spatial3d/tests/package-info.java
similarity index 81%
copy from lucene/core/build.gradle
copy to lucene/spatial-test-fixtures/src/java/org/apache/lucene/spatial3d/tests/package-info.java
index 989c57f..004a77b 100644
--- a/lucene/core/build.gradle
+++ b/lucene/spatial-test-fixtures/src/java/org/apache/lucene/spatial3d/tests/package-info.java
@@ -15,11 +15,5 @@
* limitations under the License.
*/
-apply plugin: 'java-library'
-
-description = 'Lucene core library'
-
-dependencies {
- testImplementation project(':lucene:codecs')
- testImplementation project(':lucene:test-framework')
-}
+/** Shared test fixtures for spatial packages. */
+package org.apache.lucene.spatial3d.tests;
diff --git a/lucene/spatial-test-fixtures/src/java/overview.html b/lucene/spatial-test-fixtures/src/java/overview.html
new file mode 100644
index 0000000..08e16bc
--- /dev/null
+++ b/lucene/spatial-test-fixtures/src/java/overview.html
@@ -0,0 +1,24 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+ <head>
+ <title>Apache Lucene Spatial Test Fixtures Module</title>
+ </head>
+ <body>
+ <h1>Internal test fixtures for spatial modules</h1>
+ </body>
+</html>
diff --git a/lucene/spatial3d/build.gradle b/lucene/spatial3d/build.gradle
index 219d029..0b25833 100644
--- a/lucene/spatial3d/build.gradle
+++ b/lucene/spatial3d/build.gradle
@@ -16,13 +16,17 @@
*/
apply plugin: 'java-library'
-apply plugin: 'java-test-fixtures'
description = '3D spatial planar geometry APIs'
dependencies {
moduleApi project(':lucene:core')
+ moduleTestImplementation project(':lucene:test-framework')
- testFixturesApi project(':lucene:test-framework')
- testImplementation project(':lucene:test-framework')
+ // We have to exclude ourselves because spatial-test-fixtures depend
+ // on the main source set of this project and tests would receive the
+ // dependency twice - on classpath and in module path.
+ moduleTestImplementation(project(':lucene:spatial-test-fixtures'), {
+ exclude module: "spatial3d"
+ })
}
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseCompositeShape.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseCompositeShape.java
index 8c87706..876882a 100644
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseCompositeShape.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseCompositeShape.java
@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -149,4 +150,9 @@ public abstract class GeoBaseCompositeShape<T extends GeoShape> extends BasePlan
GeoBaseCompositeShape<?> other = (GeoBaseCompositeShape<?>) o;
return super.equals(other) && shapes.equals(other.shapes);
}
+
+ /** Returns an unmodifiable list of composed shapes. */
+ public List<T> getShapes() {
+ return Collections.unmodifiableList(shapes);
+ }
}
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestGeoExactCircle.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestGeoExactCircle.java
index c99f602..28036e2 100644
--- a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestGeoExactCircle.java
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestGeoExactCircle.java
@@ -17,9 +17,10 @@
package org.apache.lucene.spatial3d.geom;
-import static org.apache.lucene.spatial3d.geom.RandomGeo3dShapeGenerator.*;
+import static org.apache.lucene.spatial3d.tests.RandomGeo3dShapeGenerator.*;
import com.carrotsearch.randomizedtesting.annotations.Repeat;
+import org.apache.lucene.spatial3d.tests.RandomGeo3dShapeGenerator;
import org.apache.lucene.tests.util.LuceneTestCase;
import org.junit.Test;
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomBinaryCodec.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomBinaryCodec.java
index 214ef7d..3c0a6a8 100644
--- a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomBinaryCodec.java
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomBinaryCodec.java
@@ -17,7 +17,7 @@
package org.apache.lucene.spatial3d.geom;
-import static org.apache.lucene.spatial3d.geom.RandomGeo3dShapeGenerator.*;
+import static org.apache.lucene.spatial3d.tests.RandomGeo3dShapeGenerator.*;
import com.carrotsearch.randomizedtesting.annotations.Repeat;
import java.io.ByteArrayInputStream;
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomGeoPolygon.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomGeoPolygon.java
index e5a9d7d..ac87144 100644
--- a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomGeoPolygon.java
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomGeoPolygon.java
@@ -16,7 +16,7 @@
*/
package org.apache.lucene.spatial3d.geom;
-import static org.apache.lucene.spatial3d.geom.RandomGeo3dShapeGenerator.*;
+import static org.apache.lucene.spatial3d.tests.RandomGeo3dShapeGenerator.*;
import com.carrotsearch.randomizedtesting.generators.BiasedNumbers;
import java.util.ArrayList;
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomGeoShapeRelationship.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomGeoShapeRelationship.java
index 9f3bd75..9b63b4e 100644
--- a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomGeoShapeRelationship.java
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomGeoShapeRelationship.java
@@ -17,7 +17,7 @@
package org.apache.lucene.spatial3d.geom;
-import static org.apache.lucene.spatial3d.geom.RandomGeo3dShapeGenerator.*;
+import static org.apache.lucene.spatial3d.tests.RandomGeo3dShapeGenerator.*;
import org.apache.lucene.tests.util.LuceneTestCase;
import org.junit.Test;
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomPlane.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomPlane.java
index 2ed0066..503188a 100644
--- a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomPlane.java
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestRandomPlane.java
@@ -17,7 +17,7 @@
package org.apache.lucene.spatial3d.geom;
-import static org.apache.lucene.spatial3d.geom.RandomGeo3dShapeGenerator.*;
+import static org.apache.lucene.spatial3d.tests.RandomGeo3dShapeGenerator.*;
import com.carrotsearch.randomizedtesting.annotations.Repeat;
import java.util.ArrayList;
diff --git a/lucene/suggest/build.gradle b/lucene/suggest/build.gradle
index 3afccd8..25a444d 100644
--- a/lucene/suggest/build.gradle
+++ b/lucene/suggest/build.gradle
@@ -23,5 +23,5 @@ dependencies {
moduleApi project(':lucene:core')
moduleApi project(':lucene:analysis:common')
- testImplementation project(':lucene:test-framework')
+ moduleTestImplementation project(':lucene:test-framework')
}
diff --git a/lucene/test-framework/src/java/module-info.java b/lucene/test-framework/src/java/module-info.java
index 81ee062..d87d56a 100644
--- a/lucene/test-framework/src/java/module-info.java
+++ b/lucene/test-framework/src/java/module-info.java
@@ -16,12 +16,12 @@
*/
/** Lucene test framework. */
-@SuppressWarnings({"module", "requires-automatic"})
+@SuppressWarnings({"module", "requires-automatic", "requires-transitive-automatic"})
module org.apache.lucene.test_framework {
requires org.apache.lucene.core;
requires org.apache.lucene.codecs;
- requires junit;
- requires randomizedtesting.runner;
+ requires transitive junit;
+ requires transitive randomizedtesting.runner;
exports org.apache.lucene.tests.analysis.standard;
exports org.apache.lucene.tests.analysis;
diff --git a/settings.gradle b/settings.gradle
index 0923e9d..971fbb6 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -63,5 +63,6 @@ include "lucene:replicator"
include "lucene:sandbox"
include "lucene:spatial3d"
include "lucene:spatial-extras"
+include "lucene:spatial-test-fixtures"
include "lucene:suggest"
include "lucene:test-framework"
diff --git a/versions.lock b/versions.lock
index c596e6e..fb12bb6 100644
--- a/versions.lock
+++ b/versions.lock
@@ -23,7 +23,7 @@ org.ow2.asm:asm-analysis:7.2 (1 constraints: e409d9a5)
org.ow2.asm:asm-commons:7.2 (1 constraints: ad042e2c)
org.ow2.asm:asm-tree:7.2 (2 constraints: 2f14468c)
ua.net.nlp:morfologik-ukrainian-search:4.9.1 (1 constraints: 10051b36)
-xerces:xercesImpl:2.12.0 (2 constraints: 1f14b675)
+xerces:xercesImpl:2.12.0 (1 constraints: 3705353b)
[Test dependencies]
org.assertj:assertj-core:3.21.0 (1 constraints: 38053c3b)