From 7555d0375aac6e0d9d51b0785d5259d80af3905d Mon Sep 17 00:00:00 2001 From: Lachlan Date: Fri, 30 Apr 2021 16:05:49 +1000 Subject: [PATCH] Improve testing for temp directories (#6139) * Improve testing for temp directories (#5483) Improve testing around WebAppContext temporary directories. Signed-off-by: Lachlan Roberts Co-authored-by: olivier lamy --- .../jetty/deploy/DeploymentTempDirTest.java | 226 +++++++++++ .../test/resources/jetty-logging.properties | 5 +- .../eclipse/jetty/webapp/WebAppContext.java | 2 +- .../jetty/webapp/WebInfConfiguration.java | 20 +- .../org/eclipse/jetty/webapp/TempDirTest.java | 383 ++++++++++++++++++ 5 files changed, 623 insertions(+), 13 deletions(-) create mode 100644 jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentTempDirTest.java create mode 100644 jetty-webapp/src/test/java/org/eclipse/jetty/webapp/TempDirTest.java diff --git a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentTempDirTest.java b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentTempDirTest.java new file mode 100644 index 000000000000..1ae25e5479a3 --- /dev/null +++ b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentTempDirTest.java @@ -0,0 +1,226 @@ +// +// ======================================================================== +// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.deploy; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jetty.deploy.providers.WebAppProvider; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.ContextHandlerCollection; +import org.eclipse.jetty.server.handler.DefaultHandler; +import org.eclipse.jetty.server.handler.HandlerCollection; +import org.eclipse.jetty.toolchain.test.FS; +import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.Scanner; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.webapp.WebAppContext; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class DeploymentTempDirTest +{ + private static final Logger LOG = Log.getLogger(DeploymentTempDirTest.class); + + private final WebAppProvider webAppProvider = new WebAppProvider(); + private final ContextHandlerCollection contexts = new ContextHandlerCollection(); + private final Path testDir = MavenTestingUtils.getTargetTestingPath(DeploymentTempDirTest.class.getSimpleName()); + private final Path tmpDir = testDir.resolve("tmpDir"); + private final Path webapps = testDir.resolve("webapps"); + private final Server server = new Server(); + private final TestListener listener = new TestListener(); + + @BeforeEach + public void setup() throws Exception + { + ServerConnector connector = new ServerConnector(server); + server.addConnector(connector); + + FS.ensureEmpty(testDir); + FS.ensureEmpty(tmpDir); + FS.ensureEmpty(webapps); + + webAppProvider.setMonitoredDirName(webapps.toString()); + webAppProvider.setScanInterval(0); + DeploymentManager deploymentManager = new DeploymentManager(); + deploymentManager.addAppProvider(webAppProvider); + server.addBean(deploymentManager); + + HandlerCollection handlerCollection = new HandlerCollection(); + handlerCollection.addHandler(contexts); + handlerCollection.addHandler(new DefaultHandler()); + deploymentManager.setContexts(contexts); + server.setHandler(handlerCollection); + } + + @AfterEach + public void stop() throws Exception + { + server.stop(); + } + + @Test + public void testTmpDirectory() throws Exception + { + Path warPath = MavenTestingUtils.getTestResourcePath("webapps/foo-webapp-1.war"); + String deploymentXml = "\n" + + "\n" + + "" + warPath + "\n" + + "" + tmpDir + "\n" + + "false\n" + + ""; + + server.start(); + webAppProvider.addScannerListener(listener); + + // Add the webapp xml which will will be detected after scan. + createNewFile(webapps, "foo-webapp.xml", deploymentXml); + webAppProvider.scan(); + webAppProvider.scan(); + listener.awaitChanges(); + WebAppContext webAppContext = getWebAppContext(); + assertThat(webAppContext.getTempDirectory(), is(tmpDir.toFile())); + + // Add a known file to the temp directory, this file will be deleted when stopping as persistTempDirectory is false. + String content = UUID.randomUUID().toString(); + createNewFile(webAppContext.getTempDirectory().toPath(), "myFile.txt", content); + + // Touch the webapp and rescan to reload the WebAppContext. + long newModifiedTime = System.currentTimeMillis() + 1000; + assertTrue(webapps.resolve("foo-webapp.xml").toFile().setLastModified(newModifiedTime)); + webAppProvider.scan(); + webAppProvider.scan(); + listener.awaitChanges(); + + // The second WebAppContext should be using the same temp directory but the file will have been deleted. + WebAppContext webAppContext2 = getWebAppContext(); + assertNotSame(webAppContext, webAppContext2); + File tmpDir2 = webAppContext2.getTempDirectory(); + assertThat(tmpDir2, is(tmpDir.toFile())); + + // The temp directory has been cleared. + assertTrue(tmpDir2.exists()); + assertThat(length(tmpDir2.listFiles()), is(0)); + } + + @Test + public void testPersistentTmpDirectory() throws Exception + { + Path warPath = MavenTestingUtils.getTestResourcePath("webapps/foo-webapp-1.war"); + String deploymentXml = "\n" + + "\n" + + "" + warPath + "\n" + + "" + tmpDir + "\n" + + "true\n" + + ""; + + server.start(); + webAppProvider.addScannerListener(listener); + + // Add the webapp xml which will will be detected after scan. + createNewFile(webapps, "foo-webapp.xml", deploymentXml); + webAppProvider.scan(); + webAppProvider.scan(); + listener.awaitChanges(); + WebAppContext webAppContext1 = getWebAppContext(); + assertThat(webAppContext1.getTempDirectory(), is(tmpDir.toFile())); + + // Add a known file to the temp directory, this file will be preserved after stop as persistTempDirectory is true. + String content = UUID.randomUUID().toString(); + createNewFile(webAppContext1.getTempDirectory().toPath(), "myFile.txt", content); + + // Touch the webapp and rescan to reload the WebAppContext. + long newModifiedTime = System.currentTimeMillis() + 1000; + assertTrue(webapps.resolve("foo-webapp.xml").toFile().setLastModified(newModifiedTime)); + webAppProvider.scan(); + webAppProvider.scan(); + listener.awaitChanges(); + + // The second WebAppContext should be using the same temp directory and file will not have been deleted. + WebAppContext webAppContext2 = getWebAppContext(); + assertNotSame(webAppContext1, webAppContext2); + assertThat(webAppContext2.getTempDirectory(), is(tmpDir.toFile())); + + // Test file is still in the temp directory. + String contentAfterReload = getContent(webAppContext2.getTempDirectory().toPath().resolve("myFile.txt")); + assertThat(contentAfterReload, is(content)); + } + + public int length(File[] files) + { + if (files == null) + throw new IllegalStateException(); + return files.length; + } + + public WebAppContext getWebAppContext() + { + Handler[] handlers = contexts.getHandlers(); + assertThat(handlers.length, is(1)); + return Arrays.stream(contexts.getHandlers()) + .filter(h -> h instanceof WebAppContext) + .map(h -> (WebAppContext)h) + .findFirst() + .orElseThrow(IllegalStateException::new); + } + + public void createNewFile(Path directory, String filename, String content) throws IOException + { + File file = directory.resolve(filename).toFile(); + try (FileWriter writer = new FileWriter(file)) + { + writer.write(content); + } + } + + public String getContent(Path filePath) throws IOException + { + return IO.toString(new FileReader(filePath.toFile())); + } + + public static class TestListener implements Scanner.BulkListener + { + private CountDownLatch _latch = new CountDownLatch(1); + + public void awaitChanges() throws Exception + { + assertTrue(_latch.await(5, TimeUnit.SECONDS)); + _latch = new CountDownLatch(1); + } + + @Override + public void filesChanged(Set filenames) + { + _latch.countDown(); + } + } +} diff --git a/jetty-deploy/src/test/resources/jetty-logging.properties b/jetty-deploy/src/test/resources/jetty-logging.properties index 363b21c3fb01..ad1ad3a27eeb 100644 --- a/jetty-deploy/src/test/resources/jetty-logging.properties +++ b/jetty-deploy/src/test/resources/jetty-logging.properties @@ -1,4 +1,5 @@ # Jetty Logging using jetty-slf4j-impl -org.eclipse.jetty.deploy.LEVEL=WARN -org.eclipse.jetty.util.Scanner=WARN +#org.eclipse.jetty.deploy.DeploymentTempDirTest.LEVEL=DEBUG +#org.eclipse.jetty.deploy.LEVEL=DEBUG #org.eclipse.jetty.webapp.LEVEL=DEBUG +#org.eclipse.jetty.util.Scanner=DEBUG diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java index 3551e43c0176..ecd65c66fcc6 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java @@ -151,7 +151,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL { static final Logger LOG = LoggerFactory.getLogger(WebAppContext.class); - public static final String TEMPDIR = "javax.servlet.context.tempdir"; + public static final String TEMPDIR = ServletContext.TEMPDIR; public static final String BASETEMPDIR = "org.eclipse.jetty.webapp.basetempdir"; public static final String WEB_DEFAULTS_XML = "org/eclipse/jetty/webapp/webdefault.xml"; public static final String ERROR_PAGE = "org.eclipse.jetty.server.error_page"; diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java index 09fcf26c7371..ec1c2a71d194 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java @@ -82,7 +82,7 @@ public void deconfigure(WebAppContext context) throws Exception File tempDirectory = context.getTempDirectory(); // if we're not persisting the temp dir contents delete it - if (!context.isPersistTempDirectory() && !IO.isEmptyDir(tempDirectory)) + if (!context.isPersistTempDirectory()) { IO.delete(tempDirectory); } @@ -165,8 +165,11 @@ public void resolveTempDirectory(WebAppContext context) //We need to make a temp dir. Check if the user has set a directory to use instead //of java.io.tmpdir as the parent of the dir File baseTemp = asFile(context.getAttribute(WebAppContext.BASETEMPDIR)); - if (baseTemp != null && baseTemp.isDirectory() && baseTemp.canWrite()) + if (baseTemp != null) { + if (!baseTemp.isDirectory() || !baseTemp.canWrite()) + throw new IllegalStateException(WebAppContext.BASETEMPDIR + " is not a writable directory"); + //Make a temp directory as a child of the given base dir makeTempDirectory(baseTemp, context); return; @@ -194,23 +197,20 @@ public void resolveTempDirectory(WebAppContext context) * Given an Object, return File reference for object. * Typically used to convert anonymous Object from getAttribute() calls to a File object. * - * @param fileattr the file attribute to analyze and return from (supports type File and type String, all others return null - * @return the File object, null if null, or null if not a File or String + * @param fileattr the file attribute to analyze and return from (supports type File, Path, and String). + * @return the File object if it can be converted otherwise null. */ private File asFile(Object fileattr) { if (fileattr == null) - { return null; - } if (fileattr instanceof File) - { return (File)fileattr; - } if (fileattr instanceof String) - { return new File((String)fileattr); - } + if (fileattr instanceof Path) + return ((Path)fileattr).toFile(); + return null; } diff --git a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/TempDirTest.java b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/TempDirTest.java new file mode 100644 index 000000000000..97803758d4a3 --- /dev/null +++ b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/TempDirTest.java @@ -0,0 +1,383 @@ +// +// ======================================================================== +// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.webapp; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import javax.servlet.ServletContext; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.toolchain.test.FS; +import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.eclipse.jetty.util.IO; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class TempDirTest +{ + private Server server; + private WebAppContext webapp; + private File jettyBase; + + @BeforeEach + public void before() + { + jettyBase = MavenTestingUtils.getTargetTestingDir(TempDirTest.class.getSimpleName()); + FS.ensureEmpty(jettyBase); + } + + public void setupServer() + { + server = new Server(); + ServerConnector connector = new ServerConnector(server); + server.addConnector(connector); + + File testWebAppDir = MavenTestingUtils.getProjectDir("src/test/webapp"); + webapp = new WebAppContext(); + webapp.setContextPath("/"); + webapp.setWar(testWebAppDir.getAbsolutePath()); + server.setHandler(webapp); + } + + @AfterEach + public void stopServer() throws Exception + { + if (server != null) + server.stop(); + } + + /** + * ServletContext.TEMPDIR has null value + * so webappContent#tempDirectory is created under java.io.tmpdir + */ + @Test + public void attributeWithNullValue() throws Exception + { + WebInfConfiguration webInfConfiguration = new WebInfConfiguration(); + WebAppContext webAppContext = new WebAppContext(); + webAppContext.setAttribute(ServletContext.TEMPDIR, null); + webInfConfiguration.resolveTempDirectory(webAppContext); + assertThat(webAppContext.getTempDirectory().getParent(), is(System.getProperty("java.io.tmpdir"))); + } + + /** + * ServletContext.TEMPDIR has "" value + * IllegalStateException + */ + @Test + public void attributeWithEmptyStringValue() + { + WebInfConfiguration webInfConfiguration = new WebInfConfiguration(); + WebAppContext webAppContext = new WebAppContext(); + webAppContext.setAttribute(ServletContext.TEMPDIR, ""); + assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext)); + } + + /** + * Test ServletContext.TEMPDIR as valid directory with types File, String and Path. + */ + @ParameterizedTest + @ValueSource(strings = {"File", "String", "Path"}) + public void attributeWithValidDirectory(String type) throws Exception + { + WebAppContext webAppContext = new WebAppContext(); + Path tmpDir = Files.createTempDirectory("jetty_test"); + switch (type) + { + case "File": + webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toFile()); + break; + case "String": + webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toString()); + break; + case "Path": + webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir); + break; + default: + throw new IllegalStateException(); + } + + // Test we have correct value as the webapp temp directory. + WebInfConfiguration webInfConfiguration = new WebInfConfiguration(); + webInfConfiguration.resolveTempDirectory(webAppContext); + assertThat(webAppContext.getTempDirectory().toPath(), is(tmpDir)); + } + + /** + * ServletContext.TEMPDIR as File to a non existent directory. + */ + @ParameterizedTest + @ValueSource(strings = {"File", "String", "Path"}) + public void attributeWithNonExistentDirectory(String type) throws Exception + { + WebAppContext webAppContext = new WebAppContext(); + Path tmpDir = Files.createTempDirectory("jetty_test").resolve("foo_test_tmp"); + Files.deleteIfExists(tmpDir); + assertFalse(Files.exists(tmpDir)); + switch (type) + { + case "File": + webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toFile()); + break; + case "String": + webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toString()); + break; + case "Path": + webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir); + break; + default: + throw new IllegalStateException(); + } + + // Test we have correct value as the webapp temp directory. + WebInfConfiguration webInfConfiguration = new WebInfConfiguration(); + webInfConfiguration.resolveTempDirectory(webAppContext); + Path webappTmpDir = webAppContext.getTempDirectory().toPath(); + assertThat(webappTmpDir, is(tmpDir)); + assertTrue(Files.exists(webappTmpDir)); + } + + /** + * WebAppContext.BASETEMPDIR has null value + * so webappContent#tempDirectory is created under java.io.tmpdir + */ + @Test + public void baseTempDirAttributeWithNullValue() throws Exception + { + WebInfConfiguration webInfConfiguration = new WebInfConfiguration(); + WebAppContext webAppContext = new WebAppContext(); + webAppContext.setAttribute(WebAppContext.BASETEMPDIR, null); + webInfConfiguration.resolveTempDirectory(webAppContext); + assertThat(webAppContext.getTempDirectory().getParent(), is(System.getProperty("java.io.tmpdir"))); + } + + /** + * WebAppContext.BASETEMPDIR has "" value + * IllegalStateException + */ + @Test + public void baseTempDirAttributeWithEmptyStringValue() + { + WebInfConfiguration webInfConfiguration = new WebInfConfiguration(); + WebAppContext webAppContext = new WebAppContext(); + webAppContext.setAttribute(WebAppContext.BASETEMPDIR, ""); + assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext)); + } + + /** + * Test WebAppContext.BASETEMPDIR as valid directory with types File, String and Path. + */ + @ParameterizedTest + @ValueSource(strings = {"File", "String", "Path"}) + public void baseTempDirAttributeWithValidDirectory(String type) throws Exception + { + WebAppContext webAppContext = new WebAppContext(); + Path tmpDir = Files.createTempDirectory("jetty_test"); + switch (type) + { + case "File": + webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toFile()); + break; + case "String": + webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toString()); + break; + case "Path": + webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir); + break; + default: + throw new IllegalStateException(); + } + + // Test we have correct value as the webapp temp directory. + WebInfConfiguration webInfConfiguration = new WebInfConfiguration(); + webInfConfiguration.resolveTempDirectory(webAppContext); + File tempDirectory = webAppContext.getTempDirectory(); + assertTrue(tempDirectory.exists()); + assertThat(tempDirectory.getParentFile().toPath(), is(tmpDir)); + } + + /** + * WebAppContext.BASETEMPDIR as File to a non existent directory. + */ + @ParameterizedTest + @ValueSource(strings = {"File", "String", "Path"}) + public void baseTempDirAttributeWithNonExistentDirectory(String type) throws Exception + { + WebAppContext webAppContext = new WebAppContext(); + Path tmpDir = Files.createTempDirectory("jetty_test").resolve("foo_test_tmp"); + Files.deleteIfExists(tmpDir); + assertFalse(Files.exists(tmpDir)); + switch (type) + { + case "File": + webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toFile()); + break; + case "String": + webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toString()); + break; + case "Path": + webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir); + break; + default: + throw new IllegalStateException(); + } + + // The base temp directory must exist for it to be used, if it does not exist or is not writable it will throw ISE. + WebInfConfiguration webInfConfiguration = new WebInfConfiguration(); + assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext)); + assertFalse(Files.exists(tmpDir)); + } + + /** + * ${jetty.base} exists but has no work subdirectory called work + * so webappContent#tempDirectory is created under java.io.tmpdir + */ + @Test + public void jettyBaseWorkDoesNotExist() throws Exception + { + Path workDir = jettyBase.toPath().resolve("work"); + FS.ensureDirExists(jettyBase); + FS.ensureDeleted(workDir); + WebInfConfiguration webInfConfiguration = new WebInfConfiguration(); + WebAppContext webAppContext = new WebAppContext(); + System.setProperty("jetty.base", jettyBase.getAbsolutePath()); + webInfConfiguration.resolveTempDirectory(webAppContext); + assertThat(webAppContext.getTempDirectory().getParent(), is(System.getProperty("java.io.tmpdir"))); + } + + /** + * ${jetty.base} directory exists and has a subdirectory called work + * so webappContent#tempDirectory is created under java.io.tmpdir + */ + @Test + public void jettyBaseWorkExists() throws Exception + { + Path workDir = jettyBase.toPath().resolve("work"); + FS.ensureDirExists(jettyBase); + FS.ensureDirExists(workDir); + WebInfConfiguration webInfConfiguration = new WebInfConfiguration(); + WebAppContext webAppContext = new WebAppContext(); + System.setProperty("jetty.base", jettyBase.getAbsolutePath()); + webInfConfiguration.resolveTempDirectory(webAppContext); + assertThat(webAppContext.getTempDirectory().getParent(), is(workDir.toString())); + } + + /** + * ServletContext.TEMPDIR has invalid String directory value (wrong permission to write into it) + * IllegalStateException + */ + @Disabled("Jenkins will run as root so we do have permission to write to this directory.") + @Test + public void attributeWithInvalidPermissions() + { + WebInfConfiguration webInfConfiguration = new WebInfConfiguration(); + WebAppContext webAppContext = new WebAppContext(); + webAppContext.setAttribute(ServletContext.TEMPDIR, "/var/foo_jetty"); + assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext)); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void testDefaultTempDirectory(boolean persistTempDir) throws Exception + { + setupServer(); + webapp.setPersistTempDirectory(persistTempDir); + + // Temp Directory Initially isn't set until started. + File tempDirectory = webapp.getTempDirectory(); + assertNull(tempDirectory); + + // Once server is started the WebApp temp directory exists and is valid directory. + server.start(); + tempDirectory = webapp.getTempDirectory(); + assertNotNull(tempDirectory); + assertTrue(tempDirectory.exists()); + assertTrue(tempDirectory.isDirectory()); + + // Once server is stopped the WebApp temp should be deleted if persistTempDir is false. + server.stop(); + tempDirectory = webapp.getTempDirectory(); + assertThat(tempDirectory != null && tempDirectory.exists(), is(persistTempDir)); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void testPreDefinedTempDirectory(boolean persistTempDir) throws Exception + { + setupServer(); + webapp.setPersistTempDirectory(persistTempDir); + + // The temp directory is defined but has not been created. + File webappTempDir = MavenTestingUtils.getTargetTestingPath("webappTempDir").toFile(); + IO.delete(webappTempDir); + webapp.setTempDirectory(webappTempDir); + assertThat(webapp.getTempDirectory(), is(webappTempDir)); + assertFalse(webappTempDir.exists()); + + // Once server is started the WebApp temp directory exists and is valid directory. + server.start(); + File tempDirectory = webapp.getTempDirectory(); + assertNotNull(tempDirectory); + assertTrue(tempDirectory.exists()); + assertTrue(tempDirectory.isDirectory()); + + // Once server is stopped the WebApp temp should be deleted if persistTempDir is false. + server.stop(); + tempDirectory = webapp.getTempDirectory(); + assertThat(tempDirectory != null && tempDirectory.exists(), is(persistTempDir)); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void testPreExistingTempDirectory(boolean persistTempDir) throws Exception + { + setupServer(); + webapp.setPersistTempDirectory(persistTempDir); + + // The temp directory is defined and has already been created. + File webappTempDir = MavenTestingUtils.getTargetTestingPath("webappTempDir").toFile(); + IO.delete(webappTempDir); + if (!webappTempDir.exists()) + assertTrue(webappTempDir.mkdir()); + webapp.setTempDirectory(webappTempDir); + assertThat(webapp.getTempDirectory(), is(webappTempDir)); + assertTrue(webappTempDir.exists()); + + // Once server is started the WebApp temp directory exists and is valid directory. + server.start(); + File tempDirectory = webapp.getTempDirectory(); + assertNotNull(tempDirectory); + assertTrue(tempDirectory.exists()); + assertTrue(tempDirectory.isDirectory()); + + // Once server is stopped the WebApp temp should be deleted if persistTempDir is false. + server.stop(); + tempDirectory = webapp.getTempDirectory(); + assertThat(tempDirectory != null && tempDirectory.exists(), is(persistTempDir)); + } +}