This is an automated email from the ASF dual-hosted git repository.
rmaucher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat-jakartaee-migration.git
The following commit(s) were added to refs/heads/main by this push:
new 024cc0e Code review for tests
024cc0e is described below
commit 024cc0e2da33d6fc00f766074264a5ac75cbbb46
Author: remm <remm@meteor>
AuthorDate: Thu Sep 3 21:10:22 2026 +0200
Code review for tests
Minor fixes and cleanups, tightening of the tests, no real "functional"
changes.
Co authored with OpenCode.
---
.../tomcat/jakartaee/ClassConverterTest.java | 2 +
.../tomcat/jakartaee/ManifestConverterTest.java | 19 +-
.../tomcat/jakartaee/MigrationCacheTest.java | 48 ++-
.../apache/tomcat/jakartaee/MigrationTaskTest.java | 49 ++-
.../org/apache/tomcat/jakartaee/MigrationTest.java | 417 ++++++++++++---------
.../tomcat/jakartaee/NoExitSecurityManager.java | 10 +
.../apache/tomcat/jakartaee/StringManagerTest.java | 11 +-
.../apache/tomcat/jakartaee/TesterConstants.java | 28 ++
.../apache/tomcat/jakartaee/TextConverterTest.java | 62 ++-
src/test/resources/testbuild.xml | 2 +-
10 files changed, 416 insertions(+), 232 deletions(-)
diff --git a/src/test/java/org/apache/tomcat/jakartaee/ClassConverterTest.java
b/src/test/java/org/apache/tomcat/jakartaee/ClassConverterTest.java
index 0aa1d55..d57a01b 100644
--- a/src/test/java/org/apache/tomcat/jakartaee/ClassConverterTest.java
+++ b/src/test/java/org/apache/tomcat/jakartaee/ClassConverterTest.java
@@ -24,6 +24,7 @@ import org.apache.bcel.classfile.JavaClass;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -53,6 +54,7 @@ public class ClassConverterTest {
// Get the original bytes
try (InputStream is =
this.getClass().getResourceAsStream("/org/apache/tomcat/jakartaee/TesterConstants.class");
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ assertNotNull(is);
byte[] buf = new byte[1024];
int len;
while ((len = is.read(buf)) > 0) {
diff --git
a/src/test/java/org/apache/tomcat/jakartaee/ManifestConverterTest.java
b/src/test/java/org/apache/tomcat/jakartaee/ManifestConverterTest.java
index 1ea90e7..79a9d82 100644
--- a/src/test/java/org/apache/tomcat/jakartaee/ManifestConverterTest.java
+++ b/src/test/java/org/apache/tomcat/jakartaee/ManifestConverterTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
@@ -45,8 +46,10 @@ public class ManifestConverterTest {
public void testConvert() throws IOException {
ManifestConverter converter = new ManifestConverter();
ByteArrayOutputStream os = new ByteArrayOutputStream();
- boolean converted = converter.convert("/MANIFEST.test.MF",
getClass().getResourceAsStream("/MANIFEST.test.MF"),
- os, EESpecProfiles.TOMCAT);
+ boolean converted;
+ try (InputStream src =
getClass().getResourceAsStream("/MANIFEST.test.MF")) {
+ converted = converter.convert("/MANIFEST.test.MF", src, os,
EESpecProfiles.TOMCAT);
+ }
assertTrue(converted);
String result = os.toString("UTF-8");
@@ -128,12 +131,14 @@ public class ManifestConverterTest {
manifest.write(manifestBytes);
ByteArrayOutputStream dest = new ByteArrayOutputStream();
- converter.convert("META-INF/MANIFEST.MF",
+ boolean converted = converter.convert("META-INF/MANIFEST.MF",
new ByteArrayInputStream(manifestBytes.toByteArray()), dest,
EESpecProfiles.TOMCAT);
+ // The suffix is added without counting as a conversion
+ assertFalse("Version suffix should not count as a conversion",
converted);
String result = dest.toString("UTF-8");
assertTrue("Implementation-Version should have migration suffix",
- result.contains("-migrated-"));
+ result.contains("Implementation-Version: 1.0.0-" +
Info.getVersion()));
}
@Test
@@ -203,9 +208,10 @@ public class ManifestConverterTest {
}
@Test
- public void testConvertPreservesNonStringValues() throws IOException {
+ public void testConvertNoConversionNeededWithTomcatProfile() throws
IOException {
ManifestConverter converter = new ManifestConverter();
+ // Create a manifest with no javax packages
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION,
"1.0");
@@ -216,7 +222,6 @@ public class ManifestConverterTest {
boolean converted = converter.convert("META-INF/MANIFEST.MF",
new ByteArrayInputStream(manifestBytes.toByteArray()), dest,
EESpecProfiles.TOMCAT);
- // Should not throw and should handle gracefully
- assertTrue("Conversion should complete", !converted);
+ assertFalse("Should not convert manifest with no javax packages",
converted);
}
}
diff --git a/src/test/java/org/apache/tomcat/jakartaee/MigrationCacheTest.java
b/src/test/java/org/apache/tomcat/jakartaee/MigrationCacheTest.java
index 7ac1864..3e1f772 100644
--- a/src/test/java/org/apache/tomcat/jakartaee/MigrationCacheTest.java
+++ b/src/test/java/org/apache/tomcat/jakartaee/MigrationCacheTest.java
@@ -20,6 +20,7 @@ package org.apache.tomcat.jakartaee;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
+import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
@@ -181,7 +182,7 @@ public class MigrationCacheTest {
String stats = cache.getStats();
assertNotNull("Stats should not be null", stats);
- assertTrue("Stats should contain entry count", stats.contains("0"));
+ assertTrue("Stats should contain entry count", stats.contains("0
entries"));
}
@Test
@@ -249,7 +250,7 @@ public class MigrationCacheTest {
public void testCacheNullDirectory() throws Exception {
try {
new MigrationCache(null, 30);
- fail("Should throw IllegalStateException for null directory");
+ fail("Should throw IllegalArgumentException for null directory");
} catch (IllegalArgumentException e) {
assertTrue("Error message should mention null",
e.getMessage().contains("null") || e.getMessage().contains("Null"));
}
@@ -263,9 +264,8 @@ public class MigrationCacheTest {
try {
new MigrationCache(regularFile, 30);
fail("Should throw IOException when path is not a directory");
- } catch (Exception e) {
- assertTrue("Should be IOException or similar",
- e instanceof Exception);
+ } catch (IOException e) {
+ // Expected
}
}
@@ -359,7 +359,7 @@ public class MigrationCacheTest {
String stats = cache.getStats();
assertNotNull("Stats should not be null", stats);
- assertTrue("Stats should contain entry count", stats.contains("3"));
+ assertTrue("Stats should contain entry count", stats.contains("3
entries"));
}
@Test
@@ -400,12 +400,12 @@ public class MigrationCacheTest {
@Test
public void testCacheMetadataWithInvalidDate() throws Exception {
- // Create a metadata file with invalid date format
+ // Create a metadata file with a valid hash but an invalid date format
File metadataFile = new File(tempCacheDir, "cache-metadata.txt");
try (FileWriter writer = new FileWriter(metadataFile)) {
writer.write("# Migration cache metadata -
hash|last_access_date\n");
- writer.write("abc123|not-a-date\n");
- writer.write("def456|2024-01-01\n");
+
writer.write("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef|not-a-date\n");
+
writer.write("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210|2024-01-01\n");
}
// Should handle invalid dates gracefully
@@ -499,7 +499,7 @@ public class MigrationCacheTest {
MigrationCache cache = new MigrationCache(tempCacheDir, 30);
String stats = cache.getStats();
assertNotNull("Stats should not be null", stats);
- assertTrue("Stats should contain entry count", stats.contains("1"));
+ assertTrue("Stats should contain entry count", stats.contains("1
entries"));
}
@Test
@@ -531,13 +531,31 @@ public class MigrationCacheTest {
byte[] sourceData = "test source
content".getBytes(StandardCharsets.UTF_8);
CacheEntry entry = cache.getCacheEntry(sourceData,
EESpecProfiles.TOMCAT);
- // Begin store creates temp file
+ // Begin store creates the temp file
OutputStream os = entry.beginStore();
+ os.write("partial data".getBytes(StandardCharsets.UTF_8));
os.close();
- // Delete temp file manually to simulate failure
- // The temp file path is internal, so we can't easily delete it
- // Instead, test that commit works normally after writing
- entry.commitStore();
+ // Locate and delete the temp file to simulate a failure between
+ // beginStore() and commitStore()
+ File tempFile = null;
+ File[] files = tempCacheDir.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.isFile() && file.getName().startsWith("temp-") &&
file.getName().endsWith(".tmp")) {
+ tempFile = file;
+ }
+ }
+ }
+ assertNotNull("Temp file should have been created", tempFile);
+ assertTrue("Temp file should be deleted", tempFile.delete());
+
+ try {
+ entry.commitStore();
+ fail("Should throw IOException when the temp file is missing");
+ } catch (IOException e) {
+ assertTrue("Unexpected error message: " + e.getMessage(),
+ e.getMessage() != null && e.getMessage().contains("does
not exist"));
+ }
}
}
diff --git a/src/test/java/org/apache/tomcat/jakartaee/MigrationTaskTest.java
b/src/test/java/org/apache/tomcat/jakartaee/MigrationTaskTest.java
index 78d9bc9..8762002 100644
--- a/src/test/java/org/apache/tomcat/jakartaee/MigrationTaskTest.java
+++ b/src/test/java/org/apache/tomcat/jakartaee/MigrationTaskTest.java
@@ -21,8 +21,11 @@ import java.io.File;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.Project;
@@ -66,9 +69,15 @@ public class MigrationTaskTest {
project.addBuildListener(logger);
}
- @Test(expected = BuildException.class)
+ @Test
public void testInvalidProfile() {
- project.executeTarget("invalid-profile");
+ try {
+ project.executeTarget("invalid-profile");
+ fail("Should throw BuildException when profile is invalid");
+ } catch (BuildException e) {
+ assertTrue("Error should mention the invalid profile",
+ e.getMessage().contains("jserv"));
+ }
}
@Test
@@ -94,8 +103,7 @@ public class MigrationTaskTest {
task.execute();
fail("Should throw BuildException when source is null");
} catch (BuildException e) {
- assertTrue("Error should mention source",
- e.getMessage().contains("source") ||
e.getMessage().toLowerCase().contains("source"));
+ assertTrue("Error should mention source",
e.getMessage().contains("source"));
}
}
@@ -103,15 +111,13 @@ public class MigrationTaskTest {
public void testMigrationTaskNoDest() {
MigrationTask task = new MigrationTask();
task.setProject(project);
- task.setLocation(null);
task.setSrc(new File("target/test-classes/HelloServlet.java"));
try {
task.execute();
fail("Should throw BuildException when dest is null");
} catch (BuildException e) {
- assertTrue("Error should mention destination",
- e.getMessage().contains("dest") ||
e.getMessage().toLowerCase().contains("dest"));
+ assertTrue("Error should mention destination",
e.getMessage().contains("dest"));
}
}
@@ -119,7 +125,6 @@ public class MigrationTaskTest {
public void testMigrationTaskSourceNotExists() {
MigrationTask task = new MigrationTask();
task.setProject(project);
- task.setLocation(null);
task.setSrc(new File("target/test-classes/nonexistent.java"));
task.setDest(new File("target/test-classes/output.java"));
@@ -127,7 +132,7 @@ public class MigrationTaskTest {
task.execute();
fail("Should throw BuildException when source does not exist");
} catch (BuildException e) {
- // Expected
+ assertTrue("Error should mention source",
e.getMessage().contains("source"));
}
}
@@ -135,23 +140,27 @@ public class MigrationTaskTest {
public void testMigrationTaskWithZipInMemory() throws Exception {
MigrationTask task = new MigrationTask();
task.setProject(project);
- task.setLocation(null);
- task.setSrc(new File("target/test-classes/HelloServlet.java"));
- File destFile = tempFolder.newFile("ant-zip-memory.java");
+ task.setSrc(new File("target/test-classes/hellocgi.jar"));
+ File destFile = tempFolder.newFile("ant-zip-memory.jar");
task.setDest(destFile);
task.setZipInMemory(true);
task.execute();
assertTrue("Migrated file should exist", destFile.exists());
- String migratedSource = FileUtils.readFileToString(destFile,
StandardCharsets.UTF_8);
- assertTrue("Imports should be migrated",
migratedSource.contains("import jakarta.servlet"));
+ try (JarFile jar = new JarFile(destFile)) {
+ JarEntry entry =
jar.getJarEntry("org/apache/tomcat/jakartaee/HelloCGI.class");
+ assertNotNull("HelloCGI class not found in migrated JAR", entry);
+ byte[] classBytes = IOUtils.toByteArray(jar.getInputStream(entry));
+ assertTrue("Class should be migrated",
+ new String(classBytes, StandardCharsets.ISO_8859_1)
+
.contains("jakarta/servlet/CommonGatewayInterface"));
+ }
}
@Test
public void testMigrationTaskWithExcludes() throws Exception {
MigrationTask task = new MigrationTask();
task.setProject(project);
- task.setLocation(null);
task.setSrc(new File("target/test-classes/HelloServlet.java"));
File destFile = tempFolder.newFile("ant-excludes.java");
task.setDest(destFile);
@@ -159,27 +168,32 @@ public class MigrationTaskTest {
task.execute();
assertTrue("Migrated file should exist", destFile.exists());
+ String content = FileUtils.readFileToString(destFile,
StandardCharsets.UTF_8);
+ assertTrue("Excluded file should not be converted",
content.contains("import javax.servlet"));
}
@Test
public void testMigrationTaskWithMatchExcludesAgainstPathName() throws
Exception {
MigrationTask task = new MigrationTask();
task.setProject(project);
- task.setLocation(null);
task.setSrc(new File("target/test-classes/HelloServlet.java"));
File destFile = tempFolder.newFile("ant-path-excludes.java");
task.setDest(destFile);
+ // Matches the full path but not the bare file name, so the exclude
+ // only takes effect when excludes are matched against the path name
+ task.setExcludes("**" + File.separator + "HelloServlet.java");
task.setMatchExcludesAgainstPathName(true);
task.execute();
assertTrue("Migrated file should exist", destFile.exists());
+ String content = FileUtils.readFileToString(destFile,
StandardCharsets.UTF_8);
+ assertTrue("Excluded file should not be converted",
content.contains("import javax.servlet"));
}
@Test
public void testMigrationTaskWithEeProfile() throws Exception {
MigrationTask task = new MigrationTask();
task.setProject(project);
- task.setLocation(null);
task.setSrc(new File("target/test-classes/HelloServlet.java"));
File destFile = tempFolder.newFile("ant-ee-profile.java");
task.setDest(destFile);
@@ -206,7 +220,6 @@ public class MigrationTaskTest {
public void testMigrationTaskDefaultProfile() throws Exception {
MigrationTask task = new MigrationTask();
task.setProject(project);
- task.setLocation(null);
task.setSrc(new File("target/test-classes/HelloServlet.java"));
File destFile = tempFolder.newFile("ant-default-profile.java");
task.setDest(destFile);
diff --git a/src/test/java/org/apache/tomcat/jakartaee/MigrationTest.java
b/src/test/java/org/apache/tomcat/jakartaee/MigrationTest.java
index ef0bac0..17e7af0 100644
--- a/src/test/java/org/apache/tomcat/jakartaee/MigrationTest.java
+++ b/src/test/java/org/apache/tomcat/jakartaee/MigrationTest.java
@@ -25,6 +25,7 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
import java.util.zip.CRC32;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -69,7 +70,7 @@ public class MigrationTest {
@Test
public void testMigrateSingleSourceFile() throws Exception {
- File migratedFile = new
File("target/test-classes/HelloServlet.migrated.java");
+ File migratedFile = tempFolder.newFile("HelloServlet.migrated.java");
MigrationCLI.main(new String[]
{"target/test-classes/HelloServlet.java", migratedFile.getAbsolutePath()});
assertTrue("Migrated file not found", migratedFile.exists());
@@ -81,7 +82,7 @@ public class MigrationTest {
@Test
public void testMigrateSingleSourceFileWithProfile() throws Exception {
- File migratedFile = new
File("target/test-classes/HelloServlet.migrated.java");
+ File migratedFile = tempFolder.newFile("HelloServlet.migrated.java");
MigrationCLI.main(new String[] {"-logLevel=FINE", "-profile=EE",
"target/test-classes/HelloServlet.java", migratedFile.getAbsolutePath()});
assertTrue("Migrated file not found", migratedFile.exists());
@@ -94,7 +95,7 @@ public class MigrationTest {
@Test
public void testMigrateSingleSourceFileInPlace() throws Exception {
File sourceFile = new File("target/test-classes/HelloServlet.java");
- File migratedFile = new
File("target/test-classes/HelloServlet.inplace.java");
+ File migratedFile = tempFolder.newFile("HelloServlet.inplace.java");
FileUtils.copyFile(sourceFile, migratedFile);
MigrationCLI.main(new String[] {"-profile=EE",
migratedFile.getAbsolutePath(), migratedFile.getAbsolutePath()});
@@ -123,7 +124,7 @@ public class MigrationTest {
@Test
public void testMigrateDirectory() throws Exception {
File sourceDirectory = new File("src/test/resources");
- File destinationDirectory = new File("target/test-classes/migration");
+ File destinationDirectory = new File(tempFolder.getRoot(),
"migration");
Migration migration = new Migration();
migration.setSource(sourceDirectory);
@@ -132,14 +133,14 @@ public class MigrationTest {
assertTrue("Destination directory not found",
destinationDirectory.exists());
- File migratedFile = new
File("target/test-classes/migration/HelloServlet.java");
+ File migratedFile = new File(destinationDirectory,
"HelloServlet.java");
assertTrue("Migrated file not found", migratedFile.exists());
String migratedSource = FileUtils.readFileToString(migratedFile,
StandardCharsets.UTF_8);
assertFalse("Imports not migrated", migratedSource.contains("import
javax.servlet"));
assertTrue("Migrated imports not found",
migratedSource.contains("import jakarta.servlet"));
- File migratedSpiFile = new
File("target/test-classes/migration/javax.enterprise.inject.spi.Extension");
+ File migratedSpiFile = new File(destinationDirectory,
"javax.enterprise.inject.spi.Extension");
assertTrue("SPI file has not been migrated by renaming",
migratedSpiFile.exists());
String migratedSpiSource = FileUtils.readFileToString(migratedSpiFile,
StandardCharsets.UTF_8);
@@ -149,7 +150,7 @@ public class MigrationTest {
@Test
public void testMigrateDirectoryWithEeProfile() throws Exception {
File sourceDirectory = new File("src/test/resources");
- File destinationDirectory = new
File("target/test-classes/migration-ee");
+ File destinationDirectory = new File(tempFolder.getRoot(),
"migration-ee");
Migration migration = new Migration();
migration.setEESpecProfile(EESpecProfiles.EE);
@@ -176,19 +177,24 @@ public class MigrationTest {
@Test
public void testMigrateClassFile() throws Exception {
File classFile = new
File("target/test-classes/org/apache/tomcat/jakartaee/HelloCGI.class");
- File classFileOriginal = new
File("target/test-classes/org/apache/tomcat/jakartaee/HelloCGI-original.class");
+ File classFileOriginal = new File(tempFolder.getRoot(),
"HelloCGI-original.class");
FileUtils.copyFile(classFile, classFileOriginal);
- Migration migration = new Migration();
- migration.setSource(classFile);
- migration.setDestination(classFile);
- migration.execute();
-
- Class<?> cls = Class.forName("org.apache.tomcat.jakartaee.HelloCGI");
- assertEquals("jakarta.servlet.CommonGatewayInterface",
cls.getSuperclass().getName());
+ try {
+ Migration migration = new Migration();
+ migration.setSource(classFile);
+ migration.setDestination(classFile);
+ migration.execute();
- Assert.assertTrue("Failed to delete migrated class file",
classFile.delete());
- FileUtils.copyFile(classFileOriginal, classFile);
+ Class<?> cls =
Class.forName("org.apache.tomcat.jakartaee.HelloCGI");
+ assertEquals("jakarta.servlet.CommonGatewayInterface",
cls.getSuperclass().getName());
+ } finally {
+ // Always restore the original class file, otherwise a failure in
+ // this test would leave the (shared) class file migrated and
+ // break other tests on the next non-clean build.
+ Assert.assertTrue("Failed to delete migrated class file",
classFile.delete());
+ FileUtils.copyFile(classFileOriginal, classFile);
+ }
}
@Test
@@ -198,7 +204,7 @@ public class MigrationTest {
private void testMigrateJarFileInternal(boolean zipInMemory) throws
Exception {
File jarFile = new File("target/test-classes/hellocgi.jar");
- File jarFileTarget = new
File("target/test-classes/hellocgi-target.jar");
+ File jarFileTarget = tempFolder.newFile("hellocgi-target.jar");
Migration migration = new Migration();
migration.setSource(jarFile);
@@ -263,8 +269,8 @@ public class MigrationTest {
private void testMigrateSignedJarFile(String algorithm, EESpecProfile
profile) throws Exception {
File jarFileSrc = new File("target/test-classes/hellocgi-signed-" +
algorithm + ".jar");
- File jarFileTmp = new File("target/test-classes/hellocgi-signed-" +
algorithm + "-tmp.jar");
- Files.copy(jarFileSrc.toPath(), jarFileTmp.toPath());
+ File jarFileTmp = tempFolder.newFile("hellocgi-signed-" + algorithm +
"-tmp.jar");
+ Files.copy(jarFileSrc.toPath(), jarFileTmp.toPath(),
StandardCopyOption.REPLACE_EXISTING);
Migration migration = new Migration();
migration.setEESpecProfile(profile);
@@ -292,57 +298,44 @@ public class MigrationTest {
@Test
public void testMigrateJarWithCache() throws Exception {
File jarFile = new File("target/test-classes/hellocgi.jar");
- File jarFileTarget = new
File("target/test-classes/hellocgi-cached.jar");
- File cacheDir = new File("target/test-classes/cache-test");
+ File jarFileTarget = tempFolder.newFile("hellocgi-cached.jar");
+ // Not pre-created: the MigrationCache constructor must create it
+ File cacheDir = new File(tempFolder.getRoot(), "cache-test");
- try {
- // Clean up cache directory
- if (cacheDir.exists()) {
- FileUtils.deleteDirectory(cacheDir);
- }
-
- // First migration - cache miss
- Migration migration1 = new Migration();
- migration1.setSource(jarFile);
- migration1.setDestination(jarFileTarget);
- migration1.setCache(new MigrationCache(cacheDir, 30));
- migration1.execute();
-
- assertTrue("Target JAR should exist after first migration",
jarFileTarget.exists());
- assertTrue("Cache directory should be created", cacheDir.exists());
+ // Note: top-level archives are not cached (only nested archives are),
+ // so the cache is only set up, not exercised, by this test.
+ Migration migration1 = new Migration();
+ migration1.setSource(jarFile);
+ migration1.setDestination(jarFileTarget);
+ migration1.setCache(new MigrationCache(cacheDir, 30));
+ migration1.execute();
- // Verify the migrated JAR works
- verifyHelloCGIMigrated(jarFileTarget);
+ assertTrue("Target JAR should exist after first migration",
jarFileTarget.exists());
+ assertTrue("Cache directory should be created", cacheDir.exists());
- // Delete target and migrate again - cache hit
- jarFileTarget.delete();
- assertFalse("Target should be deleted", jarFileTarget.exists());
+ // Verify the migrated JAR works
+ verifyHelloCGIMigrated(jarFileTarget);
- Migration migration2 = new Migration();
- migration2.setSource(jarFile);
- migration2.setDestination(jarFileTarget);
- migration2.setCache(new MigrationCache(cacheDir, 30));
- migration2.execute();
+ // Delete target and migrate again
+ jarFileTarget.delete();
+ assertFalse("Target should be deleted", jarFileTarget.exists());
- assertTrue("Target JAR should exist after second migration",
jarFileTarget.exists());
+ Migration migration2 = new Migration();
+ migration2.setSource(jarFile);
+ migration2.setDestination(jarFileTarget);
+ migration2.setCache(new MigrationCache(cacheDir, 30));
+ migration2.execute();
- // Verify the cached JAR works
- verifyHelloCGIMigrated(jarFileTarget);
+ assertTrue("Target JAR should exist after second migration",
jarFileTarget.exists());
- // Note: We don't assert that duration2 < duration1 because the
times are too short
- // and can vary. The important thing is both migrations work
correctly.
- } finally {
- // Clean up
- if (cacheDir.exists()) {
- FileUtils.deleteDirectory(cacheDir);
- }
- }
+ // Verify the migrated JAR works
+ verifyHelloCGIMigrated(jarFileTarget);
}
@Test
public void testMigrateJarWithCacheDisabled() throws Exception {
File jarFile = new File("target/test-classes/hellocgi.jar");
- File jarFileTarget = new
File("target/test-classes/hellocgi-nocache.jar");
+ File jarFileTarget = tempFolder.newFile("hellocgi-nocache.jar");
Migration migration = new Migration();
migration.setSource(jarFile);
@@ -352,58 +345,35 @@ public class MigrationTest {
assertTrue("Target JAR should exist", jarFileTarget.exists());
- File cgiapiFile = new File("target/test-classes/cgi-api.jar");
- URLClassLoader classloader = new URLClassLoader(
- new URL[]{jarFileTarget.toURI().toURL(),
cgiapiFile.toURI().toURL()},
- ClassLoader.getSystemClassLoader().getParent());
- Class<?> cls = Class.forName("org.apache.tomcat.jakartaee.HelloCGI",
true, classloader);
- assertEquals("jakarta.servlet.CommonGatewayInterface",
cls.getSuperclass().getName());
+ verifyHelloCGIMigrated(jarFileTarget);
}
@Test
public void testMigrateCLIWithCacheOption() throws Exception {
File sourceFile = new File("target/test-classes/hellocgi.jar");
- File targetFile = new
File("target/test-classes/hellocgi-cli-cached.jar");
- File cacheDir = new File("target/test-classes/cache-cli-test");
+ File targetFile = tempFolder.newFile("hellocgi-cli-cached.jar");
+ // Not pre-created: the MigrationCache constructor must create it
+ File cacheDir = new File(tempFolder.getRoot(), "cache-cli-test");
- try {
- // Clean up
- if (cacheDir.exists()) {
- FileUtils.deleteDirectory(cacheDir);
- }
- if (targetFile.exists()) {
- targetFile.delete();
- }
-
- // Run with custom cache
- MigrationCLI.main(new String[] {
- "-cache",
- "-cacheLocation=" + cacheDir.getAbsolutePath(),
- sourceFile.getAbsolutePath(),
- targetFile.getAbsolutePath()
- });
+ // Run with custom cache
+ MigrationCLI.main(new String[] {
+ "-cache",
+ "-cacheLocation=" + cacheDir.getAbsolutePath(),
+ sourceFile.getAbsolutePath(),
+ targetFile.getAbsolutePath()
+ });
- assertTrue("Target file should exist", targetFile.exists());
- assertTrue("Cache directory should be created", cacheDir.exists());
+ assertTrue("Target file should exist", targetFile.exists());
+ assertTrue("Cache directory should be created", cacheDir.exists());
- // Verify the migrated JAR works
- verifyHelloCGIMigrated(targetFile);
- } finally {
- // Clean up
- if (cacheDir.exists()) {
- FileUtils.deleteDirectory(cacheDir);
- }
- }
+ // Verify the migrated JAR works
+ verifyHelloCGIMigrated(targetFile);
}
@Test
public void testMigrateCLIWithNoCacheOption() throws Exception {
File sourceFile = new File("target/test-classes/hellocgi.jar");
- File targetFile = new
File("target/test-classes/hellocgi-cli-nocache.jar");
-
- if (targetFile.exists()) {
- targetFile.delete();
- }
+ File targetFile = tempFolder.newFile("hellocgi-cli-nocache.jar");
// Run without cache (no -cache option)
MigrationCLI.main(new String[] {
@@ -418,7 +388,7 @@ public class MigrationTest {
}
@Test
- public void testExecuteThrowsWhenAlreadyRunning() throws Exception {
+ public void testReExecuteAfterCompletion() throws Exception {
// Note: After execute() completes, state is COMPLETE, not RUNNING.
// So calling execute() again will work (it will run again).
// The IllegalStateException is only thrown if state is RUNNING.
@@ -451,8 +421,9 @@ public class MigrationTest {
public void testMigrateDirectoryCannotCreateDest() throws Exception {
Migration migration = new Migration();
File sourceDirectory = new File("src/test/resources");
- // Use a path that definitely can't be created
- File destDirectory = new File("/proc/nonexistent/immutable/path/dest");
+ // Use an existing regular file as the destination so that the
+ // destination directory cannot be created (portable across platforms)
+ File destDirectory = tempFolder.newFile("immutable-dest");
try {
migration.setSource(sourceDirectory);
@@ -504,16 +475,43 @@ public class MigrationTest {
@Test
public void testMigrateJarWithZip64ExtraField() throws Exception {
- File jarFile = new File("target/test-classes/hellocgi.jar");
- File jarFileTarget = tempFolder.newFile("zip64-test.jar");
+ // Create a JAR whose entry carries a ZIP64 extra field (ID 0x0001)
+ File jarFile = tempFolder.newFile("zip64-test.jar");
+ try (FileOutputStream fos = new FileOutputStream(jarFile);
+
org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream zos =
+ new
org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream(fos)) {
+ org.apache.commons.compress.archivers.zip.ZipArchiveEntry entry =
+ new
org.apache.commons.compress.archivers.zip.ZipArchiveEntry("test.txt");
+ // ZIP64 extended information extra field: header 0x0001, 16 bytes
of data
+ entry.setExtra(new byte[] { 0x01, 0x00, 0x10, 0x00,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
+ zos.putArchiveEntry(entry);
+
zos.write("javax.servlet.http.HttpServlet".getBytes(StandardCharsets.ISO_8859_1));
+ zos.closeArchiveEntry();
+ }
+
+ File jarFileTarget = tempFolder.newFile("zip64-migrated.jar");
Migration migration = new Migration();
migration.setSource(jarFile);
migration.setDestination(jarFileTarget);
+ migration.setZipInMemory(false); // Streaming mode removes the ZIP64
extra field
migration.execute();
assertTrue("Target JAR should exist", jarFileTarget.exists());
- assertTrue("Target JAR should have content", jarFileTarget.length() >
0);
+
+ try (org.apache.commons.compress.archivers.zip.ZipFile jar =
+
org.apache.commons.compress.archivers.zip.ZipFile.builder().setFile(jarFileTarget).get())
{
+ org.apache.commons.compress.archivers.zip.ZipArchiveEntry entry =
+
(org.apache.commons.compress.archivers.zip.ZipArchiveEntry)
jar.getEntry("test.txt");
+ assertNotNull("Entry should exist in migrated JAR", entry);
+ assertNull("ZIP64 extra field should have been removed",
+ entry.getExtraField(new
org.apache.commons.compress.archivers.zip.ZipShort(1)));
+
+ byte[] content = readAllBytes(jar.getInputStream(entry), (int)
entry.getSize());
+ assertTrue("Entry content should be migrated",
+ new String(content,
StandardCharsets.ISO_8859_1).contains("jakarta.servlet"));
+ }
}
@Test
@@ -538,22 +536,27 @@ public class MigrationTest {
@Test
public void testMigrateWithDisabledDefaultExcludes() throws Exception {
- File sourceFile = new File("target/test-classes/HelloServlet.java");
- File destFile = tempFolder.newFile("no-default-excludes.java");
+ // A valid archive whose file name matches one of the default exclude
+ // patterns (commons-lang-*.jar). With the default excludes disabled
+ // it must be processed (and converted) as a normal archive.
+ File sourceDirectory =
tempFolder.newFolder("no-default-excludes-test");
+ createNestedJarWithContent(sourceDirectory, "commons-lang-3.12.0.jar",
"nested.txt",
+ "javax.servlet.http.HttpServlet");
+ File destinationDirectory =
tempFolder.newFolder("no-default-excludes-dest");
Migration migration = new Migration();
- migration.setSource(sourceFile);
- migration.setDestination(destFile);
+ migration.setSource(sourceDirectory);
+ migration.setDestination(destinationDirectory);
migration.setEnableDefaultExcludes(false);
migration.execute();
- assertTrue("Migrated file should exist", destFile.exists());
- String migratedSource = FileUtils.readFileToString(destFile,
StandardCharsets.UTF_8);
- assertTrue("Imports should be migrated",
migratedSource.contains("import jakarta.servlet"));
+ assertTrue("Archive should have been converted",
migration.hasConverted());
+ verifyArchiveEntryContent(new File(destinationDirectory,
"commons-lang-3.12.0.jar"),
+ "nested.txt", "jakarta.servlet");
}
@Test
- public void testMigrateNestedJarInWar() throws Exception {
+ public void testMigrateJarFileInMemoryBasic() throws Exception {
File jarFile = new File("target/test-classes/hellocgi.jar");
File jarFileTarget = tempFolder.newFile("nested-test.jar");
@@ -639,7 +642,7 @@ public class MigrationTest {
@Test
public void testMigrateLargeStoredEntryInMemory() throws Exception {
// Create a large file (>10MB) to test in-memory migration with large
STORED entries
- byte[] largeContent = new byte[11 * 1024 * 024]; // 11MB
+ byte[] largeContent = new byte[11 * 1024 * 1024]; // 11MB
for (int i = 0; i < largeContent.length; i++) {
largeContent[i] = (byte) (i % 256);
}
@@ -671,7 +674,8 @@ public class MigrationTest {
@Test
public void testMigrateNestedArchiveWithCache() throws Exception {
// Create a nested JAR with javax.servlet references
- File nestedJar = createNestedJarWithContent("nested.jar",
"nested.txt", "javax.servlet.http.HttpServlet");
+ File nestedJar = createNestedJarWithContent(tempFolder.getRoot(),
"nested.jar", "nested.txt",
+ "javax.servlet.http.HttpServlet");
// Create a WAR containing the nested JAR
File warFile = tempFolder.newFile("app.war");
@@ -715,7 +719,8 @@ public class MigrationTest {
@Test
public void testMigrateNestedArchiveWithCacheHit() throws Exception {
// Create a nested JAR with javax.servlet references
- File nestedJar = createNestedJarWithContent("nested-hit.jar",
"nested.txt", "javax.servlet.http.HttpServlet");
+ File nestedJar = createNestedJarWithContent(tempFolder.getRoot(),
"nested-hit.jar", "nested.txt",
+ "javax.servlet.http.HttpServlet");
// Create two WARs with the same nested JAR
File warFile1 = createWarWithNestedJar(nestedJar, "app1.war");
@@ -733,10 +738,35 @@ public class MigrationTest {
assertTrue("First target WAR should exist", warTarget1.exists());
+ // The nested JAR should now be stored in the cache
+ File cachedJar = null;
+ File[] subdirs = cacheDir.listFiles();
+ if (subdirs != null) {
+ for (File subdir : subdirs) {
+ if (subdir.isDirectory()) {
+ File[] files = subdir.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.isFile() &&
file.getName().endsWith(".jar")) {
+ cachedJar = file;
+ }
+ }
+ }
+ }
+ }
+ }
+ assertNotNull("Nested JAR should be cached after first migration",
cachedJar);
+
// Create second WAR with same nested JAR
File warFile2 = createWarWithNestedJar(nestedJar, "app2.war");
File warTarget2 = tempFolder.newFile("app2-migrated.war");
+ // Replace the cached content with a canary: if the second migration
+ // hits the cache, the nested JAR in the second WAR must be a byte
+ // for byte copy of the canary.
+ byte[] canary = "cached nested
jar".getBytes(StandardCharsets.ISO_8859_1);
+ Files.write(cachedJar.toPath(), canary);
+
// Second migration - should hit cache for nested JAR
Migration migration2 = new Migration();
migration2.setSource(warFile2);
@@ -747,9 +777,15 @@ public class MigrationTest {
assertTrue("Second target WAR should exist", warTarget2.exists());
- // Verify both WARs have migrated nested content
- for (File warTarget : new File[]{warTarget1, warTarget2}) {
- verifyNestedJarContentMigrated(warTarget,
"WEB-INF/lib/nested.jar", "jakarta.servlet");
+ // First WAR must have the migrated nested content
+ verifyNestedJarContentMigrated(warTarget1, "WEB-INF/lib/nested.jar",
"jakarta.servlet");
+
+ // Second WAR's nested JAR must be served from the cache (the canary)
+ try (JarFile war = new JarFile(warTarget2)) {
+ JarEntry nestedEntry = war.getJarEntry("WEB-INF/lib/nested.jar");
+ assertNotNull("Nested JAR should exist", nestedEntry);
+ byte[] nestedJarBytes =
readAllBytes(war.getInputStream(nestedEntry), (int) nestedEntry.getSize());
+ assertArrayEquals("Nested JAR should be served from the cache",
canary, nestedJarBytes);
}
}
@@ -768,8 +804,8 @@ public class MigrationTest {
return warFile;
}
- private File createNestedJarWithContent(String jarName, String entryName,
String content) throws Exception {
- File nestedJar = tempFolder.newFile(jarName);
+ private File createNestedJarWithContent(File parentDir, String jarName,
String entryName, String content) throws Exception {
+ File nestedJar = new File(parentDir, jarName);
try (FileOutputStream fos = new FileOutputStream(nestedJar);
org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream zos =
new
org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream(fos)) {
@@ -784,11 +820,12 @@ public class MigrationTest {
private void verifyHelloCGIMigrated(File jarFileTarget) throws Exception {
File cgiapiFile = new File("target/test-classes/cgi-api.jar");
- URLClassLoader classloader = new URLClassLoader(
+ try (URLClassLoader classloader = new URLClassLoader(
new URL[]{jarFileTarget.toURI().toURL(),
cgiapiFile.toURI().toURL()},
- ClassLoader.getSystemClassLoader().getParent());
- Class<?> cls = Class.forName("org.apache.tomcat.jakartaee.HelloCGI",
true, classloader);
- assertEquals("jakarta.servlet.CommonGatewayInterface",
cls.getSuperclass().getName());
+ ClassLoader.getSystemClassLoader().getParent())) {
+ Class<?> cls =
Class.forName("org.apache.tomcat.jakartaee.HelloCGI", true, classloader);
+ assertEquals("jakarta.servlet.CommonGatewayInterface",
cls.getSuperclass().getName());
+ }
}
private void verifyNestedJarContentMigrated(File warFile, String
nestedEntryName, String expectedContent) throws Exception {
@@ -883,7 +920,7 @@ public class MigrationTest {
assertTrue("Large JAR should still exist", largeJar.exists());
assertTrue("hasConverted should be true", migration.hasConverted());
- // Verify the text file was migrated
+ // Verify the text file was migrated and the large entry was preserved
try (JarFile jar = new JarFile(largeJar)) {
JarEntry textEntry = jar.getJarEntry("test.txt");
assertNotNull("test.txt should exist", textEntry);
@@ -891,6 +928,11 @@ public class MigrationTest {
byte[] textBytes = readAllBytes(jar.getInputStream(textEntry),
(int) textEntry.getSize());
String migratedText = new String(textBytes,
StandardCharsets.ISO_8859_1);
assertTrue("Text should be migrated",
migratedText.contains("jakarta.servlet"));
+
+ JarEntry largeEntry = jar.getJarEntry("large-data.bin");
+ assertNotNull("large-data.bin should exist", largeEntry);
+ byte[] largeBytes = readAllBytes(jar.getInputStream(largeEntry),
(int) largeEntry.getSize());
+ assertArrayEquals("Large entry content should be preserved",
largeContent, largeBytes);
}
}
@@ -905,9 +947,11 @@ public class MigrationTest {
File sourceFile = new File(subDir2, "test.txt");
Files.write(sourceFile.toPath(),
"javax.servlet".getBytes(StandardCharsets.ISO_8859_1));
- // Create a destination where nested subdir can't be created
- // Use /proc as it's typically a read-only mount on Linux
- File destDir = new File("/proc/nested-test-dest");
+ // Create a regular file where a nested subdirectory is expected so
+ // that the subdirectory cannot be created (portable across platforms)
+ File destDir = tempFolder.newFolder("nested-test-dest");
+ File blockedSubDir = new File(destDir, "level1");
+ Files.createFile(blockedSubDir.toPath());
Migration migration = new Migration();
migration.setSource(sourceDir);
@@ -950,7 +994,8 @@ public class MigrationTest {
@Test
public void testMigrateNestedJarInWarStreaming() throws Exception {
// Create a WAR with a nested JAR that has javax references
- File nestedJar = createNestedJarWithContent("nested-streaming.jar",
"nested.txt", "javax.servlet.http.HttpServlet");
+ File nestedJar = createNestedJarWithContent(tempFolder.getRoot(),
"nested-streaming.jar", "nested.txt",
+ "javax.servlet.http.HttpServlet");
File warFile = createWarWithNestedJar(nestedJar, "streaming-test.war");
File warTarget = tempFolder.newFile("streaming-test-migrated.war");
@@ -971,7 +1016,8 @@ public class MigrationTest {
@Test
public void testMigrateNestedJarInWarInMemory() throws Exception {
// Create a WAR with a nested JAR that has javax references
- File nestedJar = createNestedJarWithContent("nested-memory.jar",
"nested.txt", "javax.servlet.http.HttpServlet");
+ File nestedJar = createNestedJarWithContent(tempFolder.getRoot(),
"nested-memory.jar", "nested.txt",
+ "javax.servlet.http.HttpServlet");
File warFile = createWarWithNestedJar(nestedJar, "memory-test.war");
File warTarget = tempFolder.newFile("memory-test-migrated.war");
@@ -991,24 +1037,48 @@ public class MigrationTest {
@Test
public void testMigrateWithStoreMethodInZip() throws Exception {
- File jarFile = new File("target/test-classes/hellocgi.jar");
- File jarFileTarget = tempFolder.newFile("stored-method-test.jar");
+ // Create a JAR with a STORED (uncompressed) entry
+ File jarFile = createStoredEntryJar("stored-method-test.jar",
"test.txt",
+ "javax.servlet.http.HttpServlet");
+ File jarFileTarget = tempFolder.newFile("stored-method-migrated.jar");
Migration migration = new Migration();
migration.setSource(jarFile);
migration.setDestination(jarFileTarget);
+ migration.setZipInMemory(false); // Streaming mode handles STORED
entries
migration.execute();
+ assertTrue("Target JAR should exist", jarFileTarget.exists());
+
try (JarFile jar = new JarFile(jarFileTarget)) {
- java.util.Enumeration<java.util.jar.JarEntry> entries =
jar.entries();
- while (entries.hasMoreElements()) {
- java.util.jar.JarEntry entry = entries.nextElement();
- if (!entry.isDirectory()) {
- break;
- }
- }
+ JarEntry entry = jar.getJarEntry("test.txt");
+ assertNotNull("Stored entry should exist in migrated JAR", entry);
+ assertEquals("Stored entry should remain stored",
java.util.zip.ZipEntry.STORED, entry.getMethod());
+
+ byte[] content = readAllBytes(jar.getInputStream(entry), (int)
entry.getSize());
+ assertTrue("Stored entry content should be migrated",
+ new String(content,
StandardCharsets.ISO_8859_1).contains("jakarta.servlet"));
}
- assertTrue("Target JAR should exist", jarFileTarget.exists());
+ }
+
+ private File createStoredEntryJar(String jarName, String entryName, String
content) throws Exception {
+ File jarFile = tempFolder.newFile(jarName);
+ byte[] data = content.getBytes(StandardCharsets.ISO_8859_1);
+ try (FileOutputStream fos = new FileOutputStream(jarFile);
+
org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream zos =
+ new
org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream(fos)) {
+ org.apache.commons.compress.archivers.zip.ZipArchiveEntry entry =
+ new
org.apache.commons.compress.archivers.zip.ZipArchiveEntry(entryName);
+
entry.setMethod(org.apache.commons.compress.archivers.zip.ZipArchiveEntry.STORED);
+ entry.setSize(data.length);
+ CRC32 crc = new CRC32();
+ crc.update(data);
+ entry.setCrc(crc.getValue());
+ zos.putArchiveEntry(entry);
+ zos.write(data);
+ zos.closeArchiveEntry();
+ }
+ return jarFile;
}
@Test
@@ -1028,7 +1098,8 @@ public class MigrationTest {
@Test
public void testMigrateFileToNewParentDirectory() throws Exception {
File sourceFile = new File("target/test-classes/HelloServlet.java");
- File destFile = new File(tempFolder.newFolder("new", "parent"),
"migrated.java");
+ // Parent directory is not pre-created: execute() must create it
+ File destFile = new File(tempFolder.getRoot(),
"new/parent/migrated.java");
Migration migration = new Migration();
migration.setSource(sourceFile);
@@ -1091,11 +1162,14 @@ public class MigrationTest {
MigrationCLI.main(new String[] {
"-matchExcludesAgainstPathName",
+ "-exclude=*/HelloServlet.java",
sourceFile.getAbsolutePath(),
targetFile.getAbsolutePath()
});
assertTrue("Target file should exist", targetFile.exists());
+ String content = FileUtils.readFileToString(targetFile,
StandardCharsets.UTF_8);
+ assertTrue("Excluded file should not be converted",
content.contains("import javax.servlet"));
}
@Test
@@ -1104,23 +1178,16 @@ public class MigrationTest {
File targetFile = tempFolder.newFile("cli-cache-retention.java");
File cacheDir = tempFolder.newFolder("cache-retention-test");
- try {
- MigrationCLI.main(new String[] {
- "-cache",
- "-cacheLocation=" + cacheDir.getAbsolutePath(),
- "-cacheRetention=7",
- sourceFile.getAbsolutePath(),
- targetFile.getAbsolutePath()
- });
-
- assertTrue("Target file should exist", targetFile.exists());
- assertTrue("Cache directory should be created", cacheDir.exists());
- } finally {
- // Clean up
- if (cacheDir.exists()) {
- FileUtils.deleteDirectory(cacheDir);
- }
- }
+ MigrationCLI.main(new String[] {
+ "-cache",
+ "-cacheLocation=" + cacheDir.getAbsolutePath(),
+ "-cacheRetention=7",
+ sourceFile.getAbsolutePath(),
+ targetFile.getAbsolutePath()
+ });
+
+ assertTrue("Target file should exist", targetFile.exists());
+ assertTrue("Cache directory should be created", cacheDir.exists());
}
@Test
@@ -1191,20 +1258,34 @@ public class MigrationTest {
}
@Test
- public void testMigrateWithDefaultExcludesDisabled() throws Exception {
- File sourceFile = new File("target/test-classes/HelloServlet.java");
- File destFile = tempFolder.newFile("no-default-excludes.java");
+ public void testMigrateWithDefaultExcludes() throws Exception {
+ // A valid archive whose file name matches one of the default exclude
+ // patterns (commons-lang-*.jar). With the default excludes enabled
+ // (the default) it is copied unchanged and not converted.
+ File sourceDirectory = tempFolder.newFolder("default-excludes-test");
+ createNestedJarWithContent(sourceDirectory, "commons-lang-3.12.0.jar",
"nested.txt",
+ "javax.servlet.http.HttpServlet");
+ File destinationDirectory =
tempFolder.newFolder("default-excludes-dest");
Migration migration = new Migration();
- migration.setSource(sourceFile);
- migration.setDestination(destFile);
- migration.setEnableDefaultExcludes(false);
- migration.setEESpecProfile(EESpecProfiles.EE);
+ migration.setSource(sourceDirectory);
+ migration.setDestination(destinationDirectory);
migration.execute();
- assertTrue("Migrated file should exist", destFile.exists());
- String migratedSource = FileUtils.readFileToString(destFile,
StandardCharsets.UTF_8);
- assertTrue("Imports should be migrated",
migratedSource.contains("import jakarta.servlet"));
+ File destArchive = new File(destinationDirectory,
"commons-lang-3.12.0.jar");
+ assertTrue("Excluded archive should still be copied",
destArchive.exists());
+ assertFalse("Excluded archive should not be converted",
migration.hasConverted());
+ verifyArchiveEntryContent(destArchive, "nested.txt", "javax.servlet");
+ }
+
+ private void verifyArchiveEntryContent(File archiveFile, String entryName,
String expectedContent) throws Exception {
+ try (JarFile archive = new JarFile(archiveFile)) {
+ JarEntry entry = archive.getJarEntry(entryName);
+ assertNotNull("Entry should exist in " + archiveFile.getName(),
entry);
+ byte[] content = readAllBytes(archive.getInputStream(entry), (int)
entry.getSize());
+ assertTrue("Entry content in " + archiveFile.getName() + " should
contain " + expectedContent,
+ new String(content,
StandardCharsets.ISO_8859_1).contains(expectedContent));
+ }
}
@Test
diff --git
a/src/test/java/org/apache/tomcat/jakartaee/NoExitSecurityManager.java
b/src/test/java/org/apache/tomcat/jakartaee/NoExitSecurityManager.java
index 446e96c..8e7405e 100644
--- a/src/test/java/org/apache/tomcat/jakartaee/NoExitSecurityManager.java
+++ b/src/test/java/org/apache/tomcat/jakartaee/NoExitSecurityManager.java
@@ -19,6 +19,16 @@ package org.apache.tomcat.jakartaee;
import java.security.Permission;
+/**
+ * A {@link SecurityManager} used by the tests to turn
+ * {@link System#exit(int)} into a {@link SecurityException} (whose message is
+ * the exit status) instead of terminating the test JVM. All other permission
+ * checks are permitted.
+ * <p>
+ * It can only be installed on JDK versions that still support a security
+ * manager. On JDK 25 and later (JEP 486) {@code System.setSecurityManager()}
+ * itself fails and the tests that rely on this class are skipped.
+ */
public class NoExitSecurityManager extends SecurityManager {
@Override
diff --git a/src/test/java/org/apache/tomcat/jakartaee/StringManagerTest.java
b/src/test/java/org/apache/tomcat/jakartaee/StringManagerTest.java
index 095baa6..1b7b51c 100644
--- a/src/test/java/org/apache/tomcat/jakartaee/StringManagerTest.java
+++ b/src/test/java/org/apache/tomcat/jakartaee/StringManagerTest.java
@@ -69,13 +69,6 @@ public class StringManagerTest {
"nonexistent.key.12345", result);
}
- @Test
- public void testGetStringWithArgsNoArgs() {
- StringManager sm = StringManager.getManager(Migration.class);
- String result = sm.getString("migration.notCompleted");
- assertEquals("Migration has not completed", result);
- }
-
@Test
public void testGetManagerByClass() {
StringManager sm1 = StringManager.getManager(Migration.class);
@@ -101,9 +94,11 @@ public class StringManagerTest {
public void testGetManagerDifferentLocale() {
StringManager sm1 =
StringManager.getManager("org.apache.tomcat.jakartaee", Locale.ENGLISH);
StringManager sm2 =
StringManager.getManager("org.apache.tomcat.jakartaee", Locale.FRANCE);
- // May or may not be the same depending on available bundles
+ // Managers are cached per (package, requested locale) so different
+ // locales always produce different instances
assertNotNull("Manager should not be null", sm1);
assertNotNull("Manager should not be null", sm2);
+ assertNotSame("Different locales should return different managers",
sm1, sm2);
}
@Test
diff --git a/src/test/java/org/apache/tomcat/jakartaee/TesterConstants.java
b/src/test/java/org/apache/tomcat/jakartaee/TesterConstants.java
index afbf569..27acfb7 100644
--- a/src/test/java/org/apache/tomcat/jakartaee/TesterConstants.java
+++ b/src/test/java/org/apache/tomcat/jakartaee/TesterConstants.java
@@ -1,5 +1,33 @@
+/*
+ * 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.tomcat.jakartaee;
+/**
+ * Test fixture whose constants exist to embed {@code javax} class names in
+ * the constant pool of this class file.
+ * <p>
+ * {@link ClassConverterTest} converts that class file and checks which of the
+ * embedded strings were changed. The {@code JAVA_PRESENT_} constants reference
+ * a class that exists in the {@code jakarta} namespace, so the converter must
+ * rewrite them. The {@code JAVA_NOT_PRESENT_} constants reference a class that
+ * does not exist in either namespace, so the converter must leave them
+ * unchanged.
+ */
public class TesterConstants {
public static final String JAVA_PRESENT_DOT =
"javax.servlet.CommonGatewayInterface";
diff --git a/src/test/java/org/apache/tomcat/jakartaee/TextConverterTest.java
b/src/test/java/org/apache/tomcat/jakartaee/TextConverterTest.java
index bde3479..0a10fad 100644
--- a/src/test/java/org/apache/tomcat/jakartaee/TextConverterTest.java
+++ b/src/test/java/org/apache/tomcat/jakartaee/TextConverterTest.java
@@ -1,3 +1,20 @@
+/*
+ * 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.tomcat.jakartaee;
import static org.junit.Assert.assertEquals;
@@ -14,26 +31,27 @@ public class TextConverterTest {
private static final String TEST_FILENAME = "text.txt";
- private static final String INPUT =
"javax.servlet.http.HttpServletRequest";
- private static final String OUTPUT =
"jakarta.servlet.http.HttpServletRequest";
+ private static final String INPUT =
"javax.servlet.http.HttpServletRequest";
+ private static final String OUTPUT =
"jakarta.servlet.http.HttpServletRequest";
- @Test
- public void testConvert() throws IOException {
+ @Test
+ public void testConvert() throws IOException {
- // prepare
- TextConverter converter = new TextConverter();
- ByteArrayInputStream in = new
ByteArrayInputStream(INPUT.getBytes(StandardCharsets.ISO_8859_1));
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- EESpecProfile profile = EESpecProfiles.EE;
+ // prepare
+ TextConverter converter = new TextConverter();
+ ByteArrayInputStream in = new
ByteArrayInputStream(INPUT.getBytes(StandardCharsets.ISO_8859_1));
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ EESpecProfile profile = EESpecProfiles.EE;
- // test
- converter.convert(TEST_FILENAME, in, out, profile);
+ // test
+ boolean converted = converter.convert(TEST_FILENAME, in, out, profile);
- // assert
- String result = new String(out.toByteArray(),
StandardCharsets.ISO_8859_1);
- assertEquals(OUTPUT, result);
+ // assert
+ assertTrue("Should convert when javax packages present", converted);
+ String result = new String(out.toByteArray(),
StandardCharsets.ISO_8859_1);
+ assertEquals(OUTPUT, result);
- }
+ }
@Test
public void testAcceptsJava() {
@@ -168,6 +186,20 @@ public class TextConverterTest {
assertEquals(content, result);
}
+ @Test
+ public void testConvertJakartaWithJee8Profile() throws IOException {
+ TextConverter converter = new TextConverter();
+ String content = "import jakarta.servlet.http.HttpServletRequest;";
+ ByteArrayInputStream in = new
ByteArrayInputStream(content.getBytes(StandardCharsets.ISO_8859_1));
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ boolean converted = converter.convert("Test.java", in, out,
EESpecProfiles.JEE8);
+
+ assertTrue("JEE8 profile should convert jakarta packages", converted);
+ String result = new String(out.toByteArray(),
StandardCharsets.ISO_8859_1);
+ assertEquals("import javax.servlet.http.HttpServletRequest;", result);
+ }
+
@Test
public void testConvertEmptyContent() throws IOException {
TextConverter converter = new TextConverter();
diff --git a/src/test/resources/testbuild.xml b/src/test/resources/testbuild.xml
index 19b4dec..9301abf 100644
--- a/src/test/resources/testbuild.xml
+++ b/src/test/resources/testbuild.xml
@@ -1,4 +1,4 @@
-<project name="Jsign Ant tests">
+<project name="Jakarta EE migration Ant tests">
<taskdef name="javax2jakarta"
classname="org.apache.tomcat.jakartaee.MigrationTask"/>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]