/** Basic load balance testing. A random distribution is used amongst nodes for client now. */
  private void loadbalance(EJBDirectory directory, String deployment1, String deployment2)
      throws Exception {
    this.start(CONTAINER_1);
    this.deploy(CONTAINER_1, deployment1);
    this.start(CONTAINER_2);
    this.deploy(CONTAINER_2, deployment2);

    final ContextSelector<EJBClientContext> previousSelector =
        EJBClientContextSelector.setup(CLIENT_PROPERTIES);

    int numberOfServers = 2;
    int numberOfCalls = 40;
    // there will be at least 20% of calls processed by all servers
    double serversProccessedAtLeast = 0.2;

    try {
      StatelessRemoteHome home =
          directory.lookupHome(StatelessBean.class, StatelessRemoteHome.class);
      StatelessRemote bean = home.create();

      String node = bean.getNodeName();
      log.info("Node called : " + node);

      validateBalancing(bean, numberOfCalls, numberOfServers, serversProccessedAtLeast);

      Properties contextChangeProperties = new Properties();
      contextChangeProperties.put(REMOTE_PORT_PROPERTY_NAME, PORT_2.toString());
      contextChangeProperties.put(REMOTE_HOST_PROPERTY_NAME, HOST_2.toString());
      EJBClientContextSelector.setup(CLIENT_PROPERTIES, contextChangeProperties);

      bean = home.create();
      node = bean.getNodeName();
      log.info("Node called : " + node);

      validateBalancing(bean, numberOfCalls, numberOfServers, serversProccessedAtLeast);
    } finally {
      // reset the selector
      if (previousSelector != null) {
        EJBClientContext.setSelector(previousSelector);
      }
      // undeploy&shutdown the containers
      undeployAll();
      shutdownAll();
    }
  }
  private void doFailover(
      boolean isStop, EJBDirectory directory, String deployment1, String deployment2)
      throws Exception {
    this.start(CONTAINER_1);
    this.deploy(CONTAINER_1, deployment1);

    final ContextSelector<EJBClientContext> selector =
        EJBClientContextSelector.setup(CLIENT_PROPERTIES);

    try {
      StatelessRemoteHome home =
          directory.lookupHome(StatelessBean.class, StatelessRemoteHome.class);
      StatelessRemote bean = home.create();

      assertEquals(
          "The only " + NODES[0] + " is active. Bean had to be invoked on it but it wasn't.",
          NODES[0],
          bean.getNodeName());

      this.start(CONTAINER_2);
      this.deploy(CONTAINER_2, deployment2);

      if (isStop) {
        this.stop(CONTAINER_1);
      } else {
        this.undeploy(CONTAINER_1, deployment1);
      }

      assertEquals(
          "Only " + NODES[1] + " is active. The bean had to be invoked on it but it wasn't.",
          NODES[1],
          bean.getNodeName());
    } finally {
      // reset the selector
      if (selector != null) {
        EJBClientContext.setSelector(selector);
      }
      // need to have the container started to undeploy deployment afterwards
      this.start(CONTAINER_1);
      // shutdown the containers
      undeployAll();
      shutdownAll();
    }
  }
  /**
   * Method calls the bean function getNodeName() {numCalls} times and checks whether all servers
   * processed at least part of calls. The necessary number of processed calls by each server is
   * {minPercentage} of the number of all calls.
   */
  private static void validateBalancing(
      StatelessRemote bean, int numCalls, int expectedServers, double minPercentage) {
    Map<String, Integer> callCount = new HashMap<String, Integer>();
    int maxNumOfProcessedCalls = -1;
    int minNumOfProcessedCalls = Integer.MAX_VALUE;

    for (int i = 0; i < numCalls; i++) {
      String nodeName = bean.getNodeName();

      Integer count = callCount.get(nodeName);
      count = count == null ? 1 : ++count;
      callCount.put(nodeName, count);
    }
    Assert.assertEquals(
        "It was running "
            + expectedServers
            + " servers but not all of them were used for loadbalancing.",
        expectedServers,
        callCount.size());

    for (Integer count : callCount.values()) {
      maxNumOfProcessedCalls = count > maxNumOfProcessedCalls ? count : maxNumOfProcessedCalls;
      minNumOfProcessedCalls = count < minNumOfProcessedCalls ? count : minNumOfProcessedCalls;
    }
    Assert.assertTrue(
        "Minimal number of calls done to all servers have to be "
            + minPercentage * numCalls
            + " but was "
            + minNumOfProcessedCalls,
        minPercentage * numCalls <= minNumOfProcessedCalls);
    log.info(
        "All "
            + expectedServers
            + " servers processed at least "
            + minNumOfProcessedCalls
            + " of calls");
  }