@Test
public void testChooseRandomWithStorageTypeWithExcluded() throws Exception {

  Node n;
  DatanodeDescriptor dd;
  // below test choose random with exclude, for /l2/d3, every rack has exactly
  // one host
  // /l2/d3 has five racks r[1~5] but only r4 and r5 have ARCHIVE
  // host12 is the one under "/l2/d3/r4", host13 is the one under "/l2/d3/r5"
  n = CLUSTER.chooseRandomWithStorageType("/l2/d3/r4", null, null,
      StorageType.ARCHIVE);
  HashSet<Node> excluded = new HashSet<>();
  // exclude the host on r4 (since there is only one host, no randomness here)
  excluded.add(n);
  for (int i = 0; i < 10; i++) {
    n = CLUSTER.chooseRandomWithStorageType("/l2/d3", null, null,
        StorageType.ARCHIVE);
    assertTrue(n instanceof DatanodeDescriptor);
    dd = (DatanodeDescriptor) n;
    assertTrue(dd.getHostName().equals("host13") ||
        dd.getHostName().equals("host14"));
  }
  // test exclude nodes
  for (int i = 0; i < 10; i++) {
    n = CLUSTER.chooseRandomWithStorageType("/l2/d3", null, excluded,
        StorageType.ARCHIVE);
    assertTrue(n instanceof DatanodeDescriptor);
    dd = (DatanodeDescriptor) n;
    assertTrue(dd.getHostName().equals("host14"));
  }
  // test exclude scope
  for (int i = 0; i < 10; i++) {
    n = CLUSTER.chooseRandomWithStorageType("/l2/d3", "/l2/d3/r4", null,
        StorageType.ARCHIVE);
    assertTrue(n instanceof DatanodeDescriptor);
    dd = (DatanodeDescriptor) n;
    assertTrue(dd.getHostName().equals("host14"));
  }
  // test exclude scope + excluded node with expected null return node
  for (int i = 0; i < 10; i++) {
    n = CLUSTER.chooseRandomWithStorageType("/l2/d3", "/l2/d3/r5", excluded,
        StorageType.ARCHIVE);
    assertNull(n);
  }
  // test exclude scope + excluded node with expected non-null return node
  n = CLUSTER.chooseRandomWithStorageType("/l1/d2", null, null,
      StorageType.DISK);
  dd = (DatanodeDescriptor)n;
  assertEquals("host6", dd.getHostName());
  // exclude the host on r4 (since there is only one host, no randomness here)
  excluded.add(n);
  Set<String> expectedSet = Sets.newHashSet("host4", "host5");
  for (int i = 0; i < 10; i++) {
    // under l1, there are four hosts with DISK:
    // /l1/d1/r1/host2, /l1/d1/r2/host4, /l1/d1/r2/host5 and /l1/d2/r3/host6
    // host6 is excludedNode, host2 is under excluded range scope /l1/d1/r1
    // so should always return r4 or r5
    n = CLUSTER.chooseRandomWithStorageType(
        "/l1", "/l1/d1/r1", excluded, StorageType.DISK);
    dd = (DatanodeDescriptor) n;
    assertTrue(expectedSet.contains(dd.getHostName()));
  }
}