/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.internal.cache;

import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_CLUSTER_CONFIGURATION;
import static org.apache.geode.distributed.ConfigurationProperties.GROUPS;
import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import org.apache.logging.log4j.Logger;
import org.assertj.core.api.Assertions;
import org.junit.Test;

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.distributed.Locator;
import org.apache.geode.distributed.internal.DistributionAdvisee;
import org.apache.geode.distributed.internal.InternalLocator;
import org.apache.geode.internal.AvailablePort.Keeper;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.test.dunit.NetworkUtils;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase;

/**
 * Tests the GridAdvisor
 *
 * @since GemFire 5.7
 */

public class GridAdvisorDUnitTest extends JUnit4DistributedTestCase {
  private final Logger logger = LogService.getLogger();
  private static InternalCache cache;


  /**
   * Tests 2 controllers and 2 cache servers
   */
  @Test
  public void test2by2() {
    disconnectAllFromDS();

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);
    VM vm3 = VM.getVM(3);

    List<Keeper> freeTCPPorts = AvailablePortHelper.getRandomAvailableTCPPortKeepers(6);
    final Keeper keeper1 = freeTCPPorts.get(0);
    final int port1 = keeper1.getPort();
    final Keeper keeper2 = freeTCPPorts.get(1);
    final int port2 = keeper2.getPort();
    final Keeper bsKeeper1 = freeTCPPorts.get(2);
    final int bsPort1 = bsKeeper1.getPort();
    final Keeper bsKeeper2 = freeTCPPorts.get(3);
    final int bsPort2 = bsKeeper2.getPort();
    final Keeper bsKeeper3 = freeTCPPorts.get(4);
    final int bsPort3 = bsKeeper3.getPort();
    final Keeper bsKeeper4 = freeTCPPorts.get(5);
    final int bsPort4 = bsKeeper4.getPort();

    final String host0 = NetworkUtils.getServerHostName();
    final String locators = host0 + "[" + port1 + "]" + "," + host0 + "[" + port2 + "]";

    final Properties dsProps = new Properties();
    dsProps.setProperty(LOCATORS, locators);
    dsProps.setProperty(MCAST_PORT, "0");
    dsProps.setProperty(LOG_LEVEL, String.valueOf(logger.getLevel()));
    dsProps.setProperty(ENABLE_CLUSTER_CONFIGURATION, "false");

    keeper1.release();
    vm0.invoke(() -> startLocatorOnPort(port1, dsProps, null));

    keeper2.release();
    vm3.invoke(() -> startLocatorOnPort(port2, dsProps, "locator2HNFC"));

    vm1.invoke(() -> createCache(locators, null));
    vm2.invoke(() -> createCache(locators, null));

    bsKeeper1.release();
    vm1.invoke(() -> startBridgeServerOnPort(bsPort1, "bs1Group1", "bs1Group2"));
    bsKeeper3.release();
    vm1.invoke(() -> startBridgeServerOnPort(bsPort3, "bs3Group1", "bs3Group2"));
    bsKeeper2.release();
    vm2.invoke(() -> startBridgeServerOnPort(bsPort2, "bs2Group1", "bs2Group2"));
    bsKeeper4.release();
    vm2.invoke(() -> startBridgeServerOnPort(bsPort4, "bs4Group1", "bs4Group2"));

    // verify that locators know about each other
    vm0.invoke(() -> {
      assertTrue(Locator.hasLocator());
      InternalLocator l = (InternalLocator) Locator.getLocator();
      DistributionAdvisee advisee = l.getServerLocatorAdvisee();
      ControllerAdvisor ca = (ControllerAdvisor) advisee.getDistributionAdvisor();
      List others = ca.fetchControllers();
      assertThat(others.size()).isEqualTo(1);
      {
        ControllerAdvisor.ControllerProfile cp =
            (ControllerAdvisor.ControllerProfile) others.get(0);
        assertThat(cp.getPort()).isEqualTo(port2);
        assertThat(cp.getHost()).isEqualTo("locator2HNFC");
      }

      others = ca.fetchBridgeServers();
      assertThat(others.size()).isEqualTo(4);
      for (Object other : others) {
        CacheServerAdvisor.CacheServerProfile bsp =
            (CacheServerAdvisor.CacheServerProfile) other;
        if (bsp.getPort() == bsPort1) {
          assertThat(new String[] {"bs1Group1", "bs1Group2"}).isEqualTo(bsp.getGroups());
        } else {
          comparePortGroups(bsp, bsPort2, bsPort3, bsPort4);
        }
      }
    });

