@VisibleForTesting
  public Map<String, HashSet<String>> runTest(Set<String> inputList, Map<String, Long> sizes)  {
    try {
      conf = msConf;
      testDatasizes = sizes;
      coverageList.clear();
      removeNestedStructure(inputList);
      createOutputList(inputList, "test", "test");
    } catch (Exception e) {
      LOG.error("MetaToolTask failed on ListExtTblLocs test: ", e);
    }
    return coverageList;
  }
@Test
  public void testGroupLocations() {
    Set<String> inputLocations = new TreeSet<>();
    Configuration conf = MetastoreConf.newMetastoreConf();
    MetastoreConf.setBoolVar(conf, MetastoreConf.ConfVars.HIVE_IN_TEST, true);
    MetaToolTaskListExtTblLocs.msConf = conf;
    MetaToolTaskListExtTblLocs task = new MetaToolTaskListExtTblLocs();

    //Case 1: Multiple unpartitioned external tables, expected o/p: 1 location
    inputLocations.add("/warehouse/customLocation/t1");
    inputLocations.add("/warehouse/customLocation/t2");
    inputLocations.add("/warehouse/customLocation/t3");
    Map<String, HashSet<String>> output = task.runTest(inputLocations, null);
    Assert.assertEquals(1, output.size());
    String expectedOutput = "/warehouse/customLocation";
    Assert.assertTrue(output.containsKey(expectedOutput));
    HashSet<String> coveredLocs = output.get(expectedOutput);
    Assert.assertEquals(3, coveredLocs.size());
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/t1"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/t2"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/t3"));

    //Case 2 : inputs at multiple depths
    // inputs   ../ext/b0 - contains 1 location
    //          ../ext/p=0 - contains 1 location
    //          ../ext/b1/b2/b3 - contains 3 locations (p1, p2, p3)
    // expected output : [../ext/b1/b2/b3 containing 3 elements, t1, p0]
    inputLocations.clear();
    inputLocations.add("/warehouse/customLocation/ext/b0");
    inputLocations.add("/warehouse/customLocation/ext/p=0");
    inputLocations.add("/warehouse/customLocation/ext/b1/b2/b3/p=1");
    inputLocations.add("/warehouse/customLocation/ext/b1/b2/b3/p=2");
    inputLocations.add("/warehouse/customLocation/ext/b1/b2/b3/p=3");
    output = task.runTest(inputLocations, null);
    Assert.assertEquals(3, output.size());
    String expectedOutput1 = "/warehouse/customLocation/ext/b0";
    Assert.assertTrue(output.containsKey(expectedOutput1));
    coveredLocs = output.get(expectedOutput1);
    Assert.assertEquals(1, coveredLocs.size());
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b0"));
    String expectedOutput2 = "/warehouse/customLocation/ext/p=0";
    Assert.assertTrue(output.containsKey(expectedOutput2));
    coveredLocs = output.get(expectedOutput2);
    Assert.assertEquals(1, coveredLocs.size());
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/p=0"));
    String expectedOutput3 = "/warehouse/customLocation/ext/b1/b2/b3";
    Assert.assertTrue(output.containsKey(expectedOutput3));
    coveredLocs = output.get(expectedOutput3);
    Assert.assertEquals(3, coveredLocs.size());
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b1/b2/b3/p=1"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b1/b2/b3/p=2"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b1/b2/b3/p=3"));

    //Case 3 : root with a lot of leaves 
    // inputs   ../ext/ - contains 4 locations
    //          ../ext/b1 - contains 3 locations
    // expected output : [../ext covering all locations] since root (ext) has more than half of locations
    inputLocations.clear();
    inputLocations.add("/warehouse/customLocation/ext/p=0");
    inputLocations.add("/warehouse/customLocation/ext/p=1");
    inputLocations.add("/warehouse/customLocation/ext/p=2");
    inputLocations.add("/warehouse/customLocation/ext/p=3");
    inputLocations.add("/warehouse/customLocation/ext/b1/p=4");
    inputLocations.add("/warehouse/customLocation/ext/b1/p=5");
    inputLocations.add("/warehouse/customLocation/ext/b1/p=6");
    output = task.runTest(inputLocations, null);
    Assert.assertEquals(1, output.size());
    expectedOutput = "/warehouse/customLocation/ext";
    Assert.assertTrue(output.containsKey(expectedOutput));
    coveredLocs = output.get(expectedOutput);
    Assert.assertEquals(7, coveredLocs.size());
    Assert.assertTrue(coveredLocs.containsAll(inputLocations));

    //Case 4 : root with a lot of trivial locations (non leaf)
    // inputs   ../ext/ - contains 4 trivial locations
    //          ../ext/b1 - contains 3 locations
    // expected output : [../ext covering all locations] since non trivial (grouped) locations under ext is less than half 
    inputLocations.clear();
    inputLocations.add("/warehouse/customLocation/ext/dir01/dir02/p=0");
    inputLocations.add("/warehouse/customLocation/ext/dir11/dir12/p=1");
    inputLocations.add("/warehouse/customLocation/ext/dir21/dir22/p=2");
    inputLocations.add("/warehouse/customLocation/ext/dir31/dir32/p=3");
    inputLocations.add("/warehouse/customLocation/ext/b1/p=4");
    inputLocations.add("/warehouse/customLocation/ext/b1/p=5");
    inputLocations.add("/warehouse/customLocation/ext/b1/p=6");
    output = task.runTest(inputLocations, null);
    Assert.assertEquals(1, output.size());
    expectedOutput = "/warehouse/customLocation/ext";
    Assert.assertTrue(output.containsKey(expectedOutput));
    coveredLocs = output.get(expectedOutput);
    Assert.assertEquals(7, coveredLocs.size());
    Assert.assertTrue(coveredLocs.containsAll(inputLocations));

    //Case 5 : several grouped locations and 1 outlier at root
    // inputs   ../ext/b0 - contains 4 locations
    //          ../ext/b1 - contains 3 locations
    // expected output : [../ext/b0, ../ext/b1, p=7 ]
    inputLocations.clear();
    inputLocations.add("/warehouse/customLocation/ext/b0/p=0");
    inputLocations.add("/warehouse/customLocation/ext/b0/p=1");
    inputLocations.add("/warehouse/customLocation/ext/b0/p=2");
    inputLocations.add("/warehouse/customLocation/ext/b0/p=3");
    inputLocations.add("/warehouse/customLocation/ext/b1/p=4");
    inputLocations.add("/warehouse/customLocation/ext/b1/p=5");
    inputLocations.add("/warehouse/customLocation/ext/b1/p=6");
    inputLocations.add("/warehouse/customLocation/ext/p=7");
    output = task.runTest(inputLocations, null);
    Assert.assertEquals(3, output.size());
    expectedOutput1 = "/warehouse/customLocation/ext/b0";
    Assert.assertTrue(output.containsKey(expectedOutput1));
    coveredLocs = output.get(expectedOutput1);
    Assert.assertEquals(4, coveredLocs.size());
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b0/p=0"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b0/p=1"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b0/p=2"));
    expectedOutput2 = "/warehouse/customLocation/ext/b1";
    Assert.assertTrue(output.containsKey(expectedOutput2));
    coveredLocs = output.get(expectedOutput2);
    Assert.assertEquals(3, coveredLocs.size());
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b1/p=4"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b1/p=5"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b1/p=6"));
    expectedOutput3 = "/warehouse/customLocation/ext/p=7";
    Assert.assertTrue(output.containsKey(expectedOutput3));
    coveredLocs = output.get(expectedOutput3);
    Assert.assertEquals(1, coveredLocs.size());
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/p=7"));

    //Case 6 : inputs with nested structure
    // inputs   ../ext/b0 - contains 4 locations
    //          ../ext/b1 
    //          ../ext/b1/b2 - contains 4 locations
    // expected output : [../ext/b0, ../ext/b1 ] : (no extra location for b2 since covered by b1 itself)
    inputLocations.clear();
    inputLocations.add("/warehouse/customLocation/ext/b0/p=0");
    inputLocations.add("/warehouse/customLocation/ext/b0/p=1");
    inputLocations.add("/warehouse/customLocation/ext/b0/p=2");
    inputLocations.add("/warehouse/customLocation/ext/b0/p=3");
    inputLocations.add("/warehouse/customLocation/ext/b1");
    inputLocations.add("/warehouse/customLocation/ext/b1/b2/p=7");
    inputLocations.add("/warehouse/customLocation/ext/b1/b2/p=8");
    inputLocations.add("/warehouse/customLocation/ext/b1/b2/p=9");
    output = task.runTest(inputLocations, null);
    Assert.assertEquals(2, output.size());
    expectedOutput1 = "/warehouse/customLocation/ext/b0";
    Assert.assertTrue(output.containsKey(expectedOutput1));
    coveredLocs = output.get(expectedOutput1);
    Assert.assertEquals(4, coveredLocs.size());
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b0/p=0"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b0/p=1"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b0/p=2"));
    expectedOutput2 = "/warehouse/customLocation/ext/b1";
    Assert.assertTrue(output.containsKey(expectedOutput2));
    coveredLocs = output.get(expectedOutput2);
    Assert.assertEquals(4, coveredLocs.size());
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b1"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b1/b2/p=7"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b1/b2/p=8"));
    Assert.assertTrue(coveredLocs.contains("/warehouse/customLocation/ext/b1/b2/p=9"));
  }