@BeforeClass
  public static void setup() throws Exception {
    registry = Registry.getNewInstanceForTestOnly();
    hub = Hub.getNewInstanceForTest(PortProber.findFreePort(), registry);

    status = new URL("http://" + hub.getHost() + ":" + hub.getPort() + "/grid/status");
    host = new HttpHost(hub.getHost(), hub.getPort());

    hub.start();

    p1 = RemoteProxyFactory.getNewBasicRemoteProxy("app1", "http://machine1:4444/");
    p2 = RemoteProxyFactory.getNewBasicRemoteProxy("app1", "http://machine2:4444/");
    p3 = RemoteProxyFactory.getNewBasicRemoteProxy("app1", "http://machine3:4444/");
    p4 = RemoteProxyFactory.getNewBasicRemoteProxy("app1", "http://machine4:4444/");

    RegistrationRequest req = new RegistrationRequest();
    Map<String, Object> capability = new HashMap<String, Object>();
    capability.put("applicationName", "custom app");
    req.addDesiredCapabilitiy(capability);

    Map<String, Object> config = new HashMap<String, Object>();
    config.put("url", "http://machine5:4444/");
    req.setConfiguration(config);
    customProxy = new MyCustomProxy(req);

    registry.add(p1);
    registry.add(p2);
    registry.add(p3);
    registry.add(p4);
    registry.add(customProxy);
  }
/** how to setup a grid that does not use FIFO for the requests. */
public class WebDriverPriorityDemo {

  private Hub hub =
      Hub.getNewInstanceForTest(PortProber.findFreePort(), Registry.getNewInstanceForTestOnly());
  private URL hubURL = hub.getUrl();

  // start a small grid that only has 1 testing slot : firefox
  @BeforeClass(alwaysRun = true)
  public void prepare() throws Exception {

    hub.start();
    hubURL = new URL("http://" + hub.getHost() + ":" + hub.getPort());

    SelfRegisteringRemote remote =
        SelfRegisteringRemote.create(
            SeleniumProtocol.WebDriver, PortProber.findFreePort(), hub.getRegistrationURL());
    remote.addFirefoxSupport(null);
    remote.setMaxConcurrentSession(1);
    remote.setTimeout(-1, -1);
    remote.launchRemoteServer();
    remote.registerToHub();

    // assigning a priority rule where requests with the flag "important"
    // go first.
    hub.getRegistry()
        .setPrioritizer(
            new Prioritizer() {
              public int compareTo(Map<String, Object> a, Map<String, Object> b) {
                boolean aImportant =
                    a.get("important") == null
                        ? false
                        : Boolean.parseBoolean(a.get("important").toString());
                boolean bImportant =
                    b.get("important") == null
                        ? false
                        : Boolean.parseBoolean(b.get("important").toString());
                if (aImportant == bImportant) {
                  return 0;
                }
                if (aImportant && !bImportant) {
                  return -1;
                } else {
                  return 1;
                }
              }
            });
  }

  WebDriver runningOne;

  // mark the grid 100% busy = having 1 firefox test running.
  @Test
  public void test() throws MalformedURLException, InterruptedException {
    DesiredCapabilities ff = DesiredCapabilities.firefox();
    runningOne = new RemoteWebDriver(new URL(hubURL + "/grid/driver"), ff);
    runningOne.get(hubURL + "/grid/console");
    Assert.assertEquals(runningOne.getTitle(), "Grid overview");
  }

  // queuing 5 requests on the grid.
  @Test(dependsOnMethods = "test")
  public void sendMoreRequests() throws MalformedURLException {
    for (int i = 0; i < 5; i++) {
      new Thread(
              new Runnable() {
                public void run() {
                  DesiredCapabilities ff = DesiredCapabilities.firefox();
                  try {
                    new RemoteWebDriver(new URL(hubURL + "/grid/driver"), ff);
                  } catch (MalformedURLException e) {
                    e.printStackTrace();
                  }
                }
              })
          .start();
    }
  }

  WebDriver importantOne;
  boolean importantOneStarted = false;

  // adding a request with high priority at the end of the queue
  @Test(dependsOnMethods = "sendMoreRequests", timeOut = 30000)
  public void sendTheImportantOne() throws MalformedURLException, InterruptedException {
    while (hub.getRegistry().getNewSessionRequests().size() != 5) {
      Thread.sleep(250);
    }
    Assert.assertEquals(hub.getRegistry().getNewSessionRequests().size(), 5);
    Assert.assertEquals(hub.getRegistry().getActiveSessions().size(), 1);

    final DesiredCapabilities ff = DesiredCapabilities.firefox();
    ff.setCapability("important", true);

    new Thread(
            new Runnable() {
              public void run() {
                try {
                  importantOne = new RemoteWebDriver(new URL(hubURL + "/grid/driver"), ff);
                  importantOneStarted = true;
                } catch (MalformedURLException e) {
                  throw new RuntimeException("bug", e);
                }
              }
            })
        .start();
  }

  // then 5 more non-important requests
  @Test(dependsOnMethods = "sendTheImportantOne")
  public void sendMoreRequests2() throws MalformedURLException {
    for (int i = 0; i < 5; i++) {
      new Thread(
              new Runnable() {
                public void run() {
                  DesiredCapabilities ff = DesiredCapabilities.firefox();
                  try {
                    new RemoteWebDriver(new URL(hubURL + "/grid/driver"), ff);
                  } catch (MalformedURLException e) {
                    e.printStackTrace();
                  }
                }
              })
          .start();
    }
  }

  @Test(dependsOnMethods = "sendMoreRequests2", timeOut = 20000)
  public void validateStateAndPickTheImportantOne() throws InterruptedException {
    try {
      while (hub.getRegistry().getNewSessionRequests().size() != 11) {
        Thread.sleep(500);
      }
      // queue = 5 + 1 important + 5.
      Assert.assertEquals(hub.getRegistry().getNewSessionRequests().size(), 11);

      // 1 firefox still running
      Assert.assertEquals(hub.getRegistry().getActiveSessions().size(), 1);

      // closing the running test.
      runningOne.quit();

      // validating new expected state
      while (!(hub.getRegistry().getActiveSessions().size() == 1
          && hub.getRegistry().getNewSessionRequests().size() == 10)) {
        Thread.sleep(250);
        Reporter.log("waiting for correct state.");
      }

      // TODO freynaud : sometines does not start. FF pops up, but address bar remains empty.
      while (!importantOneStarted) {
        Thread.sleep(250);
        Reporter.log("waiting for browser to start");
      }
      importantOne.get(hubURL + "/grid/console");
      Assert.assertEquals(importantOne.getTitle(), "Grid overview");
    } finally {
      // cleaning the queue to avoid having some browsers left over after
      // the test
      hub.getRegistry().getNewSessionRequests().clear();
      importantOne.quit();
    }
  }

  @AfterClass(alwaysRun = true)
  public void stop() throws Exception {
    hub.stop();
  }
}