Package azkaban.flow

Source Code of azkaban.flow.GroupedExecutableFlowTest

package azkaban.flow;

import azkaban.app.JobManager;
import azkaban.common.utils.Props;
import azkaban.jobs.Status;

import org.easymock.Capture;
import org.easymock.IAnswer;
import org.easymock.classextension.EasyMock;
import org.joda.time.DateTime;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
*
*/
public class GroupedExecutableFlowTest
{
    private volatile Props props;
    private volatile ExecutableFlow mockFlow1;
    private volatile ExecutableFlow mockFlow2;

    private volatile GroupedExecutableFlow flow;

   private static Map<String,Throwable> theExceptions;
   private static Map<String,Throwable> emptyExceptions;
  
   
    @BeforeClass
    public static void init() throws Exception {
      theExceptions = new HashMap<String,Throwable>();
      theExceptions.put("main", new RuntimeException());
     
      emptyExceptions = new HashMap<String, Throwable>();
    }
   
    @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);
    }

    @After
    public void tearDown() throws Exception
    {
        EasyMock.verify(mockFlow1);
        EasyMock.verify(mockFlow2);
        EasyMock.verify(props);
    }

    @Test
    public void testSanity() throws Exception
    {
        final AtomicLong numJobsComplete = new AtomicLong(0);

        /**** Setup mockFlow1 ****/
        final Capture<FlowCallback> flow1Callback = new Capture<FlowCallback>();
        mockFlow1.execute(EasyMock.eq(props), EasyMock.capture(flow1Callback));
        EasyMock.expectLastCall().andAnswer(new IAnswer<Void>() {
            @Override
            public Void answer() throws Throwable {
                Assert.assertEquals(Status.RUNNING, flow.getStatus());
                Assert.assertEquals(1, numJobsComplete.incrementAndGet());

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

                Assert.assertEquals(Status.RUNNING, flow.getStatus());

                return null;
            }
        }).once();

        Props mockFlow1Props = new Props();
        mockFlow1Props.put("1", "1");
        mockFlow1Props.put("2", "1");

        EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.SUCCEEDED).times(2);
        EasyMock.expect(mockFlow1.getReturnProps()).andReturn(mockFlow1Props).once();

        /**** Setup mockFlow2 ****/
        final Capture<FlowCallback> flow2Callback = new Capture<FlowCallback>();
        mockFlow2.execute(EasyMock.eq(props), EasyMock.capture(flow2Callback));
        EasyMock.expectLastCall().andAnswer(new IAnswer<Void>() {
            @Override
            public Void answer() throws Throwable {
                Assert.assertEquals(Status.RUNNING, flow.getStatus());
                Assert.assertEquals(2, numJobsComplete.incrementAndGet());

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

                Assert.assertEquals(Status.SUCCEEDED, flow.getStatus());

                return null;
            }
        }).once();

        EasyMock.expect(mockFlow2.getStatus()).andAnswer(new IAnswer<Status>()
        {
            private volatile AtomicInteger count = new AtomicInteger(0);

            @Override
            public Status answer() throws Throwable
            {
                switch (count.getAndIncrement()) {
                    case 0: return Status.READY;
                    case 1: return Status.SUCCEEDED;
                    default: Assert.fail("mockFlow2.getStatus() should only be called 2 times.");
                }
                return null;
            }
        }).times(2);

        Props mockFlow2Props = new Props();
        mockFlow2Props.put("2", "2");
        mockFlow2Props.put("3", "2");
        EasyMock.expect(mockFlow2.getReturnProps()).andReturn(mockFlow2Props).once();

        EasyMock.expect(props.equalsProps(props)).andReturn(true).once();

        EasyMock.replay(mockFlow1, mockFlow2, props);

        /**** Start the test ****/
        AtomicBoolean callbackRan = new AtomicBoolean(false);
        flow.execute(
                props,
                new OneCallFlowCallback(callbackRan) {
                    @Override
                    public void theCallback(Status status) {
                        Assert.assertEquals(Status.SUCCEEDED, status);
                        Assert.assertEquals(2, numJobsComplete.get());
                    }
                });

        Assert.assertTrue("Callback wasn't run.", callbackRan.get());
        Assert.assertEquals(Status.SUCCEEDED, flow.getStatus());
        Assert.assertEquals(emptyExceptions, flow.getExceptions());
        Assert.assertEquals(props, flow.getParentProps());

        callbackRan = new AtomicBoolean(false);
        flow.execute(
                props,
                new OneCallFlowCallback(callbackRan)
                {
                    @Override
                    protected void theCallback(Status status)
                    {
                        Assert.assertEquals(Status.SUCCEEDED, status);
                        Assert.assertEquals(2, numJobsComplete.get());
                    }
                });

        Assert.assertTrue("Callback wasn't run.", callbackRan.get());
        Assert.assertEquals(Status.SUCCEEDED, flow.getStatus());
        Assert.assertEquals(emptyExceptions, flow.getExceptions());

        Props retProps = flow.getReturnProps();
        Assert.assertEquals(3, retProps.size());
        Assert.assertEquals("1", retProps.get("1"));
        Assert.assertEquals("2", retProps.get("2"));
        Assert.assertEquals("2", retProps.get("3"));

        EasyMock.verify(props);
        EasyMock.reset(props);

        EasyMock.expect(props.equalsProps(props)).andReturn(false).once();

        EasyMock.replay(props);

        boolean exceptionThrown = false;
        try {
            flow.execute(
                    props,
                    new FlowCallback() {
                        @Override
                        public void progressMade() {
                        }

                        @Override
                        public void completed(Status status) {
                        }
                    }
            );
        }
        catch (IllegalArgumentException e) {
            exceptionThrown = true;
        }

        Assert.assertTrue("Expected an IllegalArgumentException to be thrown because props weren't the same.", exceptionThrown);
    }

    @Test
    public void testFailureJob1() throws Exception
    {
   
      final AtomicLong numJobsComplete = new AtomicLong(0);

        /**** Setup mockFlow1 ****/
        final Capture<FlowCallback> flow1Callback = new Capture<FlowCallback>();
        mockFlow1.execute(EasyMock.eq(props), EasyMock.capture(flow1Callback));
        EasyMock.expectLastCall().andAnswer(new IAnswer<Void>() {
            @Override
            public Void answer() throws Throwable {
                Assert.assertEquals(Status.RUNNING, flow.getStatus());
                Assert.assertEquals(1, numJobsComplete.incrementAndGet());

                flow1Callback.getValue().completed(Status.FAILED);

                return null;
            }
        }).once();

        EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.FAILED).times(1);
        EasyMock.expect(mockFlow1.getExceptions()).andReturn(theExceptions).times(1);

        EasyMock.expect(props.equalsProps(props)).andReturn(true).once();

        /**** Setup mockFlow2 ****/
        EasyMock.expect(mockFlow2.getExceptions()).andReturn(emptyExceptions).times(1);
        EasyMock.replay(mockFlow1, mockFlow2, props);

        /**** Start the test ****/
        AtomicBoolean callbackRan = new AtomicBoolean(false);
        flow.execute(
                props,
                new OneCallFlowCallback(callbackRan) {
                    @Override
                    public void theCallback(Status status) {
                        Assert.assertEquals(Status.FAILED, status);
                    }
                });

        Assert.assertTrue("Callback wasn't run.", callbackRan.get());
        Assert.assertEquals(Status.FAILED, flow.getStatus());
        Assert.assertEquals(theExceptions, flow.getExceptions());

        callbackRan = new AtomicBoolean(false);
        flow.execute(
                props,
                new OneCallFlowCallback(callbackRan)
                {
                    @Override
                    protected void theCallback(Status status)
                    {
                        Assert.assertEquals(Status.FAILED, status);
                    }
                });

        Assert.assertTrue("Callback wasn't run.", callbackRan.get());
        Assert.assertEquals(Status.FAILED, flow.getStatus());
        Assert.assertEquals(theExceptions, flow.getExceptions());

        Assert.assertTrue("Expected to be able to reset the flow", flow.reset());
        Assert.assertEquals(Status.READY, flow.getStatus());
        Assert.assertEquals(emptyExceptions, flow.getExceptions());
    }

    @Test
    public void testFailureJob2() throws Exception
    {
   
      final AtomicLong numJobsComplete = new AtomicLong(0);

        /**** Setup mockFlow1 ****/
        final Capture<FlowCallback> flow1Callback = new Capture<FlowCallback>();
        mockFlow1.execute(EasyMock.eq(props), EasyMock.capture(flow1Callback));
        EasyMock.expectLastCall().andAnswer(new IAnswer<Void>() {
            @Override
            public Void answer() throws Throwable {
                Assert.assertEquals(Status.RUNNING, flow.getStatus());
                Assert.assertEquals(1, numJobsComplete.incrementAndGet());

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

                return null;
            }
        }).once();

        EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.SUCCEEDED).times(2);
        EasyMock.expect(mockFlow1.getExceptions()).andReturn(emptyExceptions).times(1);

        /**** Setup mockFlow2 ****/
        final Capture<FlowCallback> flow2Callback = new Capture<FlowCallback>();
        mockFlow2.execute(EasyMock.eq(props), EasyMock.capture(flow2Callback));
        EasyMock.expectLastCall().andAnswer(new IAnswer<Void>() {
            @Override
            public Void answer() throws Throwable {
                Assert.assertEquals(Status.RUNNING, flow.getStatus());
                Assert.assertEquals(2, numJobsComplete.incrementAndGet());

                flow2Callback.getValue().completed(Status.FAILED);

                return null;
            }
        }).once();

        EasyMock.expect(mockFlow2.getStatus()).andAnswer(new IAnswer<Status>()
        {
            private volatile AtomicInteger count = new AtomicInteger(0);

            @Override
            public Status answer() throws Throwable
            {
                switch (count.getAndIncrement()) {
                    case 0: return Status.READY;
                    case 1: return Status.FAILED;
                    default: Assert.fail("mockFlow2.getStatus() should only be called 2 times.");
                }
                return null;
            }
        }).times(2);

      final RuntimeException e1 = new RuntimeException();
      final RuntimeException e2 = new RuntimeException();
     
      final Map<String, Throwable> e1s = new HashMap<String, Throwable>();
      e1s.put("e1", e1);
      e1s.put("e2", e2);

      EasyMock.expect(mockFlow2.getExceptions()).andReturn(e1s).times(1);
        EasyMock.expect(props.equalsProps(props)).andReturn(true).once();

        EasyMock.replay(mockFlow1, mockFlow2, props);

        /**** Start the test ****/
        AtomicBoolean callbackRan = new AtomicBoolean(false);
        flow.execute(
                props,
                new OneCallFlowCallback(callbackRan) {
                    @Override
                    public void theCallback(Status status) {
                        Assert.assertEquals(Status.FAILED, status);
                    }
                });

        Assert.assertTrue("Callback wasn't run.", callbackRan.get());
        Assert.assertEquals(Status.FAILED, flow.getStatus());
        Assert.assertEquals(e1s, flow.getExceptions());

        callbackRan = new AtomicBoolean(false);
        flow.execute(
                props,
                new OneCallFlowCallback(callbackRan)
                {
                    @Override
                    protected void theCallback(Status status)
                    {
                        Assert.assertEquals(Status.FAILED, status);
                        Assert.assertEquals(2, numJobsComplete.get());
                    }
                });

        Assert.assertTrue("Callback wasn't run.", callbackRan.get());
        Assert.assertEquals(Status.FAILED, flow.getStatus());
        Assert.assertEquals(e1s, flow.getExceptions());

        Assert.assertTrue("Expected to be able to reset the flow", flow.reset());
        Assert.assertEquals(Status.READY, flow.getStatus());
        Assert.assertEquals(emptyExceptions, flow.getExceptions());
    }

    @Test
    public void testAllCallbacksCalled() throws Exception
    {
        final AtomicLong numJobsComplete = new AtomicLong(0);
        final AtomicBoolean executeCallWhileStateWasRunningHadItsCallbackCalled = new AtomicBoolean(false);

        /**** Setup mockFlow1 ****/
        final Capture<FlowCallback> flow1Callback = new Capture<FlowCallback>();
        mockFlow1.execute(EasyMock.eq(props), EasyMock.capture(flow1Callback));
        EasyMock.expectLastCall().andAnswer(new IAnswer<Void>() {
            @Override
            public Void answer() throws Throwable {
                Assert.assertEquals(Status.RUNNING, flow.getStatus());
                Assert.assertEquals(1, numJobsComplete.incrementAndGet());

                flow.execute(
                        props,
                        new OneCallFlowCallback(executeCallWhileStateWasRunningHadItsCallbackCalled)
                        {
                            @Override
                            protected void theCallback(Status status)
                            {
                            }
                        });

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

                return null;
            }
        }).once();

        EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.SUCCEEDED).times(2);

        /**** Setup mockFlow2 ****/
        final Capture<FlowCallback> flow2Callback = new Capture<FlowCallback>();
        mockFlow2.execute(EasyMock.eq(props), EasyMock.capture(flow2Callback));
        EasyMock.expectLastCall().andAnswer(new IAnswer<Void>() {
            @Override
            public Void answer() throws Throwable {
                Assert.assertEquals(Status.RUNNING, flow.getStatus());
                Assert.assertEquals(2, numJobsComplete.incrementAndGet());

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

                return null;
            }
        }).once();

        EasyMock.expect(mockFlow2.getStatus()).andAnswer(new IAnswer<Status>()
        {
            private volatile AtomicInteger count = new AtomicInteger(0);

            @Override
            public Status answer() throws Throwable
            {
                switch (count.getAndIncrement()) {
                    case 0: return Status.READY;
                    case 1: return Status.SUCCEEDED;
                    default: Assert.fail("mockFlow2.getStatus() should only be called 2 times.");
                }
                return null;
            }
        }).times(2);

        EasyMock.expect(mockFlow1.getReturnProps()).andReturn(new Props()).once();
        EasyMock.expect(mockFlow2.getReturnProps()).andReturn(new Props()).once();
       
        EasyMock.expect(props.equalsProps(props)).andReturn(true).times(2);

        EasyMock.replay(mockFlow1, mockFlow2, props);

        /**** Start the test ****/
        AtomicBoolean callbackRan = new AtomicBoolean(false);
        flow.execute(
                props,
                new OneCallFlowCallback(callbackRan) {
                    @Override
                    public void theCallback(Status status) {
                        Assert.assertEquals(Status.SUCCEEDED, status);
                        Assert.assertEquals(2, numJobsComplete.get());
                    }
                });

        Assert.assertTrue("Callback wasn't run.", callbackRan.get());
        Assert.assertEquals(Status.SUCCEEDED, flow.getStatus());
        Assert.assertTrue("mockFlow1, upon completion, sends another execute() call to the flow.  " +
                          "The callback from that execute call was apparently not called.",
                          executeCallWhileStateWasRunningHadItsCallbackCalled.get());
        Assert.assertEquals(emptyExceptions, flow.getExceptions());

        callbackRan = new AtomicBoolean(false);
        flow.execute(
                props,
                new OneCallFlowCallback(callbackRan)
                {
                    @Override
                    protected void theCallback(Status status)
                    {
                        Assert.assertEquals(Status.SUCCEEDED, status);
                        Assert.assertEquals(2, numJobsComplete.get());
                    }
                });

        Assert.assertTrue("Callback wasn't run.", callbackRan.get());
        Assert.assertEquals(Status.SUCCEEDED, flow.getStatus());
        Assert.assertEquals(emptyExceptions, flow.getExceptions());
    }

    @Test
    public void testChildren() throws Exception
    {
        EasyMock.replay(mockFlow1, mockFlow2, props);

        Assert.assertTrue("GroupedExecutableFlow should have children.", flow.hasChildren());
        Assert.assertEquals(2, flow.getChildren().size());
        Assert.assertEquals(mockFlow1, flow.getChildren().get(0));
        Assert.assertEquals(mockFlow2, flow.getChildren().get(1));
    }

    @Test
    public void testAllBaseJobsCompleted() throws Exception
    {
        EasyMock.replay(mockFlow1, mockFlow2, props);

        final JobManager factory = EasyMock.createStrictMock(JobManager.class);
        EasyMock.replay(factory);

        final IndividualJobExecutableFlow completedJob1 = new IndividualJobExecutableFlow("blah", "blah", factory);
        final IndividualJobExecutableFlow completedJob2 = new IndividualJobExecutableFlow("blah", "blah", factory);

        flow = new GroupedExecutableFlow(
                "blah",
                completedJob1,
                completedJob2
        );

        completedJob1.markCompleted();
        completedJob2.markCompleted();

        AtomicBoolean callbackWasCalled = new AtomicBoolean(false);
        flow.execute(
                props,
                new OneCallFlowCallback(callbackWasCalled)
                {
                    @Override
                    public void theCallback(Status status)
                    {
                        Assert.assertEquals(Status.SUCCEEDED, status);
                    }
                });

        Assert.assertTrue("Callback wasn't called!?", callbackWasCalled.get());
        EasyMock.verify(factory);
    }

    @Test
    public void testInitializationFirstSucceeded() 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.SUCCEEDED).times(3);
        EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.READY).times(3);

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

        EasyMock.expect(mockFlow1.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());
        Assert.assertEquals(emptyExceptions, flow.getExceptions());
        Assert.assertEquals(props, flow.getParentProps());
    }

    @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 testInitializationBothSucceeded1() 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.SUCCEEDED).times(2);
        EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.SUCCEEDED).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(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.expect(mockFlow1.getReturnProps()).andReturn(new Props()).once();
        EasyMock.expect(mockFlow2.getReturnProps()).andReturn(new Props()).once();

        EasyMock.replay(mockFlow1, mockFlow2, props);

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

        Assert.assertEquals(Status.SUCCEEDED, flow.getStatus());
        Assert.assertEquals(expectedStartTime, flow.getStartTime());
        Assert.assertEquals(expectedEndTime, flow.getEndTime());
        Assert.assertEquals(emptyExceptions, flow.getExceptions());
        Assert.assertEquals(props, flow.getParentProps());
    }

    @Test
    public void testInitializationBothSucceeded2() 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.SUCCEEDED).times(2);
        EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.SUCCEEDED).times(2);

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

        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.expect(mockFlow1.getReturnProps()).andReturn(new Props()).once();
        EasyMock.expect(mockFlow2.getReturnProps()).andReturn(new Props()).once();

        EasyMock.replay(mockFlow1, mockFlow2, props);

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

        Assert.assertEquals(Status.SUCCEEDED, flow.getStatus());
        Assert.assertEquals(expectedStartTime, flow.getStartTime());
        Assert.assertEquals(expectedEndTime, flow.getEndTime());
        Assert.assertEquals(emptyExceptions, flow.getExceptions());
        Assert.assertEquals(props, flow.getParentProps());
    }

    @Test
    public void testInitializationBothSucceeded3() 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.SUCCEEDED).times(2);
        EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.SUCCEEDED).times(2);

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

        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.expect(mockFlow1.getReturnProps()).andReturn(new Props()).once();
        EasyMock.expect(mockFlow2.getReturnProps()).andReturn(new Props()).once();

        EasyMock.replay(mockFlow1, mockFlow2, props);

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

        Assert.assertEquals(Status.SUCCEEDED, flow.getStatus());
        Assert.assertEquals(expectedStartTime, flow.getStartTime());
        Assert.assertEquals(expectedEndTime, flow.getEndTime());
        Assert.assertEquals(emptyExceptions, flow.getExceptions());
        Assert.assertEquals(props, flow.getParentProps());
    }


    @Test
    public void testInitializationBothSucceeded4() 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.SUCCEEDED).times(2);
        EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.SUCCEEDED).times(2);

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

        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.expect(mockFlow1.getReturnProps()).andReturn(new Props()).once();
        EasyMock.expect(mockFlow2.getReturnProps()).andReturn(new Props()).once();

        EasyMock.replay(mockFlow1, mockFlow2, props);

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

        Assert.assertEquals(Status.SUCCEEDED, flow.getStatus());
        Assert.assertEquals(expectedStartTime, flow.getStartTime());
        Assert.assertEquals(expectedEndTime, flow.getEndTime());
        Assert.assertEquals(emptyExceptions, flow.getExceptions());
        Assert.assertEquals(props, flow.getParentProps());
    }

    @Test
    public void testInitializationFirstFailed() 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.FAILED).times(2);
        EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.READY).times(1);

        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(mockFlow1.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());
    }

    @Test
    public void testInitializationFirstFailedSecondReady() throws Exception
    {
        DateTime expectedStartTime = new DateTime(0);
        DateTime expectedEndTime = new DateTime(100);

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

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

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

        EasyMock.expect(mockFlow1.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());
    }

    @Test
    public void testInitializationFirstFailedSecondRunning() throws Exception
    {
        DateTime expectedStartTime = new DateTime(0);
        DateTime falseStartTime = new DateTime(1);
        DateTime expectedEndTime = new DateTime(100);

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

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

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

        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.FAILED, flow.getStatus());
        Assert.assertEquals(expectedStartTime, flow.getStartTime());
        Assert.assertEquals(expectedEndTime, flow.getEndTime());
        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());
    }

    @Test
    public void testInitializationFirstRunning() 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.RUNNING).times(3);
        EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.READY).times(3);

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

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

        EasyMock.expect(mockFlow1.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());
        Assert.assertEquals(props, flow.getParentProps());

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

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

        EasyMock.replay(mockFlow1, mockFlow2);

        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 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());
    }
   
   
   
    @Test
    public void testBothFailured() throws Exception
    {
   
      final RuntimeException e1 = new RuntimeException();
      final RuntimeException e2 = new RuntimeException();
     
      final Map<String, Throwable> e1s = new HashMap<String, Throwable>();
      e1s.put("e1", e1);
     
      final Map<String, Throwable> e2s = new HashMap<String, Throwable>();
      e2s.put("e2", e2);
     
      final Map<String, Throwable> expected = new HashMap<String, Throwable>();
      expected.putAll(e1s);
      expected.putAll(e2s);
     
      final AtomicLong numJobsComplete = new AtomicLong(0);

      /**** Setup mockFlow1 ****/
      final Capture<FlowCallback> flow1Callback = new Capture<FlowCallback>();
     
      mockFlow1.execute(EasyMock.eq(props), EasyMock.capture(flow1Callback));
      EasyMock.expectLastCall().andAnswer(new IAnswer<Void>() {
          @Override
          public Void answer() throws Throwable {
              Assert.assertEquals(Status.RUNNING, flow.getStatus());
              Assert.assertEquals(1, numJobsComplete.incrementAndGet());

              flow1Callback.getValue().completed(Status.FAILED);

              return null;
          }
      }).once();

      EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.SUCCEEDED).times(2);
      EasyMock.expect(mockFlow1.getExceptions()).andReturn(e1s).times(1);

      /**** Setup mockFlow2 ****/
      final Capture<FlowCallback> flow2Callback = new Capture<FlowCallback>();
     
      mockFlow2.execute(EasyMock.eq(props), EasyMock.capture(flow2Callback));
     
      EasyMock.expectLastCall().andAnswer(new IAnswer<Void>() {
          @Override
          public Void answer() throws Throwable {
              Assert.assertEquals(Status.RUNNING, flow.getStatus());
              Assert.assertEquals(2, numJobsComplete.incrementAndGet());

              flow2Callback.getValue().completed(Status.FAILED);

              return null;
          }
      }).once();

      EasyMock.expect(mockFlow2.getStatus()).andAnswer(new IAnswer<Status>()
      {
          private volatile AtomicInteger count = new AtomicInteger(0);

          @Override
          public Status answer() throws Throwable
          {
              switch (count.getAndIncrement()) {
                  case 0: return Status.READY;
                  case 1: return Status.FAILED;
                  default: Assert.fail("mockFlow2.getStatus() should only be called 2 times.");
              }
              return null;
          }
      }).times(2);

    EasyMock.expect(mockFlow2.getExceptions()).andReturn(e2s).times(1);

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

      /**** Start the test ****/
      AtomicBoolean callbackRan = new AtomicBoolean(false);
      flow.execute(props, new OneCallFlowCallback(callbackRan) {
          @Override
          public void theCallback(Status status) {
              Assert.assertEquals(Status.FAILED, status);
          }
      });

      Assert.assertTrue("Callback wasn't run.", callbackRan.get());
      Assert.assertEquals(Status.FAILED, flow.getStatus());

      callbackRan = new AtomicBoolean(false);
      flow.execute(props, new OneCallFlowCallback(callbackRan)
      {
          @Override
          protected void theCallback(Status status)
          {
              Assert.assertEquals(Status.FAILED, status);
              Assert.assertEquals(2, numJobsComplete.get());
          }
      });

      Assert.assertTrue("Callback wasn't run.", callbackRan.get());
      Assert.assertEquals(Status.FAILED, flow.getStatus());
      Assert.assertEquals(expected, flow.getExceptions());

      Assert.assertTrue("Expected to be able to reset the flow", flow.reset());
      Assert.assertEquals(Status.READY, flow.getStatus());
      Assert.assertEquals(emptyExceptions, flow.getExceptions());

   
    }

}
TOP

Related Classes of azkaban.flow.GroupedExecutableFlowTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.