diff --git a/src/main/java/org/jvnet/hudson/test/JenkinsRule.java b/src/main/java/org/jvnet/hudson/test/JenkinsRule.java index 75f2f4138..04d889f6a 100644 --- a/src/main/java/org/jvnet/hudson/test/JenkinsRule.java +++ b/src/main/java/org/jvnet/hudson/test/JenkinsRule.java @@ -44,6 +44,7 @@ import hudson.EnvVars; import hudson.Extension; import hudson.ExtensionList; +import hudson.FilePath; import hudson.Functions; import hudson.Launcher; import hudson.Main; @@ -3281,6 +3282,41 @@ public Description getTestDescription() { return testDescription; } + /** + * Restart the current instance with the same port and a copy of its {@code JENKINS_HOME}. + */ + public void restart() throws Throwable { + // create backup of current instance in new home + URL source = jenkins.getRootDir().toURI().toURL(); + File copy = new TemporaryDirectoryAllocator().allocate(); + + if(source.getProtocol().equals("file")) { + File src = new File(source.toURI()); + if (src.isDirectory()) { + new FilePath(src).copyRecursiveTo("**/*",new FilePath(copy)); + } else if (src.getName().endsWith(".zip")) { + new FilePath(src).unzip(new FilePath(copy)); + } + } else { + File tmp = File.createTempFile("hudson","zip"); + try { + FileUtils.copyURLToFile(source,tmp); + new FilePath(tmp).unzip(new FilePath(copy)); + } finally { + FileUtils.deleteQuietly(tmp); + } + } + + // shutdown and cleanup current instance + after(); + + // init new instance with backup + withExistingHome(copy); + + // startup new instance + before(); + } + private NameValuePair getCrumbHeaderNVP() { return new NameValuePair(jenkins.getCrumbIssuer().getDescriptor().getCrumbRequestField(), jenkins.getCrumbIssuer().getCrumb((javax.servlet.ServletRequest) null)); diff --git a/src/test/java/org/jvnet/hudson/test/JenkinsRuleTest.java b/src/test/java/org/jvnet/hudson/test/JenkinsRuleTest.java index 64fa34ad6..01ffd6efc 100644 --- a/src/test/java/org/jvnet/hudson/test/JenkinsRuleTest.java +++ b/src/test/java/org/jvnet/hudson/test/JenkinsRuleTest.java @@ -2,6 +2,9 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -14,6 +17,7 @@ import hudson.model.FreeStyleProject; import hudson.model.RootAction; import hudson.model.User; +import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.file.Files; @@ -30,6 +34,7 @@ import org.htmlunit.util.WebConnectionWrapper; import org.junit.Rule; import org.junit.Test; +import org.junit.runner.Description; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.HttpResponse; @@ -424,6 +429,31 @@ public void waitForCompletion() throws Exception { j.assertBuildStatusSuccess(j.waitForCompletion(b)); } + @Test + public void restart() throws Throwable { + // preserve relevant properties + URL previousUrl = j.getURL(); + Description previousTestDescription = j.testDescription; + File previousRoot = j.jenkins.getRootDir(); + + // create some configuration + j.createFreeStyleProject(); + assertThat(j.jenkins.getJobNames(), hasSize(1)); + + // restart the instance with same port and new JENKINS_HOME + j.restart(); + + // validate properties and configuration were preserved + assertThat(j.getURL(), equalTo(previousUrl)); + assertThat(j.testDescription, equalTo(previousTestDescription)); + assertThat(j.jenkins.getRootDir(), not(previousRoot)); + assertThat(j.jenkins.getJobNames(), hasSize(1)); + + // validate restarted instance is working + j.createFreeStyleProject(); + assertThat(j.jenkins.getJobNames(), hasSize(2)); + } + @Test public void mimeType() throws IOException { JenkinsRule.WebClient wc = j.createWebClient(); @@ -441,4 +471,5 @@ public WebResponse getResponse(WebRequest request) throws IOException { wc.getPage(j.getURL()); assertEquals("text/javascript", contentType.get()); } + } diff --git a/src/test/java/org/jvnet/hudson/test/junit/jupiter/JUnit5JenkinsRuleTest.java b/src/test/java/org/jvnet/hudson/test/junit/jupiter/JUnit5JenkinsRuleTest.java new file mode 100644 index 000000000..f4760dba5 --- /dev/null +++ b/src/test/java/org/jvnet/hudson/test/junit/jupiter/JUnit5JenkinsRuleTest.java @@ -0,0 +1,45 @@ +package org.jvnet.hudson.test.junit.jupiter; + +import org.junit.jupiter.api.Test; +import org.jvnet.hudson.test.JenkinsRule; +import org.junit.runner.Description; +import java.io.File; +import java.net.URL; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; + +/** + * Test {@link JUnit5JenkinsRule}. + */ +@WithJenkins +class JUnit5JenkinsRuleTest { + + @Test + void restart(JenkinsRule rule) throws Throwable { + // preserve relevant properties + URL previousUrl = rule.getURL(); + Description previousTestDescription = rule.getTestDescription(); + File previousRoot = rule.jenkins.getRootDir(); + + // create some configuration + rule.createFreeStyleProject(); + assertThat(rule.jenkins.getJobNames(), hasSize(1)); + + // restart the instance with same port and new JENKINS_HOME + rule.restart(); + + // validate properties and configuration were preserved + assertThat(rule.getURL(), equalTo(previousUrl)); + assertThat(rule.getTestDescription(), equalTo(previousTestDescription)); + assertThat(rule.jenkins.getRootDir(), not(previousRoot)); + assertThat(rule.jenkins.getJobNames(), hasSize(1)); + + // validate restarted instance is working + rule.createFreeStyleProject(); + assertThat(rule.jenkins.getJobNames(), hasSize(2)); + } + +} diff --git a/src/test/java/org/jvnet/hudson/test/junit/jupiter/JenkinsRuleClassResolverTest.java b/src/test/java/org/jvnet/hudson/test/junit/jupiter/JenkinsRuleClassResolverTest.java new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/java/org/jvnet/hudson/test/junit/jupiter/JenkinsRuleResolverTest.java b/src/test/java/org/jvnet/hudson/test/junit/jupiter/JenkinsRuleResolverTest.java index bf9c8c900..d0618ca36 100644 --- a/src/test/java/org/jvnet/hudson/test/junit/jupiter/JenkinsRuleResolverTest.java +++ b/src/test/java/org/jvnet/hudson/test/junit/jupiter/JenkinsRuleResolverTest.java @@ -3,6 +3,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.collection.IsEmptyCollection.empty; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import java.io.IOException; import org.junit.jupiter.api.Test; @@ -17,4 +18,9 @@ void jenkinsRuleIsAccessible(JenkinsRule rule) throws IOException { rule.createFreeStyleProject("job-0"); assertThat(rule.jenkins.getJobNames(), hasSize(1)); } + + @Test + void instanceOf(JenkinsRule rule) { + assertInstanceOf(JUnit5JenkinsRule.class, rule); + } } diff --git a/src/test/java/org/jvnet/hudson/test/junit/jupiter/JenkinsRuleResolverWithMethodScopeTest.java b/src/test/java/org/jvnet/hudson/test/junit/jupiter/JenkinsRuleResolverWithMethodScopeTest.java index 3bb7b7335..37548b86b 100644 --- a/src/test/java/org/jvnet/hudson/test/junit/jupiter/JenkinsRuleResolverWithMethodScopeTest.java +++ b/src/test/java/org/jvnet/hudson/test/junit/jupiter/JenkinsRuleResolverWithMethodScopeTest.java @@ -3,6 +3,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.collection.IsEmptyCollection.empty; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import java.io.IOException; import org.junit.jupiter.api.Test; @@ -17,4 +18,10 @@ void jenkinsRuleIsAccessible(JenkinsRule rule) throws IOException { rule.createFreeStyleProject("job-0"); assertThat(rule.jenkins.getJobNames(), hasSize(1)); } + + @Test + @WithJenkins + void instanceOf(JenkinsRule rule) { + assertInstanceOf(JUnit5JenkinsRule.class, rule); + } }