private void runTestsOnRemoteMachine(URL baseURL) {
   List<TestRunResult> results = new ArrayList<TestRunResult>();
   try {
     URL fullURL = buildURL(baseURL);
     logger.info("Requesting run on remove machine URL " + baseURL);
     Document documentFromRemoteMachine = hitter.hitURL(fullURL);
     logger.info("Received response from remove machine URL " + baseURL);
     if (isMultipleTestRunResultsResult(documentFromRemoteMachine)) {
       DistributedTestRunResult multiple =
           new DistributedTestRunResultBuilder(configuration).build(documentFromRemoteMachine);
       results.addAll(multiple.getTestRunResults());
     } else {
       TestRunResult single =
           new TestRunResultBuilder(configuration).build(documentFromRemoteMachine);
       results.add(single);
     }
   } catch (IOException e) {
     if (configuration.shouldIgnoreUnresponsiveRemoteMachines())
       logger.info("Ignoring unresponsive machine " + baseURL.toString());
     else {
       logger.info("Remote machine URL is unresponsive: " + baseURL.toString());
       TestRunResult unresponsiveResult = new TestRunResult(baseURL);
       unresponsiveResult.setUnresponsive();
       results.add(unresponsiveResult);
     }
   }
   for (TestRunResult result : results) {
     result.setURL(baseURL);
     //noinspection SynchronizeOnNonFinalField
     synchronized (distributedTestRunResult) {
       distributedTestRunResult.addTestRunResult(result);
     }
   }
 }
 private URL buildURL(URL url) throws UnsupportedEncodingException, MalformedURLException {
   String fullURLString = url.toString();
   fullURLString += "/runner";
   boolean hasFirstParameter = false;
   if (overrideURL != null) {
     fullURLString += "?url=" + URLEncoder.encode(overrideURL, "UTF-8");
     hasFirstParameter = true;
   } else if (configuration.getTestURL() != null) {
     fullURLString += "?url=" + URLEncoder.encode(configuration.getTestURL().toString(), "UTF-8");
     hasFirstParameter = true;
   }
   if (remoteBrowser != null) {
     fullURLString += (hasFirstParameter ? "&" : "?");
     fullURLString += "browserId=" + remoteBrowser.getId();
   }
   return new URL(fullURLString);
 }
 public void runTests() {
   List<Thread> threads = new ArrayList<Thread>();
   for (final URL baseURL : configuration.getRemoteMachineURLs())
     threads.add(
         new Thread("Run JsUnit tests on " + baseURL) {
           public void run() {
             runTestsOnRemoteMachine(baseURL);
           }
         });
   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.");
     }
   }
 }