package net.jsunit;
import net.jsunit.configuration.Configuration;
import net.jsunit.model.DistributedTestRunResult;
import net.jsunit.model.DistributedTestRunResultBuilder;
import net.jsunit.model.TestRunResult;
import net.jsunit.model.TestRunResultBuilder;
import org.jdom.Document;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
public class DistributedTestRunManager {
private Logger logger = Logger.getLogger("net.jsunit");
private RemoteServerHitter hitter;
private String overrideURL;
private Configuration localConfiguration;
private List<RemoteRunSpecification> remoteRunSpecs;
private DistributedTestRunResult distributedTestRunResult = new DistributedTestRunResult();
private DistributedTestRunListener listener;
public DistributedTestRunManager(
RemoteServerHitter hitter, Configuration localConfiguration, String overrideURL, List<RemoteRunSpecification> specs) {
this.localConfiguration = localConfiguration;
this.hitter = hitter;
this.overrideURL = overrideURL;
this.remoteRunSpecs = specs;
}
public void runTests() {
Date startDate = new Date();
List<Thread> threads = new ArrayList<Thread>();
for (final RemoteRunSpecification spec : remoteRunSpecs)
threads.add(new Thread("Running JsUnit tests on " + spec.getRemoteMachineBaseURL()) {
public void run() {
runTestsOnRemoteMachine(spec);
}
});
for (Thread thread : threads)
thread.start();
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
throw new RuntimeException("One of the test threads was interrupted.");
}
}
if (listener != null)
listener.notifyRunComplete(distributedTestRunResult, startDate, new Date().getTime() - startDate.getTime());
}
private void runTestsOnRemoteMachine(RemoteRunSpecification spec) {
List<TestRunResult> results = new ArrayList<TestRunResult>();
URL baseURL = spec.getRemoteMachineBaseURL();
String baseURLString = baseURL.toString();
try {
URL fullURL = spec.buildFullURL(localConfiguration, overrideURL);
logger.info("Requesting run on remote machine " + spec.getDisplayString());
Document responseDocument = hitter.hitURL(fullURL);
logger.info("Received response from remote machine URL " + baseURLString);
if (responseDocument == null)
throw new IOException("null response received from remote machine URL " + baseURLString);
addResultsTo(responseDocument, results);
} catch (IOException e) {
if (localConfiguration.shouldIgnoreUnresponsiveRemoteMachines())
logger.info("Ignoring unresponsive machine URL: " + baseURLString);
else {
logger.info("Remote machine URL is unresponsive: " + baseURLString);
addUnresponsiveResultTo(baseURL, results);
}
}
for (TestRunResult result : results) {
if (result.getUrl() == null) {
result.setUrl(baseURL.toString());
}
//noinspection SynchronizeOnNonFinalField
synchronized (distributedTestRunResult) {
distributedTestRunResult.addTestRunResult(result);
}
}
}
private void addUnresponsiveResultTo(URL baseURL, List<TestRunResult> results) {
TestRunResult unresponsiveResult = new TestRunResult(baseURL);
unresponsiveResult.setUnresponsive();
results.add(unresponsiveResult);
}
private void addResultsTo(Document responseDocument, List<TestRunResult> results) {
if (isMultipleTestRunResultsResult(responseDocument)) {
DistributedTestRunResult multiple = new DistributedTestRunResultBuilder().build(responseDocument);
results.addAll(multiple._getTestRunResults());
} else {
TestRunResult single = new TestRunResultBuilder().build(responseDocument);
results.add(single);
}
}
private boolean isMultipleTestRunResultsResult(Document document) {
return document.getRootElement().getName().equals(DistributedTestRunResult.NAME);
}
public DistributedTestRunResult getDistributedTestRunResult() {
return distributedTestRunResult;
}
public String getOverrideURL() {
return overrideURL;
}
public void setOverrideURL(String overrideURL) {
this.overrideURL = overrideURL;
}
public List<RemoteRunSpecification> getRemoteRunSpecs() {
return remoteRunSpecs;
}
public void setListener(DistributedTestRunListener listener) {
this.listener = listener;
}
}