protected void merge(TestHardwareLayout that) {
      if (this == that) {
        return;
      }
      // make sure the cluster name is the same
      if (clusterName != that.clusterName) {
        throw new IllegalArgumentException("Cluster name is different " + clusterName + " != " + that.clusterName);
      }
      if (diskCount != that.diskCount) {
        throw new IllegalArgumentException("Disk count is different " + diskCount + " != " + that.diskCount);
      }
      if (rackAware != that.rackAware) {
        throw new IllegalArgumentException("RackAware is different " + rackAware + " != " + that.rackAware);
      }
      // make sure the datacenters are the same
      Set<String> dcInThis =
          hardwareLayout.getDatacenters().stream().map(dc -> dc.getName()).collect(Collectors.toSet());
      Set<String> dcInThat =
          that.hardwareLayout.getDatacenters().stream().map(dc -> dc.getName()).collect(Collectors.toSet());
      if (!dcInThis.equals(dcInThat)) {
        throw new IllegalArgumentException("Dcs are different " + dcInThis + " != " + dcInThat);
      }
      // make sure nodes are different in each datacenter
      Set<String> dataNodesInThis = getAllExistingDataNodes().stream()
          .map(dn -> ClusterMapUtils.getInstanceName(dn.getHostname(), dn.getPort()))
          .collect(Collectors.toSet());
      Set<String> dataNodesInThat = that.getAllExistingDataNodes()
          .stream()
          .map(dn -> ClusterMapUtils.getInstanceName(dn.getHostname(), dn.getPort()))
          .collect(Collectors.toSet());
      boolean modified = dataNodesInThis.removeAll(dataNodesInThat);
      if (modified) {
        System.out.println("DataNodes in this: " + dataNodesInThis);
        System.out.println("DataNodes in that: " + dataNodesInThat);
        throw new IllegalArgumentException("DataNodes should not share");
      }

      basePort = Math.max(basePort, that.basePort);
      version += 1;
      dataNodeCount = Math.max(dataNodeCount, that.dataNodeCount);
      numRacks = Math.max(numRacks, that.numRacks);
      for (int i = 0; i < datanodeJSONArrays.size(); i++) {
        JSONArray dnja = datanodeJSONArrays.get(i);
        JSONArray dnjaInThat = that.datanodeJSONArrays.get(i);
        for (int j = 0; j < dnjaInThat.length(); j++) {
          dnja.put(dnjaInThat.getJSONObject(j));
        }
      }
      List<String> dcNames =
          hardwareLayout.getDatacenters().stream().map(dc -> dc.getName()).collect(Collectors.toList());
      hardwareLayout = new HardwareLayout(getJsonHardwareLayout(clusterName, defaultHardwareLayoutVersion,
          TestUtils.getJsonArrayDatacenters(dcNames, datanodeJSONArrays)), clusterMapConfig);
    }
Get given number of datanodes from each datacenter.
@param dataNodeCountPerDc number of datanodes to get from each datacenter.
@return a list of datanodes.
ambry-clustermap/src/test/java/com/github/ambry/clustermap/TestUtils.java