package net.jsunit;
import junit.extensions.ActiveTestSuite;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import net.jsunit.configuration.CompositeConfigurationSource;
import net.jsunit.configuration.ConfigurationSource;
import net.jsunit.configuration.ServerConfiguration;
import net.jsunit.model.Browser;
import net.jsunit.model.DistributedTestRunResult;
import net.jsunit.model.ResultType;
import net.jsunit.model.TestRunResult;
import net.jsunit.server.RemoteRunSpecificationBuilder;
import org.mortbay.util.MultiException;
import java.net.BindException;
import java.util.ArrayList;
import java.util.List;
public class DistributedTest extends TestCase {
protected DistributedTestRunManager manager;
private static WebServer temporaryServer;
private static Object blocker = new Object();
private static int serverCount = 0;
private ConfigurationSource source;
private Browser remoteBrowser;
private String overrideURL;
private WebServerFactory serverFactory;
public DistributedTest(ConfigurationSource source) {
this(source, new WebServerFactory() {
public WebServer create(ServerConfiguration configuration) {
return new JsUnitServer(configuration);
}
});
}
public DistributedTest(ConfigurationSource source, WebServerFactory serverFactory) {
super(source.remoteMachineURLs().replace('.', '_'));
this.source = source;
this.serverFactory = serverFactory;
}
private void ensureTemporaryServerIsCreated() {
//noinspection SynchronizeOnNonFinalField
synchronized (blocker) {
if (temporaryServer == null) {
temporaryServer = serverFactory.create(new ServerConfiguration(source));
}
}
}
public void setUp() throws Exception {
super.setUp();
RemoteMachineServerHitter serverHitter = new RemoteMachineServerHitter();
ServerConfiguration configuration = new ServerConfiguration(source);
List<RemoteRunSpecification> specs = new ArrayList<RemoteRunSpecification>();
RemoteRunSpecificationBuilder builder = new RemoteRunSpecificationBuilder();
if (remoteBrowser != null)
specs.add(builder.forSingleRemoteBrowser(configuration.getRemoteMachineURLs().get(0), remoteBrowser));
else
specs.addAll(builder.forAllBrowsersFromRemoteURLs(configuration.getRemoteMachineURLs()));
manager = new DistributedTestRunManager(serverHitter, configuration, overrideURL, specs);
manager.setListener(new DistributedTestRunListenerImpl(configuration));
ensureTemporaryServerIsCreated();
startServerIfNecessary();
}
private void startServerIfNecessary() throws Exception {
serverCount++;
//noinspection SynchronizeOnNonFinalField
synchronized (blocker) {
if (!temporaryServer.isAlive()) {
try {
temporaryServer.start();
} catch (MultiException e) {
if (!isMultiExceptionASingleBindException(e))
throw e;
//if a temporaryServer is already running, fine -
//we only need it to serve content to remote machines
}
}
}
}
private boolean isMultiExceptionASingleBindException(MultiException e) {
List exceptions = e.getExceptions();
return exceptions.size() == 1 && exceptions.get(0) instanceof BindException;
}
public void tearDown() throws Exception {
serverCount--;
if (serverCount == 0) {
if (temporaryServer != null && temporaryServer.isAlive()) {
temporaryServer.dispose();
temporaryServer = null;
}
}
super.tearDown();
}
public static Test suite(ConfigurationSource source) {
TestSuite suite = new ActiveTestSuite();
new DistributedTestSuiteBuilder(source).addTestsTo(suite);
return suite;
}
public static Test suite() {
return suite(CompositeConfigurationSource.resolve());
}
protected void runTest() throws Throwable {
manager.runTests();
DistributedTestRunResult result = manager.getDistributedTestRunResult();
if (!result.wasSuccessful()) {
StringBuffer buffer = new StringBuffer();
result.addErrorStringTo(buffer);
fail(result.displayString() + "\n" + buffer.toString() + "\n");
}
}
public DistributedTestRunManager getDistributedTestRunManager() {
return manager;
}
public WebServer getTemporaryServer() {
return temporaryServer;
}
public void limitToBrowser(Browser remoteBrowser) {
this.remoteBrowser = remoteBrowser;
setName(remoteBrowser.getDisplayName());
}
public DistributedTestRunResult getResult() {
return manager.getDistributedTestRunResult();
}
public ResultType getResultType() {
return getResult()._getResultType();
}
public List<TestRunResult> getTestRunResults() {
return getResult()._getTestRunResults();
}
public void setOverrideURL(String overrideURL) {
this.overrideURL = overrideURL;
}
}