diff --git a/core/src/main/java/org/testcontainers/utility/DockerImageName.java b/core/src/main/java/org/testcontainers/utility/DockerImageName.java index e3a35855bf8..7010e4f3704 100644 --- a/core/src/main/java/org/testcontainers/utility/DockerImageName.java +++ b/core/src/main/java/org/testcontainers/utility/DockerImageName.java @@ -233,15 +233,13 @@ public DockerImageName asCompatibleSubstituteFor(DockerImageName otherImageName) * @return whether this image has declared compatibility. */ public boolean isCompatibleWith(DockerImageName other) { - // Make sure we always compare against a version of the image name containing the LIBRARY_PREFIX - String finalImageName; - if (this.repository.startsWith(LIBRARY_PREFIX)) { - finalImageName = this.repository; - } else { - finalImageName = LIBRARY_PREFIX + this.repository; + if (other.equals(this)) { + return true; } - DockerImageName imageWithLibraryPrefix = DockerImageName.parse(finalImageName); - if (other.equals(this) || imageWithLibraryPrefix.equals(this)) { + + // 'library/foo' and 'foo' refer to the same official Docker Hub image, so compare both + // names normalized to include the LIBRARY_PREFIX. + if (withLibraryPrefix(other).equals(withLibraryPrefix(this))) { return true; } @@ -252,6 +250,13 @@ public boolean isCompatibleWith(DockerImageName other) { return this.compatibleSubstituteFor.isCompatibleWith(other); } + private static DockerImageName withLibraryPrefix(DockerImageName image) { + if (!image.registry.isEmpty() || image.repository.startsWith(LIBRARY_PREFIX)) { + return image; + } + return image.withRepository(LIBRARY_PREFIX + image.repository); + } + /** * Behaves as {@link DockerImageName#isCompatibleWith(DockerImageName)} but throws an exception * rather than returning false if a mismatch is detected. diff --git a/core/src/test/java/org/testcontainers/utility/DockerImageNameCompatibilityTest.java b/core/src/test/java/org/testcontainers/utility/DockerImageNameCompatibilityTest.java index dc7bf9ba1ab..1cac92b38af 100644 --- a/core/src/test/java/org/testcontainers/utility/DockerImageNameCompatibilityTest.java +++ b/core/src/test/java/org/testcontainers/utility/DockerImageNameCompatibilityTest.java @@ -97,6 +97,54 @@ void testAssertMethodAcceptsCompatibleLibraryPrefix() { subject.assertCompatibleWith(DockerImageName.parse("foo")); } + @Test + void testLibraryPrefixedImageIsNotCompatibleWithDifferentImage() { + DockerImageName subject = DockerImageName.parse("library/foo:1.2.3"); + + assertThat(subject.isCompatibleWith(DockerImageName.parse("bar"))).as("library/foo:1.2.3 != bar").isFalse(); + assertThat(subject.isCompatibleWith(DockerImageName.parse("repo/bar"))) + .as("library/foo:1.2.3 != repo/bar") + .isFalse(); + assertThat(subject.isCompatibleWith(DockerImageName.parse("library/bar"))) + .as("library/foo:1.2.3 != library/bar") + .isFalse(); + } + + @Test + void testLibraryPrefixIsInterchangeable() { + assertThat(DockerImageName.parse("library/foo").isCompatibleWith(DockerImageName.parse("foo"))) + .as("library/foo ~= foo") + .isTrue(); + assertThat(DockerImageName.parse("foo").isCompatibleWith(DockerImageName.parse("library/foo"))) + .as("foo ~= library/foo") + .isTrue(); + assertThat(DockerImageName.parse("library/foo:1.2.3").isCompatibleWith(DockerImageName.parse("foo"))) + .as("library/foo:1.2.3 ~= foo") + .isTrue(); + assertThat(DockerImageName.parse("foo:1.2.3").isCompatibleWith(DockerImageName.parse("library/foo"))) + .as("foo:1.2.3 ~= library/foo") + .isTrue(); + assertThat(DockerImageName.parse("library/foo:1.2.3").isCompatibleWith(DockerImageName.parse("foo:1.2.3"))) + .as("library/foo:1.2.3 ~= foo:1.2.3") + .isTrue(); + assertThat(DockerImageName.parse("library/foo:1.2.3").isCompatibleWith(DockerImageName.parse("foo:4.5.6"))) + .as("library/foo:1.2.3 != foo:4.5.6") + .isFalse(); + assertThat(DockerImageName.parse("some.registry/foo").isCompatibleWith(DockerImageName.parse("library/foo"))) + .as("some.registry/foo != library/foo") + .isFalse(); + } + + @Test + void testLibraryPrefixedImageWithClaimedCompatibility() { + DockerImageName subject = DockerImageName.parse("library/foo:1.2.3").asCompatibleSubstituteFor("bar"); + + assertThat(subject.isCompatibleWith(DockerImageName.parse("bar"))).as("library/foo:1.2.3(bar) ~= bar").isTrue(); + assertThat(subject.isCompatibleWith(DockerImageName.parse("fizz"))) + .as("library/foo:1.2.3(bar) != fizz") + .isFalse(); + } + @Test void testAssertMethodRejectsIncompatible() { DockerImageName subject = DockerImageName.parse("foo");