@Test
public void testDowngradeComponentTasks() throws Exception {

  Map<String, UpgradePack> upgrades = ambariMetaInfo.getUpgradePacks("HDP", "2.1.1");
  UpgradePack upgradePack = upgrades.get("upgrade_component_tasks_test");
  assertNotNull(upgradePack);
  Map<String, Map<String, ProcessingComponent>> components = upgradePack.getTasks();
  assertTrue(components.containsKey("ZOOKEEPER"));
  assertTrue(components.containsKey("HDFS"));
  Map<String, ProcessingComponent> zkMap = components.get("ZOOKEEPER");
  Map<String, ProcessingComponent> hdfsMap = components.get("HDFS");
  assertTrue(zkMap.containsKey("ZOOKEEPER_SERVER"));
  assertTrue(zkMap.containsKey("ZOOKEEPER_CLIENT"));
  assertTrue(hdfsMap.containsKey("NAMENODE"));
  assertTrue(hdfsMap.containsKey("DATANODE"));
  assertTrue(hdfsMap.containsKey("HDFS_CLIENT"));
  assertTrue(hdfsMap.containsKey("JOURNALNODE"));
  ProcessingComponent zkServer = zkMap.get("ZOOKEEPER_SERVER");
  ProcessingComponent zkClient = zkMap.get("ZOOKEEPER_CLIENT");
  ProcessingComponent hdfsNN = hdfsMap.get("NAMENODE");
  ProcessingComponent hdfsDN = hdfsMap.get("DATANODE");
  ProcessingComponent hdfsClient = hdfsMap.get("HDFS_CLIENT");
  ProcessingComponent hdfsJN = hdfsMap.get("JOURNALNODE");
  // ZK server has only pretasks defined, with pre-downgrade being a copy of pre-upgrade
  assertNotNull(zkServer.preTasks);
  assertNotNull(zkServer.preDowngradeTasks);
  assertNull(zkServer.postTasks);
  assertNull(zkServer.postDowngradeTasks);
  assertEquals(1, zkServer.preTasks.size());
  assertEquals(1, zkServer.preDowngradeTasks.size());
  // ZK client has only post-tasks defined, with post-downgrade being a copy of pre-upgrade
  assertNull(zkClient.preTasks);
  assertNull(zkClient.preDowngradeTasks);
  assertNotNull(zkClient.postTasks);
  assertNotNull(zkClient.postDowngradeTasks);
  assertEquals(1, zkClient.postTasks.size());
  assertEquals(1, zkClient.postDowngradeTasks.size());
  // NN has only pre-tasks defined, with an empty pre-downgrade
  assertNotNull(hdfsNN.preTasks);
  assertNotNull(hdfsNN.preDowngradeTasks);
  assertNull(hdfsNN.postTasks);
  assertNull(hdfsNN.postDowngradeTasks);
  assertEquals(1, hdfsNN.preTasks.size());
  assertEquals(0, hdfsNN.preDowngradeTasks.size());
  // DN has only post-tasks defined, with post-downgrade being empty
  assertNull(hdfsDN.preTasks);
  assertNull(hdfsDN.preDowngradeTasks);
  assertNotNull(hdfsDN.postTasks);
  assertNotNull(hdfsDN.postDowngradeTasks);
  assertEquals(1, hdfsDN.postTasks.size());
  assertEquals(0, hdfsDN.postDowngradeTasks.size());
  // HDFS client has only post and post-downgrade tasks
  assertNull(hdfsClient.preTasks);
  assertNotNull(hdfsClient.preDowngradeTasks);
  assertNull(hdfsClient.postTasks);
  assertNotNull(hdfsClient.postDowngradeTasks);
  assertEquals(1, hdfsClient.preDowngradeTasks.size());
  assertEquals(1, hdfsClient.postDowngradeTasks.size());
  // JN has differing tasks for pre and post downgrade
  assertNotNull(hdfsJN.preTasks);
  assertNotNull(hdfsJN.preDowngradeTasks);
  assertNotNull(hdfsJN.postTasks);
  assertNotNull(hdfsJN.postDowngradeTasks);
  assertEquals(1, hdfsJN.preTasks.size());
  assertEquals(2, hdfsJN.preDowngradeTasks.size());
  assertEquals(1, hdfsJN.postTasks.size());
  assertEquals(2, hdfsJN.postDowngradeTasks.size());
  // make sure all ids are accounted for
  Set<String> allIds = Sets.newHashSet("some_id", "some_id1", "some_id2", "some_id3", "some_id4", "some_id5");
  @SuppressWarnings("unchecked")
  Set<List<Task>> allTasks = Sets.newHashSet(hdfsJN.preTasks, hdfsJN.preDowngradeTasks,
      hdfsJN.postTasks, hdfsJN.postDowngradeTasks);
  for (List<Task> list : allTasks) {
    for (Task t : list) {
      assertEquals(ConfigureTask.class, t.getClass());
      ConfigureTask ct = (ConfigureTask) t;
      assertTrue(allIds.contains(ct.id));
      allIds.remove(ct.id);
    }
  }
  assertTrue(allIds.isEmpty());
}