@Test
public void testHostGroupingOrchestration() throws Exception {

  Clusters clusters = injector.getInstance(Clusters.class);
  ServiceFactory serviceFactory = injector.getInstance(ServiceFactory.class);
  String clusterName = "c1";
  StackId stackId = new StackId("HDP-2.1.1");
  StackId stackId2 = new StackId("HDP-2.2.0");
  clusters.addCluster(clusterName, stackId);
  Cluster c = clusters.getCluster(clusterName);
  helper.getOrCreateRepositoryVersion(stackId,
      c.getDesiredStackVersion().getStackVersion());
  helper.getOrCreateRepositoryVersion(stackId2, "2.2.0");
  c.createClusterVersion(stackId,
      c.getDesiredStackVersion().getStackVersion(), "admin",
      RepositoryVersionState.INSTALLING);
  // create 2 hosts
  for (int i = 0; i < 2; i++) {
    String hostName = "h" + (i+1);
    clusters.addHost(hostName);
    Host host = clusters.getHost(hostName);
    Map<String, String> hostAttributes = new HashMap<>();
    hostAttributes.put("os_family", "redhat");
    hostAttributes.put("os_release_version", "6");
    host.setHostAttributes(hostAttributes);
    clusters.mapHostToCluster(hostName, clusterName);
  }
  // add ZK Server to both hosts, and then Nimbus to only 1 - this will test
  // how the HOU breaks out dependencies into stages
  c.addService(serviceFactory.createNew(c, "ZOOKEEPER"));
  c.addService(serviceFactory.createNew(c, "HBASE"));
  Service zookeeper = c.getService("ZOOKEEPER");
  Service hbase = c.getService("HBASE");
  ServiceComponent zookeeperServer = zookeeper.addServiceComponent("ZOOKEEPER_SERVER");
  ServiceComponentHost zookeeperServer1 = zookeeperServer.addServiceComponentHost("h1");
  ServiceComponentHost zookeeperServer2 = zookeeperServer.addServiceComponentHost("h2");
  ServiceComponent hbaseMaster = hbase.addServiceComponent("HBASE_MASTER");
  ServiceComponentHost hbaseMaster1 = hbaseMaster.addServiceComponentHost("h1");
  // !!! make a custom grouping
  HostOrderItem hostItem = new HostOrderItem(HostOrderActionType.HOST_UPGRADE,
      Lists.newArrayList("h1", "h2"));
  HostOrderItem checkItem = new HostOrderItem(HostOrderActionType.SERVICE_CHECK,
      Lists.newArrayList("ZOOKEEPER", "HBASE"));
  Grouping g = new HostOrderGrouping();
  ((HostOrderGrouping) g).setHostOrderItems(Lists.newArrayList(hostItem, checkItem));
  g.title = "Some Title";
  UpgradePack upgradePack = new UpgradePack();
  // !!! set the groups directly; allow the logic in getGroups(Direction) to happen
  Field field = UpgradePack.class.getDeclaredField("groups");
  field.setAccessible(true);
  field.set(upgradePack, Lists.newArrayList(g));
  field = UpgradePack.class.getDeclaredField("type" );
  field.setAccessible(true);
  field.set(upgradePack, UpgradeType.HOST_ORDERED);
  MasterHostResolver resolver = new MasterHostResolver(m_configHelper, c);
  UpgradeContext context = m_upgradeContextFactory.create(c, UpgradeType.HOST_ORDERED,
      Direction.UPGRADE, "2.2.0", new HashMap<String, Object>());
  context.setResolver(resolver);
  List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgradePack, context);
  assertEquals(1, groups.size());
  UpgradeGroupHolder holder = groups.get(0);
  assertEquals(9, holder.items.size());
  for (int i = 0; i < 7; i++) {
    StageWrapper w = holder.items.get(i);
    if (i == 0 || i == 4) {
      assertEquals(StageWrapper.Type.STOP, w.getType());
    } else if (i == 1 || i == 5) {
      assertEquals(StageWrapper.Type.SERVER_SIDE_ACTION, w.getType());
      assertEquals(1, w.getTasks().size());
      assertEquals(1, w.getTasks().get(0).getTasks().size());
      Task t = w.getTasks().get(0).getTasks().get(0);
      assertEquals(ManualTask.class, t.getClass());
      ManualTask mt = (ManualTask) t;
      assertNotNull(mt.structuredOut);
      assertTrue(mt.structuredOut.contains("type"));
      assertTrue(mt.structuredOut.contains(HostOrderItem.HostOrderActionType.HOST_UPGRADE.toString()));
      assertTrue(mt.structuredOut.contains("host"));
      assertTrue(mt.structuredOut.contains(i == 1 ? "h1" : "h2"));
    } else {
      assertEquals(StageWrapper.Type.RESTART, w.getType());
    }
  }
  assertEquals(StageWrapper.Type.SERVICE_CHECK, holder.items.get(7).getType());
  assertEquals(StageWrapper.Type.SERVICE_CHECK, holder.items.get(8).getType());
  // !!! test downgrade when all host components have failed
  zookeeperServer1.setVersion("2.1.1");
  zookeeperServer2.setVersion("2.1.1");
  hbaseMaster1.setVersion("2.1.1");
  resolver = new MasterHostResolver(m_configHelper, c, "2.1.1");
  m_upgradeContextFactory.create(c, UpgradeType.HOST_ORDERED, Direction.DOWNGRADE,
      "2.1.1", new HashMap<String, Object>());
  context.setResolver(resolver);
  groups = m_upgradeHelper.createSequence(upgradePack, context);
  assertEquals(1, groups.size());
  assertEquals(2, groups.get(0).items.size());
  // !!! test downgrade when one of the hosts had failed
  zookeeperServer1.setVersion("2.1.1");
  zookeeperServer2.setVersion("2.2.0");
  hbaseMaster1.setVersion("2.1.1");
  resolver = new MasterHostResolver(m_configHelper, c, "2.1.1");
  m_upgradeContextFactory.create(c, UpgradeType.HOST_ORDERED, Direction.DOWNGRADE,
      "2.1.1", new HashMap<String, Object>());
  context.setResolver(resolver);
  groups = m_upgradeHelper.createSequence(upgradePack, context);
  assertEquals(1, groups.size());
  assertEquals(5, groups.get(0).items.size());
}