diff --git a/build.gradle.kts b/build.gradle.kts
index 1f1dd6c..0776aaf 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -46,6 +46,8 @@ dependencies {
annotationProcessor("org.openjdk.jmh:jmh-generator-annprocess:$jmhVersion")
implementation("com.fasterxml.jackson.core:jackson-databind")
+ implementation("org.ow2.asm:asm:9.4")
+
implementation("org.json:json:20230227")
implementation("com.worldturner.medeia:medeia-validator-jackson:1.1.0")
diff --git a/docs/_docs/1. implementations.md b/docs/_docs/1. implementations.md
index 8caa46b..d6c5edd 100644
--- a/docs/_docs/1. implementations.md
+++ b/docs/_docs/1. implementations.md
@@ -34,19 +34,21 @@ against the underlying [ GitHub Repo](http
"headings": [
"Implementation",
"Short Name",
+ "Supported Schema Versions",
"Language",
"Licence",
- "Jar size",
- "Supported Schema Versions",
+ "Minimum Java Version",
+ "Jar size",
"Project activity"
],
"data": implData.filter(row => row.shortName !== "Jackson").map(row => [
"" + row.longName + "",
- row.shortName,
+ row.shortName,
+ row.supported.join(', '),
row.language,
row.licence,
+ row.minJavaVersion,
Math.ceil(row.jarSize / 1024) + ' KB',
- row.supported.join(', '),
row.inactive ?? 'Active'
])
}
diff --git a/src/main/java/org/creekservice/kafka/test/perf/implementations/Implementation.java b/src/main/java/org/creekservice/kafka/test/perf/implementations/Implementation.java
index 34e717d..d993386 100644
--- a/src/main/java/org/creekservice/kafka/test/perf/implementations/Implementation.java
+++ b/src/main/java/org/creekservice/kafka/test/perf/implementations/Implementation.java
@@ -30,7 +30,7 @@
import org.creekservice.kafka.test.perf.model.TestModel;
import org.creekservice.kafka.test.perf.testsuite.AdditionalSchemas;
import org.creekservice.kafka.test.perf.testsuite.SchemaSpec;
-import org.creekservice.kafka.test.perf.util.JarFile;
+import org.creekservice.kafka.test.perf.util.ImplJarFile;
public interface Implementation {
@@ -100,6 +100,7 @@ class MetaData {
private final URL url;
private final Color color;
private final long jarSize;
+ private final String minJavaVersion;
private final String inactiveMsg;
/**
@@ -143,8 +144,9 @@ public MetaData(
}
this.color = requireNonNull(color, "color");
this.jarSize =
- JarFile.jarSizeForClass(
+ ImplJarFile.jarSizeForClass(
requireNonNull(typeFromImplementation, "typeFromImplementation"));
+ this.minJavaVersion = ImplJarFile.jarMinJavaVersion(typeFromImplementation);
this.inactiveMsg = requireNonNull(inactiveMsg, "inactiveMsg").trim();
if (longName.isBlank()) {
@@ -201,6 +203,11 @@ public long jarSize() {
return jarSize;
}
+ @JsonProperty("minJavaVersion")
+ public String minJavaVersion() {
+ return minJavaVersion;
+ }
+
@JsonProperty("inactive")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public String inactiveMsg() {
diff --git a/src/main/java/org/creekservice/kafka/test/perf/util/ImplJarFile.java b/src/main/java/org/creekservice/kafka/test/perf/util/ImplJarFile.java
new file mode 100644
index 0000000..4b8d1fc
--- /dev/null
+++ b/src/main/java/org/creekservice/kafka/test/perf/util/ImplJarFile.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2023 Creek Contributors (https://github.com/creek-service)
+ *
+ * Licensed 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.creekservice.kafka.test.perf.util;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.VisibleForTesting;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.CodeSource;
+import java.util.Enumeration;
+import java.util.function.Function;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import org.objectweb.asm.ClassReader;
+
+/** Utility for determining the size of a jar file a class is loaded from. */
+public final class ImplJarFile {
+
+ /**
+ * Determine the size of the jar the supplied type is loaded from.
+ *
+ * @param type a class loaded from the jar.
+ * @return the size of the jar, in bytes.
+ * @throws IllegalArgumentException if the supplied {@code type} isn't loaded from an accessible
+ * jar.
+ */
+ public static long jarSizeForClass(final Class> type) {
+ return new JarSize(JarTaskBase::sourceCode).size(type);
+ }
+
+ /**
+ * Determine the minimum supported Java version for the jar the supplied type is loaded from.
+ *
+ * @param type a class loaded from the jar.
+ * @return the minimum supported Java version
+ * @throws IllegalArgumentException if the supplied {@code type} isn't loaded from an accessible
+ * jar.
+ */
+ public static String jarMinJavaVersion(final Class> type) {
+ return new JarMinJavaVersion(JarTaskBase::sourceCode).minJavaVersion(type);
+ }
+
+ private ImplJarFile() {}
+
+ @VisibleForTesting
+ static class JarTaskBase {
+
+ final Function, CodeSource> sourceAccessor;
+
+ JarTaskBase(final Function, CodeSource> locator) {
+ this.sourceAccessor = requireNonNull(locator, "locator");
+ }
+
+ @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "Location supplied by JVM")
+ Path pathToJar(final Class> type) {
+ final URL location = location(type);
+
+ try {
+ return Paths.get(location.toURI());
+ } catch (final Exception e) {
+ throw new IllegalArgumentException(
+ "Type not loaded from accessible jar file. location: " + location, e);
+ }
+ }
+
+ private URL location(final Class> type) {
+ final CodeSource codeSource = sourceAccessor.apply(type);
+ if (codeSource == null) {
+ throw new IllegalArgumentException("Type not loaded from a jar file: " + type);
+ }
+
+ return codeSource.getLocation();
+ }
+
+ private static CodeSource sourceCode(final Class> type) {
+ return type.getProtectionDomain().getCodeSource();
+ }
+ }
+
+ @VisibleForTesting
+ static final class JarSize extends JarTaskBase {
+
+ JarSize(final Function, CodeSource> locator) {
+ super(locator);
+ }
+
+ long size(final Class> type) {
+ final Path path = pathToJar(type);
+
+ try {
+ return Files.size(path);
+ } catch (final Exception e) {
+ throw new IllegalArgumentException(
+ "Failed to read file size. location: " + path, e);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ static final class JarMinJavaVersion extends JarTaskBase {
+
+ JarMinJavaVersion(final Function, CodeSource> locator) {
+ super(locator);
+ }
+
+ String minJavaVersion(final Class> type) {
+ final Path path = pathToJar(type);
+
+ try (JarFile jarFile = new JarFile(path.toFile())) {
+ final Enumeration entries = jarFile.entries();
+
+ while (entries.hasMoreElements()) {
+ final JarEntry entry = entries.nextElement();
+
+ if (entry.getName().endsWith(".class")) {
+ try (InputStream classInputStream = jarFile.getInputStream(entry)) {
+ return minJavaVersion(classInputStream);
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException(
+ "Failed to extract the min Java version the jar supports. Path: " + path,
+ e);
+ }
+
+ return "Unknown";
+ }
+
+ public static String minJavaVersion(final InputStream classFile) throws IOException {
+ final ClassReader classReader = new ClassReader(classFile);
+ final VersionClassVisitor versionClassVisitor = new VersionClassVisitor();
+ classReader.accept(versionClassVisitor, 0);
+
+ final int majorVersion = versionClassVisitor.majorVersion;
+ if (majorVersion < 0) {
+ throw new IllegalArgumentException("Failed to determine Java version");
+ }
+
+ final String javaVersion =
+ majorVersion < 49
+ ? "1." + (majorVersion - 44)
+ : String.valueOf(majorVersion - 44);
+
+ return "Java " + javaVersion;
+ }
+
+ private static class VersionClassVisitor extends org.objectweb.asm.ClassVisitor {
+
+ private int majorVersion = -1;
+
+ VersionClassVisitor() {
+ super(org.objectweb.asm.Opcodes.ASM9);
+ }
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ if (version > majorVersion) {
+ majorVersion = version;
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/creekservice/kafka/test/perf/util/JarFile.java b/src/main/java/org/creekservice/kafka/test/perf/util/JarFile.java
deleted file mode 100644
index 529c56a..0000000
--- a/src/main/java/org/creekservice/kafka/test/perf/util/JarFile.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2023 Creek Contributors (https://github.com/creek-service)
- *
- * Licensed 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.creekservice.kafka.test.perf.util;
-
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.annotations.VisibleForTesting;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.CodeSource;
-import java.util.function.Function;
-
-/** Utility for determining the size of a jar file a class is loaded from. */
-public final class JarFile {
-
- private final Function, CodeSource> sourceAccessor;
-
- /**
- * Determine the size of the jar the supplied type is loaded from.
- *
- * @param type a class loaded from the jar.
- * @return the size of the jar, in bytes.
- * @throws IllegalArgumentException if the supplied {@code type} isn't loaded from an accessible
- * jar.
- */
- public static long jarSizeForClass(final Class> type) {
- return new JarFile(JarFile::sourceCode).size(type);
- }
-
- @VisibleForTesting
- JarFile(final Function, CodeSource> locator) {
- this.sourceAccessor = requireNonNull(locator, "locator");
- }
-
- long size(final Class> type) {
- final Path path = pathToJar(type);
- return size(path);
- }
-
- private Path pathToJar(final Class> type) {
- return asPath(location(type));
- }
-
- private URL location(final Class> type) {
- final CodeSource codeSource = sourceAccessor.apply(type);
- if (codeSource == null) {
- throw new IllegalArgumentException("Type not loaded from a jar file: " + type);
- }
-
- return codeSource.getLocation();
- }
-
- private static CodeSource sourceCode(final Class> type) {
- return type.getProtectionDomain().getCodeSource();
- }
-
- @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "Location supplied by JVM")
- private static Path asPath(final URL location) {
- try {
- return Paths.get(location.toURI());
- } catch (final Exception e) {
- throw new IllegalArgumentException(
- "Type not loaded from accessible jar file. location: " + location, e);
- }
- }
-
- private static long size(final Path path) {
- try {
- return Files.size(path);
- } catch (final Exception e) {
- throw new IllegalArgumentException("Failed to read file size. location: " + path, e);
- }
- }
-}
diff --git a/src/test/java/org/creekservice/kafka/test/perf/util/ImplJarFileTest.java b/src/test/java/org/creekservice/kafka/test/perf/util/ImplJarFileTest.java
new file mode 100644
index 0000000..a3c7219
--- /dev/null
+++ b/src/test/java/org/creekservice/kafka/test/perf/util/ImplJarFileTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2023 Creek Contributors (https://github.com/creek-service)
+ *
+ * Licensed 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.creekservice.kafka.test.perf.util;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mock.Strictness.LENIENT;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.file.Path;
+import java.security.CodeSource;
+import java.util.function.Function;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+class ImplJarFileTest {
+
+ @Mock(strictness = LENIENT)
+ private Function, CodeSource> sourceAccessor;
+
+ @Mock(strictness = LENIENT)
+ private CodeSource codeSource;
+
+ @BeforeEach
+ void setUp() {
+ when(sourceAccessor.apply(any())).thenReturn(codeSource);
+ when(codeSource.getLocation())
+ .thenReturn(Test.class.getProtectionDomain().getCodeSource().getLocation());
+ }
+
+ @Nested
+ class JarBaseTaskTest {
+
+ private ExampleTask task;
+
+ @BeforeEach
+ void setUp() {
+ task = new ExampleTask(sourceAccessor);
+ }
+
+ @Test
+ void shouldPassSuppliedTypeToLocator() {
+ // When:
+ task.getPath(Test.class);
+
+ // Then:
+ verify(sourceAccessor).apply(Test.class);
+ }
+
+ @Test
+ void shouldThrowIfSourceCodeNotAvailable() {
+ // Given:
+ when(sourceAccessor.apply(any())).thenReturn(null);
+
+ // When:
+ final Exception e =
+ assertThrows(IllegalArgumentException.class, () -> task.getPath(Test.class));
+
+ // Then:
+ assertThat(e.getMessage(), is("Type not loaded from a jar file: " + Test.class));
+ }
+
+ @Test
+ void shouldThrowIfNotLoadedFromFile() throws Exception {
+ // Given:
+ when(codeSource.getLocation()).thenReturn(new URL("ftp:/localhost/something"));
+
+ // When:
+ final Exception e =
+ assertThrows(IllegalArgumentException.class, () -> task.getPath(Test.class));
+
+ // Then:
+ assertThat(
+ e.getMessage(),
+ is(
+ "Type not loaded from accessible jar file. location:"
+ + " ftp:/localhost/something"));
+ }
+
+ @Test
+ void shouldGetPathOfJar() {
+ // When:
+ final Path path = task.getPath(Test.class);
+
+ // Then:
+ assertThat(path.toString(), containsString(".gradle" + File.separator + "caches"));
+ }
+
+ private final class ExampleTask extends ImplJarFile.JarTaskBase {
+
+ ExampleTask(final Function, CodeSource> locator) {
+ super(locator);
+ }
+
+ Path getPath(final Class testClass) {
+ return pathToJar(testClass);
+ }
+ }
+ }
+
+ @Nested
+ class JarSizeTest {
+ @Test
+ void shouldReturnJarSize() {
+ assertThat(ImplJarFile.jarSizeForClass(Test.class), is(greaterThan(1000L)));
+ }
+ }
+
+ @Nested
+ class JarMinJavaVersionTest {
+ @Test
+ void shouldReturnJarMinJavaVersion() {
+ assertThat(ImplJarFile.jarMinJavaVersion(Test.class), is("Java 9"));
+ }
+ }
+}
diff --git a/src/test/java/org/creekservice/kafka/test/perf/util/ImplsJsonFormatterTest.java b/src/test/java/org/creekservice/kafka/test/perf/util/ImplsJsonFormatterTest.java
index b5c78d5..c29e0d7 100644
--- a/src/test/java/org/creekservice/kafka/test/perf/util/ImplsJsonFormatterTest.java
+++ b/src/test/java/org/creekservice/kafka/test/perf/util/ImplsJsonFormatterTest.java
@@ -17,7 +17,10 @@
package org.creekservice.kafka.test.perf.util;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.matchesPattern;
+import static org.hamcrest.Matchers.not;
+import static org.mockito.Mock.Strictness.LENIENT;
import static org.mockito.Mockito.when;
import java.awt.Color;
@@ -58,9 +61,11 @@ class ImplsJsonFormatterTest {
Test.class,
"No release since dot");
- @Mock private Implementation implA;
+ @Mock(strictness = LENIENT)
+ private Implementation implA;
- @Mock private Implementation implB;
+ @Mock(strictness = LENIENT)
+ private Implementation implB;
@BeforeEach
void setUp() {
@@ -69,16 +74,27 @@ void setUp() {
}
@Test
- void shouldFormatAsJson() {
+ void shouldFormatAll() {
// Given:
// When:
final String json = ImplsJsonFormatter.implDetailsAsJson(List.of(implA, implB));
+ // Then:
+ assertThat(json, containsString("[{\"longName\":\"Implementation A\","));
+
+ assertThat(json, containsString("{\"longName\":\"Implementation B\","));
+ }
+
+ @Test
+ void shouldFormatAsJson() {
+ // When:
+ final String json = ImplsJsonFormatter.implDetailsAsJson(List.of(implA));
+
// Then:
assertThat(
json,
- is(
+ containsString(
"[{\"longName\":\"Implementation A\","
+ "\"shortName\":\"ImplA\","
+ "\"language\":\"Java\","
@@ -86,16 +102,42 @@ void shouldFormatAsJson() {
+ "\"supported\":[\"DRAFT_04\","
+ "\"DRAFT_2019_09\"],"
+ "\"url\":\"http://a\","
- + "\"color\":\"rgb(0,0,0)\","
- + "\"jarSize\":210954},"
- + "{\"longName\":\"Implementation B\","
- + "\"shortName\":\"ImplB\","
- + "\"language\":\"Java\","
- + "\"licence\":\"Apache Licence 2.0\","
- + "\"supported\":[\"DRAFT_07\"],"
- + "\"url\":\"http://b\","
- + "\"color\":\"rgb(0,0,255)\","
- + "\"jarSize\":210954,"
- + "\"inactive\":\"No release since dot\"}]"));
+ + "\"color\":\"rgb(0,0,0)\","));
+ }
+
+ @Test
+ void shouldNotIncludeInactiveForActiveProjects() {
+ // When:
+ final String json = ImplsJsonFormatter.implDetailsAsJson(List.of(implA));
+
+ // Then:
+ assertThat(json, not(containsString("\"inactive\":")));
+ }
+
+ @Test
+ void shouldIncludeInactiveMsgForInactiveProjects() {
+ // When:
+ final String json = ImplsJsonFormatter.implDetailsAsJson(List.of(implB));
+
+ // Then:
+ assertThat(json, containsString("\"inactive\":\"No release since dot\""));
+ }
+
+ @Test
+ void shouldIncludeJarSize() {
+ // When:
+ final String json = ImplsJsonFormatter.implDetailsAsJson(List.of(implA));
+
+ // Then:
+ assertThat(json, matchesPattern(".*\"jarSize\":\\d+[,}].*"));
+ }
+
+ @Test
+ void shouldIncludeMinJavaVersion() {
+ // When:
+ final String json = ImplsJsonFormatter.implDetailsAsJson(List.of(implA));
+
+ // Then:
+ assertThat(json, matchesPattern(".*\"minJavaVersion\":\"Java \\d+\".*"));
}
}
diff --git a/src/test/java/org/creekservice/kafka/test/perf/util/JarFileTest.java b/src/test/java/org/creekservice/kafka/test/perf/util/JarFileTest.java
deleted file mode 100644
index 4d81ca9..0000000
--- a/src/test/java/org/creekservice/kafka/test/perf/util/JarFileTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2023 Creek Contributors (https://github.com/creek-service)
- *
- * Licensed 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.creekservice.kafka.test.perf.util;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.is;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.security.CodeSource;
-import java.util.function.Function;
-import org.creekservice.api.test.util.TestPaths;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-@ExtendWith(MockitoExtension.class)
-class JarFileTest {
-
- private static final URL THIS_FILE;
-
- static {
- try {
- THIS_FILE =
- TestPaths.moduleRoot("json-schema-validation-comparison")
- .resolve(
- "src/test/java/org/creekservice/kafka/test/perf/util/JarFileTest.java")
- .toUri()
- .toURL();
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Mock(strictness = Mock.Strictness.LENIENT)
- private Function, CodeSource> sourceAccessor;
-
- @Mock private CodeSource codeSource;
- private JarFile jarFile;
-
- @BeforeEach
- void setUp() {
- jarFile = new JarFile(sourceAccessor);
-
- when(sourceAccessor.apply(any())).thenReturn(codeSource);
- }
-
- @Test
- void shouldPassSuppliedTypeToLocator() throws Exception {
- // Given:
- when(codeSource.getLocation()).thenReturn(THIS_FILE.toURI().toURL());
-
- // When:
- jarFile.size(Test.class);
-
- // Then:
- verify(sourceAccessor).apply(Test.class);
- }
-
- @Test
- void shouldThrowIfSourceCodeNotAvailable() {
- // Given:
- when(sourceAccessor.apply(any())).thenReturn(null);
-
- // When:
- final Exception e =
- assertThrows(IllegalArgumentException.class, () -> jarFile.size(Test.class));
-
- // Then:
- assertThat(e.getMessage(), is("Type not loaded from a jar file: " + Test.class));
- }
-
- @Test
- void shouldThrowIfNotLoadedFromFile() throws Exception {
- // Given:
- when(codeSource.getLocation()).thenReturn(new URL("ftp:/localhost/something"));
-
- // When:
- final Exception e =
- assertThrows(IllegalArgumentException.class, () -> jarFile.size(Test.class));
-
- // Then:
- assertThat(
- e.getMessage(),
- is("Type not loaded from accessible jar file. location: ftp:/localhost/something"));
- }
-
- @Test
- void shouldReturnJarSize() {
- assertThat(JarFile.jarSizeForClass(Test.class), is(greaterThan(1000L)));
- }
-}