@Test
  public void testInitializationSecondSucceeded() throws Exception {
    DateTime expectedStartTime = new DateTime(0);

    EasyMock.expect(mockFlow1.getName()).andReturn("a").once();
    EasyMock.expect(mockFlow2.getName()).andReturn("b").once();

    EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.READY).times(3);
    EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.SUCCEEDED).times(3);

    EasyMock.expect(mockFlow1.getStartTime()).andReturn(null).once();
    EasyMock.expect(mockFlow2.getStartTime()).andReturn(expectedStartTime).once();

    EasyMock.expect(mockFlow2.getParentProps()).andReturn(props).once();

    EasyMock.expect(mockFlow1.getName()).andReturn("1").once();
    EasyMock.expect(mockFlow2.getName()).andReturn("2").once();

    EasyMock.replay(mockFlow1, mockFlow2, props);

    flow = new GroupedExecutableFlow("blah", mockFlow1, mockFlow2);

    Assert.assertEquals(Status.READY, flow.getStatus());
    Assert.assertEquals(expectedStartTime, flow.getStartTime());
    Assert.assertEquals(null, flow.getEndTime());
    // <<<<<<< HEAD:azkaban/src/unit/azkaban/flow/GroupedExecutableFlowTest.java
    Assert.assertEquals(emptyExceptions, flow.getExceptions());
    Assert.assertEquals(props, flow.getParentProps());
  }
  @Test
  public void testInitializationSecondFailed() throws Exception {
    DateTime expectedStartTime = new DateTime(0);
    DateTime falseStartTime = new DateTime(1);
    DateTime expectedEndTime = new DateTime(100);
    DateTime falseEndTime = new DateTime(99);

    EasyMock.expect(mockFlow1.getName()).andReturn("a").once();
    EasyMock.expect(mockFlow2.getName()).andReturn("b").once();

    EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.READY).times(2);
    EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.FAILED).times(2);

    EasyMock.expect(mockFlow1.getStartTime()).andReturn(expectedStartTime).once();
    EasyMock.expect(mockFlow1.getEndTime()).andReturn(falseEndTime).once();
    EasyMock.expect(mockFlow2.getStartTime()).andReturn(falseStartTime).once();
    EasyMock.expect(mockFlow2.getEndTime()).andReturn(expectedEndTime).once();

    EasyMock.expect(mockFlow2.getParentProps()).andReturn(props).once();

    EasyMock.expect(mockFlow1.getName()).andReturn("1").once();
    EasyMock.expect(mockFlow2.getName()).andReturn("2").once();

    EasyMock.replay(mockFlow1, mockFlow2, props);

    flow = new GroupedExecutableFlow("blah", mockFlow1, mockFlow2);

    Assert.assertEquals(Status.FAILED, flow.getStatus());
    Assert.assertEquals(expectedStartTime, flow.getStartTime());
    Assert.assertEquals(expectedEndTime, flow.getEndTime());
    Assert.assertEquals(emptyExceptions, flow.getExceptions());
    Assert.assertEquals(props, flow.getParentProps());
  }
  @Before
  public void setUp() throws Exception {
    props = EasyMock.createStrictMock(Props.class);
    mockFlow1 = EasyMock.createMock(ExecutableFlow.class);
    mockFlow2 = EasyMock.createMock(ExecutableFlow.class);

    EasyMock.expect(mockFlow1.getName()).andReturn("a").once();
    EasyMock.expect(mockFlow2.getName()).andReturn("b").once();

    EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.READY).times(3);
    EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.READY).times(3);

    EasyMock.expect(mockFlow1.getStartTime()).andReturn(null).once();
    EasyMock.expect(mockFlow2.getStartTime()).andReturn(null).once();

    EasyMock.expect(mockFlow1.getName()).andReturn("1").once();
    EasyMock.expect(mockFlow2.getName()).andReturn("2").once();
    EasyMock.replay(mockFlow1, mockFlow2, props);

    flow = new GroupedExecutableFlow("blah", mockFlow1, mockFlow2);
    Assert.assertEquals("1 + 2", flow.getName());

    EasyMock.verify(mockFlow1, mockFlow2, props);
    EasyMock.reset(mockFlow1, mockFlow2, props);
  }
  @Test
  public void testInitializationSecondRunning() throws Exception {
    DateTime expectedStartTime = new DateTime(0);

    EasyMock.expect(mockFlow1.getName()).andReturn("a").once();
    EasyMock.expect(mockFlow2.getName()).andReturn("b").once();

    EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.READY).times(3);
    EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.RUNNING).times(3);

    EasyMock.expect(mockFlow1.getStartTime()).andReturn(null).once();
    EasyMock.expect(mockFlow2.getStartTime()).andReturn(expectedStartTime).once();

    Capture<FlowCallback> callbackCapture = new Capture<FlowCallback>();
    mockFlow2.execute(EasyMock.eq(props), EasyMock.capture(callbackCapture));

    EasyMock.expect(mockFlow1.getName()).andReturn("1").once();
    EasyMock.expect(mockFlow2.getName()).andReturn("2").once();

    EasyMock.expect(mockFlow2.getParentProps()).andReturn(props).once();

    EasyMock.replay(mockFlow1, mockFlow2, props);

    flow = new GroupedExecutableFlow("blah", mockFlow1, mockFlow2);

    Assert.assertEquals(Status.READY, flow.getStatus());
    Assert.assertEquals(expectedStartTime, flow.getStartTime());
    Assert.assertEquals(null, flow.getEndTime());
    Assert.assertEquals(props, flow.getParentProps());

    EasyMock.verify(mockFlow1, mockFlow2, props);
    EasyMock.reset(mockFlow1, mockFlow2, props);

    EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.READY).once();
    EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.SUCCEEDED).once();

    EasyMock.replay(mockFlow1, mockFlow2, props);

    callbackCapture.getValue().completed(Status.SUCCEEDED);

    Assert.assertEquals(Status.READY, flow.getStatus());
    Assert.assertEquals(expectedStartTime, flow.getStartTime());
    Assert.assertEquals(null, flow.getEndTime());
    Assert.assertEquals(emptyExceptions, flow.getExceptions());
  }
  @Test
  public void testInitializationBothRunning() throws Exception {
    DateTime expectedStartTime = new DateTime(0);
    DateTime falseStartTime = new DateTime(1);

    EasyMock.expect(mockFlow1.getName()).andReturn("a").once();
    EasyMock.expect(mockFlow2.getName()).andReturn("b").once();

    EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.RUNNING).times(3);
    EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.RUNNING).times(3);

    EasyMock.expect(mockFlow1.getStartTime()).andReturn(falseStartTime).once();
    EasyMock.expect(mockFlow2.getStartTime()).andReturn(expectedStartTime).once();

    Capture<FlowCallback> callbackCapture1 = new Capture<FlowCallback>();
    Capture<FlowCallback> callbackCapture2 = new Capture<FlowCallback>();
    mockFlow1.execute(EasyMock.eq(props), EasyMock.capture(callbackCapture1));
    mockFlow2.execute(EasyMock.eq(props), EasyMock.capture(callbackCapture2));

    EasyMock.expect(mockFlow1.getParentProps()).andReturn(props).once();
    EasyMock.expect(mockFlow2.getParentProps()).andReturn(props).once();
    EasyMock.expect(props.equalsProps(props)).andReturn(true).once();

    EasyMock.expect(mockFlow1.getName()).andReturn("1").once();
    EasyMock.expect(mockFlow2.getName()).andReturn("2").once();

    EasyMock.replay(mockFlow1, mockFlow2, props);

    flow = new GroupedExecutableFlow("blah", mockFlow1, mockFlow2);

    Assert.assertEquals(Status.RUNNING, flow.getStatus());
    Assert.assertEquals(expectedStartTime, flow.getStartTime());
    Assert.assertEquals(null, flow.getEndTime());

    EasyMock.verify(mockFlow1, mockFlow2, props);
    EasyMock.reset(mockFlow1, mockFlow2, props);

    EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.RUNNING).once();
    EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.SUCCEEDED).once();

    EasyMock.replay(mockFlow1, mockFlow2, props);

    Assert.assertSame(callbackCapture1.getValue(), callbackCapture2.getValue());

    callbackCapture1.getValue().completed(Status.SUCCEEDED);

    Assert.assertEquals(Status.RUNNING, flow.getStatus());
    Assert.assertEquals(expectedStartTime, flow.getStartTime());
    Assert.assertEquals(null, flow.getEndTime());
    Assert.assertEquals(emptyExceptions, flow.getExceptions());
    Assert.assertEquals(props, flow.getParentProps());

    EasyMock.verify(mockFlow1, mockFlow2, props);
    EasyMock.reset(mockFlow1, mockFlow2, props);

    EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.SUCCEEDED).once();
    EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.SUCCEEDED).once();

    EasyMock.expect(mockFlow1.getReturnProps()).andReturn(new Props()).once();
    EasyMock.expect(mockFlow2.getReturnProps()).andReturn(new Props()).once();

    EasyMock.replay(mockFlow1, mockFlow2, props);

    DateTime beforeTheEnd = new DateTime();
    callbackCapture2.getValue().completed(Status.SUCCEEDED);

    Assert.assertEquals(Status.SUCCEEDED, flow.getStatus());
    Assert.assertEquals(expectedStartTime, flow.getStartTime());
    Assert.assertFalse(
        String.format(
            "flow's end time[%s] should be after beforeTheEnd[%s]",
            flow.getEndTime(), beforeTheEnd),
        beforeTheEnd.isAfter(flow.getEndTime()));
    Assert.assertEquals(emptyExceptions, flow.getExceptions());
  }