Skip to content

Commit

Permalink
[JENKINS-20609] test case
Browse files Browse the repository at this point in the history
  • Loading branch information
kohsuke committed Nov 16, 2013
1 parent 0c5338d commit 3b0e6ac
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 8 deletions.
6 changes: 5 additions & 1 deletion core/src/main/java/hudson/WebAppMain.java
Expand Up @@ -72,7 +72,7 @@
*
* @author Kohsuke Kawaguchi
*/
public final class WebAppMain implements ServletContextListener {
public class WebAppMain implements ServletContextListener {
private final RingBufferLogHandler handler = new RingBufferLogHandler() {
@Override public synchronized void publish(LogRecord record) {
if (record.getLevel().intValue() >= Level.INFO.intValue()) {
Expand Down Expand Up @@ -251,6 +251,10 @@ public void run() {
}
}

public void joinInit() throws InterruptedException {
initThread.join();
}

/**
* To assist boot failure script, record the number of boot attempts.
* This file gets deleted in case of successful boot.
Expand Down
17 changes: 10 additions & 7 deletions test/src/main/java/org/jvnet/hudson/test/JenkinsRule.java
Expand Up @@ -229,9 +229,9 @@
@SuppressWarnings({"deprecation","rawtypes"})
public class JenkinsRule implements TestRule, MethodRule, RootAction {

private TestEnvironment env;
protected TestEnvironment env;

private Description testDescription;
protected Description testDescription;

/**
* Points to the same object as {@link #jenkins} does.
Expand Down Expand Up @@ -313,7 +313,7 @@ public Jenkins getInstance() {
* Override to set up your specific external resource.
* @throws Throwable if setup fails (which will disable {@code after}
*/
protected void before() throws Throwable {
public void before() throws Throwable {
env = new TestEnvironment(testDescription);
env.pin();
recipe();
Expand Down Expand Up @@ -394,10 +394,12 @@ public void run() {
/**
* Override to tear down your specific external resource.
*/
protected void after() throws Exception {
public void after() throws Exception {
try {
for (EndOfTestListener tl : jenkins.getExtensionList(EndOfTestListener.class))
tl.onTearDown();
if (jenkins!=null) {
for (EndOfTestListener tl : jenkins.getExtensionList(EndOfTestListener.class))
tl.onTearDown();
}

if (timeoutTimer!=null) {
timeoutTimer.cancel();
Expand Down Expand Up @@ -429,7 +431,8 @@ protected void after() throws Exception {
// ignore
}

jenkins.cleanUp();
if (jenkins!=null)
jenkins.cleanUp();
ExtensionList.clearLegacyInstances();
DescriptorExtensionList.clearLegacyInstances();

Expand Down
110 changes: 110 additions & 0 deletions test/src/test/groovy/hudson/util/BootFailureTest.groovy
@@ -0,0 +1,110 @@
package hudson.util

import hudson.WebAppMain
import hudson.model.Hudson
import hudson.model.listeners.ItemListener
import jenkins.model.Jenkins
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import org.jvnet.hudson.test.HudsonHomeLoader
import org.jvnet.hudson.test.JenkinsRule
import org.jvnet.hudson.test.TestEnvironment
import org.jvnet.hudson.test.TestExtension
import org.kohsuke.stapler.WebApp

import javax.servlet.ServletContextEvent

/**
*
*
* @author Kohsuke Kawaguchi
*/
class BootFailureTest extends Assert {
@Rule
public TemporaryFolder tmpDir = new TemporaryFolder();

static boolean makeBootFail = true;

@Rule
public JenkinsRule j = new JenkinsRule() {
@Override
void before() throws Throwable {
env = new TestEnvironment(testDescription);
env.pin();
// don't let Jenkins start automatically
}

@Override
public Hudson newHudson() throws Exception {
def ws = createWebServer()
def wa = new WebAppMain() {
@Override
WebAppMain.FileAndDescription getHomeDir(ServletContextEvent event) {
return new WebAppMain.FileAndDescription(homeLoader.allocate(),"test");
}
}
wa.contextInitialized(new ServletContextEvent(ws));
wa.joinInit();

def a = WebApp.get(ws).app;
if (a instanceof Jenkins)
return a;
return null; // didn't boot
}
}

public static class SeriousError extends Error {}

@TestExtension()
public static class InduceBootFailure extends ItemListener {
@Override
void onLoaded() {
if (makeBootFail)
throw new SeriousError();
}
}

@Test
void runBootFailureScript() {
final def home = tmpDir.newFolder()
j.with({ -> home} as HudsonHomeLoader)

// creates a script
new File(home,"boot-failure.groovy").text = "hudson.util.BootFailureTest.problem = exception";
def d = new File(home, "boot-failure.groovy.d")
d.mkdirs();
new File(d,"1.groovy").text = "hudson.util.BootFailureTest.runRecord << '1'";
new File(d,"2.groovy").text = "hudson.util.BootFailureTest.runRecord << '2'";

// first failed boot
makeBootFail = true;
assert j.newHudson()==null;
assert bootFailures(home)==1;

// second failed boot
problem = null;
runRecord = [];
assert j.newHudson()==null;
assert bootFailures(home)==2;
assert runRecord==["1","2"]

// make sure the script has actually run
assert problem.cause instanceof SeriousError

// if it boots well, the failure record should be gone
makeBootFail = false;
assert j.newHudson()!=null;
assert !BootFailure.getBootFailureFile(home).exists()
}

private static int bootFailures(File home) {
return BootFailure.getBootFailureFile(home).readLines().size()
}

// to be set by the script
public static Exception problem;
public static def runRecord = [];

}

0 comments on commit 3b0e6ac

Please sign in to comment.