@Before
  public void setUp() throws Exception {
    super.setUp();
    threadPool = new ThreadPool(getClass().getName());
    serviceA = build(ImmutableSettings.builder().put("name", "TS_A").build(), version0);
    nodeA =
        new DiscoveryNode(
            "TS_A",
            "TS_A",
            serviceA.boundAddress().publishAddress(),
            ImmutableMap.<String, String>of(),
            version0);
    serviceB = build(ImmutableSettings.builder().put("name", "TS_B").build(), version1);
    nodeB =
        new DiscoveryNode(
            "TS_B",
            "TS_B",
            serviceB.boundAddress().publishAddress(),
            ImmutableMap.<String, String>of(),
            version1);

    // wait till all nodes are properly connected and the event has been sent, so tests in this
    // class
    // will not get this callback called on the connections done in this setup
    final CountDownLatch latch = new CountDownLatch(4);
    TransportConnectionListener waitForConnection =
        new TransportConnectionListener() {
          @Override
          public void onNodeConnected(DiscoveryNode node) {
            latch.countDown();
          }

          @Override
          public void onNodeDisconnected(DiscoveryNode node) {
            fail("disconnect should not be called " + node);
          }
        };
    serviceA.addConnectionListener(waitForConnection);
    serviceB.addConnectionListener(waitForConnection);

    serviceA.connectToNode(nodeB);
    serviceA.connectToNode(nodeA);
    serviceB.connectToNode(nodeA);
    serviceB.connectToNode(nodeB);

    assertThat(
        "failed to wait for all nodes to connect", latch.await(5, TimeUnit.SECONDS), equalTo(true));
    serviceA.removeConnectionListener(waitForConnection);
    serviceB.removeConnectionListener(waitForConnection);
  }
  public static MockNode createMockNode(
      String name,
      final Settings basSettings,
      @Nullable ClusterStateListener listener,
      ThreadPool threadPool,
      Logger logger,
      Map<String, MockNode> nodes)
      throws Exception {
    final Settings settings =
        Settings.builder()
            .put("name", name)
            .put(
                TransportService.TRACE_LOG_INCLUDE_SETTING.getKey(), "",
                TransportService.TRACE_LOG_EXCLUDE_SETTING.getKey(), "NOTHING")
            .put(basSettings)
            .build();

    MockTransportService service = buildTransportService(settings, threadPool);
    DiscoveryNode discoveryNode =
        DiscoveryNode.createLocal(
            settings,
            service.boundAddress().publishAddress(),
            NodeEnvironment.generateNodeId(settings));
    MockNode node = new MockNode(discoveryNode, service, listener, logger);
    node.action = buildPublishClusterStateAction(settings, service, () -> node.clusterState, node);
    final CountDownLatch latch = new CountDownLatch(nodes.size() * 2 + 1);
    TransportConnectionListener waitForConnection =
        new TransportConnectionListener() {
          @Override
          public void onNodeConnected(DiscoveryNode node) {
            latch.countDown();
          }

          @Override
          public void onNodeDisconnected(DiscoveryNode node) {
            fail("disconnect should not be called " + node);
          }
        };
    node.service.addConnectionListener(waitForConnection);
    for (MockNode curNode : nodes.values()) {
      curNode.service.addConnectionListener(waitForConnection);
      curNode.connectTo(node.discoveryNode);
      node.connectTo(curNode.discoveryNode);
    }
    node.connectTo(node.discoveryNode);
    assertThat(
        "failed to wait for all nodes to connect", latch.await(5, TimeUnit.SECONDS), equalTo(true));
    for (MockNode curNode : nodes.values()) {
      curNode.service.removeConnectionListener(waitForConnection);
    }
    node.service.removeConnectionListener(waitForConnection);
    if (nodes.put(name, node) != null) {
      fail("Node with the name " + name + " already exist");
    }
    return node;
  }