Skip to content

Commit

Permalink
test: add integration test for caffeine (#302)
Browse files Browse the repository at this point in the history
Adds an integration test. Caffeine is patched and
built against Guava with JPMS as a sanity test.

- test: add integration test for `caffeine`
- fix: makefile steps to copy libs
- fix: shallow submodule clone
- chore: caffeine patch at latest
- chore: readme updates

Signed-off-by: Sam Gammon <[email protected]>
  • Loading branch information
sgammon authored Feb 6, 2025
1 parent ba345cd commit 27e30f1
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 65 deletions.
38 changes: 21 additions & 17 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
path = org.checkerframework
url = [email protected]:typetools/checker-framework.git
branch = master
depth = 0
depth = 1
[submodule "error-prone"]
path = com.google.errorprone
url = [email protected]:google/error-prone.git
branch = master
depth = 0
depth = 1
[submodule "j2objc"]
path = com.google.j2objc
url = [email protected]:google/j2objc.git
branch = master
depth = 0
depth = 1
[submodule "guava"]
path = com.google.guava
url = [email protected]:sgammon/guava.git
Expand All @@ -21,56 +21,60 @@
[submodule "reactive-streams"]
path = org.reactivestreams
url = [email protected]:sgammon/reactive-streams-jvm.git
depth = 0
depth = 1
[submodule "protobuf"]
path = com.google.protobuf
url = [email protected]:sgammon/protobuf.git
depth = 0
depth = 1
[submodule "dubbo"]
path = tests/integration/dubbo
url = [email protected]:javamodules/dubbo.git
depth = 0
depth = 1
[submodule "pmd"]
path = tests/integration/pmd
url = [email protected]:javamodules/pmd.git
depth = 0
depth = 1
[submodule "ghidra"]
path = tests/integration/ghidra
url = [email protected]:javamodules/ghidra.git
depth = 0
depth = 1
[submodule "armeria"]
path = tests/integration/armeria
url = [email protected]:javamodules/armeria.git
depth = 0
depth = 1
[submodule "bazel"]
path = tests/integration/bazel
url = [email protected]:bazelbuild/bazel.git
depth = 0
depth = 1
[submodule "signal-server"]
path = tests/integration/signal-server
url = [email protected]:javamodules/Signal-Server.git
depth = 0
depth = 1
[submodule "pkl"]
path = tests/integration/pkl
url = [email protected]:javamodules/pkl.git
depth = 0
depth = 1
[submodule "checkstyle"]
path = tests/integration/checkstyle
url = [email protected]:javamodules/checkstyle.git
depth = 0
depth = 1
[submodule "gson"]
path = tests/integration/gson
url = [email protected]:google/gson.git
depth = 0
depth = 1
[submodule "geantyref"]
path = io.leangen.geantyref
url = [email protected]:leangen/geantyref.git
depth = 0
depth = 1
[submodule "kotlinx-collections-immutable"]
path = kotlinx.collections.immutable
url = [email protected]:javamodules/kotlinx.collections.immutable.git
depth = 0
depth = 1
[submodule "maven-resolver"]
path = org.apache.maven.resolver
url = [email protected]:javamodules/maven-resolver.git
depth = 0
depth = 1
[submodule "caffeine"]
path = tests/integration/caffeine
url = [email protected]:ben-manes/caffeine.git
depth = 1
2 changes: 0 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -770,9 +770,7 @@ $(LIBS):
$(RULE)$(CP) \
com.google.guava/guava/target/*.jar \
com.google.protobuf/bazel-bin/java/*/amended_*_mvn-project.jar \
io.leangen.geantyref/target/*.jar \
kotlinx.collections.immutable/core/build/libs/*.jar \
org.checkerframework/checker-qual/build/libs/*.jar \
org.reactivestreams/api/build/libs/*.jar \
$(LIBS)

Expand Down
76 changes: 34 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,41 +38,44 @@ becomes obsolete.

### What's in the box?

- **[`com.google.errorprone`][2]:** **Error Prone Compiler** "is a static analysis tool for Java that catches common
programming mistakes at compile time," built by Google. Error Prone's annotations module is JPMS-enabled at the
embedded sub-module, and is used by Guava. The [PR enabling JPMS support in Error Prone Annotations][3] has been
filed, merged, and released, as [`2.26.1`](https://github.com/google/error-prone/releases/tag/v2.26.1).

- **[`com.google.guava`][11]:** **Google Guava** is Google's core Java commons, used throughout Google's code and the
wider JVM ecosystem. Guava is an immensely popular artifact, with tons of fantastic utilities. JPMS support is [in
draft][12].

- **[`com.google.j2objc`][4]:** **J2ObjC** is a Java to Objective-C cross-compiling layer used by Google to effectively
- **[`com.google.protobuf`][4]:** **Protocol Buffers** (a.k.a., protobuf) are Google's language-neutral,
platform-neutral, extensible mechanism for serializing structured data. JPMS support is [in draft][17].

- **[`kotlinx.collections.immutable`][20]:** **KotlinX Immutable Collections** is a library provided as part of the
_Kotlin Extensions_ suite, maintained by the JetBrains team. It provides immutable and persistent collection types in
Kotlin. JPMS support is in [draft][21], but not yet merged or released.

- **[`org.reactivestreams`][16]:** **Reactive Streams** is a universal JVM API for building reactive software in an
implementation-agnostic manner.

<details>
<summary>See libraries which have been retired</summary>
- com.google.errorprone (Error Prone Compiler) "is a static analysis tool for Java that catches common
programming mistakes at compile time," built by Google. Error Prone's annotations module is JPMS-enabled at the
embedded sub-module, and is used by Guava. The [PR enabling JPMS support in Error Prone Annotations][3] has been
filed, merged, and released, as [`2.26.1`](https://github.com/google/error-prone/releases/tag/v2.26.1).

- com.google.j2objc (J2ObjC) is a Java to Objective-C cross-compiling layer used by Google to effectively
share Java logic on iOS and macOS platforms. J2ObjC itself is very complex and powerful, but here we have just
JPMS-enabled the `annotations` module, which is used by Guava. The [PR enabling JPMS support for J2ObjC
annotations][5] has been filed, merged, and released as
[`3.0.0`](https://github.com/google/j2objc/commit/a883dd3f90d51d5ccad4aa3af8feaaeed6560109).

- **[`com.google.protobuf`][4]:** **Protocol Buffers** (a.k.a., protobuf) are Google's language-neutral,
platform-neutral, extensible mechanism for serializing structured data. JPMS support is [in draft][17].

- **[`io.leangen.geantyref`][18]:** **Geantyref** is a fork of the excellent GenTyRef library, adding support for
- io.leangen.geantyref (Geantyref) is a fork of the excellent GenTyRef library, adding support for
working with AnnotatedTypes introduced in Java 8 plus many nifty features. JPMS support has been [proposed][19], but
not yet merged or released.

- **[`kotlinx.collections.immutable`][20]:** **KotlinX Immutable Collections** is a library provided as part of the
_Kotlin Extensions_ suite, maintained by the JetBrains team. It provides immutable and persistent collection types in
Kotlin. JPMS support is in [draft][21], but not yet merged or released.

- **[`org.apache.maven.resolver`][22]:** **Maven Resolver** is how Maven and many other build tools resolve graphs of
- org.apache.maven.resolver (Maven Resolver) is how Maven and many other build tools resolve graphs of
dependencies, and perform downloads of dependency artifacts. JPMS support is in early draft; no PR has been filed yet.

- **[`org.checkerframework`][0]:** **Checker Framework** is a type-checking framework for Java. The `checker-qual`
- org.checkerframework (Checker Framework) is a type-checking framework for Java. The `checker-qual`
package is used by Guava, so it is included here transitively. Checker Framework added a JPMS module definition in a
[recent PR][1], so this is sub-moduled at `master`. At the time of this writing no release has taken place.

- **[`org.reactivestreams`][16]:** **Reactive Streams** is a universal JVM API for building reactive software in an
implementation-agnostic manner.
</details>

### How do I use it?

Expand Down Expand Up @@ -155,18 +158,7 @@ pick a library.
| `com.google.protobuf:protobuf-kotlin` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Fcom%2Fgoogle%2Fprotobuf%2Fprotobuf-kotlin%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `com.google.protobuf:protobuf-kotlin-lite` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Fcom%2Fgoogle%2Fprotobuf%2Fprotobuf-kotlin-lite%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `io.leangen.geantyref:geantyref` | ![Central](https://img.shields.io/maven-central/v/io.leangen.geantyref/geantyref?label=Central&labelColor=blue) |
| `org.apache.maven.resolver:maven-resolver-api` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fapache%2Fmaven%2Fresolver%2Fmaven-resolver-api%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.apache.maven.resolver:maven-resolver-connector-basic` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fapache%2Fmaven%2Fresolver%2Fmaven-resolver-connector-basic%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.apache.maven.resolver:maven-resolver-generator-gnupg` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fapache%2Fmaven%2Fresolver%2Fmaven-resolver-generator-gnupg%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.apache.maven.resolver:maven-resolver-impl` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fapache%2Fmaven%2Fresolver%2Fmaven-resolver-impl%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.apache.maven.resolver:maven-resolver-named-locks` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fapache%2Fmaven%2Fresolver%2Fmaven-resolver-named-locks%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.apache.maven.resolver:maven-resolver-spi` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fapache%2Fmaven%2Fresolver%2Fmaven-resolver-spi%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.apache.maven.resolver:maven-resolver-transport-classpath` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fapache%2Fmaven%2Fresolver%2Fmaven-resolver-transport-classpath%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.apache.maven.resolver:maven-resolver-transport-file` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fapache%2Fmaven%2Fresolver%2Fmaven-resolver-transport-file%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.apache.maven.resolver:maven-resolver-transport-jdk` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fapache%2Fmaven%2Fresolver%2Fmaven-resolver-transport-jdk%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.apache.maven.resolver:maven-resolver-transport-jetty` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fapache%2Fmaven%2Fresolver%2Fmaven-resolver-transport-jetty%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.apache.maven.resolver:maven-resolver-util` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fapache%2Fmaven%2Fresolver%2Fmaven-resolver-util%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.checkerframework:checker-qual` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fcheckerframework%2Fchecker-qual%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.jetbrains.kotlinx:kotlinx-collections-immutable` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Fjetbrains%2Fkotlinx%2Fkotlinx-collections-immutable%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |
| `org.reactivestreams:reactive-streams` | ![JPMS](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fjpms.pkg.st%2Frepository%2Forg%2Freactivestreams%2Freactive-streams%2Fmaven-metadata.xml&logo=maven&label=JPMS&labelColor=white&color=black) |

Expand All @@ -185,18 +177,6 @@ Use the modules in your `module-info.java`:
| `com.google.protobuf:protobuf-kotlin` | `com.google.protobuf.kotlin` |
| `com.google.protobuf:protobuf-kotlin-lite` | `com.google.protobuf.kotlin` |
| `io.leangen.geantyref:geantyref` | `io.leangen.geantyref` |
| `org.apache.maven.resolver:maven-resolver-api` | `org.apache.maven.resolver` |
| `org.apache.maven.resolver:maven-resolver-connector-basic` | `org.apache.maven.resolver.connector.basic` |
| `org.apache.maven.resolver:maven-resolver-generator-gnupg` | `org.apache.maven.resolver.generator.gnupg` |
| `org.apache.maven.resolver:maven-resolver-impl` | `org.apache.maven.resolver.impl` |
| `org.apache.maven.resolver:maven-resolver-named-locks` | `org.apache.maven.resolver.named` |
| `org.apache.maven.resolver:maven-resolver-spi` | `org.apache.maven.resolver.spi` |
| `org.apache.maven.resolver:maven-resolver-transport-classpath` | `org.apache.maven.resolver.transport.classpath` |
| `org.apache.maven.resolver:maven-resolver-transport-file` | `org.apache.maven.resolver.transport.file` |
| `org.apache.maven.resolver:maven-resolver-transport-jdk` | `org.apache.maven.resolver.transport.jdk` |
| `org.apache.maven.resolver:maven-resolver-transport-jetty` | `org.apache.maven.resolver.transport.jetty` |
| `org.apache.maven.resolver:maven-resolver-util` | `org.apache.maven.resolver.util` |
| `org.checkerframework:checker-qual` | `org.checkerframework.checker.qual` |
| `org.jetbrains.kotlinx:kotlinx-collections-immutable` | `kotlinx.collections.immutable` |
| `org.reactivestreams:reactive-streams` | `org.reactivestreams` |

Expand Down Expand Up @@ -274,6 +254,15 @@ classifier-equipped JARs in local repositories is annoying.
Sample projects are provided in the [samples](./samples) directory, which show how to hook up the repository and
override libraries.

### Integration Testing

JPMS-patched modules are tested against some popular downstream projects, to make sure there is no unexpected breakage. Here is a matrix of tested projects:

| **JPMS Module** | **Status** | **Tested Project(s)** |
| --------------- | ---------- | ---------------------------------------------------- |
| Guava | ✅ Passing | [Caffeine][23], [GSON][24] |
| Protobuf | ⚠️ Issues | [GSON][24], [Bazel][25] |

### Coming soon

Future badges
Expand Down Expand Up @@ -310,3 +299,6 @@ testing and development against new code; no warranty is provided of any kind.
[20]: https://github.com/Kotlin/kotlinx.collections.immutable
[21]: https://github.com/Kotlin/kotlinx.collections.immutable/pull/175
[22]: https://maven.apache.org/resolver/
[23]: https://github.com/ben-manes/caffeine
[24]: https://github.com/google/gson
[25]: https://bazel.build
21 changes: 18 additions & 3 deletions tests/integration/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ checkstyle:
-U \
-DskipTests \
package
@echo "Checkstyle test complete."

# Ghidra's build is pretty complex; it is not included for now.
ghidra:
$(info Building Ghidra...)
@cd ghidra && $(GRADLE_TEST) \
-Pguava.version=$(GUAVA_VERSION) \
-Pfailureaccess.version=1.0.3-jpms
@echo "Ghidra test complete."

pmd:
$(info Building PMD...)
Expand All @@ -37,21 +39,34 @@ pmd:
-U \
-DskipTests \
package
@echo "PMD test complete."

gson:
$(info Cleaning GSON...)
@cd gson && git clean -fdx && git reset --hard
$(info Patching GSON...)
@echo "Patching GSON..."
@cd gson && git apply ../../../tools/patches/gson-guava-version.diff
$(info Building GSON...)
@echo "Building GSON..."
@cd gson && $(MAVEN_TEST) \
-Dprotobuf.version=$(PROTOBUF_VERSION) \
-Dguava.version=$(GUAVA_VERSION) \
-Derror-prone.version=$(ERROR_PRONE_VERSION) \
--settings ../settings.xml \
-U \
$(MAVEN_TEST_GOAL)
$(info Resetting GSON...)
@echo "Resetting GSON..."
@cd gson && git reset --hard
@echo "Gson test complete."

caffeine:
$(info Cleaning Caffeine...)
@cd caffeine && git clean -fdx && git reset --hard
@echo "Patching Caffeine..."
@cd caffeine && git apply ../../../tools/patches/caffeine-guava-version.diff
@echo "Building Caffeine..."
cd caffeine && $(GRADLE_TEST)
@echo "Resetting Caffeine..."
@cd caffeine && git reset --hard
@echo "Caffeine test complete."

.PHONY: $(INTEGRATION_TESTS)
1 change: 1 addition & 0 deletions tests/integration/caffeine
Submodule caffeine added at 18c03d
2 changes: 1 addition & 1 deletion tools/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ NODE ?= $(shell which node)
MAVEN ?= $(ENV_PREFIX) $(MAVEN_CMD) $(MAVEN_ARGS)
MAVEN_TEST ?= $(ENV_PREFIX) $(MAVEN_CMD) $(MAVEN_TEST_ARGS)
GRADLE ?= $(ENV_PREFIX) $(GRADLE_CMD) $(GRADLE_ARGS)
GRADLE_TEST ?= $(ENV_PREFIX) $(GRADLE_CMD) $(GRADLE_TEST_ARGS)
GRADLE_TEST ?= $(ENV_PREFIX) $(GRADLE_CMD) $(GRADLE_TEST_ARGS) $(GRADLE_TEST_TASK)
BAZEL ?= $(ENV_PREFIX) $(BAZEL_CMD) $(BAZEL_ARGS)
BAZEL_TEST ?= $(ENV_PREFIX) $(BAZEL_CMD) $(BAZEL_TEST_ARGS)
RM ?= rm -f$(POSIX_FLAGS)
Expand Down
61 changes: 61 additions & 0 deletions tools/patches/caffeine-guava-version.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 351c9b3..90957f4 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -33,7 +33,7 @@ findsecbugs = "1.13.0"
flip-tables = "1.1.1"
forbidden-apis = "3.8"
google-java-format = "1.25.2"
-guava = "33.4.0-jre"
+guava = "33.4.0-jre-jpms"
guice = "7.0.0"
h2 = "2.3.232"
hamcrest = "3.0"
diff --git a/guava/build.gradle.kts b/guava/build.gradle.kts
index 462d8f0..c6d46bf 100644
--- a/guava/build.gradle.kts
+++ b/guava/build.gradle.kts
@@ -29,6 +29,9 @@ tasks.named<JavaCompile>("compileTestJava").configure {
}
}

+val absoluteJpmsRepoPath =
+ rootProject.layout.projectDirectory.dir("../../../repository").asFile.absolutePath
+
tasks.withType<Test>().configureEach {
useJUnitPlatform()

diff --git a/guava/src/test/java/com/github/benmanes/caffeine/guava/OSGiTest.java b/guava/src/test/java/com/github/benmanes/caffeine/guava/OSGiTest.java
index f244daa..c7b1dfd 100644
--- a/guava/src/test/java/com/github/benmanes/caffeine/guava/OSGiTest.java
+++ b/guava/src/test/java/com/github/benmanes/caffeine/guava/OSGiTest.java
@@ -48,7 +48,7 @@ public final class OSGiTest {
bundle("file:" + System.getProperty("caffeine.osgi.jar")),
bundle("file:" + System.getProperty("caffeine-guava.osgi.jar")),
mavenBundle("com.google.guava", "failureaccess", "1.0.1"),
- mavenBundle("com.google.guava", "guava", System.getProperty("guava.osgi.version")));
+ mavenBundle("com.google.guava", "guava", System.getProperty("guava.osgi.version").replace("-jpms", "")));
}

@Test
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 1fc36e2..56f0c71 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -8,9 +8,13 @@ plugins {
}

dependencyResolutionManagement {
- repositories {
- mavenCentral()
- }
+ repositories {
+ maven {
+ name = "jpms-attic"
+ url = uri("file:///${rootProject.projectDir}/../../../repository")
+ }
+ mavenCentral()
+ }
}

apply(from = "$rootDir/gradle/develocity.gradle")

0 comments on commit 27e30f1

Please sign in to comment.