    vm3.invoke(
        () -> verifyLocatorOnOtherPort(port1, bsPort1, bsPort2, bsPort3, bsPort4, "bs3Group1",
            "bs3Group2", "bs4Group1",
            "bs4Group2"));
    vm1.invoke(
        () -> verifyBridgeServerViewOnTwoPorts(port1, port2));
    vm2.invoke(
        () -> verifyBridgeServerViewOnTwoPorts(port1, port2));

    vm1.invoke(this::stopBridgeServer);

    // now check to see if everyone else noticed it going away
    vm0.invoke(() -> verifyOtherLocatorOnPortWithName(port2, bsPort2, bsPort3, bsPort4, "bs3Group1",
        "bs3Group2",
        "bs4Group1", "bs4Group2"));

    vm3.invoke(() -> {
      assertTrue(Locator.hasLocator());
      InternalLocator l = (InternalLocator) Locator.getLocator();
      DistributionAdvisee advisee = l.getServerLocatorAdvisee();
      ControllerAdvisor ca = (ControllerAdvisor) advisee.getDistributionAdvisor();
      List others = ca.fetchControllers();
      assertThat(others.size()).isEqualTo(1);
      {
        ControllerAdvisor.ControllerProfile cp =
            (ControllerAdvisor.ControllerProfile) others.get(0);
        assertThat(cp.getPort()).isEqualTo(port1);
      }
      others = ca.fetchBridgeServers();
      assertThat(others.size()).isEqualTo(3);
      for (Object other : others) {
        CacheServerAdvisor.CacheServerProfile bsp =
            (CacheServerAdvisor.CacheServerProfile) other;
        comparePortGroups(bsp, bsPort2, bsPort3, bsPort4);
      }
    });

    vm0.invoke(() -> stopLocatorAndCheckIt());

    // now make sure everyone else saw the locator go away
    vm3.invoke(() -> verifyLocatorStopped());
    vm2.invoke(() -> verifyBridgeServerSawLocatorStop(port2));
    vm1.invoke(() -> verifyBridgeServerSawLocatorStopWithName(port2));

    // restart bridge server 1 and see if controller sees it
    vm1.invoke(() -> restartBridgeServer());

    vm3.invoke(() -> verifyBridgeServerRestart(bsPort1, bsPort2, bsPort3, bsPort4, "bs3Group1",
        "bs3Group2",
        "bs4Group1",
        "bs4Group2"));

    vm1.invoke("Disconnect from " + locators, this::safeCloseCache);
    vm2.invoke("Disconnect from " + locators, this::safeCloseCache);
    // now make sure controller saw all bridge servers stop

