Improve queue restart tests (#6453)

This commit is contained in:
Basil Crow authored and GitHub committed 2022-04-10 10:36:58 -07:00
1 parent 76f4ae7905
commit cb64da57f4
3 files changed
+119 -44

No files matched your search

@@ -0,0 +1,72 @@
package hudson.model;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import hudson.ExtensionList;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.RestartableJenkinsRule;
public class QueueCrashTest {
@Rule public RestartableJenkinsRule rr = new RestartableJenkinsRule();
@Test
public void persistQueueOnCrash() {
rr.thenWithHardShutdown(j -> {
// Speed up the test run by shortening the periodic save interval from 60 seconds to 5
// seconds.
Queue.Saver.DELAY_SECONDS = 5;
scheduleSomeBuild(j);
assertBuildIsScheduled(j);
// Wait for the periodic save to complete.
ExtensionList.lookupSingleton(Queue.Saver.class)
.getNextSave()
.get(30, TimeUnit.SECONDS);
// Ensure the periodic save process saved the queue, since the cleanup process will not
// run on a crash.
assertTrue(new File(j.jenkins.getRootDir(), "queue.xml").exists());
});
rr.then(QueueCrashTest::assertBuildIsScheduled);
}
@Test
public void doNotPersistQueueOnCrashBeforeSave() {
rr.thenWithHardShutdown(j -> {
// Avoid periodic save in order to simulate the scenario of a crash before initial save.
Queue.Saver.DELAY_SECONDS = (int) TimeUnit.DAYS.toSeconds(1);
scheduleSomeBuild(j);
assertBuildIsScheduled(j);
// Ensure the queue has not been saved in order to test that a crash in this scenario
// results in the queue being lost.
assertFalse(new File(j.jenkins.getRootDir(), "queue.xml").exists());
});
rr.then(QueueCrashTest::assertBuildIsNotScheduled);
}
private static void assertBuildIsScheduled(JenkinsRule j) {
j.jenkins.getQueue().maintain();
assertFalse(j.jenkins.getQueue().isEmpty());
}
private static void assertBuildIsNotScheduled(JenkinsRule j) {
j.jenkins.getQueue().maintain();
assertTrue(j.jenkins.getQueue().isEmpty());
}
private static void scheduleSomeBuild(JenkinsRule j) throws IOException {
FreeStyleProject p = j.createFreeStyleProject();
p.setAssignedLabel(Label.get("waitforit"));
p.scheduleBuild2(0);
}
}
@@ -24,66 +24,65 @@
package hudson.model;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import hudson.ExtensionList;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runners.model.Statement;
import org.jvnet.hudson.test.RestartableJenkinsRule;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.RealJenkinsRule;
import org.jvnet.hudson.test.recipes.LocalData;
public class QueueRestartTest {
@Rule
public RestartableJenkinsRule j = new RestartableJenkinsRule();
@Rule public RealJenkinsRule rr = new RealJenkinsRule();
@LocalData("quietDown")
@Test
public void persistQueueOnRestart() {
j.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
Queue.Saver.DELAY_SECONDS = 24 * 60 * 60; // Avoid period save as we are after the explicit one
scheduleSomeBuild();
assertBuildIsScheduled();
}
});
j.addStep(new Statement() {
@Override public void evaluate() {
assertBuildIsScheduled();
}
});
public void persistQueueOnRestart() throws Throwable {
// Avoid periodic save in order to test that the cleanup process saves the queue.
rr.javaOptions("-Dhudson.model.Queue.Saver.DELAY_SECONDS=" + TimeUnit.DAYS.toSeconds(1));
rr.then(QueueRestartTest::queueBuild);
rr.then(QueueRestartTest::assertBuildFinishes);
}
@LocalData("quietDown")
@Test
public void persistQueueOnCrash() {
j.addStepWithDirtyShutdown(new Statement() {
@Override public void evaluate() throws Throwable {
Queue.Saver.DELAY_SECONDS = 0; // Call Queue#save() on every queue modification simulating time has passed before crash
scheduleSomeBuild();
assertBuildIsScheduled();
public void persistQueueOnConsecutiveRestarts() throws Throwable {
// Avoid periodic save in order to test that the cleanup process saves the queue.
rr.javaOptions("-Dhudson.model.Queue.Saver.DELAY_SECONDS=" + TimeUnit.DAYS.toSeconds(1));
// Save have no delay though is not synchronous
ExtensionList.lookup(Queue.Saver.class).get(0).getNextSave().get(3, TimeUnit.SECONDS);
assertTrue("queue.xml does not exist", j.j.jenkins.getQueue().getXMLQueueFile().exists());
}
});
j.addStep(new Statement() {
@Override public void evaluate() {
assertBuildIsScheduled();
}
});
rr.then(QueueRestartTest::queueBuild);
rr.then(QueueRestartTest::assertBuildIsScheduled);
rr.then(QueueRestartTest::assertBuildFinishes);
}
private void assertBuildIsScheduled() {
assertEquals(1, j.j.jenkins.getQueue().getItems().length);
}
private void scheduleSomeBuild() throws IOException {
FreeStyleProject p = j.j.createFreeStyleProject();
p.setAssignedLabel(Label.get("waitforit"));
private static void queueBuild(JenkinsRule j) throws IOException {
FreeStyleProject p = j.createFreeStyleProject("p");
p.scheduleBuild2(0);
assertBuildIsScheduled(j);
// Ensure the queue has not been saved in order to test that the cleanup process saves
// the queue.
assertFalse(new File(j.jenkins.getRootDir(), "queue.xml").exists());
}
private static void assertBuildFinishes(JenkinsRule j) throws Exception {
assertBuildIsScheduled(j);
j.jenkins.doCancelQuietDown();
FreeStyleProject p = j.jenkins.getItemByFullName("p", FreeStyleProject.class);
FreeStyleBuild b;
while ((b = p.getLastBuild()) == null) {
Thread.sleep(100);
}
j.assertBuildStatusSuccess(j.waitForCompletion(b));
}
private static void assertBuildIsScheduled(JenkinsRule j) {
j.jenkins.getQueue().maintain();
assertFalse(j.jenkins.getQueue().isEmpty());
}
}
@@ -0,0 +1,4 @@
import jenkins.model.Jenkins
// Start in a state that doesn't do any builds.
Jenkins.get().doQuietDown()