提交 82493ab8 编写于 作者: K kohsuke

added more abstraction, especially to allow Hudson to be started from an existing data set.

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@11459 71c3de6d-444a-0410-be80-ed276b4c234a
上级 48014634
......@@ -2,7 +2,7 @@
<parent>
<artifactId>pom</artifactId>
<groupId>org.jvnet.hudson.main</groupId>
<version>1.246-SNAPSHOT</version>
<version>1.248-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.jvnet.hudson.main</groupId>
......
package org.jvnet.hudson.test;
import hudson.FilePath;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* Controls how a {@link HudsonTestCase} initializes <tt>HUDSON_HOME</tt>.
*
* @author Kohsuke Kawaguchi
*/
public interface HudsonHomeLoader {
/**
* Returns a directory to be used as <tt>HUDSON_HOME</tt>
*
* @throws Exception
* to cause a test to fail.
*/
File allocate() throws Exception;
/**
* Allocates a new empty directory, meaning this will emulate the fresh Hudson installation.
*/
public static final HudsonHomeLoader NEW = new HudsonHomeLoader() {
public File allocate() throws IOException {
return TestEnvironment.get().temporaryDirectoryAllocator.allocate();
}
};
/**
* Allocates a new directory by copying from an existing directory, or unzipping from a zip file.
*/
public static class CopyExisting implements HudsonHomeLoader {
private final File source;
/**
* Either a zip file or a directory that contains the home image.
*/
public CopyExisting(File source) {
if(source==null) throw new IllegalArgumentException();
this.source = source;
}
/**
* Extracts from a zip file in the resource.
*
* <p>
* This is useful in case you want to have a test data in the resources.
* Only file URL is supported.
*/
public CopyExisting(URL source) {
if(!source.getProtocol().equals("file"))
throw new UnsupportedOperationException("Unsupported protocol: "+source);
this.source = new File(source.getPath());
}
public File allocate() throws Exception {
File target = NEW.allocate();
if(source.isDirectory())
new FilePath(source).copyRecursiveTo("**/*",new FilePath(target));
else
if(source.getName().endsWith(".zip"))
new FilePath(source).unzip(new FilePath(target));
return target;
}
}
}
package org.jvnet.hudson.main;
package org.jvnet.hudson.test;
import hudson.FilePath;
import hudson.model.Hudson;
import junit.framework.TestCase;
import org.jvnet.hudson.test.HudsonHomeLoader.CopyExisting;
import org.kohsuke.stapler.Stapler;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.Context;
......@@ -12,34 +12,33 @@ import javax.servlet.ServletContext;
import java.io.File;
/**
* Base class for all Hudson test cases.
*
* @author Kohsuke Kawaguchi
*/
public abstract class HudsonTestCase extends TestCase {
protected Hudson hudson;
protected final TestEnvironment env = new TestEnvironment();
protected HudsonHomeLoader homeLoader;
protected HudsonTestCase(String name) {
super(name);
}
protected void setUp() throws Exception {
env.pin();
recipe();
hudson = newHudson();
}
protected void tearDown() throws Exception {
hudson.cleanUp();
new FilePath(hudson.root).deleteRecursive();
env.dispose();
}
protected Hudson newHudson() throws Exception {
return new Hudson(allocateHome(), createWebServer());
}
protected File allocateHome() throws Exception {
File home = new File("data");
if(home.exists())
new FilePath(home).deleteRecursive();
home.mkdirs();
return home;
return new Hudson(homeLoader.allocate(), createWebServer());
}
/**
......@@ -55,4 +54,28 @@ public abstract class HudsonTestCase extends TestCase {
return holder.getServletHandler().getServletContext();
}
//
// recipe methods. Control the test environments.
//
/**
* Called during the {@link #setUp()} to give a test case an opportunity to
* control the test environment in which Hudson is run.
*
* <p>
* From here, call a series of {@code withXXX} methods.
*/
protected void recipe() {
withNewHome();
}
protected HudsonTestCase withNewHome() {
homeLoader = HudsonHomeLoader.NEW;
return this;
}
protected HudsonTestCase withExistingHome(File source) {
homeLoader = new CopyExisting(source);
return this;
}
}
package org.jvnet.hudson.test;
import hudson.FilePath;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
/**
* Allocates temporary directories and cleans it up at the end.
* @author Kohsuke Kawaguchi
*/
public class TemporaryDirectoryAllocator {
/**
* Remember allocated directories to delete them later.
*/
private final Set<File> tmpDirectories = new HashSet<File>();
/**
* Directory in which we allocate temporary directories.
*/
private final File base;
public TemporaryDirectoryAllocator(File base) {
this.base = base;
}
public TemporaryDirectoryAllocator() {
this(new File(System.getProperty("java.io.tmpdir")));
}
/**
* Allocates a new empty temporary directory and returns it.
*
* This directory will be wiped out when {@link TemporaryDirectoryAllocator} gets disposed.
* When this method returns, the directory already exists.
*/
public synchronized File allocate() throws IOException {
File f = File.createTempFile("hudson", "test", base);
f.delete();
f.mkdirs();
tmpDirectories.add(f);
return f;
}
/**
* Deletes all allocated temporary directories.
*/
public synchronized void dispose() throws IOException, InterruptedException {
for (File dir : tmpDirectories)
new FilePath(dir).deleteRecursive();
tmpDirectories.clear();
}
/**
* Deletes all allocated temporary directories asynchronously.
*/
public synchronized void disposeAsync() {
final Set<File> tbr = new HashSet<File>(tmpDirectories);
tmpDirectories.clear();
new Thread("Disposing "+base) {
public void run() {
try {
for (File dir : tbr)
new FilePath(dir).deleteRecursive();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}
package org.jvnet.hudson.test;
/**
* @author Kohsuke Kawaguchi
*/
public class TestEnvironment {
public final TemporaryDirectoryAllocator temporaryDirectoryAllocator = new TemporaryDirectoryAllocator();
public void pin() {
ENVIRONMENT.set(this);
}
public void dispose() {
ENVIRONMENT.set(null);
temporaryDirectoryAllocator.disposeAsync();
}
public static final ThreadLocal<TestEnvironment> ENVIRONMENT = new InheritableThreadLocal<TestEnvironment>();
public static TestEnvironment get() {
return ENVIRONMENT.get();
}
}
package hudson.tasks;
import org.jvnet.hudson.main.HudsonTestCase;
import org.jvnet.hudson.test.Bug;
import org.jvnet.hudson.test.FailureBuilder;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.mock_javamail.Mailbox;
import javax.mail.internet.InternetAddress;
......
......@@ -4,6 +4,7 @@ import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.tasks.Shell;
import org.apache.commons.io.FileUtils;
import org.jvnet.hudson.test.HudsonTestCase;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册