@Test
  public void testServiceComponentUpdateRecursive() throws Exception, AuthorizationException {
    String cluster1 = getUniqueName();

    createCluster(cluster1);
    String serviceName1 = "HDFS";
    createService(cluster1, serviceName1, null);
    String componentName1 = "NAMENODE";
    String componentName2 = "DATANODE";
    String componentName3 = "HDFS_CLIENT";
    createServiceComponent(cluster1, serviceName1, componentName1,
        State.INIT);
    createServiceComponent(cluster1, serviceName1, componentName2,
        State.INIT);
    createServiceComponent(cluster1, serviceName1, componentName3,
        State.INIT);

    String host1 = getUniqueName();
    String host2 = getUniqueName();

    addHostToCluster(host1, cluster1);
    addHostToCluster(host2, cluster1);

    Set<ServiceComponentHostRequest> set1 =
      new HashSet<>();
    ServiceComponentHostRequest r1 =
        new ServiceComponentHostRequest(cluster1, serviceName1,
            componentName1, host1, State.INIT.toString());
    ServiceComponentHostRequest r2 =
        new ServiceComponentHostRequest(cluster1, serviceName1,
            componentName2, host1, State.INIT.toString());
    ServiceComponentHostRequest r3 =
        new ServiceComponentHostRequest(cluster1, serviceName1,
            componentName1, host2, State.INIT.toString());
    ServiceComponentHostRequest r4 =
        new ServiceComponentHostRequest(cluster1, serviceName1,
            componentName2, host2, State.INIT.toString());
    ServiceComponentHostRequest r5 =
        new ServiceComponentHostRequest(cluster1, serviceName1,
            componentName3, host1, State.INIT.toString());

    set1.add(r1);
    set1.add(r2);
    set1.add(r3);
    set1.add(r4);
    set1.add(r5);
    controller.createHostComponents(set1);

    Cluster c1 = clusters.getCluster(cluster1);
    Service s1 = c1.getService(serviceName1);
    ServiceComponent sc1 = s1.getServiceComponent(componentName1);
    ServiceComponent sc2 = s1.getServiceComponent(componentName2);
    ServiceComponent sc3 = s1.getServiceComponent(componentName3);
    ServiceComponentHost sch1 = sc1.getServiceComponentHost(host1);
    ServiceComponentHost sch2 = sc2.getServiceComponentHost(host1);
    ServiceComponentHost sch3 = sc1.getServiceComponentHost(host2);
    ServiceComponentHost sch4 = sc2.getServiceComponentHost(host2);
    ServiceComponentHost sch5 = sc3.getServiceComponentHost(host1);

    s1.setDesiredState(State.INSTALLED);
    sc1.setDesiredState(State.INIT);
    sc2.setDesiredState(State.INIT);
    sc3.setDesiredState(State.STARTED);
    sch1.setDesiredState(State.INSTALLED);
    sch2.setDesiredState(State.INSTALLED);
    sch3.setDesiredState(State.STARTED);
    sch4.setDesiredState(State.INSTALLED);
    sch5.setDesiredState(State.INSTALLED);
    sch1.setState(State.INSTALLED);
    sch2.setState(State.INSTALLED);
    sch3.setState(State.STARTED);
    sch4.setState(State.INSTALLED);
    sch5.setState(State.UNKNOWN);

    Set<ServiceComponentRequest> reqs =
      new HashSet<>();
    ServiceComponentRequest req1, req2, req3;

    // confirm an UNKOWN doesn't fail
    req1 = new ServiceComponentRequest(cluster1, serviceName1,
        sc3.getName(), State.INSTALLED.toString());
    reqs.add(req1);
    ComponentResourceProviderTest.updateComponents(controller, reqs, Collections.emptyMap(), true);
    try {
      reqs.clear();
      req1 = new ServiceComponentRequest(cluster1, serviceName1,
          sc1.getName(), State.INIT.toString());
      reqs.add(req1);
      ComponentResourceProviderTest.updateComponents(controller, reqs, Collections.emptyMap(), true);
      fail("Expected failure for invalid state update");
    } catch (Exception e) {
      // Expected
    }

    s1.setDesiredState(State.INSTALLED);
    sc1.setDesiredState(State.STARTED);
    sc2.setDesiredState(State.INSTALLED);
    sc3.setDesiredState(State.STARTED);
    sch1.setDesiredState(State.INIT);
    sch2.setDesiredState(State.INIT);
    sch3.setDesiredState(State.INIT);
    sch4.setDesiredState(State.INIT);
    sch5.setDesiredState(State.INIT);
    sch1.setState(State.INIT);
    sch2.setState(State.INSTALLED);
    sch3.setState(State.INIT);
    sch4.setState(State.INSTALLED);
    sch5.setState(State.INSTALLED);

    try {
      reqs.clear();
      req1 = new ServiceComponentRequest(cluster1, serviceName1,
          sc1.getName(), State.STARTED.toString());
      reqs.add(req1);
      ComponentResourceProviderTest.updateComponents(controller, reqs, Collections.emptyMap(), true);
      fail("Expected failure for invalid state update");
    } catch (Exception e) {
      // Expected
    }

    s1.setDesiredState(State.INSTALLED);
    sc1.setDesiredState(State.STARTED);
    sc2.setDesiredState(State.INIT);
    sc3.setDesiredState(State.STARTED);
    sch1.setDesiredState(State.INIT);
    sch2.setDesiredState(State.INIT);
    sch3.setDesiredState(State.INIT);
    sch4.setDesiredState(State.INIT);
    sch5.setDesiredState(State.INIT);
    sch1.setState(State.STARTED);
    sch2.setState(State.INIT);
    sch3.setState(State.INSTALLED);
    sch4.setState(State.STARTED);
    sch5.setState(State.INIT);

    reqs.clear();
    req1 = new ServiceComponentRequest(cluster1, serviceName1,
        sc1.getName(), State.INSTALLED.toString());
    req2 = new ServiceComponentRequest(cluster1, serviceName1,
        sc2.getName(), State.INSTALLED.toString());
    req3 = new ServiceComponentRequest(cluster1, serviceName1,
        sc3.getName(), State.INSTALLED.toString());
    reqs.add(req1);
    reqs.add(req2);
    reqs.add(req3);
    RequestStatusResponse trackAction = ComponentResourceProviderTest.updateComponents(controller, reqs, Collections.emptyMap(), true);

    Assert.assertEquals(State.INSTALLED, s1.getDesiredState());
    Assert.assertEquals(State.INSTALLED, sc1.getDesiredState());
    Assert.assertEquals(State.INSTALLED, sc2.getDesiredState());
    Assert.assertEquals(State.INSTALLED, sc3.getDesiredState());
    Assert.assertEquals(State.INSTALLED, sch1.getDesiredState());
    Assert.assertEquals(State.INSTALLED, sch2.getDesiredState());
    Assert.assertEquals(State.INSTALLED, sch3.getDesiredState());
    Assert.assertEquals(State.INSTALLED, sch4.getDesiredState());
    Assert.assertEquals(State.INSTALLED, sch5.getDesiredState());
    Assert.assertEquals(State.STARTED, sch1.getState());
    Assert.assertEquals(State.INIT, sch2.getState());
    Assert.assertEquals(State.INSTALLED, sch3.getState());
    Assert.assertEquals(State.STARTED, sch4.getState());
    Assert.assertEquals(State.INIT, sch5.getState());

    long requestId = trackAction.getRequestId();
    List<Stage> stages = actionDB.getAllStages(requestId);
    Assert.assertTrue(!stages.isEmpty());

    // FIXME check stage count

    for (Stage stage : stages) {
      LOG.debug("Stage dump: {}", stage);
    }

    // FIXME verify stages content - execution commands, etc

    // maually set live state
    sch1.setState(State.INSTALLED);
    sch2.setState(State.INSTALLED);
    sch3.setState(State.INSTALLED);
    sch4.setState(State.INSTALLED);
    sch5.setState(State.INSTALLED);

    // test no-op
    reqs.clear();
    req1 = new ServiceComponentRequest(cluster1, serviceName1,
        sc1.getName(), State.INSTALLED.toString());
    req2 = new ServiceComponentRequest(cluster1, serviceName1,
        sc2.getName(), State.INSTALLED.toString());
    reqs.add(req1);
    reqs.add(req2);
    trackAction = ComponentResourceProviderTest.updateComponents(controller, reqs, Collections.emptyMap(), true);
    Assert.assertNull(trackAction);
  }
Create a cluster with a service, and verify that the request tasks have the correct output log and error log paths.
ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java