Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 71 additions & 79 deletions src/test/java/hudson/plugins/ws_cleanup/CleanupTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.FilePath;
Expand Down Expand Up @@ -69,28 +69,34 @@
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestBuilder;
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;

public class CleanupTest {
@WithJenkins
class CleanupTest {

@Rule
public JenkinsRule j = new JenkinsRule();
private JenkinsRule j;

@Rule
public TemporaryFolder ws = new EnhancedTemporaryFolder();
@TempDir
private File ws;

@BeforeEach
void setUp(JenkinsRule rule) {
j = rule;
}

// "IllegalArgumentException: Illegal group reference" observed when filename contained '$';
@Test
public void doNotTreatFilenameAsRegexReplaceWhenUsingCustomCommand() throws Exception {
void doNotTreatFilenameAsRegexReplaceWhenUsingCustomCommand() throws Exception {
String filename = "\\s! Dozen for $5 only!";

FreeStyleProject p = j.jenkins.createProject(FreeStyleProject.class, "sut");
populateWorkspace(p, filename);
populateWorkspace(j, p, filename);

p.getBuildWrappersList()
.add(new PreBuildCleanup(
Expand All @@ -104,9 +110,9 @@ public void doNotTreatFilenameAsRegexReplaceWhenUsingCustomCommand() throws Exce

@Test
@Issue("JENKINS-20056")
public void wipeOutWholeWorkspaceBeforeBuild() throws Exception {
void wipeOutWholeWorkspaceBeforeBuild() throws Exception {
FreeStyleProject p = j.jenkins.createProject(FreeStyleProject.class, "sut");
populateWorkspace(p, "content.txt");
populateWorkspace(j, p, "content.txt");

p.getBuildWrappersList().add(new PreBuildCleanup(Collections.emptyList(), false, null, null, false));
FreeStyleBuild b = j.buildAndAssertSuccess(p);
Expand All @@ -115,7 +121,7 @@ public void wipeOutWholeWorkspaceBeforeBuild() throws Exception {

@Test
@Issue("JENKINS-20056")
public void wipeOutWholeWorkspaceAfterBuild() throws Exception {
void wipeOutWholeWorkspaceAfterBuild() throws Exception {
FreeStyleProject p = j.jenkins.createProject(FreeStyleProject.class, "sut");
p.getBuildersList().add(getTouchBuilder("content.txt"));

Expand All @@ -126,7 +132,7 @@ public void wipeOutWholeWorkspaceAfterBuild() throws Exception {

@Test
@Issue("JENKINS-20056")
public void wipeOutWholeWorkspaceAfterBuildMatrix() throws Exception {
void wipeOutWholeWorkspaceAfterBuildMatrix() throws Exception {
MatrixProject p = j.jenkins.createProject(MatrixProject.class, "sut");
p.setAxes(new AxisList(new TextAxis("name", "a b")));
p.getBuildWrappersList().add(new MatrixWsPopulator());
Expand All @@ -141,7 +147,7 @@ public void wipeOutWholeWorkspaceAfterBuildMatrix() throws Exception {

@Test
@Issue("JENKINS-20056")
public void workspaceShouldNotBeManipulated() throws Exception {
void workspaceShouldNotBeManipulated() throws Exception {
int ITERATIONS = 50;

FreeStyleProject p = j.jenkins.createProject(FreeStyleProject.class, "sut");
Expand Down Expand Up @@ -176,7 +182,7 @@ public void workspaceShouldNotBeManipulated() throws Exception {
}

@Test
public void deleteWorkspaceWithNonAsciiCharacters() throws Exception {
void deleteWorkspaceWithNonAsciiCharacters() throws Exception {
FreeStyleProject p = j.jenkins.createProject(FreeStyleProject.class, "sut");
p.getBuildersList().add(getTouchBuilder("a¶‱ﻷ.txt"));

Expand All @@ -189,19 +195,19 @@ public void deleteWorkspaceWithNonAsciiCharacters() throws Exception {

@Test
@Issue("JENKINS-26250")
public void doNotFailToWipeoutWhenRenameFails() throws Exception {
void doNotFailToWipeoutWhenRenameFails() throws Exception {
assumeTrue(!Functions.isWindows()); // In MSFT we can't disable renaming a folder without enable to delete it

FreeStyleProject p = j.jenkins.createProject(FreeStyleProject.class, "sut");
populateWorkspace(p, "content.txt");
populateWorkspace(j, p, "content.txt");
p.getPublishersList().add(wipeoutPublisher());

FilePath workspace = p.getLastBuild().getWorkspace();
workspace.getParent().chmod(0555); // Remove write for parent dir so rename will fail

try {
workspace.renameTo(workspace.withSuffix("2"));
assumeTrue("Rename operation should fail", workspace.exists());
assumeTrue(workspace.exists(), "Rename operation should fail");
} catch (java.nio.file.AccessDeniedException ade) {
// expected on Java 9 +
}
Expand All @@ -211,7 +217,7 @@ public void doNotFailToWipeoutWhenRenameFails() throws Exception {
}

@Test
public void reportCleanupCommandFailure() throws Exception {
void reportCleanupCommandFailure() throws Exception {
String command = Functions.isWindows() ? "cmd /c md %s" : "mkdir %s";

FreeStyleProject p = j.jenkins.createProject(FreeStyleProject.class, "sut");
Expand Down Expand Up @@ -246,12 +252,12 @@ public void reportCleanupCommandFailure() throws Exception {

@Test
@Issue("JENKINS-28454")
public void pipelineWorkspaceCleanup() throws Exception {
void pipelineWorkspaceCleanup() throws Exception {
WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"" + "node { \n"
"node { \n"
+ " ws ('"
+ ws.getRoot() + "') { \n" + " try { \n"
+ sanitizeFilePath(ws) + "') { \n" + " try { \n"
+ " writeFile file: 'foo.txt', text: 'foobar' \n"
+ " } finally { \n"
+ " step([$class: 'WsCleanup']) \n"
Expand All @@ -263,17 +269,17 @@ public void pipelineWorkspaceCleanup() throws Exception {
j.assertLogContains("[WS-CLEANUP] Deleting project workspace...", run);
j.assertLogContains("[WS-CLEANUP] done", run);

assertThat(ws.getRoot().listFiles(), nullValue());
assertThat(ws.listFiles(), nullValue());
}

@Test
@Issue("JENKINS-28454")
public void pipelineWorkspaceCleanupUsingPattern() throws Exception {
void pipelineWorkspaceCleanupUsingPattern() throws Exception {
WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"" + "node { \n"
"node { \n"
+ " ws ('"
+ ws.getRoot() + "') { \n" + " try { \n"
+ sanitizeFilePath(ws) + "') { \n" + " try { \n"
+ " writeFile file: 'foo.txt', text: 'first file' \n"
+ " writeFile file: 'bar.txt', text: 'second file' \n"
+ " } finally { \n"
Expand All @@ -291,12 +297,12 @@ public void pipelineWorkspaceCleanupUsingPattern() throws Exception {

@Test
@Issue("JENKINS-28454")
public void pipelineWorkspaceCleanupUnlessBuildFails() throws Exception {
void pipelineWorkspaceCleanupUnlessBuildFails() throws Exception {
WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"" + "node { \n"
"node { \n"
+ " ws ('"
+ ws.getRoot() + "'){ \n" + " try { \n"
+ sanitizeFilePath(ws) + "'){ \n" + " try { \n"
+ " writeFile file: 'foo.txt', text: 'foobar' \n"
+ " throw new Exception() \n"
+ " } catch (err) { \n"
Expand All @@ -317,12 +323,12 @@ public void pipelineWorkspaceCleanupUnlessBuildFails() throws Exception {

@Test
@Issue("JENKINS-37054")
public void symbolAnnotationWorkspaceCleanup() throws Exception {
void symbolAnnotationWorkspaceCleanup() throws Exception {
WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"" + "node { \n"
"node { \n"
+ " ws ('"
+ ws.getRoot() + "') { \n" + " try { \n"
+ sanitizeFilePath(ws) + "') { \n" + " try { \n"
+ " writeFile file: 'foo.txt', text: 'foobar' \n"
+ " } finally { \n"
+ " cleanWs() \n"
Expand All @@ -334,17 +340,17 @@ public void symbolAnnotationWorkspaceCleanup() throws Exception {
j.assertLogContains("[WS-CLEANUP] Deleting project workspace...", run);
j.assertLogContains("[WS-CLEANUP] done", run);

assertThat(ws.getRoot().listFiles(), nullValue());
assertThat(ws.listFiles(), nullValue());
}

@Test
@Issue("JENKINS-37054")
public void symbolWorkspaceCleanupAnnotationUsingPattern() throws Exception {
void symbolWorkspaceCleanupAnnotationUsingPattern() throws Exception {
WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"" + "node { \n"
"node { \n"
+ " ws ('"
+ ws.getRoot() + "') { \n" + " try { \n"
+ sanitizeFilePath(ws) + "') { \n" + " try { \n"
+ " writeFile file: 'foo.txt', text: 'first file' \n"
+ " writeFile file: 'bar.txt', text: 'second file' \n"
+ " } finally { \n"
Expand All @@ -362,12 +368,12 @@ public void symbolWorkspaceCleanupAnnotationUsingPattern() throws Exception {

@Test
@Issue("JENKINS-37054")
public void symbolAnnotationWorkspaceCleanupUnlessBuildFails() throws Exception {
void symbolAnnotationWorkspaceCleanupUnlessBuildFails() throws Exception {
WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"" + "node { \n"
"node { \n"
+ " ws ('"
+ ws.getRoot() + "'){ \n" + " try { \n"
+ sanitizeFilePath(ws) + "'){ \n" + " try { \n"
+ " writeFile file: 'foo.txt', text: 'foobar' \n"
+ " error 'error'\n"
+ " } catch (err) { \n"
Expand All @@ -387,11 +393,11 @@ public void symbolAnnotationWorkspaceCleanupUnlessBuildFails() throws Exception
}

@Test
public void doNotRunExternalCommandWhenNull() throws Exception {
void doNotRunExternalCommandWhenNull() throws Exception {
String command = null;

FreeStyleProject p = j.jenkins.createProject(FreeStyleProject.class, "sut");
populateWorkspace(p, "content.txt");
populateWorkspace(j, p, "content.txt");

p.getBuildWrappersList().add(new PreBuildCleanup(Collections.emptyList(), false, null, command, false));

Expand All @@ -401,11 +407,11 @@ public void doNotRunExternalCommandWhenNull() throws Exception {
}

@Test
public void doNotRunExternalCommandWhenWhitespace() throws Exception {
void doNotRunExternalCommandWhenWhitespace() throws Exception {
String command = " \n ";

FreeStyleProject p = j.jenkins.createProject(FreeStyleProject.class, "sut");
populateWorkspace(p, "content.txt");
populateWorkspace(j, p, "content.txt");

p.getBuildWrappersList().add(new PreBuildCleanup(Collections.emptyList(), false, null, command, false));

Expand All @@ -415,7 +421,7 @@ public void doNotRunExternalCommandWhenWhitespace() throws Exception {
}

@Test
public void retryAsyncDirDeletion() throws Exception {
void retryAsyncDirDeletion() throws Exception {
FreeStyleProject p = j.jenkins.createProject(FreeStyleProject.class, "sut");

p.getPublishersList().add(CleanupTest.wipeoutPublisher());
Expand All @@ -441,7 +447,6 @@ void performDelete(FilePath workspace) throws IOException {

Wipeout.INSTANCE = new Wipeout();

//noinspection deprecation
disposer.reschedule();

Thread.sleep(100);
Expand All @@ -450,7 +455,7 @@ void performDelete(FilePath workspace) throws IOException {
}

@Test
public void deferredWipeoutAfterBuild() throws Exception {
void deferredWipeoutAfterBuild() throws Exception {
// Deferred wipeout enabled
FreeStyleProject p = j.jenkins.createProject(FreeStyleProject.class, "sut1");
p.getBuildersList().add(getTouchBuilder("content.txt"));
Expand Down Expand Up @@ -514,7 +519,7 @@ public void deferredWipeoutAfterBuild() throws Exception {
}

private void verifyFileExists(String fileName) {
File[] files = ws.getRoot().listFiles();
File[] files = ws.listFiles();
assertThat(files, notNullValue());
assertThat(files, arrayWithSize(1));
assertThat(files[0].getName(), is(fileName));
Expand All @@ -528,7 +533,7 @@ public static WsCleanup wipeoutPublisher() {
return wsCleanup;
}

private TestBuilder getTouchBuilder(String filename) {
private static TestBuilder getTouchBuilder(String filename) {
return new TestBuilder() {
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
Expand All @@ -539,25 +544,31 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
};
}

private void populateWorkspace(FreeStyleProject p, String filename) throws Exception {
private static void populateWorkspace(JenkinsRule j, FreeStyleProject p, String filename) throws Exception {
p.getBuildersList().add(getTouchBuilder(filename));
FreeStyleBuild b = j.buildAndAssertSuccess(p);
p.getBuildersList().clear();
assertFalse("Workspace populated", b.getWorkspace().list().isEmpty());
assertFalse(b.getWorkspace().list().isEmpty(), "Workspace populated");
}

private void assertWorkspaceCleanedUp(AbstractBuild<?, ?> b) throws Exception {
private static void assertWorkspaceCleanedUp(AbstractBuild<?, ?> b) throws Exception {
FilePath workspace = b.getWorkspace();
if (workspace == null) {
return; // removed
}

List<FilePath> files = workspace.list();
if (files == null) {
return; // removed
}

assertTrue("Workspace contains: " + files, files.isEmpty());
assertTrue(files.isEmpty(), "Workspace contains: " + files);
}

/**
* Replaces {@code \} with {@code /} on Windows.
* @param file the file
* @return the sanitized path
*/
private static String sanitizeFilePath(File file) {
return Functions.isWindows() ? file.getAbsolutePath().replaceAll("\\\\", "/") : file.getAbsolutePath();
}

/**
Expand Down Expand Up @@ -591,23 +602,4 @@ public String getDisplayName() {
}
}
}

private static final class EnhancedTemporaryFolder extends TemporaryFolder {
@Override
public EnhancedFile getRoot() {
return new EnhancedFile(super.getRoot());
}

private static final class EnhancedFile extends File {
public EnhancedFile(File f) {
super(f.getPath());
}

@Override
public String toString() {
String org = super.getPath();
return Functions.isWindows() ? org.replaceAll("\\\\", "/") : org;
}
}
}
}
Loading
Loading