    vm3.invoke(() -> verifyLocatorsAndBridgeServersStoppped());
    vm3.invoke(() -> stopLocatorAndCheckIt());
  }


  @Test
  public void test2by2usingGroups() {
    disconnectAllFromDS();

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);
    VM vm3 = VM.getVM(3);

    List<Keeper> freeTCPPorts = AvailablePortHelper.getRandomAvailableTCPPortKeepers(6);
    final Keeper keeper1 = freeTCPPorts.get(0);
    final int port1 = keeper1.getPort();
    final Keeper keeper2 = freeTCPPorts.get(1);
    final int port2 = keeper2.getPort();
    final Keeper bsKeeper1 = freeTCPPorts.get(2);
    final int bsPort1 = bsKeeper1.getPort();
    final Keeper bsKeeper2 = freeTCPPorts.get(3);
    final int bsPort2 = bsKeeper2.getPort();
    final Keeper bsKeeper3 = freeTCPPorts.get(4);
    final int bsPort3 = bsKeeper3.getPort();
    final Keeper bsKeeper4 = freeTCPPorts.get(5);
    final int bsPort4 = bsKeeper4.getPort();

    final String host0 = NetworkUtils.getServerHostName();
    final String locators = host0 + "[" + port1 + "]" + "," + host0 + "[" + port2 + "]";

    final Properties dsProps = new Properties();
    dsProps.setProperty(LOCATORS, locators);
    dsProps.setProperty(MCAST_PORT, "0");
    dsProps.setProperty(LOG_LEVEL, String.valueOf(logger.getLevel()));
    dsProps.setProperty(ENABLE_CLUSTER_CONFIGURATION, "false");

    keeper1.release();
    vm0.invoke(() -> startLocatorOnPort(port1, dsProps, null));

    keeper2.release();
    vm3.invoke(() -> startLocatorOnPort(port2, dsProps, "locator2HNFC"));

    vm1.invoke(() -> createCache(locators, "bs1Group1, bs1Group2"));
    vm2.invoke(() -> createCache(locators, "bs2Group1, bs2Group2"));

    bsKeeper1.release();
    vm1.invoke(() -> startBridgeServerOnPort(bsPort1));
    bsKeeper3.release();
    vm1.invoke(() -> startBridgeServerOnPort(bsPort3));
    bsKeeper2.release();
    vm2.invoke(() -> startBridgeServerOnPort(bsPort2));
    bsKeeper4.release();
    vm2.invoke(() -> startBridgeServerOnPort(bsPort4));

    // verify that locators know about each other
    vm0.invoke(
        () -> verifyLocatorOnOtherPort(port2, bsPort1, bsPort2, bsPort3, bsPort4, "bs1Group1",
            "bs1Group2", "bs2Group1", "bs2Group2"));
    vm3.invoke(
        () -> verifyLocatorOnOtherPort(port1, bsPort1, bsPort2, bsPort3, bsPort4, "bs1Group1",
            "bs1Group2", "bs2Group1", "bs2Group2"));

    vm1.invoke(
        () -> verifyBridgeServerViewOnTwoPorts(port1, port2));
    vm2.invoke(
        () -> verifyBridgeServerViewOnTwoPorts(port1, port2));

    vm1.invoke(this::stopBridgeServer);

    // now check to see if everyone else noticed it going away
    vm0.invoke(() -> verifyOtherLocatorOnPortWithName(port2, bsPort2, bsPort3, bsPort4, "bs1Group1",
        "bs1Group2",
        "bs2Group1",
        "bs2Group2"));

    vm3.invoke(() -> {
      assertTrue(Locator.hasLocator());
      InternalLocator l = (InternalLocator) Locator.getLocator();
      DistributionAdvisee advisee = l.getServerLocatorAdvisee();
      ControllerAdvisor ca = (ControllerAdvisor) advisee.getDistributionAdvisor();
      List others = ca.fetchControllers();
      assertThat(others.size()).isEqualTo(1);
      {
        ControllerAdvisor.ControllerProfile cp =
            (ControllerAdvisor.ControllerProfile) others.get(0);
        assertThat(cp.getPort()).isEqualTo(port1);
      }
      others = ca.fetchBridgeServers();
      assertThat(others.size()).isEqualTo(3);
      for (Object other : others) {
        CacheServerAdvisor.CacheServerProfile bsp =
            (CacheServerAdvisor.CacheServerProfile) other;
        if (bsp.getPort() == bsPort2) {
          assertThat(new String[] {"bs2Group1", "bs2Group2"}).isEqualTo(bsp.getGroups());
        } else if (bsp.getPort() == bsPort3) {
          assertThat(new String[] {"bs1Group1", "bs1Group2"}).isEqualTo(bsp.getGroups());
        } else if (bsp.getPort() == bsPort4) {
          assertThat(new String[] {"bs2Group1", "bs2Group2"}).isEqualTo(bsp.getGroups());
        } else {
          fail("unexpected port " + bsp.getPort() + " in " + bsp);
        }
      }
    });

    vm0.invoke(() -> stopLocatorAndCheckIt());

    // now make sure everyone else saw the locator go away
    vm3.invoke(() -> verifyLocatorStopped());
    vm2.invoke(() -> verifyBridgeServerSawLocatorStop(port2));
    vm1.invoke(() -> verifyBridgeServerSawLocatorStopWithName(port2));

    // restart bridge server 1 and see if controller sees it
    vm1.invoke(() -> restartBridgeServer());

    vm3.invoke(() -> verifyBridgeServerRestart(bsPort1, bsPort2, bsPort3, bsPort4, "bs1Group1",
        "bs1Group2",
        "bs2Group1", "bs2Group2"));

    vm1.invoke("Disconnect from " + locators, this::safeCloseCache);
    vm2.invoke("Disconnect from " + locators, this::safeCloseCache);
    // now make sure controller saw all bridge servers stop

    vm3.invoke(() -> verifyLocatorsAndBridgeServersStoppped());
    vm3.invoke(() -> stopLocatorAndCheckIt());
  }

  private void createCache(String locators, String groups) {
    Properties props = new Properties();
    props.setProperty(MCAST_PORT, "0");
    props.setProperty(LOCATORS, locators);
    if (groups != null) {
      props.setProperty(GROUPS, groups);
    }
    props.setProperty(LOG_LEVEL, String.valueOf(logger.getLevel()));
    cache = (InternalCache) new CacheFactory(props).create();
  }


  private void comparePortGroups(CacheServerAdvisor.CacheServerProfile bsp, int bsPort2,
      int bsPort3, int bsPort4) {
    if (bsp.getPort() == bsPort2) {
      assertThat(new String[] {"bs2Group1", "bs2Group2"}).isEqualTo(bsp.getGroups());
    } else if (bsp.getPort() == bsPort3) {
      assertThat(new String[] {"bs3Group1", "bs3Group2"}).isEqualTo(bsp.getGroups());
    } else if (bsp.getPort() == bsPort4) {
      assertThat(new String[] {"bs4Group1", "bs4Group2"}).isEqualTo(bsp.getGroups());
    } else {
      fail("unexpected port " + bsp.getPort() + " in " + bsp);
    }
  }

  private void stopLocatorAndCheckIt() {
    assertTrue(Locator.hasLocator());
    Locator.getLocator().stop();
    assertFalse(Locator.hasLocator());
  }


  private void verifyBridgeServerViewOnTwoPorts(int port1, int port2) {
    Cache c = cache;
    List bslist = c.getCacheServers();
    assertThat(bslist.size()).isEqualTo(2);
    for (Object aBslist : bslist) {
      DistributionAdvisee advisee = (DistributionAdvisee) aBslist;
      CacheServerAdvisor bsa = (CacheServerAdvisor) advisee.getDistributionAdvisor();
      List others = bsa.fetchBridgeServers();
      logger.info("found these bridgeservers in " + advisee + ": " + others);
      assertThat(others.size()).isEqualTo(3);
      others = bsa.fetchControllers();
      assertThat(others.size()).isEqualTo(2);
      for (Object other : others) {
        ControllerAdvisor.ControllerProfile cp =
            (ControllerAdvisor.ControllerProfile) other;
        if (cp.getPort() != port1) {
          if (cp.getPort() == port2) {
            assertThat(cp.getHost()).isEqualTo("locator2HNFC");
            // ok
          } else {
            fail("unexpected port " + cp.getPort() + " in " + cp);
          }
        }
      }
    }
  }

  private void verifyBridgeServerRestart(int bsPort1, int bsPort2, int bsPort3, int bsPort4,
      String bs3Group1, String bs3Group2, String bs4Group1,
      String bs4Group2) {
    assertTrue(Locator.hasLocator());
    InternalLocator l = (InternalLocator) Locator.getLocator();
    DistributionAdvisee advisee = l.getServerLocatorAdvisee();
    ControllerAdvisor ca = (ControllerAdvisor) advisee.getDistributionAdvisor();
    assertThat(ca.fetchControllers().size()).isEqualTo(0);
    List others = ca.fetchBridgeServers();
    assertThat(others.size()).isEqualTo(4);
    for (Object other : others) {
      CacheServerAdvisor.CacheServerProfile bsp =
          (CacheServerAdvisor.CacheServerProfile) other;
      if (bsp.getPort() == bsPort1) {
        assertThat(new String[] {"bs1Group1", "bs1Group2"}).isEqualTo(bsp.getGroups());
        assertThat(bsp.getHost()).isEqualTo("nameForClients");
      } else if (bsp.getPort() == bsPort2) {
        assertThat(new String[] {"bs2Group1", "bs2Group2"}).isEqualTo(bsp.getGroups());
        assertThat(bsp.getHost()).isNotEqualTo("nameForClients");
      } else {
        comparePortGroupsTwo(bsPort3, bsPort4, bs3Group1, bs3Group2, bs4Group1, bs4Group2, bsp);
      }
    }
  }

  private void comparePortGroupsTwo(int bsPort3, int bsPort4, String bs3Group1, String bs3Group2,
      String bs4Group1, String bs4Group2,
      CacheServerAdvisor.CacheServerProfile bsp) {
    if (bsp.getPort() == bsPort3) {
      assertThat(Arrays.asList(bsp.getGroups())).isEqualTo(Arrays.asList(bs3Group1, bs3Group2));
    } else if (bsp.getPort() == bsPort4) {
      assertThat(Arrays.asList(bsp.getGroups())).isEqualTo(Arrays.asList(bs4Group1, bs4Group2));
    } else {
      fail("unexpected port " + bsp.getPort() + " in " + bsp);
    }
  }

  private void verifyLocatorStopped() {
    assertTrue(Locator.hasLocator());
    InternalLocator l = (InternalLocator) Locator.getLocator();
    DistributionAdvisee advisee = l.getServerLocatorAdvisee();
    ControllerAdvisor ca = (ControllerAdvisor) advisee.getDistributionAdvisor();
    List others = ca.fetchControllers();
    assertThat(others.size()).isEqualTo(0);
  }

  private void verifyBridgeServerSawLocatorStop(int port2) {
    Cache c = cache;
    List bslist = c.getCacheServers();
    assertThat(bslist.size()).isEqualTo(2);
    for (Object aBslist : bslist) {
      DistributionAdvisee advisee = (DistributionAdvisee) aBslist;
      CacheServerAdvisor bsa = (CacheServerAdvisor) advisee.getDistributionAdvisor();
      List others = bsa.fetchControllers();
      assertThat(others.size()).isEqualTo(1);
      verifyHostNameForPort(port2, others);
    }
  }

  private void verifyHostNameForPort(int port2, List others) {
    for (Object other : others) {
      ControllerAdvisor.ControllerProfile cp =
          (ControllerAdvisor.ControllerProfile) other;
      if (cp.getPort() == port2) {
        assertThat(cp.getHost()).isEqualTo("locator2HNFC");
        // ok
      } else {
        fail("unexpected port " + cp.getPort() + " in " + cp);
      }
    }
  }

  private void verifyLocatorOnOtherPort(int port1, int bsPort1, int bsPort2, int bsPort3,
      int bsPort4, String bs3Group1, String bs3Group2,
      String bs4Group1, String bs4Group2) {
    assertTrue(Locator.hasLocator());
    InternalLocator l = (InternalLocator) Locator.getLocator();
    DistributionAdvisee advisee = l.getServerLocatorAdvisee();
    ControllerAdvisor ca = (ControllerAdvisor) advisee.getDistributionAdvisor();
    List others = ca.fetchControllers();
    assertThat(others.size()).isEqualTo(1);
    {
      ControllerAdvisor.ControllerProfile cp =
          (ControllerAdvisor.ControllerProfile) others.get(0);
      assertThat(cp.getPort()).isEqualTo(port1);
    }
    others = ca.fetchBridgeServers();
    assertThat(others.size()).isEqualTo(4);
    for (Object other : others) {
      CacheServerAdvisor.CacheServerProfile bsp =
          (CacheServerAdvisor.CacheServerProfile) other;
      if (bsp.getPort() == bsPort1) {
        assertThat(new String[] {"bs1Group1", "bs1Group2"}).isEqualTo(bsp.getGroups());
      } else if (bsp.getPort() == bsPort2) {
        assertThat(new String[] {"bs2Group1", "bs2Group2"}).isEqualTo(bsp.getGroups());
      } else {
        comparePortGroupsTwo(bsPort3, bsPort4, bs3Group1, bs3Group2, bs4Group1, bs4Group2, bsp);
      }
    }
  }

  private void startBridgeServerOnPort(int bsPort1, String bs1Group1, String bs1Group2) {
    try {
      Cache c = cache;
      CacheServer bs = c.addCacheServer();
      bs.setPort(bsPort1);
      bs.setGroups(new String[] {bs1Group1, bs1Group2});
      bs.start();
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    }
  }

  private void startLocatorOnPort(int port1, Properties dsProps, String name) {
    File logFile = new File(getUniqueName() + "-locator" + port1 + ".log");
    try {
      Locator.startLocatorAndDS(port1, logFile, null, dsProps, true, true, name);
    } catch (IllegalStateException | IOException ex) {
      Assertions.fail("While starting locator on port " + port1, ex);
    }
  }


  private void safeCloseCache() {
    if (cache != null) {
      cache.close();
    }
  }

  private void startBridgeServerOnPort(int bsPort4) {
    try {
      Cache c = cache;
      CacheServer bs = c.addCacheServer();
      bs.setPort(bsPort4);
      bs.start();
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    }
  }

  private void stopBridgeServer() {
    Cache c = cache;
    List bslist = c.getCacheServers();
    assertThat(bslist.size()).isEqualTo(2);
    CacheServer bs = (CacheServer) bslist.get(0);
    bs.stop();
  }

  private void verifyLocatorsAndBridgeServersStoppped() {
    assertTrue(Locator.hasLocator());
    InternalLocator l = (InternalLocator) Locator.getLocator();
    DistributionAdvisee advisee = l.getServerLocatorAdvisee();
    ControllerAdvisor ca = (ControllerAdvisor) advisee.getDistributionAdvisor();
    assertThat(ca.fetchControllers().size()).isEqualTo(0);
    assertThat(ca.fetchBridgeServers().size()).isEqualTo(0);
  }

  private void restartBridgeServer() {
    try {
      Cache c = cache;
      List bslist = c.getCacheServers();
      assertThat(bslist.size()).isEqualTo(2);
      CacheServer bs = (CacheServer) bslist.get(0);
      bs.setHostnameForClients("nameForClients");
      bs.start();
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    }
  }

  private void verifyBridgeServerSawLocatorStopWithName(int port2) {
    Cache c = cache;
    List bslist = c.getCacheServers();
    assertThat(bslist.size()).isEqualTo(2);
    for (int i = 0; i < bslist.size(); i++) {
      DistributionAdvisee advisee = (DistributionAdvisee) bslist.get(i);
      if (i == 0) {
        // skip this one since it is stopped
        continue;
      }
      CacheServerAdvisor bsa = (CacheServerAdvisor) advisee.getDistributionAdvisor();
      List others = bsa.fetchControllers();
      assertThat(others.size()).isEqualTo(1);
      verifyHostNameForPort(port2, others);
    }
  }

  private void verifyOtherLocatorOnPortWithName(int port2, int bsPort2, int bsPort3, int bsPort4,
      String bs1Group1, String bs1Group2,
      String bs2Group1, String bs2Group2) {
    assertTrue(Locator.hasLocator());
    InternalLocator l = (InternalLocator) Locator.getLocator();
    DistributionAdvisee advisee = l.getServerLocatorAdvisee();
    ControllerAdvisor ca = (ControllerAdvisor) advisee.getDistributionAdvisor();
    List others = ca.fetchControllers();
    assertThat(others.size()).isEqualTo(1);
    {
      ControllerAdvisor.ControllerProfile cp =
          (ControllerAdvisor.ControllerProfile) others.get(0);
      assertThat(cp.getPort()).isEqualTo(port2);
      assertThat(cp.getHost()).isEqualTo("locator2HNFC");
    }

    others = ca.fetchBridgeServers();
    assertThat(others.size()).isEqualTo(3);
    for (Object other : others) {
      CacheServerAdvisor.CacheServerProfile bsp =
          (CacheServerAdvisor.CacheServerProfile) other;
      if (bsp.getPort() == bsPort2) {
        assertThat(new String[] {"bs2Group1", "bs2Group2"}).isEqualTo(bsp.getGroups());
      } else if (bsp.getPort() == bsPort3) {
        assertThat(new String[] {bs1Group1, bs1Group2}).isEqualTo(bsp.getGroups());
      } else if (bsp.getPort() == bsPort4) {
        assertThat(new String[] {bs2Group1, bs2Group2}).isEqualTo(bsp.getGroups());
      } else {
        fail("unexpected port " + bsp.getPort() + " in " + bsp);
      }
    }
  }
}
