You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@falcon.apache.org by pi...@apache.org on 2015/10/20 11:37:52 UTC

[1/3] falcon git commit: Add ProcessUpdateTest, PipelineInstanceDependencyTest and other tests and test fixes. Contributed by Raghav Gautam and Paul Isaychuk

Repository: falcon
Updated Branches:
  refs/heads/master 5a55baed3 -> 9e6d5a6c5


http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/triage/PipelineInstanceDependencyTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/triage/PipelineInstanceDependencyTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/triage/PipelineInstanceDependencyTest.java
new file mode 100644
index 0000000..81d5fcc
--- /dev/null
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/triage/PipelineInstanceDependencyTest.java
@@ -0,0 +1,335 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.falcon.regression.triage;
+
+import org.apache.falcon.entity.v0.EntityType;
+import org.apache.falcon.entity.v0.Frequency;
+import org.apache.falcon.regression.Entities.FeedMerlin;
+import org.apache.falcon.regression.Entities.ProcessMerlin;
+import org.apache.falcon.regression.core.bundle.Bundle;
+import org.apache.falcon.regression.core.helpers.ColoHelper;
+import org.apache.falcon.regression.core.helpers.entity.AbstractEntityHelper;
+import org.apache.falcon.regression.core.util.AssertUtil;
+import org.apache.falcon.regression.core.util.BundleUtil;
+import org.apache.falcon.regression.core.util.EntityLineageUtil;
+import org.apache.falcon.regression.core.util.EntityLineageUtil.PipelineEntityType;
+import org.apache.falcon.regression.core.util.HadoopUtil;
+import org.apache.falcon.regression.core.util.InstanceUtil;
+import org.apache.falcon.regression.core.util.OSUtil;
+import org.apache.falcon.regression.core.util.TimeUtil;
+import org.apache.falcon.regression.testHelper.BaseTestClass;
+import org.apache.falcon.resource.APIResult;
+import org.apache.falcon.resource.InstanceDependencyResult;
+import org.apache.falcon.resource.LineageGraphResult;
+import org.apache.falcon.resource.LineageGraphResult.Edge;
+import org.apache.falcon.resource.SchedulableEntityInstance;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
+import org.apache.log4j.Logger;
+import org.apache.oozie.client.CoordinatorAction;
+import org.apache.oozie.client.OozieClient;
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Test for instance dependency endpoint.
+ */
+@Test(groups = "embedded")
+public class PipelineInstanceDependencyTest extends BaseTestClass {
+
+    private ColoHelper cluster = servers.get(0);
+    private FileSystem clusterFS = serverFS.get(0);
+    private OozieClient clusterOC = serverOC.get(0);
+    private String baseTestHDFSDir = cleanAndGetTestDir();
+    private String aggregateWorkflowDir = baseTestHDFSDir + "/aggregator";
+    private String feedInputPath = baseTestHDFSDir + "/input" + MINUTE_DATE_PATTERN;
+    private String feedOutputPath = baseTestHDFSDir + "/output-data" + MINUTE_DATE_PATTERN;
+    private final String startTimeStr = "2010-01-02T01:00Z";
+    private final DateTime startTime = TimeUtil.oozieDateToDate(startTimeStr);
+    private final String endTimeStr = "2010-01-02T01:11Z";
+    private List<String> inputFeedNames, outputFeedNames, processNames;
+    private List<Integer> inputFeedFrequencies;
+    private static final Logger LOGGER = Logger.getLogger(PipelineInstanceDependencyTest.class);
+    private String clusterName;
+
+    private static final Comparator<SchedulableEntityInstance> DEPENDENCY_COMPARATOR =
+        new Comparator<SchedulableEntityInstance>() {
+            @Override
+            public int compare(SchedulableEntityInstance o1, SchedulableEntityInstance o2) {
+                int tagDiff = o1.getTags().compareTo(o2.getTags());
+                if (tagDiff != 0) {
+                    return tagDiff;
+                }
+                int clusterDiff = o1.getCluster().compareTo(o2.getCluster());
+                if (clusterDiff != 0) {
+                    return clusterDiff;
+                }
+                int typeDiff = o1.getEntityType().compareTo(o2.getEntityType());
+                if (typeDiff != 0) {
+                    return typeDiff;
+                }
+                int dateDiff = o1.getInstanceTime().compareTo(o2.getInstanceTime());
+                if (dateDiff != 0) {
+                    return dateDiff;
+                }
+                return 0;
+            }
+        };
+    private final Comparator<Edge> edgeComparator =
+        new Comparator<Edge>() {
+            @Override
+            public int compare(Edge o1, Edge o2) {
+                return o1.toString().compareTo(o2.toString());
+            }
+        };
+
+    @BeforeClass(alwaysRun = true)
+    public void createTestData() throws Exception {
+        LOGGER.info("in @BeforeClass");
+        HadoopUtil.uploadDir(clusterFS, aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE);
+    }
+
+    /**
+     *  The scenario that we will setup looks like:<br>
+     *  inputFeed1 -> process1 -> outputFeed1 -> process2 -> outputFeed2 -> process3 -> outputFeed3.
+     * @throws Exception
+     */
+    @BeforeMethod(alwaysRun = true)
+    public void setup() throws Exception {
+        bundles[0] = BundleUtil.readELBundle();
+        bundles[0] = new Bundle(bundles[0], cluster);
+        bundles[0].generateUniqueBundle(this);
+        clusterName = bundles[0].getClusterNames().get(0);
+        bundles[0].setProcessWorkflow(aggregateWorkflowDir);
+        bundles[0].setProcessValidity(startTimeStr, endTimeStr);
+        bundles[0].setProcessPeriodicity(5, Frequency.TimeUnit.minutes);
+        bundles[0].setInputFeedDataPath(feedInputPath);
+        bundles[0].setOutputFeedPeriodicity(5, Frequency.TimeUnit.minutes);
+        bundles[0].setOutputFeedLocationData(feedOutputPath);
+        bundles[0].submitFeedsScheduleProcess(prism);
+        final String oldInputFeedName = bundles[0].getInputFeedNameFromBundle();
+        final String oldOutputFeedName = bundles[0].getOutputFeedNameFromBundle();
+        final String oldProcessName = bundles[0].getProcessName();
+        inputFeedFrequencies = Arrays.asList(20, 5, 5);
+        inputFeedNames = Arrays.asList(oldInputFeedName, oldOutputFeedName, oldOutputFeedName + "-2");
+        outputFeedNames = Arrays.asList(oldOutputFeedName, oldOutputFeedName + "-2", oldOutputFeedName + "-3");
+        processNames = Arrays.asList(oldProcessName, oldProcessName + "-2", oldProcessName + "-3");
+        List<String> feedOutputPaths = Arrays.asList(
+            feedOutputPath,
+            baseTestHDFSDir + "/output-data-2" + MINUTE_DATE_PATTERN,
+            baseTestHDFSDir + "/output-data-3" + MINUTE_DATE_PATTERN
+        );
+
+        //create second, third process that consumes output of bundle[0]
+        for (int bIndex = 1; bIndex < 3; ++bIndex) {
+            final FeedMerlin outputFeed = new FeedMerlin(bundles[0].getOutputFeedFromBundle());
+            final ProcessMerlin processMerlin = bundles[0].getProcessObject();
+
+            processMerlin.setName(processNames.get(bIndex));
+
+            outputFeed.setDataLocationPath(feedOutputPaths.get(bIndex));
+            outputFeed.setName(outputFeedNames.get(bIndex));
+
+            //rename output feeds before renaming input feeds
+            processMerlin.renameFeeds(Collections.singletonMap(oldOutputFeedName, outputFeedNames.get(bIndex)));
+            processMerlin.renameFeeds(Collections.singletonMap(oldInputFeedName, inputFeedNames.get(bIndex)));
+            AssertUtil.assertSucceeded(prism.getFeedHelper().submitEntity(outputFeed.toString()));
+            AssertUtil.assertSucceeded(prism.getProcessHelper().submitAndSchedule(processMerlin.toString()));
+        }
+
+        for (int index = 0; index < 3; ++index) {
+            InstanceUtil.waitTillInstanceReachState(clusterOC, processNames.get(index), 3,
+                CoordinatorAction.Status.WAITING, EntityType.PROCESS, 5);
+        }
+        LOGGER.info(inputFeedNames.get(0) + "(" + inputFeedFrequencies.get(0) + ") -> *" + processNames.get(0)+ "* -> "
+            + inputFeedNames.get(1) + "(" + inputFeedFrequencies.get(1) + ") -> *" + processNames.get(1)+ "* -> "
+            + inputFeedNames.get(2) + "(" + inputFeedFrequencies.get(2) + ") -> *" + processNames.get(2)+ "* -> "
+            + outputFeedNames.get(2));
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void tearDown() {
+        removeTestClassEntities();
+    }
+
+    @Test
+    public void processInstanceDependencyTest() throws Exception {
+        final DateTime startTimeMinus20 = startTime.minusMinutes(20);
+
+        for (int index = 0; index < 3; ++index) {
+            List<SchedulableEntityInstance> expectedDependencies = new ArrayList<>();
+            final SchedulableEntityInstance outputInstance =
+                new SchedulableEntityInstance(outputFeedNames.get(index), clusterName, startTime.toDate(),
+                    EntityType.FEED);
+            outputInstance.setTags("Output");
+            expectedDependencies.add(outputInstance);
+            for (DateTime dt = new DateTime(startTime); !dt.isBefore(startTimeMinus20);
+                 dt = dt.minusMinutes(inputFeedFrequencies.get(index))) {
+                final SchedulableEntityInstance inputInstance =
+                    new SchedulableEntityInstance(inputFeedNames.get(index), clusterName, dt.toDate(), EntityType.FEED);
+                inputInstance.setTags("Input");
+                expectedDependencies.add(inputInstance);
+            }
+            InstanceDependencyResult r = prism.getProcessHelper().getInstanceDependencies(processNames.get(index),
+                "?instanceTime=" + startTimeStr, null);
+
+            List<SchedulableEntityInstance> actualDependencies = Arrays.asList(r.getDependencies());
+            Collections.sort(expectedDependencies, DEPENDENCY_COMPARATOR);
+            Collections.sort(actualDependencies, DEPENDENCY_COMPARATOR);
+            Assert.assertEquals(actualDependencies, expectedDependencies,
+                "Unexpected dependencies for process: " + processNames.get(index));
+        }
+    }
+
+    @Test
+    public void inputFeedInstanceDependencyTest() throws Exception {
+        final String inputFeedToTest = inputFeedNames.get(1);
+        final DateTime endTime = TimeUtil.oozieDateToDate(endTimeStr);
+
+        List<SchedulableEntityInstance> expectedDependencies = new ArrayList<>();
+        final SchedulableEntityInstance outputInstance =
+            new SchedulableEntityInstance(processNames.get(0), clusterName, startTime.toDate(), EntityType.PROCESS);
+        outputInstance.setTags("Output");
+        expectedDependencies.add(outputInstance);
+        final int processFrequency = 5;
+        for (DateTime dt = new DateTime(startTime); !dt.isAfter(endTime); dt = dt.plusMinutes(processFrequency)) {
+            final SchedulableEntityInstance inputInstance =
+                new SchedulableEntityInstance(processNames.get(1), clusterName, dt.toDate(), EntityType.PROCESS);
+            inputInstance.setTags("Input");
+            expectedDependencies.add(inputInstance);
+        }
+        InstanceDependencyResult r = prism.getFeedHelper().getInstanceDependencies(inputFeedToTest,
+            "?instanceTime=" + startTimeStr, null);
+
+        List<SchedulableEntityInstance> actualDependencies = Arrays.asList(r.getDependencies());
+        Collections.sort(expectedDependencies, DEPENDENCY_COMPARATOR);
+        Collections.sort(actualDependencies, DEPENDENCY_COMPARATOR);
+        Assert.assertEquals(actualDependencies, expectedDependencies,
+            "Unexpected dependencies for process: " + inputFeedToTest);
+    }
+
+    @Test
+    public void outputFeedInstanceDependencyTest() throws Exception {
+        final String outputFeedToTest = outputFeedNames.get(1);
+        final DateTime endTime = TimeUtil.oozieDateToDate(endTimeStr);
+
+        List<SchedulableEntityInstance> expectedDependencies = new ArrayList<>();
+        final SchedulableEntityInstance outputInstance =
+            new SchedulableEntityInstance(processNames.get(1), clusterName, startTime.toDate(), EntityType.PROCESS);
+        outputInstance.setTags("Output");
+        expectedDependencies.add(outputInstance);
+        final int processFrequency = 5;
+        for (DateTime dt = new DateTime(startTime); !dt.isAfter(endTime); dt = dt.plusMinutes(processFrequency)) {
+            final SchedulableEntityInstance inputInstance =
+                new SchedulableEntityInstance(processNames.get(2), clusterName, dt.toDate(), EntityType.PROCESS);
+            inputInstance.setTags("Input");
+            expectedDependencies.add(inputInstance);
+        }
+        InstanceDependencyResult r = prism.getFeedHelper().getInstanceDependencies(outputFeedToTest,
+            "?instanceTime=" + startTimeStr, null);
+
+        List<SchedulableEntityInstance> actualDependencies = Arrays.asList(r.getDependencies());
+        Collections.sort(expectedDependencies, DEPENDENCY_COMPARATOR);
+        Collections.sort(actualDependencies, DEPENDENCY_COMPARATOR);
+        Assert.assertEquals(actualDependencies, expectedDependencies,
+            "Unexpected dependencies for process: " + outputFeedToTest);
+    }
+
+    /**
+     * Particular check for https://issues.apache.org/jira/browse/FALCON-1317.
+     */
+    @Test
+    public void testInstanceDependencySingleElement()
+        throws URISyntaxException, AuthenticationException, InterruptedException, IOException {
+        InstanceDependencyResult r = prism.getFeedHelper().getInstanceDependencies(outputFeedNames.get(2),
+            "?instanceTime=" + startTimeStr, null);
+        Assert.assertEquals(r.getStatus(), APIResult.Status.SUCCEEDED, "Request shouldn't fail.");
+        List<SchedulableEntityInstance> actualDependencies = Arrays.asList(r.getDependencies());
+        Assert.assertEquals(actualDependencies.size(), 1, "There should be single dependency element.");
+    }
+
+    /**
+     * Run triage for different pipeline feeds and processes.
+     * @param bundleInd pipeline bundle
+     * @param entityType process or feed
+     */
+    @Test(dataProvider = "getParameters")
+    public void testTriageInstance(int bundleInd, EntityType entityType)
+        throws URISyntaxException, AuthenticationException, InterruptedException, IOException {
+        AbstractEntityHelper helper;
+        String entityName;
+        if (entityType == EntityType.FEED) {
+            helper = prism.getFeedHelper();
+            entityName = outputFeedNames.get(bundleInd);
+        } else {
+            helper = prism.getProcessHelper();
+            entityName = processNames.get(bundleInd);
+        }
+        Map<PipelineEntityType, List<String>> entitiesNames = new HashMap<>();
+        entitiesNames.put(PipelineEntityType.PROCESS, processNames);
+        entitiesNames.put(PipelineEntityType.INPUT_FEED, inputFeedNames);
+        entitiesNames.put(PipelineEntityType.OUTPUT_FEED, outputFeedNames);
+        LineageGraphResult expected = EntityLineageUtil.getExpectedResult(bundleInd, entitiesNames,
+            inputFeedFrequencies, entityName, clusterName, startTimeStr);
+        LineageGraphResult actual = helper.getInstanceTriage(entityName,
+            "?start=" + startTimeStr).getTriageGraphs()[0];
+
+        final List<String> expectedVertices = new ArrayList<>(Arrays.asList(expected.getVertices()));
+        final List<Edge> expectedEdges = new ArrayList<>(Arrays.asList(expected.getEdges()));
+        final List<String> actualVertices = Arrays.asList(actual.getVertices());
+        final List<Edge> actualEdges = Arrays.asList(actual.getEdges());
+        Collections.sort(actualVertices);
+        Collections.sort(expectedVertices);
+        Collections.sort(actualEdges, edgeComparator);
+        Collections.sort(expectedEdges, edgeComparator);
+        Assert.assertEquals(actualVertices, expectedVertices,
+            "Actual vertices & expected vertices in triage graph don't match");
+        Assert.assertEquals(actualEdges, expectedEdges,
+            "Actual edges & expected edges in triage graph don't match");
+    }
+
+    @DataProvider
+    public Object[][] getParameters() {
+        return new Object[][]{
+            {0, EntityType.FEED},
+            {0, EntityType.PROCESS},
+            {1, EntityType.FEED},
+            {1, EntityType.PROCESS},
+            {2, EntityType.FEED},
+            {2, EntityType.PROCESS},
+        };
+    }
+
+}


[3/3] falcon git commit: Add ProcessUpdateTest, PipelineInstanceDependencyTest and other tests and test fixes. Contributed by Raghav Gautam and Paul Isaychuk

Posted by pi...@apache.org.
Add ProcessUpdateTest, PipelineInstanceDependencyTest and other tests and test fixes. Contributed by Raghav Gautam and Paul Isaychuk


Project: http://git-wip-us.apache.org/repos/asf/falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/falcon/commit/9e6d5a6c
Tree: http://git-wip-us.apache.org/repos/asf/falcon/tree/9e6d5a6c
Diff: http://git-wip-us.apache.org/repos/asf/falcon/diff/9e6d5a6c

Branch: refs/heads/master
Commit: 9e6d5a6c58d99479cc58c11b5b05b11bf8d90821
Parents: 5a55bae
Author: Paul Isaychuk <pi...@apache.org>
Authored: Thu Oct 15 14:15:58 2015 +0300
Committer: Paul Isaychuk <pi...@apache.org>
Committed: Tue Oct 20 11:46:31 2015 +0300

----------------------------------------------------------------------
 falcon-regression/CHANGES.txt                   |   3 +
 .../regression/Entities/ProcessMerlin.java      |   9 +
 .../helpers/entity/AbstractEntityHelper.java    |  10 +
 .../regression/core/util/EntityLineageUtil.java |  63 ++++
 .../regression/core/util/InstanceUtil.java      |  40 ++-
 .../regression/core/util/KerberosHelper.java    |   9 +
 .../falcon/regression/core/util/OozieUtil.java  |  52 +++
 .../falcon/regression/core/util/Util.java       |  22 ++
 .../ui/search/AbstractSearchPage.java           |  69 +++-
 .../regression/ui/search/ClusterWizardPage.java |  40 +--
 .../regression/ui/search/EntityWizardPage.java  |  94 ++++++
 .../regression/ui/search/FeedWizardPage.java    |  27 +-
 .../falcon/regression/ui/search/LoginPage.java  |   1 +
 .../regression/ui/search/MirrorWizardPage.java  |  13 +-
 .../falcon/regression/ui/search/PageHeader.java |  30 +-
 .../regression/ui/search/ProcessWizardPage.java |  37 +-
 .../falcon/regression/ExternalFSTest.java       |   2 +-
 .../falcon/regression/FeedReplicationTest.java  | 109 +++++-
 .../regression/ProcessInstanceStatusTest.java   |  39 +++
 .../falcon/regression/ProcessUpdateTest.java    | 112 +++++++
 .../falcon/regression/TestngListener.java       |   2 +-
 .../falcon/regression/hive/dr/HiveDRTest.java   | 118 ++++---
 .../falcon/regression/hive/dr/HiveDbDRTest.java |  61 ++--
 .../regression/hive/dr/RecipeExecLocation.java  |  63 ++++
 .../lineage/ListProcessInstancesTest.java       |  27 +-
 .../regression/searchUI/ClusterSetupTest.java   |  48 ++-
 .../regression/searchUI/FeedSetupTest.java      |  61 ++--
 .../regression/searchUI/HomePageTest.java       |   4 +-
 .../searchUI/MirrorSourceTargetOptionsTest.java |   2 +
 .../falcon/regression/searchUI/MirrorTest.java  |  76 ++++-
 .../regression/searchUI/ProcessSetupTest.java   |  65 ++--
 .../regression/security/FalconClientTest.java   |   7 +-
 .../triage/PipelineInstanceDependencyTest.java  | 335 +++++++++++++++++++
 33 files changed, 1365 insertions(+), 285 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/CHANGES.txt
----------------------------------------------------------------------
diff --git a/falcon-regression/CHANGES.txt b/falcon-regression/CHANGES.txt
index 5ea229a..d285661 100644
--- a/falcon-regression/CHANGES.txt
+++ b/falcon-regression/CHANGES.txt
@@ -5,6 +5,9 @@ Trunk (Unreleased)
   INCOMPATIBLE CHANGES
 
   NEW FEATURES
+   FALCON-1546 Add ProcessUpdateTest, PipelineInstanceDependencyTest and other tests and test fixes
+    (Raghav Gautam and Paul Isaychuk via Paul Isaychuk)
+
    FALCON-1387 Add Instance Dependency API Test(Pragya Mittal via Ajay Yadava)
 
    FALCON-1382 Add a test for feed retention to make sure that data directory is not deleted (Paul Isaychuk)

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ProcessMerlin.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ProcessMerlin.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ProcessMerlin.java
index b905bee..7607aa6 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ProcessMerlin.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ProcessMerlin.java
@@ -213,6 +213,15 @@ public class ProcessMerlin extends Process {
         return this;
     }
 
+    public String getProperty(String name) {
+        for (Property property : properties.getProperties()) {
+            if (property.getName().equals(name)) {
+                return property.getValue();
+            }
+        }
+        return null;
+    }
+
     @Override
     public String toString() {
         try {

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/helpers/entity/AbstractEntityHelper.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/helpers/entity/AbstractEntityHelper.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/helpers/entity/AbstractEntityHelper.java
index 83d06a2..e406cae 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/helpers/entity/AbstractEntityHelper.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/helpers/entity/AbstractEntityHelper.java
@@ -38,6 +38,7 @@ import org.apache.falcon.resource.FeedInstanceResult;
 import org.apache.falcon.resource.InstanceDependencyResult;
 import org.apache.falcon.resource.InstancesResult;
 import org.apache.falcon.resource.InstancesSummaryResult;
+import org.apache.falcon.resource.TriageResult;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.security.authentication.client.AuthenticationException;
@@ -554,6 +555,15 @@ public abstract class AbstractEntityHelper {
     }
 
     /**
+     * Retrieves instance triage.
+     */
+    public TriageResult getInstanceTriage(String entityName, String params)
+        throws AuthenticationException, IOException, URISyntaxException, InterruptedException {
+        String url = createUrl(this.hostname + URLS.INSTANCE_TRIAGE.getValue(), getEntityType(), entityName);
+        return (TriageResult) InstanceUtil.createAndSendRequestProcessInstance(url, params, allColo, null);
+    }
+
+    /**
      * Lists all entities which are tagged by a given pipeline.
      * @param pipeline filter
      * @return service response

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/EntityLineageUtil.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/EntityLineageUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/EntityLineageUtil.java
index fc42cf5..2df474d 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/EntityLineageUtil.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/EntityLineageUtil.java
@@ -20,10 +20,14 @@ package org.apache.falcon.regression.core.util;
 
 import org.apache.falcon.resource.LineageGraphResult;
 import org.apache.log4j.Logger;
+import org.joda.time.DateTime;
 import org.testng.Assert;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 
@@ -34,6 +38,13 @@ public final class EntityLineageUtil{
 
     private static final Logger LOGGER = Logger.getLogger(EntityLineageUtil.class);
 
+    /**
+     * Enum to represent entity role in pipeline.
+     */
+    public enum PipelineEntityType {
+        PROCESS, INPUT_FEED, OUTPUT_FEED
+    }
+
     private EntityLineageUtil() {
         throw new AssertionError("Instantiating utility class...");
     }
@@ -61,5 +72,57 @@ public final class EntityLineageUtil{
         Assert.assertEquals(expectedVerticesSet, actualVerticesSet, "Vertices dont match");
     }
 
+    /**
+     * Produces list of expected vertices and edges in triage result.
+     */
+    public static LineageGraphResult getExpectedResult(int bundleIndx,
+                                                       Map<PipelineEntityType, List<String>> entityNamesMap,
+                                                       List<Integer> inputFeedFrequencies, String entityName,
+                                                       String clusterName, String startTime) {
+        List<String> processNames = entityNamesMap.get(PipelineEntityType.PROCESS);
+        List<String> inputFeedNames = entityNamesMap.get(PipelineEntityType.INPUT_FEED);
+        List<String> outputFeedNames = entityNamesMap.get(PipelineEntityType.OUTPUT_FEED);
+        List<String> vertices = new ArrayList<>();
+        List<LineageGraphResult.Edge> edges = new ArrayList<>();
+        final String startTimeMinus20 = TimeUtil.addMinsToTime(startTime, -20);
+        String vertexTemplate = "name: %s, type: %s, cluster: %s, instanceTime: %s, tags: %s";
+        for (int i = 0; i <= bundleIndx; ++i) {
+            //add vertex of i-th bundle process
+            boolean isTerminalInstance = processNames.contains(entityName) && i == bundleIndx;
+            String tag = isTerminalInstance ? "[WAITING]" : "Output[WAITING]";
+            final String processVertex = String.format(vertexTemplate,
+                processNames.get(i), "PROCESS", clusterName, startTime, tag);
+            vertices.add(processVertex);
+
+            //add all input feed vertices & edges for i-th bundle
+            LineageGraphResult.Edge edge;
+            String feedVertex;
+            for (DateTime dt = new DateTime(startTime); !dt.isBefore(new DateTime(startTimeMinus20));
+                 dt = dt.minusMinutes(inputFeedFrequencies.get(i))) {
+                feedVertex = String.format(vertexTemplate, inputFeedNames.get(i), "FEED",
+                    clusterName, TimeUtil.dateToOozieDate(dt.toDate()), "Input[MISSING]");
+                edge = new LineageGraphResult.Edge(feedVertex, processVertex, "consumed by");
+                vertices.add(feedVertex);
+                edges.add(edge);
+            }
+            //add output feed edge for i-th bundle
+            tag = (outputFeedNames.contains(entityName) && i == bundleIndx) ? "[MISSING]" : "Input[MISSING]";
+            feedVertex = String.format(vertexTemplate, outputFeedNames.get(i), "FEED", clusterName, startTime, tag);
+            isTerminalInstance = i == bundleIndx && outputFeedNames.contains(entityName);
+            if (i < bundleIndx || isTerminalInstance) {
+                edge = new LineageGraphResult.Edge(processVertex, feedVertex, "produces");
+                edges.add(edge);
+            }
+            //add output feed vertex only if it is terminal; it will be added as the input for next bundle otherwise
+            if (isTerminalInstance) {
+                vertices.add(feedVertex);
+            }
+        }
+        LineageGraphResult lineageGraphResult = new LineageGraphResult();
+        lineageGraphResult.setVertices(vertices.toArray(new String[vertices.size()]));
+        lineageGraphResult.setEdges(edges.toArray(new LineageGraphResult.Edge[edges.size()]));
+        return lineageGraphResult;
+    }
+
 }
 

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/InstanceUtil.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/InstanceUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/InstanceUtil.java
index 10463c2..3d05ae9 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/InstanceUtil.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/InstanceUtil.java
@@ -36,6 +36,7 @@ import org.apache.falcon.resource.InstanceDependencyResult;
 import org.apache.falcon.resource.InstancesResult;
 import org.apache.falcon.resource.InstancesSummaryResult;
 import org.apache.falcon.resource.SchedulableEntityInstance;
+import org.apache.falcon.resource.TriageResult;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.security.authentication.client.AuthenticationException;
 import org.apache.http.HttpResponse;
@@ -96,8 +97,10 @@ public final class InstanceUtil {
             result = new InstancesSummaryResult(APIResult.Status.FAILED, responseString);
         }else if (url.contains("/listing/")) {
             result = new FeedInstanceResult(APIResult.Status.FAILED, responseString);
-        }else if (url.contains("/dependencies/")) {
+        }else if (url.contains("instance/dependencies")) {
             result = new InstanceDependencyResult(APIResult.Status.FAILED, responseString);
+        }else if (url.contains("instance/triage")) {
+            result = new TriageResult(APIResult.Status.FAILED, responseString);
         }else {
             result = new InstancesResult(APIResult.Status.FAILED, responseString);
         }
@@ -126,10 +129,7 @@ public final class InstanceUtil {
                 public Date deserialize(JsonElement json, Type t, JsonDeserializationContext c) {
                     return new DateTime(json.getAsString()).toDate();
                 }
-            }).create().fromJson(responseString,
-                    url.contains("/listing/") ? FeedInstanceResult.class : url.contains("/summary/")
-                            ? InstancesSummaryResult.class : url.contains("/dependencies/")
-                            ? InstanceDependencyResult.class : InstancesResult.class);
+            }).create().fromJson(responseString, getClassOfResult(url));
         } catch (JsonSyntaxException e) {
             Assert.fail("Not a valid json:\n" + responseString);
         }
@@ -140,6 +140,25 @@ public final class InstanceUtil {
     }
 
     /**
+     * Returns API result class matching to API request url.
+     */
+    private static Class<? extends APIResult> getClassOfResult(String url) {
+        final Class<? extends APIResult> classOfResult;
+        if (url.contains("/listing/")) {
+            classOfResult = FeedInstanceResult.class;
+        } else if (url.contains("/summary/")) {
+            classOfResult = InstancesSummaryResult.class;
+        } else if (url.contains("instance/dependencies")) {
+            classOfResult = InstanceDependencyResult.class;
+        } else if (url.contains("instance/triage")) {
+            classOfResult = TriageResult.class;
+        } else {
+            classOfResult = InstancesResult.class;
+        }
+        return classOfResult;
+    }
+
+    /**
      * Checks if API response reflects success and if it's instances match to expected status.
      *
      * @param instancesResult  - kind of response from API which should contain information about
@@ -717,8 +736,8 @@ public final class InstanceUtil {
      * @throws ParseException
      */
     public static void assertProcessInstances(InstanceDependencyResult instancesResult, OozieClient oozieClient,
-                                        String bundleID, String time) throws OozieClientException,
-                                        JSONException, ParseException {
+                                        String bundleID, String time)
+        throws OozieClientException, ParseException, JSONException {
         List<String> inputPath = new ArrayList<>();
         List<String> outputPath = new ArrayList<>();
         SchedulableEntityInstance[] instances = instancesResult.getDependencies();
@@ -808,13 +827,10 @@ public final class InstanceUtil {
      * @param processName  process name for given bundle
      * @param tag     Input/Output
      * @param expectedInstances  instance for given instanceTime.
-     * @throws JSONException
      * @throws ParseException
-     * @throws OozieClientException
      */
     public static void assertFeedInstances(InstanceDependencyResult instancesResult, String processName, String tag,
-                                            List<String> expectedInstances)
-        throws OozieClientException, JSONException, ParseException {
+                                            List<String> expectedInstances) throws ParseException {
         List<String> actualInstances = new ArrayList<>();
         SchedulableEntityInstance[] instances = instancesResult.getDependencies();
         LOGGER.info("instances: " + Arrays.toString(instances));
@@ -833,7 +849,7 @@ public final class InstanceUtil {
 
         Set<String> expectedInstancesSet = new HashSet<>(expectedInstances);
         Set<String> actualInstancesSet = new HashSet<>(actualInstances);
-        Assert.assertEquals(expectedInstancesSet, actualInstancesSet, "Instances dont match");
+        Assert.assertEquals(expectedInstancesSet, actualInstancesSet, "Instances don't match");
     }
 }
 

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/KerberosHelper.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/KerberosHelper.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/KerberosHelper.java
index 9d028fa..c9f540f 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/KerberosHelper.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/KerberosHelper.java
@@ -18,6 +18,7 @@
 
 package org.apache.falcon.regression.core.util;
 
+import org.apache.commons.exec.CommandLine;
 import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants;
 import org.apache.hadoop.security.UserGroupInformation;
 
@@ -41,6 +42,14 @@ public final class KerberosHelper {
             getKeyTab(user));
     }
 
+    /**
+     * Switches user in kerberos.
+     */
+    public static void initUserWithKeytab(String user){
+        ExecUtil.executeCommand(new CommandLine("sudo").addArgument("kinit").addArgument(getPrincipal(user))
+            .addArgument("-k").addArgument("-t").addArgument(getKeyTab(user)));
+    }
+
     private static String getKeyTab(String user) {
         return MerlinConstants.getKeytabForUser(user);
     }

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OozieUtil.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OozieUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OozieUtil.java
index 5e2c7b2..ae96044 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OozieUtil.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OozieUtil.java
@@ -37,6 +37,10 @@ import org.joda.time.format.DateTimeFormat;
 import org.joda.time.format.DateTimeFormatter;
 import org.json.JSONException;
 import org.testng.Assert;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -45,6 +49,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
 import java.util.EnumSet;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
@@ -754,4 +759,51 @@ public final class OozieUtil {
         }
         return conf;
     }
+
+    /**
+     * Method retrieves and parses replication coordinator action workflow definition and checks whether specific
+     * properties are present in list of workflow args or not.
+     * @param workflowDefinition workflow definition
+     * @param actionName action within workflow, e.g pre-processing, replication etc.
+     * @param propMap specific properties which are expected to be in arg list
+     * @return true if all keys and values are present, false otherwise
+     */
+    public static boolean propsArePresentInWorkflow(String workflowDefinition, String actionName,
+                                              HashMap<String, String> propMap) {
+        //get action definition
+        Document definition = Util.convertStringToDocument(workflowDefinition);
+        Assert.assertNotNull(definition, "Workflow definition shouldn't be null.");
+        NodeList actions = definition.getElementsByTagName("action");
+        Element action = null;
+        for (int i = 0; i < actions.getLength(); i++) {
+            Node node = actions.item(i);
+            if (node.getNodeType() == Node.ELEMENT_NODE) {
+                action = (Element) node;
+                if (action.getAttribute("name").equals(actionName)) {
+                    break;
+                }
+                action = null;
+            }
+        }
+        Assert.assertNotNull(action, actionName + " action not found.");
+
+        //retrieve and checks whether properties are present in workflow args
+        Element javaElement = (Element) action.getElementsByTagName("java").item(0);
+        NodeList args = javaElement.getElementsByTagName("arg");
+        int counter = 0;
+        String key = null;
+        for (int i = 0; i < args.getLength(); i++) {
+            Node node = args.item(i);
+            if (node.getNodeType() == Node.ELEMENT_NODE) {
+                String argKey = node.getTextContent().replace("-", "");
+                if (key != null && propMap.get(key).equals(argKey)) {
+                    counter++;
+                    key = null;
+                } else if (key == null && propMap.containsKey(argKey)) {
+                    key = argKey;
+                }
+            }
+        }
+        return counter == propMap.size();
+    }
 }

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Util.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Util.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Util.java
index 83547e7..ccd083b 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Util.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Util.java
@@ -46,6 +46,7 @@ import org.joda.time.DateTime;
 import org.joda.time.format.DateTimeFormat;
 import org.joda.time.format.DateTimeFormatter;
 import org.testng.Assert;
+import org.w3c.dom.Document;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
@@ -54,6 +55,8 @@ import javax.jms.MapMessage;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
@@ -391,6 +394,7 @@ public final class Util {
         INSTANCE_RERUN("/api/instance/rerun"),
         INSTANCE_SUMMARY("/api/instance/summary"),
         INSTANCE_PARAMS("/api/instance/params"),
+        INSTANCE_TRIAGE("/api/instance/triage"),
         INSTANCE_LIST("/api/instance/list"),
         INSTANCE_LISTING("/api/instance/listing"),
         INSTANCE_LOGS("/api/instance/logs"),
@@ -563,6 +567,24 @@ public final class Util {
     }
 
     /**
+     * Converts string to xml document.
+     * @param xmlStr string representation
+     * @return document representation.
+     */
+    public static Document convertStringToDocument(String xmlStr) {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder builder;
+        try {
+            builder = factory.newDocumentBuilder();
+            Document doc = builder.parse(new InputSource(new StringReader(xmlStr)));
+            return doc;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
      * Sends api requests.
      * @param url target url
      * @param method request method

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java
index d956549..ab73092 100644
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java
@@ -20,14 +20,15 @@ package org.apache.falcon.regression.ui.search;
 
 import com.google.common.util.concurrent.SimpleTimeLimiter;
 import com.google.common.util.concurrent.TimeLimiter;
-import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.commons.lang3.tuple.MutablePair;
 import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants;
 import org.apache.falcon.regression.core.util.TimeUtil;
 import org.apache.falcon.regression.ui.pages.Page;
 import org.apache.log4j.Logger;
 import org.openqa.selenium.By;
 import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.NoSuchElementException;
 import org.openqa.selenium.TimeoutException;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
@@ -50,11 +51,14 @@ public abstract class AbstractSearchPage extends Page {
     public static final String UI_URL = MerlinConstants.PRISM_URL;
     private static final Logger LOGGER = Logger.getLogger(AbstractSearchPage.class);
     public static final int PAGELOAD_TIMEOUT_THRESHOLD = 10;
+    public static final int ALERT_LIFETIME = 3000;
 
     public AbstractSearchPage(WebDriver driver) {
         super(driver);
         waitForAngularToFinish();
+        LOGGER.info("Going to initialize Page Header.");
         pageHeader = PageFactory.initElements(driver, PageHeader.class);
+        LOGGER.info("Initialization done.");
     }
 
     private PageHeader pageHeader;
@@ -163,13 +167,54 @@ public abstract class AbstractSearchPage extends Page {
     public String getActiveAlertText() {
         if (waitForAlert()) {
             waitForAngularToFinish();
-            return driver.findElement(By.xpath("//div[@class='messages notifs']/div[last()]")).getText();
+            String script = "return $('div.messages.notifs > div:last-child').text();";
+            String message = (String)((JavascriptExecutor)driver).executeScript(script);
+            return message.trim();
         } else {
             return null;
         }
     }
 
     /**
+     * Wait for active alert. Check it's lifetime (the period when alert is displayed).
+     */
+    public void validateAlertLifetime() {
+        final WebElement alertsBlock = driver.findElement(By.xpath("//div[@class='messages notifs']"));
+        try {
+            final MutablePair<Long, Long> pair = new MutablePair<>(Long.MAX_VALUE, Long.MAX_VALUE);
+            // wait 5 seconds for alert to start blinking and record time of first blink
+            new WebDriverWait(driver, 5, 100).until(new ExpectedCondition<Boolean>() {
+                @Nullable
+                @Override
+                public Boolean apply(WebDriver webDriver) {
+                    String style = alertsBlock.getAttribute("style");
+                    if ((style.contains("opacity") && !style.contains("opacity: 1;"))
+                            || style.contains("display: block;")) {
+                        pair.setLeft(System.currentTimeMillis());
+                        return true;
+                    }
+                    return false;
+                }
+            });
+            // wait 5 seconds for alert to stop blinking and record time of stoppage
+            for (int i = 0; i < ALERT_LIFETIME + 3000; i += 100) {
+                String style = alertsBlock.getAttribute("style");
+                if (style.contains("display: none;")) {
+                    pair.setRight(Math.min(System.currentTimeMillis(), pair.getRight()));
+                } else {
+                    pair.setRight(Long.MAX_VALUE);
+                }
+                TimeUtil.sleepSeconds(0.1);
+            }
+            long diff = pair.getRight() - pair.getLeft();
+            LOGGER.info(String.format("Alert was live %d millis.", pair.getRight() - pair.getLeft()));
+            Assert.assertTrue(ALERT_LIFETIME <= diff, "Alert was present for too short period of time");
+        } catch (TimeoutException e) {
+            Assert.fail("Alert didn't appear in 5 seconds.");
+        }
+    }
+
+    /**
      * Wait for active alert.
      * @return true is alert is present
      */
@@ -181,12 +226,8 @@ public abstract class AbstractSearchPage extends Page {
                 @Override
                 public Boolean apply(WebDriver webDriver) {
                     String style = alertsBlock.getAttribute("style");
-                    if (style.contains("opacity") && !style.contains("opacity: 1;")) {
-                        String alert = alertsBlock.findElement(By.xpath("./div[last()]")).getText();
-                        return StringUtils.isNotEmpty(alert);
-                    } else {
-                        return false;
-                    }
+                    return (style.contains("opacity") && !style.contains("opacity: 1;"))
+                            || style.contains("display: block;");
                 }
             });
             return true;
@@ -196,6 +237,18 @@ public abstract class AbstractSearchPage extends Page {
     }
 
     /**
+     * Performs simple check of element presence.
+     */
+    public WebElement getElementOrNull(String xpath) {
+        try {
+            return driver.findElement(By.xpath(xpath));
+        } catch (NoSuchElementException ignored) {
+            return null;
+        }
+    }
+
+
+    /**
      * Method imitates click on check box. If click is not performed method retries the click.
      * @param expectedState whether check box is expected to be enabled or not after click.
      */

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ClusterWizardPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ClusterWizardPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ClusterWizardPage.java
index 0fbfc38..bcada4a 100644
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ClusterWizardPage.java
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ClusterWizardPage.java
@@ -38,7 +38,7 @@ import org.testng.Assert;
 import java.util.List;
 
 /** Page object of the Cluster creation page. */
-public class ClusterWizardPage extends AbstractSearchPage {
+public class ClusterWizardPage extends EntityWizardPage {
     private static final Logger LOGGER = Logger.getLogger(ClusterWizardPage.class);
     @FindBys({
         @FindBy(className = "mainUIView"),
@@ -53,12 +53,8 @@ public class ClusterWizardPage extends AbstractSearchPage {
     private WebElement previous;
     @FindBy(xpath = "//a[contains(text(), 'Cancel')]")
     private WebElement cancel;
-    @FindBy(id = "cluster.editXML")
-    private WebElement editXML;
     @FindBy(xpath = "//div[contains(@class, 'clusterSummaryRow')][h4]")
     private WebElement summaryBox;
-    @FindBy(xpath = "//div[contains(@class, 'xmlPreviewContainer')]//textarea")
-    private WebElement xmlPreview;
 
     public ClusterWizardPage(WebDriver driver) {
         super(driver);
@@ -273,21 +269,6 @@ public class ClusterWizardPage extends AbstractSearchPage {
         return false;
     }
 
-    public ClusterMerlin getXmlPreview() {
-        //preview block fetches changes slower then they appear on the form
-        waitForAngularToFinish();
-        String previewData = xmlPreview.getAttribute("value");
-        return new ClusterMerlin(previewData);
-    }
-
-    public void setClusterXml(String clusterXml) {
-        clickEditXml(true);
-        xmlPreview.clear();
-        xmlPreview.sendKeys(clusterXml);
-        waitForAngularToFinish();
-        clickEditXml(false);
-    }
-
     /**
      * Retrieves hte value of the summary box and parses it to cluster properties.
      * @param draft empty cluster to contain all properties.
@@ -402,16 +383,6 @@ public class ClusterWizardPage extends AbstractSearchPage {
     }
 
     /**
-     * Clicks on editXml button.
-     */
-    public void clickEditXml(boolean shouldBeEnabled) {
-        editXML.click();
-        String disabled = xmlPreview.getAttribute("disabled");
-        Assert.assertEquals(disabled == null, shouldBeEnabled,
-            "Xml preview should be " + (shouldBeEnabled ? "enabled" : "disabled"));
-    }
-
-    /**
      *  Click on next button which is the same as finish step 1.
      */
     public void clickNext() {
@@ -486,4 +457,13 @@ public class ClusterWizardPage extends AbstractSearchPage {
         }
     }
 
+    @Override
+    public WebElement getEditXMLButton() {
+        return driver.findElement(By.id("cluster.editXML"));
+    }
+
+    @Override
+    public ClusterMerlin getEntityFromXMLPreview() {
+        return new ClusterMerlin(getXMLPreview());
+    }
 }

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/EntityWizardPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/EntityWizardPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/EntityWizardPage.java
new file mode 100644
index 0000000..72c03cf
--- /dev/null
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/EntityWizardPage.java
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.falcon.regression.ui.search;
+
+import org.apache.falcon.entity.v0.Entity;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+import org.testng.Assert;
+
+/**
+ * https://issues.apache.org/jira/browse/FALCON-1546.
+ * Parent class for cluster, feed and process wizard pages.
+ */
+public abstract class EntityWizardPage extends AbstractSearchPage {
+    @FindBy(xpath = "//i[contains(@class, 'pointer')]")
+    protected WebElement xmlPreviewPointer;
+    protected WebElement xmlPreview = null;
+
+    public EntityWizardPage(WebDriver driver) {
+        super(driver);
+    }
+
+    /**
+     * Expand/collapse xml preview.
+     * @param shouldBeExpanded should preview be expanded or collapsed.
+     */
+    public void clickXMLPreview(boolean shouldBeExpanded) {
+        if (isXmlPreviewExpanded() != shouldBeExpanded) {
+            xmlPreviewPointer.click();
+        }
+        Assert.assertEquals(isXmlPreviewExpanded(), shouldBeExpanded,
+            "Xml preview should be " + (shouldBeExpanded ? " expanded." : " collapsed."));
+    }
+
+    /**
+     * @return true if xml preview exists and is displayed, false otherwise.
+     */
+    public boolean isXmlPreviewExpanded() {
+        xmlPreview = getElementOrNull("//textarea[@ng-model='prettyXml']");
+        return xmlPreview != null && xmlPreview.isDisplayed();
+    }
+
+    public String getXMLPreview() {
+        //preview block fetches changes slower then they appear on the form
+        waitForAngularToFinish();
+        clickXMLPreview(true);
+        return xmlPreview.getAttribute("value");
+    }
+
+    public abstract Entity getEntityFromXMLPreview();
+
+    /**
+     * Pushes xml into xml preview block.
+     * @param xml entity definition
+     */
+    public void setXmlPreview(String xml) {
+        clickEditXml(true);
+        xmlPreview.clear();
+        xmlPreview.sendKeys(xml);
+        waitForAngularToFinish();
+        clickEditXml(false);
+    }
+
+    /**
+     * Clicks on editXml button.
+     */
+    public void clickEditXml(boolean shouldBeEnabled) {
+        waitForAngularToFinish();
+        clickXMLPreview(true);
+        getEditXMLButton().click();
+        String disabled = xmlPreview.getAttribute("disabled");
+        Assert.assertEquals(disabled == null, shouldBeEnabled,
+            "Xml preview should be " + (shouldBeEnabled ? "enabled" : "disabled"));
+    }
+
+    public abstract WebElement getEditXMLButton();
+}

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/FeedWizardPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/FeedWizardPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/FeedWizardPage.java
index f3a107c..3dfab38 100644
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/FeedWizardPage.java
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/FeedWizardPage.java
@@ -34,7 +34,7 @@ import java.util.Date;
 import java.util.List;
 
 /** Page object of the Feed creation page. */
-public class FeedWizardPage extends AbstractSearchPage {
+public class FeedWizardPage extends EntityWizardPage {
 
     private static final Logger LOGGER = Logger.getLogger(FeedWizardPage.class);
 
@@ -83,17 +83,9 @@ public class FeedWizardPage extends AbstractSearchPage {
     })
     private WebElement saveFeedButton;
 
-    @FindBys({
-        @FindBy(id = "feed.editXML")
-    })
-    private WebElement editXmlButton;
-
     @FindBy(xpath = "//a[contains(.,'Cancel')]")
     private WebElement cancelButton;
 
-    @FindBy(xpath = "//textarea[@ng-model='prettyXml']")
-    private WebElement feedXml;
-
     public FeedWizardPage(WebDriver driver) {
         super(driver);
     }
@@ -327,11 +319,6 @@ public class FeedWizardPage extends AbstractSearchPage {
         cancelButton.click();
     }
 
-    public void clickEditXml(){
-        waitForAngularToFinish();
-        editXmlButton.click();
-    }
-
     public void clickCatalogStorageButton(){
         catalogStorageButton.click();
         waitForAngularToFinish();
@@ -652,14 +639,14 @@ public class FeedWizardPage extends AbstractSearchPage {
         waitForAlert();
     }
 
-    public FeedMerlin getFeedMerlinFromFeedXml() throws Exception{
-        waitForAngularToFinish();
-        return FeedMerlin.fromString(feedXml.getAttribute("value"));
+    @Override
+    public FeedMerlin getEntityFromXMLPreview() {
+        return FeedMerlin.fromString(getXMLPreview());
     }
 
-    public void setFeedXml(String xml) throws Exception{
-        feedXml.clear();
-        feedXml.sendKeys(xml);
+    @Override
+    public WebElement getEditXMLButton() {
+        return driver.findElement(By.id("feed.editXML"));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/LoginPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/LoginPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/LoginPage.java
index 3193d21..5b261fb 100644
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/LoginPage.java
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/LoginPage.java
@@ -46,6 +46,7 @@ public class LoginPage extends AbstractSearchPage {
 
     public static LoginPage open(WebDriver driver) {
         driver.get(UI_URL);
+        LOGGER.info("Opened a URL: " + UI_URL);
         return PageFactory.initElements(driver, LoginPage.class);
     }
 

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/MirrorWizardPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/MirrorWizardPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/MirrorWizardPage.java
index 6dfa1ca..f990c92 100644
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/MirrorWizardPage.java
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/MirrorWizardPage.java
@@ -278,7 +278,12 @@ public class MirrorWizardPage extends AbstractSearchPage {
         return new ClusterBlock("Target");
     }
 
-    public void applyRecipe(RecipeMerlin recipe) {
+    /**
+     * Populates hive dr UI with parameters from recipe.
+     * @param recipe recipe
+     * @param overwriteDefaults should it overwrite HiveDR default values automatically picked up by UI
+     */
+    public void applyRecipe(RecipeMerlin recipe, boolean overwriteDefaults) {
         final ClusterMerlin srcCluster = recipe.getSrcCluster();
         final ClusterMerlin tgtCluster = recipe.getTgtCluster();
         setName(recipe.getName());
@@ -303,8 +308,10 @@ public class MirrorWizardPage extends AbstractSearchPage {
             setHiveReplicationMaxMaps(recipe.getReplicationMaxMaps());
             setMaxEvents(recipe.getMaxEvents());
             setHiveMaxBandwidth(recipe.getMapBandwidth());
-            setSourceInfo(recipe.getSrcCluster());
-            setTargetInfo(recipe.getTgtCluster());
+            if (overwriteDefaults) {
+                setSourceInfo(recipe.getSrcCluster());
+                setTargetInfo(recipe.getTgtCluster());
+            }
             break;
         default:
             break;

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/PageHeader.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/PageHeader.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/PageHeader.java
index 2a75b20..7f87091 100644
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/PageHeader.java
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/PageHeader.java
@@ -159,8 +159,8 @@ public class PageHeader {
             //checking if logged-in username is displayed
             if (!MerlinConstants.IS_SECURE) {
                 UIAssert.assertDisplayed(getLogoutButton(), "Logout button");
+                AssertUtil.assertNotEmpty(getLoggedInUser(), "Expecting logged-in username.");
             }
-            AssertUtil.assertNotEmpty(getLoggedInUser(), "Expecting logged-in username.");
 
             //create button navigation
             doCreateCluster();
@@ -249,7 +249,33 @@ public class PageHeader {
     }
 
     private WebElement getLogoutButton() {
-        return loginHeaderBox.findElements(By.tagName("button")).get(1);
+        return loginHeaderBox.findElements(By.xpath("button[@ng-click='logOut()']")).get(0);
+    }
+
+    private WebElement getNotificationButton() {
+        return loginHeaderBox.findElements(By.xpath("button[@ng-click='notify()']")).get(0);
+    }
+
+    /**
+     * Validates number of notifications contained by notification bar and last notification message.
+     */
+    public void validateNotificationCountAndCheckLast(int count, String message) {
+        WebElement notificationButton = getNotificationButton();
+        notificationButton.click();
+        waitForAngularToFinish();
+
+        // Test notifications dropdown visibility
+        WebElement notificationDropdown = notificationButton.findElement(By.className("messages"));
+        Assert.assertTrue(notificationDropdown.getAttribute("style").contains("display: block;"),
+            "Notifications are not visible.");
+
+        // Test validity of number of notifications
+        List<WebElement> notifications = notificationDropdown.findElements(By.xpath("div"));
+        Assert.assertEquals(notifications.size() - 1, count, "Invalid notification count.");
+
+        // Test validity of last notification
+        String lastNotification = notifications.get(0).getText();
+        Assert.assertTrue(lastNotification.contains(message), "Invalid last notification text.");
     }
 
     public LoginPage doLogout() {

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ProcessWizardPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ProcessWizardPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ProcessWizardPage.java
index 706328f..5dcd700 100644
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ProcessWizardPage.java
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ProcessWizardPage.java
@@ -32,8 +32,8 @@ import org.apache.falcon.entity.v0.process.Output;
 import org.apache.falcon.entity.v0.process.Outputs;
 import org.apache.falcon.entity.v0.process.PolicyType;
 import org.apache.falcon.entity.v0.process.Retry;
-import org.apache.falcon.entity.v0.process.Workflow;
 import org.apache.falcon.entity.v0.process.Validity;
+import org.apache.falcon.entity.v0.process.Workflow;
 import org.apache.falcon.regression.Entities.ProcessMerlin;
 import org.apache.falcon.regression.core.util.UIAssert;
 import org.apache.log4j.Logger;
@@ -52,7 +52,7 @@ import java.util.List;
 import java.util.TimeZone;
 
 /** Page object of the Process creation page. */
-public class ProcessWizardPage extends AbstractSearchPage {
+public class ProcessWizardPage extends EntityWizardPage {
 
     private static final Logger LOGGER = Logger.getLogger(ProcessWizardPage.class);
 
@@ -62,9 +62,6 @@ public class ProcessWizardPage extends AbstractSearchPage {
     })
     private WebElement processBox;
 
-    @FindBy(xpath = "//textarea[@ng-model='prettyXml']")
-    private WebElement processXml;
-
     @FindBy(xpath = "//form[@name='processForm']/div[1]")
     private WebElement summaryBox;
 
@@ -82,15 +79,10 @@ public class ProcessWizardPage extends AbstractSearchPage {
     })
     private WebElement previousButton;
 
-    @FindBys({
-        @FindBy(id = "editXmlButton")
-    })
-    private WebElement editXmlButton;
-
     @FindBy(xpath = "//a[contains(.,'Cancel')]")
     private WebElement cancelButton;
 
-    @FindBy(xpath = "//div[contains(@class,'formBoxContainer')]")
+    @FindBy(xpath = "//fieldset[@id='fieldWrapper']")
     private WebElement formBox;
 
     public ProcessWizardPage(WebDriver driver) {
@@ -130,11 +122,6 @@ public class ProcessWizardPage extends AbstractSearchPage {
         cancelButton.click();
     }
 
-    public void clickEditXml(){
-        waitForAngularToFinish();
-        editXmlButton.click();
-    }
-
     /*----- Step1 General info ----*/
 
     private WebElement getName() {
@@ -828,20 +815,14 @@ public class ProcessWizardPage extends AbstractSearchPage {
         waitForAlert();
     }
 
-    /**
-     * Creates ProcessMerlin object from xml preview string.
-     */
-    public ProcessMerlin getProcessMerlinFromProcessXml() throws Exception{
-        waitForAngularToFinish();
-        return new ProcessMerlin(processXml.getAttribute("value"));
+    @Override
+    public ProcessMerlin getEntityFromXMLPreview() {
+        return new ProcessMerlin(getXMLPreview());
     }
 
-    /**
-     * Pushes xml string to xml preview.
-     */
-    public void setProcessXml(String xml) throws Exception{
-        processXml.clear();
-        processXml.sendKeys(xml);
+    @Override
+    public WebElement getEditXMLButton() {
+        return driver.findElement(By.id("editXmlButton"));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ExternalFSTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ExternalFSTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ExternalFSTest.java
index 0662562..728b797 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ExternalFSTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ExternalFSTest.java
@@ -182,9 +182,9 @@ public class ExternalFSTest extends BaseTestClass{
         Path dstPath = new Path(endpoint + testWasbTargetDir + '/' + timePattern);
 
         //check if coordinator exists
+        TimeUtil.sleepSeconds(10);
         InstanceUtil.waitTillInstancesAreCreated(clusterOC, feed.toString(), 0);
         Assert.assertEquals(OozieUtil.checkIfFeedCoordExist(clusterOC, feed.getName(), "REPLICATION"), 1);
-        TimeUtil.sleepSeconds(10);
 
         //replication should start, wait while it ends
         InstanceUtil.waitTillInstanceReachState(clusterOC, Util.readEntityName(feed.toString()), 1,

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/FeedReplicationTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/FeedReplicationTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/FeedReplicationTest.java
index 9ac9f24..6728edf 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/FeedReplicationTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/FeedReplicationTest.java
@@ -18,11 +18,11 @@
 
 package org.apache.falcon.regression;
 
-import org.apache.falcon.regression.Entities.FeedMerlin;
-import org.apache.falcon.regression.core.bundle.Bundle;
 import org.apache.falcon.entity.v0.EntityType;
 import org.apache.falcon.entity.v0.feed.ActionType;
 import org.apache.falcon.entity.v0.feed.ClusterType;
+import org.apache.falcon.regression.Entities.FeedMerlin;
+import org.apache.falcon.regression.core.bundle.Bundle;
 import org.apache.falcon.regression.core.helpers.ColoHelper;
 import org.apache.falcon.regression.core.util.AssertUtil;
 import org.apache.falcon.regression.core.util.BundleUtil;
@@ -36,9 +36,11 @@ import org.apache.falcon.regression.testHelper.BaseTestClass;
 import org.apache.falcon.resource.InstancesResult;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
 import org.apache.log4j.Logger;
 import org.apache.oozie.client.CoordinatorAction;
 import org.apache.oozie.client.OozieClient;
+import org.apache.oozie.client.OozieClientException;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.joda.time.format.DateTimeFormat;
@@ -51,7 +53,10 @@ import org.testng.annotations.Test;
 
 import javax.xml.bind.JAXBException;
 import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * feed replication test.
@@ -383,6 +388,106 @@ public class FeedReplicationTest extends BaseTestClass {
     }
 
     /**
+     * Test for https://issues.apache.org/jira/browse/FALCON-668.
+     * Check that new DistCp options are allowed.
+     */
+    @Test
+    public void testNewDistCpOptions()
+        throws URISyntaxException, AuthenticationException, InterruptedException, IOException, JAXBException,
+        OozieClientException {
+        Bundle.submitCluster(bundles[0], bundles[1]);
+        String startTime = TimeUtil.getTimeWrtSystemTime(0);
+        String endTime = TimeUtil.addMinsToTime(startTime, 5);
+        LOGGER.info("Time range between : " + startTime + " and " + endTime);
+        //configure feed
+        String feedName = Util.readEntityName(bundles[0].getDataSets().get(0));
+        FeedMerlin feedElement = bundles[0].getFeedElement(feedName);
+        bundles[0].writeFeedElement(feedElement, feedName);
+        FeedMerlin feed = new FeedMerlin(bundles[0].getDataSets().get(0));
+        feed.setFilePath(feedDataLocation);
+        //erase all clusters from feed definition
+        feed.clearFeedClusters();
+        //set cluster1 as source
+        feed.addFeedCluster(
+            new FeedMerlin.FeedClusterBuilder(Util.readEntityName(bundles[0].getClusters().get(0)))
+                .withRetention("days(1000000)", ActionType.DELETE)
+                .withValidity(startTime, endTime)
+                .withClusterType(ClusterType.SOURCE)
+                .build());
+        //set cluster2 as target
+        feed.addFeedCluster(
+            new FeedMerlin.FeedClusterBuilder(Util.readEntityName(bundles[1].getClusters().get(0)))
+                .withRetention("days(1000000)", ActionType.DELETE)
+                .withValidity(startTime, endTime)
+                .withClusterType(ClusterType.TARGET)
+                .withDataLocation(targetDataLocation)
+                .build());
+
+        //add custom properties to feed
+        HashMap<String, String> propMap = new HashMap<>();
+        propMap.put("overwrite", "true");
+        propMap.put("ignoreErrors", "false");
+        propMap.put("skipChecksum", "false");
+        propMap.put("removeDeletedFiles", "true");
+        propMap.put("preserveBlockSize", "true");
+        propMap.put("preserveReplicationNumber", "true");
+        propMap.put("preservePermission", "true");
+        for (Map.Entry<String, String> entry : propMap.entrySet()) {
+            feed.withProperty(entry.getKey(), entry.getValue());
+        }
+        //add custom property which shouldn't be passed to workflow
+        HashMap<String, String> unsupportedPropMap = new HashMap<>();
+        unsupportedPropMap.put("myCustomProperty", "true");
+        feed.withProperty("myCustomProperty", "true");
+
+        //upload necessary data to source
+        DateTime date = new DateTime(startTime, DateTimeZone.UTC);
+        DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy'/'MM'/'dd'/'HH'/'mm'");
+        String timePattern = fmt.print(date);
+        String sourceLocation = sourcePath + "/" + timePattern + "/";
+        HadoopUtil.recreateDir(cluster1FS, sourceLocation);
+        HadoopUtil.copyDataToFolder(cluster1FS, sourceLocation, OSUtil.concat(OSUtil.NORMAL_INPUT, "dataFile.xml"));
+        HadoopUtil.copyDataToFolder(cluster1FS, sourceLocation, OSUtil.concat(OSUtil.NORMAL_INPUT,  "dataFile1.txt"));
+
+        //copy 2 files to target to check if they will be deleted because of removeDeletedFiles property
+        String targetLocation = targetPath + "/" + timePattern + "/";
+        cluster2FS.copyFromLocalFile(new Path(OSUtil.concat(OSUtil.NORMAL_INPUT, "dataFile3.txt")),
+            new Path(targetLocation + "dataFile3.txt"));
+
+        //submit and schedule feed
+        LOGGER.info("Feed : " + Util.prettyPrintXml(feed.toString()));
+        AssertUtil.assertSucceeded(prism.getFeedHelper().submitAndSchedule(feed.toString()));
+
+        //check while instance is got created
+        InstanceUtil.waitTillInstancesAreCreated(cluster2OC, feed.toString(), 0);
+
+        //check if coordinator exists and replication starts
+        Assert.assertEquals(OozieUtil.checkIfFeedCoordExist(cluster2OC, feed.getName(), "REPLICATION"), 1);
+        InstanceUtil.waitTillInstanceReachState(cluster2OC, feed.getName(), 1,
+            CoordinatorAction.Status.RUNNING, EntityType.FEED);
+
+        //check that properties were passed to workflow definition
+        String bundleId = OozieUtil.getLatestBundleID(cluster2OC, feedName, EntityType.FEED);
+        String coordId = OozieUtil.getReplicationCoordID(bundleId, cluster2.getFeedHelper()).get(0);
+        CoordinatorAction coordinatorAction = cluster2OC.getCoordJobInfo(coordId).getActions().get(0);
+        String wfDefinition = cluster2OC.getJobDefinition(coordinatorAction.getExternalId());
+        LOGGER.info(String.format("Definition of coordinator job action %s : \n %s \n",
+            coordinatorAction.getExternalId(), Util.prettyPrintXml(wfDefinition)));
+        Assert.assertTrue(OozieUtil.propsArePresentInWorkflow(wfDefinition, "replication", propMap),
+            "New distCp supported properties should be passed to replication args list.");
+        Assert.assertFalse(OozieUtil.propsArePresentInWorkflow(wfDefinition, "replication", unsupportedPropMap),
+            "Unsupported properties shouldn't be passed to replication args list.");
+
+        //check that replication succeeds
+        InstanceUtil.waitTillInstanceReachState(cluster2OC, feed.getName(), 1,
+            CoordinatorAction.Status.SUCCEEDED, EntityType.FEED);
+
+        List<Path> finalFiles = HadoopUtil.getAllFilesRecursivelyHDFS(cluster2FS, new Path(targetPath));
+        Assert.assertEquals(finalFiles.size(), 2, "Only replicated files should be present on target "
+            + "because of 'removeDeletedFiles' distCp property.");
+    }
+
+    /**
      * Test demonstrates failure pf replication of stored data from one source cluster to one target cluster.
      * When replication job fails test checks if failed logs are present in staging directory or not.
      */

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ProcessInstanceStatusTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ProcessInstanceStatusTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ProcessInstanceStatusTest.java
index 7f1e445..6493133 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ProcessInstanceStatusTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ProcessInstanceStatusTest.java
@@ -434,6 +434,45 @@ public class ProcessInstanceStatusTest extends BaseTestClass {
         InstanceUtil.validateFailedInstances(r, 3);
     }
 
+    /**
+     * Check that default end time param value is now.
+     */
+    @Test
+    public void testDefaultEndTimeParam()
+        throws OozieClientException, IOException, InterruptedException, AuthenticationException, URISyntaxException,
+        JAXBException {
+        //set validity to have 12 instances
+        String start = TimeUtil.getTimeWrtSystemTime(-60);
+        String end = TimeUtil.getTimeWrtSystemTime(0);
+        bundles[0].setProcessValidity(start, end);
+        bundles[0].setProcessPeriodicity(5, TimeUnit.minutes);
+        bundles[0].setProcessConcurrency(3);
+        bundles[0].submitFeedsScheduleProcess(prism);
+        InstanceUtil.waitTillInstancesAreCreated(clusterOC, bundles[0].getProcessData(), 0);
+        //make first 3 instances running
+        OozieUtil.createMissingDependencies(cluster, EntityType.PROCESS, processName, 0, 0);
+        OozieUtil.createMissingDependencies(cluster, EntityType.PROCESS, processName, 0, 1);
+        OozieUtil.createMissingDependencies(cluster, EntityType.PROCESS, processName, 0, 2);
+        InstanceUtil.waitTillInstanceReachState(clusterOC, processName, 3, Status.RUNNING,
+            EntityType.PROCESS);
+        //check instances status with end, expected first 10 instances
+        InstancesResult r = prism.getProcessHelper().getProcessInstanceStatus(processName,
+            "?start=" + start + "&end=" + TimeUtil.addMinsToTime(end, -11));
+        InstanceUtil.validateResponse(r, 10, 3, 0, 7, 0);
+        //request the same but without end, expected to have the latest 10 instances
+        r = prism.getProcessHelper().getProcessInstanceStatus(processName,
+            "?start=" + start);
+        InstanceUtil.validateResponse(r, 10, 1, 0, 9, 0);
+        //the same with numResults which includes/excludes all running instances
+        r = prism.getProcessHelper().getProcessInstanceStatus(processName,
+            "?start=" + start + "&end=" + TimeUtil.addMinsToTime(end, -16) + "&numResults=9");
+        InstanceUtil.validateResponse(r, 9, 3, 0, 6, 0);
+        //expected end is set to now, thus getting last 9 instances
+        r = prism.getProcessHelper().getProcessInstanceStatus(processName,
+            "?start=" + start + "&numResults=9");
+        InstanceUtil.validateResponse(r, 9, 0, 0, 9, 0);
+    }
+
     /*
     * Function to match the workflows obtained from instance status and oozie.
     */

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ProcessUpdateTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ProcessUpdateTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ProcessUpdateTest.java
new file mode 100644
index 0000000..efbb503
--- /dev/null
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/ProcessUpdateTest.java
@@ -0,0 +1,112 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.falcon.regression;
+
+import org.apache.falcon.entity.v0.EntityType;
+import org.apache.falcon.entity.v0.Frequency;
+import org.apache.falcon.entity.v0.process.LateInput;
+import org.apache.falcon.entity.v0.process.LateProcess;
+import org.apache.falcon.entity.v0.process.PolicyType;
+import org.apache.falcon.regression.Entities.ProcessMerlin;
+import org.apache.falcon.regression.core.bundle.Bundle;
+import org.apache.falcon.regression.core.helpers.ColoHelper;
+import org.apache.falcon.regression.core.util.AssertUtil;
+import org.apache.falcon.regression.core.util.BundleUtil;
+import org.apache.falcon.regression.core.util.InstanceUtil;
+import org.apache.falcon.regression.core.util.OSUtil;
+import org.apache.falcon.regression.core.util.OozieUtil;
+import org.apache.falcon.regression.core.util.TimeUtil;
+import org.apache.falcon.regression.core.util.Util;
+import org.apache.falcon.regression.testHelper.BaseTestClass;
+import org.apache.log4j.Logger;
+import org.apache.oozie.client.OozieClient;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests related to update feature.
+ */
+@Test(groups = "embedded")
+public class ProcessUpdateTest extends BaseTestClass {
+
+    private ColoHelper cluster = servers.get(0);
+    private OozieClient clusterOC = serverOC.get(0);
+    private String baseTestHDFSDir = cleanAndGetTestDir();
+    private String aggregateWorkflowDir = baseTestHDFSDir + "/aggregator";
+    private String feedInputPath = baseTestHDFSDir + "/input" + MINUTE_DATE_PATTERN;
+    private String feedOutputPath = baseTestHDFSDir + "/output-data" + MINUTE_DATE_PATTERN;
+    private static final Logger LOGGER = Logger.getLogger(ProcessUpdateTest.class);
+
+    @BeforeClass(alwaysRun = true)
+    public void uploadWorkflow() throws Exception {
+        uploadDirToClusters(aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE);
+    }
+
+    @BeforeMethod(alwaysRun = true)
+    public void setUp() throws Exception {
+        Bundle bundle = BundleUtil.readELBundle();
+        bundles[0] = new Bundle(bundle, servers.get(0));
+        bundles[0].generateUniqueBundle(this);
+        bundles[0].setProcessWorkflow(aggregateWorkflowDir);
+        bundles[0].setInputFeedDataPath(feedInputPath);
+        bundles[0].setOutputFeedLocationData(feedOutputPath);
+    }
+
+    /**
+     * Test for https://issues.apache.org/jira/browse/FALCON-99.
+     * Scenario: schedule a process which doesn't have late data handling and then update it to have it.
+     * Check that new coordinator was created.
+     */
+    @Test
+    public void updateProcessWithLateData() throws Exception {
+        String start = TimeUtil.getTimeWrtSystemTime(-60);
+        String end = TimeUtil.getTimeWrtSystemTime(10);
+        bundles[0].submitAndScheduleAllFeeds();
+        ProcessMerlin process = bundles[0].getProcessObject();
+        process.setValidity(start, end);
+        process.setLateProcess(null);
+        cluster.getProcessHelper().submitAndSchedule(process.toString());
+        InstanceUtil.waitTillInstancesAreCreated(clusterOC, process.toString(), 0);
+        String bundleId = OozieUtil.getLatestBundleID(clusterOC, process.getName(), EntityType.PROCESS);
+
+        //update process to have late data handling
+        LateProcess lateProcess = new LateProcess();
+        lateProcess.setDelay(new Frequency("hours(1)"));
+        lateProcess.setPolicy(PolicyType.EXP_BACKOFF);
+        LateInput lateInput = new LateInput();
+        lateInput.setInput("inputData");
+        lateInput.setWorkflowPath(aggregateWorkflowDir);
+        lateProcess.getLateInputs().add(lateInput);
+        process.setLateProcess(lateProcess);
+        LOGGER.info("Updated process xml: " + Util.prettyPrintXml(process.toString()));
+        AssertUtil.assertSucceeded(cluster.getProcessHelper().update(process.toString(), process.toString()));
+
+        //check that new coordinator was created
+        String newBundleId = OozieUtil.getLatestBundleID(clusterOC, process.getName(), EntityType.PROCESS);
+        Assert.assertNotEquals(bundleId, newBundleId, "New Bundle should be created.");
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void tearDown() {
+        removeTestClassEntities();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
index 9ea8471..ca6ee88 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
@@ -77,7 +77,7 @@ public class TestngListener implements ITestListener, IExecutionListener {
             LOGGER.info("Dumping of falcon store failed: " + e);
         }
         LOGGER.info(
-            String.format("Testing going to end for: %s.%s(%s) %s", result.getTestClass().getName(),
+            String.format("Testing going to end for: %s.%s(%s) ----- Status: %s", result.getTestClass().getName(),
                 result.getName(), Arrays.toString(result.getParameters()), outcome));
         NDC.pop();
         LOGGER.info(hr);


[2/3] falcon git commit: Add ProcessUpdateTest, PipelineInstanceDependencyTest and other tests and test fixes. Contributed by Raghav Gautam and Paul Isaychuk

Posted by pi...@apache.org.
http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/HiveDRTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/HiveDRTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/HiveDRTest.java
index 1c788a3..bfc0d66 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/HiveDRTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/HiveDRTest.java
@@ -30,6 +30,7 @@ import org.apache.falcon.regression.core.supportClasses.NotifyingAssert;
 import org.apache.falcon.regression.core.util.BundleUtil;
 import org.apache.falcon.regression.core.util.HiveAssert;
 import org.apache.falcon.regression.core.util.InstanceUtil;
+import org.apache.falcon.regression.core.util.MatrixUtil;
 import org.apache.falcon.regression.core.util.OozieUtil;
 import org.apache.falcon.regression.core.util.TimeUtil;
 import org.apache.falcon.regression.testHelper.BaseTestClass;
@@ -42,14 +43,12 @@ import org.apache.oozie.client.CoordinatorJob;
 import org.apache.oozie.client.OozieClient;
 import org.testng.Assert;
 import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 import org.testng.asserts.SoftAssert;
 
 import java.io.IOException;
 import java.sql.Connection;
-import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -76,6 +75,7 @@ public class HiveDRTest extends BaseTestClass {
     private final FileSystem clusterFS3 = serverFS.get(2);
     private final OozieClient clusterOC = serverOC.get(0);
     private final OozieClient clusterOC2 = serverOC.get(1);
+    private final OozieClient clusterOC3 = serverOC.get(2);
     private final String baseTestHDFSDir = cleanAndGetTestDir() + "/HiveDR/";
     private HCatClient clusterHC;
     private HCatClient clusterHC2;
@@ -83,8 +83,12 @@ public class HiveDRTest extends BaseTestClass {
     private Connection connection;
     private Connection connection2;
 
-    @BeforeMethod(alwaysRun = true)
-    public void setUp() throws Exception {
+    @DataProvider
+    public Object[][] getRecipeLocation() {
+        return MatrixUtil.crossProduct(RecipeExecLocation.values());
+    }
+
+    private void setUp(RecipeExecLocation recipeExecLocation) throws Exception {
         clusterHC = cluster.getClusterHelper().getHCatClient();
         clusterHC2 = cluster2.getClusterHelper().getHCatClient();
         bundles[0] = new Bundle(BundleUtil.readHCatBundle(), cluster);
@@ -93,21 +97,17 @@ public class HiveDRTest extends BaseTestClass {
         bundles[1].generateUniqueBundle(this);
         final ClusterMerlin srcCluster = bundles[0].getClusterElement();
         final ClusterMerlin tgtCluster = bundles[1].getClusterElement();
-        Bundle.submitCluster(bundles[0]);
-
+        String recipeDir = "HiveDrRecipe";
         if (MerlinConstants.IS_SECURE) {
-            recipeMerlin = RecipeMerlin.readFromDir("HiveDrSecureRecipe",
-                FalconCLI.RecipeOperation.HIVE_DISASTER_RECOVERY)
-                .withRecipeCluster(srcCluster);
-        } else {
-            recipeMerlin = RecipeMerlin.readFromDir("HiveDrRecipe",
-                FalconCLI.RecipeOperation.HIVE_DISASTER_RECOVERY)
-                .withRecipeCluster(srcCluster);
+            recipeDir = "HiveDrSecureRecipe";
         }
+        Bundle.submitCluster(recipeExecLocation.getRecipeBundle(bundles[0], bundles[1]));
+        recipeMerlin = RecipeMerlin.readFromDir(recipeDir, FalconCLI.RecipeOperation.HIVE_DISASTER_RECOVERY)
+            .withRecipeCluster(recipeExecLocation.getRecipeCluster(srcCluster, tgtCluster));
         recipeMerlin.withSourceCluster(srcCluster)
             .withTargetCluster(tgtCluster)
             .withFrequency(new Frequency("5", Frequency.TimeUnit.minutes))
-            .withValidity(TimeUtil.getTimeWrtSystemTime(-5), TimeUtil.getTimeWrtSystemTime(5));
+            .withValidity(TimeUtil.getTimeWrtSystemTime(-5), TimeUtil.getTimeWrtSystemTime(15));
         recipeMerlin.setUniqueName(this.getClass().getSimpleName());
 
         connection = cluster.getClusterHelper().getHiveJdbcConnection();
@@ -121,8 +121,9 @@ public class HiveDRTest extends BaseTestClass {
         runSql(connection2, "use hdr_sdb1");
     }
 
-    @Test
-    public void drPartition() throws Exception {
+    @Test(dataProvider = "getRecipeLocation")
+    public void drPartition(final RecipeExecLocation recipeExecLocation) throws Exception {
+        setUp(recipeExecLocation);
         final String tblName = "partitionDR";
         recipeMerlin.withSourceDb(DB_NAME).withSourceTable(tblName);
         final List<String> command = recipeMerlin.getSubmissionCommand();
@@ -157,8 +158,8 @@ public class HiveDRTest extends BaseTestClass {
 
         Assert.assertEquals(Bundle.runFalconCLI(command), 0, "Recipe submission failed.");
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(DB_NAME, tblName),
             cluster2, clusterHC2.getTable(DB_NAME, tblName), new NotifyingAssert(true)
@@ -167,6 +168,8 @@ public class HiveDRTest extends BaseTestClass {
 
     @Test
     public void drInsertOverwritePartition() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.SourceCluster;
+        setUp(recipeExecLocation);
         final String tblName = "drInsertOverwritePartition";
         final String hlpTblName = "drInsertOverwritePartitionHelperTbl";
         recipeMerlin.withSourceDb(DB_NAME).withSourceTable(tblName);
@@ -200,8 +203,8 @@ public class HiveDRTest extends BaseTestClass {
 
         Assert.assertEquals(Bundle.runFalconCLI(command), 0, "Recipe submission failed.");
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(DB_NAME, tblName),
             cluster2, clusterHC2.getTable(DB_NAME, tblName), new NotifyingAssert(true)
@@ -210,6 +213,8 @@ public class HiveDRTest extends BaseTestClass {
 
     @Test
     public void drTwoTablesOneRequest() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.TargetCluster;
+        setUp(recipeExecLocation);
         final String tblName = "firstTableDR";
         final String tbl2Name = "secondTableDR";
         recipeMerlin.withSourceDb(DB_NAME).withSourceTable(tblName + ',' + tbl2Name);
@@ -232,8 +237,8 @@ public class HiveDRTest extends BaseTestClass {
 
         Assert.assertEquals(Bundle.runFalconCLI(command), 0, "Recipe submission failed.");
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         final NotifyingAssert anAssert = new NotifyingAssert(true);
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(DB_NAME, tblName),
@@ -246,6 +251,8 @@ public class HiveDRTest extends BaseTestClass {
 
     @Test
     public void drSerDeWithProperties() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.SourceCluster;
+        setUp(recipeExecLocation);
         final String tblName = "serdeTable";
         recipeMerlin.withSourceDb(DB_NAME).withSourceTable(tblName);
         final List<String> command = recipeMerlin.getSubmissionCommand();
@@ -265,8 +272,8 @@ public class HiveDRTest extends BaseTestClass {
 
         Assert.assertEquals(Bundle.runFalconCLI(command), 0, "Recipe submission failed.");
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(DB_NAME, tblName),
             cluster2, clusterHC2.getTable(DB_NAME, tblName), new NotifyingAssert(true)
@@ -276,6 +283,8 @@ public class HiveDRTest extends BaseTestClass {
 
     @Test
     public void drChangeColumn() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.SourceCluster;
+        setUp(recipeExecLocation);
         final String tblName = "tableForColumnChange";
         recipeMerlin.withSourceDb(DB_NAME).withSourceTable(tblName);
         final List<String> command1 = recipeMerlin.getSubmissionCommand();
@@ -289,10 +298,8 @@ public class HiveDRTest extends BaseTestClass {
         runSql(connection,
             "ALTER TABLE " + tblName + " CHANGE id id STRING COMMENT 'some_comment'");
 
-
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipe1Name, 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
-
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipe1Name, 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(DB_NAME, tblName),
             cluster2, clusterHC2.getTable(DB_NAME, tblName), new NotifyingAssert(true)
@@ -302,6 +309,8 @@ public class HiveDRTest extends BaseTestClass {
 
     @Test
     public void drTwoDstTablesTwoRequests() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.TargetCluster;
+        setUp(recipeExecLocation);
         final HCatClient clusterHC3 = cluster3.getClusterHelper().getHCatClient();
         final Connection connection3 = cluster3.getClusterHelper().getHiveJdbcConnection();
         runSql(connection3, "drop database if exists hdr_sdb1 cascade");
@@ -313,9 +322,12 @@ public class HiveDRTest extends BaseTestClass {
         final String recipe1Name = recipeMerlin.getName();
         final List<String> command1 = recipeMerlin.getSubmissionCommand();
 
-        final Bundle bundle = BundleUtil.readHCatBundle();
-        bundle.generateUniqueBundle(this);
-        recipeMerlin.withTargetCluster(new Bundle(bundle, cluster3).getClusterElement());
+        final Bundle bundle3 = new Bundle(BundleUtil.readHCatBundle(), cluster3);
+        bundle3.generateUniqueBundle(this);
+        bundle3.submitClusters(prism);
+        recipeMerlin.withTargetCluster(bundle3.getClusterElement())
+                .withRecipeCluster(recipeExecLocation.getRecipeCluster(
+                        bundles[0].getClusterElement(), bundle3.getClusterElement()));
         recipeMerlin.setUniqueName(this.getClass().getSimpleName());
 
         final List<String> command2 = recipeMerlin.getSubmissionCommand();
@@ -334,10 +346,10 @@ public class HiveDRTest extends BaseTestClass {
         Assert.assertEquals(Bundle.runFalconCLI(command2), 0, "Recipe submission failed.");
 
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipe1Name, 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipe2Name, 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipe1Name, 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC3),
+            recipe2Name, 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         final NotifyingAssert anAssert = new NotifyingAssert(true);
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(DB_NAME, tblName),
@@ -349,6 +361,8 @@ public class HiveDRTest extends BaseTestClass {
 
     @Test
     public void drExternalToNonExternal() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.SourceCluster;
+        setUp(recipeExecLocation);
         final String tblName = "externalToNonExternal";
         recipeMerlin.withSourceDb(DB_NAME).withSourceTable(tblName);
         final List<String> command = recipeMerlin.getSubmissionCommand();
@@ -362,8 +376,8 @@ public class HiveDRTest extends BaseTestClass {
 
         Assert.assertEquals(Bundle.runFalconCLI(command), 0, "Recipe submission failed.");
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         final NotifyingAssert anAssert = new NotifyingAssert(true);
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(DB_NAME, tblName),
@@ -379,6 +393,8 @@ public class HiveDRTest extends BaseTestClass {
 
     @Test
     public void drExtPartitionedToNonExtPartitioned() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.SourceCluster;
+        setUp(recipeExecLocation);
         final String tblName = "extPartitionedToNonExtPartitioned";
         recipeMerlin.withSourceDb(DB_NAME).withSourceTable(tblName);
         final List<String> command = recipeMerlin.getSubmissionCommand();
@@ -408,8 +424,8 @@ public class HiveDRTest extends BaseTestClass {
         runSql(connection,
             "alter table " + tblName + " change column data data_new string");
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(DB_NAME, tblName),
             cluster2, clusterHC2.getTable(DB_NAME, tblName), anAssert, false);
@@ -428,6 +444,8 @@ public class HiveDRTest extends BaseTestClass {
      */
     @Test
     public void drChangeCommentAndPropertyTest() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.SourceCluster;
+        setUp(recipeExecLocation);
         final String tblName = "myTable";
         recipeMerlin.withSourceDb(DB_NAME).withSourceTable(tblName);
         final List<String> command = recipeMerlin.getSubmissionCommand();
@@ -458,8 +476,8 @@ public class HiveDRTest extends BaseTestClass {
 
         Assert.assertEquals(Bundle.runFalconCLI(command), 0, "Recipe submission failed.");
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(DB_NAME, tblName),
             cluster2, clusterHC2.getTable(DB_NAME, tblName), new NotifyingAssert(true)
@@ -468,6 +486,7 @@ public class HiveDRTest extends BaseTestClass {
 
     @Test
     public void dataGeneration() throws Exception {
+        setUp(RecipeExecLocation.SourceCluster);
         runSql(connection, "use hdr_sdb1");
         createVanillaTable(connection, "store_sales");
         createSerDeTable(connection);
@@ -498,6 +517,7 @@ public class HiveDRTest extends BaseTestClass {
 
     @Test(enabled = false)
     public void assertionTest() throws Exception {
+        setUp(RecipeExecLocation.SourceCluster);
         final SoftAssert anAssert = new SoftAssert();
         HiveAssert.assertTableEqual(
             cluster, clusterHC.getTable("default", "hcatsmoke10546"),
@@ -515,7 +535,8 @@ public class HiveDRTest extends BaseTestClass {
      * @throws IOException
      */
     @Test
-    public void dynamicPartitionsTest() throws SQLException, IOException {
+    public void dynamicPartitionsTest() throws Exception {
+        setUp(RecipeExecLocation.SourceCluster);
         //create table with static partitions on first cluster
         createPartitionedTable(connection, false);
 
@@ -535,6 +556,8 @@ public class HiveDRTest extends BaseTestClass {
      */
     @Test
     public void drInsertDropReplaceDynamicPartition() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.SourceCluster;
+        setUp(recipeExecLocation);
         final String tblName = "dynamicPartitionDR";
         recipeMerlin.withSourceDb(DB_NAME).withSourceTable(tblName);
         final List<String> command = recipeMerlin.getSubmissionCommand();
@@ -577,8 +600,8 @@ public class HiveDRTest extends BaseTestClass {
 
         Assert.assertEquals(Bundle.runFalconCLI(command), 0, "Recipe submission failed.");
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(DB_NAME, tblName),
             cluster2, clusterHC2.getTable(DB_NAME, tblName), new NotifyingAssert(true)
@@ -592,6 +615,8 @@ public class HiveDRTest extends BaseTestClass {
      */
     @Test
     public void drInsertOverwriteDynamicPartition() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.SourceCluster;
+        setUp(recipeExecLocation);
         final String tblName = "drInsertOverwritePartition";
         final String hlpTblName = "drInsertOverwritePartitionHelperTbl";
         recipeMerlin.withSourceDb(DB_NAME).withSourceTable(tblName);
@@ -637,8 +662,8 @@ public class HiveDRTest extends BaseTestClass {
 
         Assert.assertEquals(Bundle.runFalconCLI(command), 0, "Recipe submission failed.");
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(DB_NAME, tblName),
             cluster2, clusterHC2.getTable(DB_NAME, tblName), new NotifyingAssert(true)
@@ -651,6 +676,7 @@ public class HiveDRTest extends BaseTestClass {
      */
     @Test(dataProvider = "frequencyGenerator")
     public void differentRecipeFrequenciesTest(String frequency) throws Exception {
+        setUp(RecipeExecLocation.SourceCluster);
         LOGGER.info("Testing with frequency: " + frequency);
         String tblName = "myTable";
         recipeMerlin.withSourceDb(DB_NAME).withSourceTable(tblName)

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/HiveDbDRTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/HiveDbDRTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/HiveDbDRTest.java
index a64bd6d..5efd69f 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/HiveDbDRTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/HiveDbDRTest.java
@@ -32,6 +32,7 @@ import org.apache.falcon.regression.core.util.Config;
 import org.apache.falcon.regression.core.util.HadoopUtil;
 import org.apache.falcon.regression.core.util.HiveAssert;
 import org.apache.falcon.regression.core.util.InstanceUtil;
+import org.apache.falcon.regression.core.util.MatrixUtil;
 import org.apache.falcon.regression.core.util.TimeUtil;
 import org.apache.falcon.regression.testHelper.BaseTestClass;
 import org.apache.hadoop.fs.FileSystem;
@@ -43,7 +44,6 @@ import org.apache.oozie.client.CoordinatorAction;
 import org.apache.oozie.client.OozieClient;
 import org.testng.Assert;
 import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
@@ -67,14 +67,19 @@ public class HiveDbDRTest extends BaseTestClass {
     private final FileSystem clusterFS = serverFS.get(0);
     private final FileSystem clusterFS2 = serverFS.get(1);
     private final OozieClient clusterOC = serverOC.get(0);
+    private final OozieClient clusterOC2 = serverOC.get(1);
     private HCatClient clusterHC;
     private HCatClient clusterHC2;
     private RecipeMerlin recipeMerlin;
     private Connection connection;
     private Connection connection2;
 
-    @BeforeMethod(alwaysRun = true)
-    public void setUp() throws Exception {
+    @DataProvider
+    public Object[][] getRecipeLocation() {
+        return MatrixUtil.crossProduct(RecipeExecLocation.values());
+    }
+
+    private void setUp(RecipeExecLocation recipeExecLocation) throws Exception {
         clusterHC = cluster.getClusterHelper().getHCatClient();
         clusterHC2 = cluster2.getClusterHelper().getHCatClient();
         bundles[0] = new Bundle(BundleUtil.readHCatBundle(), cluster);
@@ -83,17 +88,14 @@ public class HiveDbDRTest extends BaseTestClass {
         bundles[1].generateUniqueBundle(this);
         final ClusterMerlin srcCluster = bundles[0].getClusterElement();
         final ClusterMerlin tgtCluster = bundles[1].getClusterElement();
-        Bundle.submitCluster(bundles[0]);
+        Bundle.submitCluster(recipeExecLocation.getRecipeBundle(bundles[0], bundles[1]));
 
+        String recipeDir = "HiveDrRecipe";
         if (MerlinConstants.IS_SECURE) {
-            recipeMerlin = RecipeMerlin.readFromDir("HiveDrSecureRecipe",
-                FalconCLI.RecipeOperation.HIVE_DISASTER_RECOVERY)
-                .withRecipeCluster(srcCluster);
-        } else {
-            recipeMerlin = RecipeMerlin.readFromDir("HiveDrRecipe",
-                FalconCLI.RecipeOperation.HIVE_DISASTER_RECOVERY)
-                .withRecipeCluster(srcCluster);
+            recipeDir = "HiveDrSecureRecipe";
         }
+        recipeMerlin = RecipeMerlin.readFromDir(recipeDir, FalconCLI.RecipeOperation.HIVE_DISASTER_RECOVERY)
+            .withRecipeCluster(recipeExecLocation.getRecipeCluster(srcCluster, tgtCluster));
         recipeMerlin.withSourceCluster(srcCluster)
             .withTargetCluster(tgtCluster)
             .withFrequency(new Frequency("5", Frequency.TimeUnit.minutes))
@@ -111,8 +113,9 @@ public class HiveDbDRTest extends BaseTestClass {
         runSql(conn, "use " + dbName);
     }
 
-    @Test
-    public void drDbDropDb() throws Exception {
+    @Test(dataProvider = "getRecipeLocation")
+    public void drDbDropDb(final RecipeExecLocation recipeExecLocation) throws Exception {
+        setUp(recipeExecLocation);
         final String dbName = "drDbDropDb";
         setUpDb(dbName, connection);
         setUpDb(dbName, connection2);
@@ -123,8 +126,8 @@ public class HiveDbDRTest extends BaseTestClass {
 
         runSql(connection, "drop database " + dbName);
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         final List<String> dstDbs = runSql(connection2, "show databases");
         Assert.assertFalse(dstDbs.contains(dbName), "dstDbs = " + dstDbs + " was not expected to "
@@ -134,6 +137,8 @@ public class HiveDbDRTest extends BaseTestClass {
 
     @Test(dataProvider = "isDBReplication")
     public void drDbFailPass(Boolean isDBReplication) throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.SourceCluster;
+        setUp(recipeExecLocation);
         final String dbName = "drDbFailPass";
         final String tblName = "vanillaTable";
         final String hiveWarehouseLocation = Config.getProperty("hive.warehouse.location", "/apps/hive/warehouse/");
@@ -153,15 +158,15 @@ public class HiveDbDRTest extends BaseTestClass {
         LOGGER.info("Setting " + clusterFS2.getUri() + dbPath + " to : " + noReadWritePerm);
         clusterFS2.setPermission(new Path(dbPath), FsPermission.valueOf(noReadWritePerm));
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.KILLED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.KILLED, EntityType.PROCESS);
 
         final String readWritePerm = "drwxr-xr-x";
         LOGGER.info("Setting " + clusterFS2.getUri() + dbPath + " to : " + readWritePerm);
         clusterFS2.setPermission(new Path(dbPath), FsPermission.valueOf(readWritePerm));
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(dbName, tblName),
             cluster2, clusterHC2.getTable(dbName, tblName), new NotifyingAssert(true)
@@ -170,6 +175,8 @@ public class HiveDbDRTest extends BaseTestClass {
 
     @Test
     public void drDbAddDropTable() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.SourceCluster;
+        setUp(recipeExecLocation);
         final String dbName = "drDbAddDropTable";
         final String tblToBeDropped = "table_to_be_dropped";
         final String tblToBeDroppedAndAdded = "table_to_be_dropped_and_readded";
@@ -195,8 +202,8 @@ public class HiveDbDRTest extends BaseTestClass {
 
         Assert.assertEquals(Bundle.runFalconCLI(command), 0, "Recipe submission failed.");
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         final NotifyingAssert anAssert = new NotifyingAssert(true);
         HiveAssert.assertDbEqual(cluster, clusterHC.getDatabase(dbName),
@@ -205,16 +212,18 @@ public class HiveDbDRTest extends BaseTestClass {
         /* For second replication - a dropped tables is added back */
         createVanillaTable(connection, tblToBeDroppedAndAdded);
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 2,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 2, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         HiveAssert.assertDbEqual(cluster, clusterHC.getDatabase(dbName),
             cluster2, clusterHC2.getDatabase(dbName), anAssert);
         anAssert.assertAll();
     }
 
-    @Test(enabled = false)
+    @Test
     public void drDbNonReplicatableTable() throws Exception {
+        final RecipeExecLocation recipeExecLocation = RecipeExecLocation.SourceCluster;
+        setUp(recipeExecLocation);
         final String dbName = "drDbNonReplicatableTable";
         final String tblName = "vanillaTable";
         final String tblView = "vanillaTableView";
@@ -237,8 +246,8 @@ public class HiveDbDRTest extends BaseTestClass {
         runSql(connection, "alter table " + tblOffline + " enable offline");
         Assert.assertEquals(Bundle.runFalconCLI(command), 0, "Recipe submission failed.");
 
-        InstanceUtil.waitTillInstanceReachState(clusterOC, recipeMerlin.getName(), 1,
-            CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
+        InstanceUtil.waitTillInstanceReachState(recipeExecLocation.getRecipeOC(clusterOC, clusterOC2),
+            recipeMerlin.getName(), 1, CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS);
 
         //vanilla table gets replicated, offline table & view are not replicated
         HiveAssert.assertTableEqual(cluster, clusterHC.getTable(dbName, tblName),

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/RecipeExecLocation.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/RecipeExecLocation.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/RecipeExecLocation.java
new file mode 100644
index 0000000..a124082
--- /dev/null
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/hive/dr/RecipeExecLocation.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.falcon.regression.hive.dr;
+
+import org.apache.falcon.regression.Entities.ClusterMerlin;
+import org.apache.falcon.regression.core.bundle.Bundle;
+import org.apache.oozie.client.OozieClient;
+
+/**
+ * Enum to represent location of recipe execution.
+ */
+enum RecipeExecLocation {
+    SourceCluster {
+        protected OozieClient getRecipeOC(OozieClient srcOC, OozieClient tgtOC) {
+            return srcOC;
+        }
+        protected ClusterMerlin getRecipeCluster(ClusterMerlin srcCM, ClusterMerlin tgtCM) {
+            return srcCM;
+        }
+        protected Bundle getRecipeBundle(Bundle srcBundle, Bundle tgtBundle) {
+            return srcBundle;
+        }
+    },
+    TargetCluster {
+        protected OozieClient getRecipeOC(OozieClient srcOC, OozieClient tgtOC) {
+            return tgtOC;
+        }
+        protected ClusterMerlin getRecipeCluster(ClusterMerlin srcCM, ClusterMerlin tgtCM) {
+            return tgtCM;
+        }
+        protected Bundle getRecipeBundle(Bundle srcBundle, Bundle tgtBundle) {
+            return tgtBundle;
+        }
+    };
+
+    /** Get oozie client for the Oozie that is going to run the recipe.
+     * @param srcOC the oozie client for the source cluster
+     * @param tgtOC the oozie client for the target cluster
+     * @return oozie client for the Oozie that is going to run the recipe
+     */
+    abstract OozieClient getRecipeOC(OozieClient srcOC, OozieClient tgtOC);
+
+    abstract ClusterMerlin getRecipeCluster(ClusterMerlin srcCM, ClusterMerlin tgtCM);
+
+    abstract Bundle getRecipeBundle(Bundle srcBundle, Bundle tgtBundle);
+
+}

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/lineage/ListProcessInstancesTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/lineage/ListProcessInstancesTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/lineage/ListProcessInstancesTest.java
index be8a631..43bdd87 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/lineage/ListProcessInstancesTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/lineage/ListProcessInstancesTest.java
@@ -40,6 +40,7 @@ import org.testng.asserts.SoftAssert;
 
 import java.io.IOException;
 import java.util.Date;
+import java.util.UUID;
 
 /**
  * Test list instances api for process.
@@ -58,21 +59,23 @@ public class ListProcessInstancesTest extends BaseTestClass {
 
     @BeforeClass(alwaysRun = true)
     public void setUp() throws IOException {
-        uploadDirToClusters(aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE);
-        startTime = TimeUtil.getTimeWrtSystemTime(-55);
-        endTime = TimeUtil.getTimeWrtSystemTime(5);
+        startTime = TimeUtil.getTimeWrtSystemTime(-65);
+        //setting end time in past to make "now" be later then actual end time
+        endTime = TimeUtil.getTimeWrtSystemTime(-5);
         LOGGER.info("Time range is between : " + startTime + " and " + endTime);
     }
 
     @BeforeMethod(alwaysRun = true)
     public void prepareData() throws Exception {
+        uploadDirToClusters(aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE);
         bundles[0] = BundleUtil.readELBundle();
         bundles[0] = new Bundle(bundles[0], servers.get(0));
         bundles[0].generateUniqueBundle(this);
         //prepare process
         bundles[0].setProcessWorkflow(aggregateWorkflowDir);
         bundles[0].setInputFeedDataPath(feedDataLocation);
-        bundles[0].setOutputFeedLocationData(baseTestHDFSDir + "/output" + MINUTE_DATE_PATTERN);
+        String suffix = UUID.randomUUID().toString();
+        bundles[0].setOutputFeedLocationData(baseTestHDFSDir + "/output/" + suffix + MINUTE_DATE_PATTERN);
         bundles[0].setProcessValidity(startTime, endTime);
         bundles[0].setProcessConcurrency(3);
         bundles[0].submitAndScheduleProcess();
@@ -94,6 +97,9 @@ public class ListProcessInstancesTest extends BaseTestClass {
      */
     @Test
     public void testProcessOrderBy() throws Exception {
+        //provide data for 4th and 5th instances (fyi: indexing starts from 0th instance)
+        OozieUtil.createMissingDependencies(cluster, EntityType.PROCESS, processName, 0, 3);
+        OozieUtil.createMissingDependencies(cluster, EntityType.PROCESS, processName, 0, 4);
         SoftAssert softAssert = new SoftAssert();
         //orderBy startTime descending order
         InstancesResult r = prism.getProcessHelper().listInstances(processName,
@@ -152,6 +158,7 @@ public class ListProcessInstancesTest extends BaseTestClass {
     }
 
     /**
+     * List process instances using orderBy - status, -startTime, -endTime params
      * List process instances using -offset and -numResults params expecting list of process
      * instances to start at the right offset and give expected number of instances.
      */
@@ -214,6 +221,10 @@ public class ListProcessInstancesTest extends BaseTestClass {
      */
     @Test
     public void testProcessFilterBy() throws Exception {
+        //provide data for 4th and 5th instances (fyi: indexing starts from 0th instance)
+        OozieUtil.createMissingDependencies(cluster, EntityType.PROCESS, processName, 0, 3);
+        OozieUtil.createMissingDependencies(cluster, EntityType.PROCESS, processName, 0, 4);
+
         //test with simple filters
         InstancesResult r = prism.getProcessHelper().listInstances(processName,
             "filterBy=STATUS:RUNNING", null);
@@ -293,9 +304,13 @@ public class ListProcessInstancesTest extends BaseTestClass {
                 + "&end=" + TimeUtil.addMinsToTime(startTime, 16), null);
         InstanceUtil.validateResponse(r, 1, 0, 0, 1, 0);
 
-        //only start, actual startTime (end is automatically set to start + frequency * 10)
+        //only start, actual startTime (end is automatically set to now - which is later then validity end time)
         r = prism.getProcessHelper().listInstances(processName, "start=" + startTime, null);
-        InstanceUtil.validateResponse(r, 10, 3, 0, 7, 0);
+        InstanceUtil.validateResponse(r, 10, 1, 0, 9, 0);
+
+        //the same without start, end should be set to now
+        r = prism.getProcessHelper().listInstances(processName, "", null);
+        InstanceUtil.validateResponse(r, 10, 1, 0, 9, 0);
 
         //only start, greater then actual startTime
         r = prism.getProcessHelper().listInstances(processName,

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ClusterSetupTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ClusterSetupTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ClusterSetupTest.java
index b0ddcf3..5efa5b2 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ClusterSetupTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ClusterSetupTest.java
@@ -83,6 +83,7 @@ public class ClusterSetupTest extends BaseUITestClass{
     @Test
     public void testDefaultScenario()
         throws URISyntaxException, AuthenticationException, InterruptedException, IOException {
+        Assert.assertFalse(clusterSetup.isXmlPreviewExpanded(), "Xml preview should be collapsed by default.");
         clusterSetup.fillForm(sourceCluster);
         clusterSetup.clickNext();
         clusterSetup.clickPrevious();
@@ -93,6 +94,9 @@ public class ClusterSetupTest extends BaseUITestClass{
         clusterSetup.clickSave();
         String alertText = clusterSetup.getActiveAlertText();
         Assert.assertEquals(alertText, "falcon/default/Submit successful (cluster) " + sourceCluster.getName());
+        //check the same via notifications bar
+        clusterSetup.getPageHeader().validateNotificationCountAndCheckLast(1,
+            "falcon/default/Submit successful (cluster) " + sourceCluster.getName());
         ClusterMerlin definition = new ClusterMerlin(cluster.getClusterHelper()
             .getEntityDefinition(bundles[0].getClusterElement().toString()).getMessage());
         //definition should be the same that the source
@@ -106,11 +110,11 @@ public class ClusterSetupTest extends BaseUITestClass{
     @Test
     public void testXmlPreview() {
         clusterSetup.fillForm(sourceCluster);
-        ClusterMerlin generalStepPreview = clusterSetup.getXmlPreview();
+        ClusterMerlin generalStepPreview = clusterSetup.getEntityFromXMLPreview();
         cleanGeneralPreview(generalStepPreview);
         sourceCluster.assertEquals(generalStepPreview);
         clusterSetup.clickNext();
-        ClusterMerlin summaryStepPreview = clusterSetup.getXmlPreview();
+        ClusterMerlin summaryStepPreview = clusterSetup.getEntityFromXMLPreview();
         sourceCluster.assertEquals(summaryStepPreview);
         generalStepPreview.assertEquals(summaryStepPreview);
     }
@@ -145,7 +149,7 @@ public class ClusterSetupTest extends BaseUITestClass{
         clusterSetup.fillForm(sourceCluster);
 
         //check without extra location
-        ClusterMerlin preview = clusterSetup.getXmlPreview();
+        ClusterMerlin preview = clusterSetup.getEntityFromXMLPreview();
         cleanGeneralPreview(preview);
         sourceCluster.assertEquals(preview);
 
@@ -157,7 +161,7 @@ public class ClusterSetupTest extends BaseUITestClass{
         clusterSetup.clickAddLocation();
         clusterSetup.fillAdditionalLocation(location);
         Assert.assertTrue(clusterSetup.checkElementByContent("input", path), "Location should be present.");
-        preview = clusterSetup.getXmlPreview();
+        preview = clusterSetup.getEntityFromXMLPreview();
         cleanGeneralPreview(preview);
         //add location to source to compare equality
         sourceCluster.addLocation(ClusterLocationType.WORKING, path);
@@ -166,7 +170,7 @@ public class ClusterSetupTest extends BaseUITestClass{
         //delete location and check results
         clusterSetup.clickDeleteLocation();
         Assert.assertFalse(clusterSetup.checkElementByContent("input", path), "Location should be absent.");
-        preview = clusterSetup.getXmlPreview();
+        preview = clusterSetup.getEntityFromXMLPreview();
         cleanGeneralPreview(preview);
         //remove location from source to check equality
         int last = sourceCluster.getLocations().getLocations().size() - 1;
@@ -183,7 +187,7 @@ public class ClusterSetupTest extends BaseUITestClass{
         clusterSetup.fillForm(sourceCluster);
 
         //check without extra tag
-        ClusterMerlin preview = clusterSetup.getXmlPreview();
+        ClusterMerlin preview = clusterSetup.getEntityFromXMLPreview();
         cleanGeneralPreview(preview);
         sourceCluster.assertEquals(preview);
 
@@ -192,7 +196,7 @@ public class ClusterSetupTest extends BaseUITestClass{
         clusterSetup.addTag("myTag2", "myValue2");
         Assert.assertTrue(clusterSetup.checkElementByContent("input", "myTag2"), "Tag should be present");
         Assert.assertTrue(clusterSetup.checkElementByContent("input", "myValue2"), "Tag should be present");
-        preview = clusterSetup.getXmlPreview();
+        preview = clusterSetup.getEntityFromXMLPreview();
         cleanGeneralPreview(preview);
         //add tag to source to compare equality
         sourceCluster.setTags("myTag1=myValue1,myTag2=myValue2");
@@ -202,7 +206,7 @@ public class ClusterSetupTest extends BaseUITestClass{
         clusterSetup.clickDeleteTag();
         Assert.assertFalse(clusterSetup.checkElementByContent("input", "myTag2"), "Tag should be absent.");
         Assert.assertFalse(clusterSetup.checkElementByContent("input", "myValue2"), "Tag should be absent.");
-        preview = clusterSetup.getXmlPreview();
+        preview = clusterSetup.getEntityFromXMLPreview();
         cleanGeneralPreview(preview);
         //remove location from source to check equality
         sourceCluster.setTags("myTag1=myValue1");
@@ -254,11 +258,27 @@ public class ClusterSetupTest extends BaseUITestClass{
         clusterSetup.clickNext();
         clusterSetup.clickSave();
         String alertMessage = clusterSetup.getActiveAlertText();
-        Assert.assertEquals(alertMessage,
+        Assert.assertTrue(alertMessage.contains(String.format("Location %s for cluster %s must exist.",
+            nonExistent, sourceCluster.getName())), "Alert message should match to expected.");
+        //check the same through notification bar
+        clusterSetup.getPageHeader().validateNotificationCountAndCheckLast(1,
             String.format("Location %s for cluster %s must exist.", nonExistent, sourceCluster.getName()));
     }
 
     /**
+     * Validate alert lifetime.
+     */
+    @Test
+    public void testValidateAlertLifeTime() throws IOException {
+        String nonExistent = "/non-existent-directory";
+        sourceCluster.getLocation(ClusterLocationType.STAGING).setPath(nonExistent);
+        clusterSetup.fillForm(sourceCluster);
+        clusterSetup.clickNext();
+        clusterSetup.clickSave();
+        clusterSetup.validateAlertLifetime();
+    }
+
+    /**
      * Populate cluster with properties. Click Edit XML. Change cluster name and
      * description, add registry interface. Check that they were enabled and populated
      * in wizard.
@@ -283,7 +303,7 @@ public class ClusterSetupTest extends BaseUITestClass{
         sourceCluster.getInterfaces().getInterfaces().add(iFace);
 
         //populate it to xmlPreview
-        clusterSetup.setClusterXml(sourceCluster.toString());
+        clusterSetup.setXmlPreview(sourceCluster.toString());
 
         //check values on wizard
         registryEndpoint = clusterSetup.getInterfaceEndpoint(Interfacetype.REGISTRY);
@@ -304,24 +324,24 @@ public class ClusterSetupTest extends BaseUITestClass{
     @Test
     public void testEditXmlInvalidValues(){
         clusterSetup.fillForm(sourceCluster);
-        ClusterMerlin initialPreview = clusterSetup.getXmlPreview();
+        ClusterMerlin initialPreview = clusterSetup.getEntityFromXMLPreview();
 
         //break xml
         String brokenXml = new ClusterMerlin(sourceCluster.toString()).toString();
         brokenXml = brokenXml.substring(0, brokenXml.length() - 3);
 
         //enter it into xml preview form
-        clusterSetup.setClusterXml(brokenXml);
+        clusterSetup.setXmlPreview(brokenXml);
 
         //compare preview before and after changes
-        ClusterMerlin finalPreview = clusterSetup.getXmlPreview();
+        ClusterMerlin finalPreview = clusterSetup.getEntityFromXMLPreview();
         Assert.assertEquals(initialPreview, finalPreview, "Broken xml shouldn't be accepted.");
 
         //change properties to malformed
         sourceCluster.setName("abc123!@#");
 
         //enter it into xml preview form
-        clusterSetup.setClusterXml(sourceCluster.toString());
+        clusterSetup.setXmlPreview(sourceCluster.toString());
 
         //check the value on a wizard
         Assert.assertEquals(clusterSetup.getName(), sourceCluster.getName(), "Malformed name should be accepted.");

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/FeedSetupTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/FeedSetupTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/FeedSetupTest.java
index 47b1d19..e18fb47 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/FeedSetupTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/FeedSetupTest.java
@@ -123,6 +123,7 @@ public class FeedSetupTest extends BaseUITestClass{
      */
     @Test
     public void testWizardDefaultScenario() throws Exception {
+        Assert.assertFalse(feedWizardPage.isXmlPreviewExpanded(), "Xml preview should be collapsed by default.");
         feed.setTags(getRandomTags());
         feed.setGroups("groups");
         feed.setAvailabilityFlag("_SUCCESS");
@@ -201,7 +202,7 @@ public class FeedSetupTest extends BaseUITestClass{
 
         // Set values on the General Info Page
         feedWizardPage.setFeedGeneralInfo(feed);
-        FeedMerlin feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        FeedMerlin feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert all the values entered on the General Info Page
         feed.assertGeneralProperties(feedFromXML);
@@ -209,7 +210,7 @@ public class FeedSetupTest extends BaseUITestClass{
         // Set values on the Properties Info Page
         feedWizardPage.clickNext();
         feedWizardPage.setFeedPropertiesInfo(feed);
-        feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert all the values entered on the Properties Info Page
         feed.assertPropertiesInfo(feedFromXML);
@@ -217,7 +218,7 @@ public class FeedSetupTest extends BaseUITestClass{
         // Set values on the Location Info Page
         feedWizardPage.clickNext();
         feedWizardPage.setFeedLocationInfo(feed);
-        feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert all the values entered on the Location Info Page
         feed.assertLocationInfo(feedFromXML);
@@ -226,7 +227,7 @@ public class FeedSetupTest extends BaseUITestClass{
         // Set values on the Cluster Info Page
         feedWizardPage.clickNext();
         feedWizardPage.setFeedClustersInfo(feed);
-        feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
 
         // Assert all the values entered on the Cluster Info Page
@@ -253,15 +254,13 @@ public class FeedSetupTest extends BaseUITestClass{
         feedWizardPage.setFeedGroups(feed.getGroups());
 
         // Get XML, and set tag and group back to null
-        FeedMerlin feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        FeedMerlin feedFromXML = feedWizardPage.getEntityFromXMLPreview();
         feedFromXML.setTags(null);
         feedFromXML.setGroups(null);
 
         // Now click EditXML and set the updated XML here
-        feedWizardPage.clickEditXml();
         String xmlToString = feedFromXML.toString();
-        feedWizardPage.setFeedXml(xmlToString);
-        feedWizardPage.clickEditXml();
+        feedWizardPage.setXmlPreview(xmlToString);
 
         // Assert that there is only one Tag on the Wizard window
         feedWizardPage.isTagsDisplayed(0, true);
@@ -282,10 +281,8 @@ public class FeedSetupTest extends BaseUITestClass{
         feedFromXML.setGroups("groups_new");
 
         // Now click EditXML and set the updated XML here
-        feedWizardPage.clickEditXml();
         xmlToString = feedFromXML.toString();
-        feedWizardPage.setFeedXml(xmlToString);
-        feedWizardPage.clickEditXml();
+        feedWizardPage.setXmlPreview(xmlToString);
 
         // Assert that there are two Tags on the Wizard window
         feedWizardPage.isTagsDisplayed(0, true);
@@ -340,7 +337,7 @@ public class FeedSetupTest extends BaseUITestClass{
 
         // Set values on the General Info Page
         feedWizardPage.setFeedGeneralInfo(feed);
-        FeedMerlin feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        FeedMerlin feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert all the values entered on the General Info Page
         feed.assertGeneralProperties(feedFromXML);
@@ -367,7 +364,7 @@ public class FeedSetupTest extends BaseUITestClass{
         feedWizardPage.isTagsDisplayed(1, true);
 
         // Get feed from XML Preview
-        FeedMerlin feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        FeedMerlin feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert Tag values in the XML Preview
         Assert.assertEquals(feedFromXML.getTags(), feed.getTags());
@@ -380,7 +377,7 @@ public class FeedSetupTest extends BaseUITestClass{
         feedWizardPage.isTagsDisplayed(1, false);
 
         // Get feed from XML Preview
-        feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        feedFromXML = feedWizardPage.getEntityFromXMLPreview();
         // Assert that there are is only one Tag in the XML Preview
         Assert.assertEquals(feedFromXML.getTags(), "first=yes",
             "Unexpected Tags on the XML preview");
@@ -470,7 +467,7 @@ public class FeedSetupTest extends BaseUITestClass{
         // Set values on the Properties Info Page
         feedWizardPage.clickNext();
         feedWizardPage.setFeedPropertiesInfo(feed);
-        FeedMerlin feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        FeedMerlin feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert all the values entered on the Properties Info Page
         feed.assertPropertiesInfo(feedFromXML);
@@ -499,15 +496,13 @@ public class FeedSetupTest extends BaseUITestClass{
         feedWizardPage.setFeedLateArrivalCutOffUnit(feed.getLateArrival().getCutOff().getTimeUnit().toString());
 
         // Get XML, and set Frequency and Late Arrival back to null
-        FeedMerlin feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        FeedMerlin feedFromXML = feedWizardPage.getEntityFromXMLPreview();
         feedFromXML.setFrequency(null);
         feedFromXML.setLateArrival(null);
 
         // Now click EditXML and set the updated XML here
-        feedWizardPage.clickEditXml();
         String xmlToString = feedFromXML.toString();
-        feedWizardPage.setFeedXml(xmlToString);
-        feedWizardPage.clickEditXml();
+        feedWizardPage.setXmlPreview(xmlToString);
 
         // Assert that the Frequency value is empty on the Wizard window
         Assert.assertEquals(feedWizardPage.getFeedFrequencyQuantityText(), "",
@@ -523,10 +518,8 @@ public class FeedSetupTest extends BaseUITestClass{
         feedFromXML.getLateArrival().setCutOff(new Frequency("1", Frequency.TimeUnit.days));
 
         // Now click EditXML and set the updated XML here
-        feedWizardPage.clickEditXml();
         xmlToString = feedFromXML.toString();
-        feedWizardPage.setFeedXml(xmlToString);
-        feedWizardPage.clickEditXml();
+        feedWizardPage.setXmlPreview(xmlToString);
 
         // Assert that the Frequency values are correct on the Wizard window
         Assert.assertEquals(feedWizardPage.getFeedFrequencyQuantityText(), "5",
@@ -595,7 +588,7 @@ public class FeedSetupTest extends BaseUITestClass{
         feedWizardPage.isPropertyDisplayed(1, true);
 
         // Get feed from XML Preview
-        FeedMerlin feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        FeedMerlin feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert Property values in the XML Preview
         Assert.assertEquals(feedFromXML.getProperties().getProperties().get(0).getName(),
@@ -621,7 +614,7 @@ public class FeedSetupTest extends BaseUITestClass{
 
 
         // Get feed from XML Preview
-        feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert Property value in the XML Preview
         Assert.assertEquals(feedFromXML.getProperties().getProperties().get(0).getName(),
@@ -741,7 +734,7 @@ public class FeedSetupTest extends BaseUITestClass{
         feedWizardPage.setFeedLocationInfo(feed);
 
         // Get feed from XML Preview
-        FeedMerlin feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        FeedMerlin feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert all the values entered on the Location Info Page
         feed.assertLocationInfo(feedFromXML);
@@ -752,13 +745,11 @@ public class FeedSetupTest extends BaseUITestClass{
         feedFromXML.getLocations().getLocations().get(2).setPath(baseTestHDFSDir + "/newFalcon/clicksMetaData");
 
         // Now click EditXML and set the updated XML here
-        feedWizardPage.clickEditXml();
         String xmlToString = feedFromXML.toString();
-        feedWizardPage.setFeedXml(xmlToString);
-        feedWizardPage.clickEditXml();
+        feedWizardPage.setXmlPreview(xmlToString);
 
         // Get feed from XML Preview
-        feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        feedFromXML = feedWizardPage.getEntityFromXMLPreview();
         // Assert all the values on the Location Info Page
         Assert.assertEquals(feedFromXML.getLocations().getLocations().get(0).getPath(),
             baseTestHDFSDir + "/newInput/${YEAR}/${MONTH}/${DAY}/${HOUR}/${MINUTE}");
@@ -877,7 +868,7 @@ public class FeedSetupTest extends BaseUITestClass{
 
         feedWizardPage.clickNext();
         // Get feed from XML Preview
-        FeedMerlin feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        FeedMerlin feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert all the values entered on the Location Info Page
         feed.assertLocationInfo(feedFromXML);
@@ -895,7 +886,7 @@ public class FeedSetupTest extends BaseUITestClass{
         feedWizardPage.clickNext();
 
         // Get feed from XML Preview
-        feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert the Table Uri value entered on the Location Info Page
         Assert.assertEquals(feedFromXML.getTable().getUri(), catalogUri,
@@ -928,7 +919,7 @@ public class FeedSetupTest extends BaseUITestClass{
         feedWizardPage.setFeedClustersInfo(feed);
 
         // Get feed from XML Preview
-        FeedMerlin feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        FeedMerlin feedFromXML = feedWizardPage.getEntityFromXMLPreview();
 
         // Assert all the values on the Cluster Info Page
         feed.assertClusterInfo(feedFromXML);
@@ -946,13 +937,11 @@ public class FeedSetupTest extends BaseUITestClass{
 
 
         // Now click EditXML and set the updated XML here
-        feedWizardPage.clickEditXml();
         String xmlToString = feedFromXML.toString();
-        feedWizardPage.setFeedXml(xmlToString);
-        feedWizardPage.clickEditXml();
+        feedWizardPage.setXmlPreview(xmlToString);
 
         // Get feed from XML Preview
-        feedFromXML = feedWizardPage.getFeedMerlinFromFeedXml();
+        feedFromXML = feedWizardPage.getEntityFromXMLPreview();
         // Assert all the values on the Location Info Page
         Assert.assertEquals(feedFromXML.getClusters().getClusters().get(0)
                 .getLocations().getLocations().get(0).getPath(),

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/HomePageTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/HomePageTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/HomePageTest.java
index 20864f6..46ace0f 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/HomePageTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/HomePageTest.java
@@ -172,8 +172,8 @@ public class HomePageTest extends BaseUITestClass {
         alertText = homePage.getActiveAlertText();
         Assert.assertEquals(alertText, "Invalid xml. File not uploaded",
             "XML file with invalid text was allowed to be uploaded");
-
-
+        //check the same with notification bar
+        homePage.getPageHeader().validateNotificationCountAndCheckLast(2, "Invalid xml. File not uploaded");
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/MirrorSourceTargetOptionsTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/MirrorSourceTargetOptionsTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/MirrorSourceTargetOptionsTest.java
index 552c15e..8bec758 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/MirrorSourceTargetOptionsTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/MirrorSourceTargetOptionsTest.java
@@ -193,6 +193,8 @@ public class MirrorSourceTargetOptionsTest extends BaseUITestClass{
         mirrorPage.save();
         Assert.assertTrue(mirrorPage.getActiveAlertText().contains("should be before process end"),
             "Warning about wrong Validity should be present");
+        //check the same through notification bar
+        mirrorPage.getPageHeader().validateNotificationCountAndCheckLast(1, "should be before process end");
     }
 
     @AfterClass(alwaysRun = true)

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/MirrorTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/MirrorTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/MirrorTest.java
index c54789b..e99202b 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/MirrorTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/MirrorTest.java
@@ -21,6 +21,7 @@ package org.apache.falcon.regression.searchUI;
 import org.apache.falcon.cli.FalconCLI;
 import org.apache.falcon.entity.v0.Frequency;
 import org.apache.falcon.entity.v0.cluster.ClusterLocationType;
+import org.apache.falcon.entity.v0.cluster.Interfacetype;
 import org.apache.falcon.regression.Entities.ClusterMerlin;
 import org.apache.falcon.regression.Entities.ProcessMerlin;
 import org.apache.falcon.regression.Entities.RecipeMerlin;
@@ -39,15 +40,18 @@ import org.apache.falcon.regression.ui.search.SearchPage;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.permission.FsPermission;
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
 import org.apache.hive.hcatalog.api.HCatClient;
 import org.apache.log4j.Logger;
 import org.apache.oozie.client.OozieClient;
+import org.testng.Assert;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 import java.io.IOException;
+import java.net.URISyntaxException;
 import java.sql.Connection;
 import java.util.Arrays;
 
@@ -75,6 +79,7 @@ public class MirrorTest extends BaseUITestClass {
     private Connection connection;
     private Connection connection2;
     private MirrorWizardPage mirrorPage;
+
     /**
      * Submit one cluster, 2 feeds and 10 processes with 1 to 10 tags (1st process has 1 tag,
      * 2nd - two tags.. 10th has 10 tags).
@@ -82,7 +87,6 @@ public class MirrorTest extends BaseUITestClass {
      * @throws IOException
      * @throws AuthenticationException
      * @throws InterruptedException
-     * @throws JAXBException
      */
     @BeforeMethod(alwaysRun = true)
     public void setup() throws Exception {
@@ -148,7 +152,7 @@ public class MirrorTest extends BaseUITestClass {
         hdfsRecipe.withSourceDir(hdfsSrcDir).withTargetDir(hdfsTgtDir);
         hdfsRecipe.setTags(Arrays.asList("key1=val1", "key2=val2", "key3=val3"));
 
-        mirrorPage.applyRecipe(hdfsRecipe);
+        mirrorPage.applyRecipe(hdfsRecipe, true);
         mirrorPage.next();
         mirrorPage.save();
 
@@ -169,7 +173,7 @@ public class MirrorTest extends BaseUITestClass {
         recipeMerlin.withSourceDb(dbName);
         recipeMerlin.withSourceTable(tblName);
         recipeMerlin.setTags(Arrays.asList("key1=val1", "key2=val2", "key3=val3"));
-        mirrorPage.applyRecipe(recipeMerlin);
+        mirrorPage.applyRecipe(recipeMerlin, true);
         mirrorPage.next();
         mirrorPage.save();
         AssertUtil.assertSucceeded(prism.getProcessHelper().getStatus(
@@ -186,6 +190,66 @@ public class MirrorTest extends BaseUITestClass {
     }
 
     /**
+     *  If "send alerts to" is empty on HiveDR UI, default value for drNotificationReceivers property must be "NA".
+     */
+    @Test
+    public void testSendAlertsDefaultValue()
+        throws InterruptedException, IOException, URISyntaxException, AuthenticationException {
+        recipeMerlin.withSourceDb(DB_NAME);
+        recipeMerlin.withSourceTable(TBL1_NAME);
+        mirrorPage.applyRecipe(recipeMerlin, false);
+        mirrorPage.next();
+        mirrorPage.save();
+        ProcessMerlin process = bundles[0].getProcessObject();
+        process.setName(recipeMerlin.getName());
+        process = new ProcessMerlin(cluster.getProcessHelper().getEntityDefinition(process.toString()).getMessage());
+        String drNotificationReceivers = process.getProperty("drNotificationReceivers");
+        Assert.assertTrue(drNotificationReceivers != null && drNotificationReceivers.equals("NA"),
+            "Default value for drNotificationReceivers should be NA.");
+
+        /* particular check that on table replication scenario UI doesn't pick up thrift server
+           end point in place of Hive server2 end point*/
+        String expectedUri = recipeMerlin.getTgtCluster().getInterfaceEndpoint(Interfacetype.REGISTRY)
+            .replace("thrift", "hive2").replace("9083", "10000");
+        Assert.assertEquals(process.getProperty("targetHiveServer2Uri"), expectedUri,
+            "Hive server2 end point should be picked by UI.");
+        expectedUri = recipeMerlin.getSrcCluster().getInterfaceEndpoint(Interfacetype.REGISTRY)
+            .replace("thrift", "hive2").replace("9083", "10000");
+        Assert.assertEquals(process.getProperty("sourceHiveServer2Uri"), expectedUri,
+            "Hive server2 end point should be picked by UI.");
+    }
+
+    /**
+     * Test that Hive DR UI doesn't picks thrift server end point in place of Hive server2 end point.
+     * Test that specified HDFS target staging path on Hive DR UI, isn't getting assigned to "*".
+     */
+    @Test
+    public void testHDFSTargetStagingPath()
+        throws URISyntaxException, AuthenticationException, InterruptedException, IOException {
+        recipeMerlin.withSourceDb(DB_NAME);
+        mirrorPage.applyRecipe(recipeMerlin, false);
+        mirrorPage.next();
+        mirrorPage.save();
+        ProcessMerlin process = bundles[0].getProcessObject();
+        process.setName(recipeMerlin.getName());
+        process = new ProcessMerlin(cluster.getProcessHelper().getEntityDefinition(process.toString()).getMessage());
+
+        // check that that Hive DR UI doesn't picks thrift server end point in place of Hive server2 end point
+        String expectedUri = recipeMerlin.getTgtCluster().getInterfaceEndpoint(Interfacetype.REGISTRY)
+            .replace("thrift", "hive2").replace("9083", "10000");
+        Assert.assertEquals(process.getProperty("targetHiveServer2Uri"), expectedUri,
+            "Hive server2 end point should be picked by UI.");
+        expectedUri = recipeMerlin.getSrcCluster().getInterfaceEndpoint(Interfacetype.REGISTRY)
+            .replace("thrift", "hive2").replace("9083", "10000");
+        Assert.assertEquals(process.getProperty("sourceHiveServer2Uri"), expectedUri,
+            "Hive server2 end point should be picked by UI.");
+
+        //check that that specified HDFS target staging path on Hive DR UI, isn't getting assigned to "*"
+        Assert.assertFalse(process.getProperty("targetStagingPath").equals("*"),
+            "HDFS target staging path shouldn't be assigned to '*'.");
+    }
+
+    /**
      * Test recipe with bad acls.
      * Set owner/group as invalid string (utf-8, special chars, number).
      * Check that user is not allowed to go to the next step and has been notified with an alert.
@@ -197,7 +261,7 @@ public class MirrorTest extends BaseUITestClass {
         final String goodAclOwner = MerlinConstants.CURRENT_USER_NAME;
         final String goodAclGroup = MerlinConstants.CURRENT_USER_GROUP;
         final String goodAclPerms = "777";
-        mirrorPage.applyRecipe(recipeMerlin);
+        mirrorPage.applyRecipe(recipeMerlin, true);
         NotifyingAssert notifyingAssert = new NotifyingAssert(true);
         for(String badAclOwner: new String[] {"utf8\u20ACchar", "speci@l", "123"}) {
             mirrorPage.setAclOwner(badAclOwner);
@@ -253,7 +317,7 @@ public class MirrorTest extends BaseUITestClass {
     public void testHiveAdvancedInvalidStaging() {
         recipeMerlin.withSourceDb(DB_NAME);
         recipeMerlin.setTags(Arrays.asList("key1=val1", "key2=val2", "key3=val3"));
-        mirrorPage.applyRecipe(recipeMerlin);
+        mirrorPage.applyRecipe(recipeMerlin, true);
         NotifyingAssert notifyingAssert = new NotifyingAssert(true);
         final String goodSrcStaging = recipeMerlin.getSrcCluster().getLocation(ClusterLocationType.STAGING).getPath();
         final String goodTgtStaging = recipeMerlin.getTgtCluster().getLocation(ClusterLocationType.STAGING).getPath();
@@ -297,7 +361,7 @@ public class MirrorTest extends BaseUITestClass {
     public void testHiveAdvancedStagingAcl() throws Exception {
         recipeMerlin.withSourceDb(DB_NAME);
         recipeMerlin.setTags(Arrays.asList("key1=val1", "key2=val2", "key3=val3"));
-        mirrorPage.applyRecipe(recipeMerlin);
+        mirrorPage.applyRecipe(recipeMerlin, true);
         NotifyingAssert notifyingAssert = new NotifyingAssert(true);
         final String goodSrcStaging = recipeMerlin.getSrcCluster().getLocation(ClusterLocationType.STAGING).getPath();
         final String goodTgtStaging = recipeMerlin.getTgtCluster().getLocation(ClusterLocationType.STAGING).getPath();

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ProcessSetupTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ProcessSetupTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ProcessSetupTest.java
index 728646f..eae5137 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ProcessSetupTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ProcessSetupTest.java
@@ -153,6 +153,7 @@ public class ProcessSetupTest extends BaseUITestClass {
      */
     @Test
     public void testGeneralStepDefaultScenario() throws Exception {
+        Assert.assertFalse(processWizardPage.isXmlPreviewExpanded(), "Xml preview should be collapsed by default.");
         processWizardPage.setProcessGeneralInfo(process);
         processWizardPage.clickNext();
 
@@ -172,7 +173,7 @@ public class ProcessSetupTest extends BaseUITestClass {
         processWizardPage.setProcessGeneralInfo(process);
 
         // Get process from XML Preview
-        ProcessMerlin processFromXML = processWizardPage.getProcessMerlinFromProcessXml();
+        ProcessMerlin processFromXML = processWizardPage.getEntityFromXMLPreview();
 
         // Assert all the values entered on the General Info Page
         LOGGER.info(String.format("Comparing source process: %n%s%n and preview: %n%s%n.", process, processFromXML));
@@ -196,14 +197,12 @@ public class ProcessSetupTest extends BaseUITestClass {
         processWizardPage.setTags(process.getTags());
 
         // Get XML, and set tag and group back to null
-        ProcessMerlin processFromXML = processWizardPage.getProcessMerlinFromProcessXml();
+        ProcessMerlin processFromXML = processWizardPage.getEntityFromXMLPreview();
         processFromXML.setTags(null);
 
         // Now click EditXML and set the updated XML here
-        processWizardPage.clickEditXml();
         String xmlToString = processFromXML.toString();
-        processWizardPage.setProcessXml(xmlToString);
-        processWizardPage.clickEditXml();
+        processWizardPage.setXmlPreview(xmlToString);
 
         Thread.sleep(1000);
         // Assert that there is only one Tag on the Wizard window
@@ -222,10 +221,8 @@ public class ProcessSetupTest extends BaseUITestClass {
         processFromXML.getWorkflow().setVersion("pig-0.13.0");
 
         // Now click EditXML and set the updated XML here
-        processWizardPage.clickEditXml();
         xmlToString = processFromXML.toString();
-        processWizardPage.setProcessXml(xmlToString);
-        processWizardPage.clickEditXml();
+        processWizardPage.setXmlPreview(xmlToString);
 
         // Assert that there are two Tags on the Wizard window
         processWizardPage.isTagsDisplayed(0, true);
@@ -316,7 +313,7 @@ public class ProcessSetupTest extends BaseUITestClass {
         processWizardPage.setProcessPropertiesInfo(process);
 
         // Get process from XML Preview
-        ProcessMerlin processFromXML = processWizardPage.getProcessMerlinFromProcessXml();
+        ProcessMerlin processFromXML = processWizardPage.getEntityFromXMLPreview();
 
         // Assert all the values entered on the Properties Page
         LOGGER.info(String.format("Comparing source process: %n%s%n and preview: %n%s%n.", process, processFromXML));
@@ -343,15 +340,13 @@ public class ProcessSetupTest extends BaseUITestClass {
         processWizardPage.setMaxParallelInstances(5);
 
         // Get process from XML Preview
-        ProcessMerlin processFromXML = processWizardPage.getProcessMerlinFromProcessXml();
+        ProcessMerlin processFromXML = processWizardPage.getEntityFromXMLPreview();
         processFromXML.setFrequency(null);
         processFromXML.setParallel(1);
 
         // Now click EditXML and set the updated XML here
-        processWizardPage.clickEditXml();
         String xmlToString = processFromXML.toString();
-        processWizardPage.setProcessXml(xmlToString);
-        processWizardPage.clickEditXml();
+        processWizardPage.setXmlPreview(xmlToString);
 
         // Assert Frequency and Parallel values
         Assert.assertEquals(processWizardPage.getFrequencyQuantityText(), "",
@@ -360,17 +355,15 @@ public class ProcessSetupTest extends BaseUITestClass {
             "Unexpected Parallel on the Wizard window");
 
         // Get process from XML Preview
-        processFromXML = processWizardPage.getProcessMerlinFromProcessXml();
+        processFromXML = processWizardPage.getEntityFromXMLPreview();
         // Set TimeZone and Order
         TimeZone tz = TimeZone.getTimeZone("GMT-08:00");
         processFromXML.setTimezone(tz);
         processFromXML.setOrder(ExecutionType.LIFO);
 
         // Now click EditXML and set the updated XML here
-        processWizardPage.clickEditXml();
         xmlToString = processFromXML.toString();
-        processWizardPage.setProcessXml(xmlToString);
-        processWizardPage.clickEditXml();
+        processWizardPage.setXmlPreview(xmlToString);
 
         // Assert TimeZone and Order
         Assert.assertEquals(processWizardPage.getOrderText(), "LIFO",
@@ -511,7 +504,7 @@ public class ProcessSetupTest extends BaseUITestClass {
 
         // Add clusters
         processWizardPage.setClusters(process.getClusters());
-        ProcessMerlin xmlPreview = processWizardPage.getProcessMerlinFromProcessXml();
+        ProcessMerlin xmlPreview = processWizardPage.getEntityFromXMLPreview();
 
         //compare clusters
         LOGGER.info(String.format("Comparing clusters of process: %n%s%n and preview: %n%s%n.", process, xmlPreview));
@@ -519,7 +512,7 @@ public class ProcessSetupTest extends BaseUITestClass {
 
         //delete one cluster and repeat the check
         processWizardPage.deleteLastCluster();
-        xmlPreview = processWizardPage.getProcessMerlinFromProcessXml();
+        xmlPreview = processWizardPage.getEntityFromXMLPreview();
         process.getClusters().getClusters().remove(1);
 
         //compare clusters
@@ -553,7 +546,7 @@ public class ProcessSetupTest extends BaseUITestClass {
         processWizardPage.setClusters(process.getClusters());
 
         //compare preview and source data
-        ProcessMerlin xmlPreview = processWizardPage.getProcessMerlinFromProcessXml();
+        ProcessMerlin xmlPreview = processWizardPage.getEntityFromXMLPreview();
         LOGGER.info(String.format("Comparing clusters of process: %n%s%n and preview: %n%s%n.", process, xmlPreview));
         ProcessMerlin.assertClustersEqual(process.getClusters().getClusters(), xmlPreview.getClusters().getClusters());
 
@@ -561,9 +554,7 @@ public class ProcessSetupTest extends BaseUITestClass {
         Date date = new Date();
         xmlPreview.getClusters().getClusters().get(0).getValidity().setEnd(date);
         xmlPreview.getClusters().getClusters().get(0).setName(clusterMerlin.getName());
-        processWizardPage.clickEditXml();
-        processWizardPage.setProcessXml(xmlPreview.toString());
-        processWizardPage.clickEditXml();
+        processWizardPage.setXmlPreview(xmlPreview.toString());
 
         //check that validity end is changed on wizard
         String endUI = processWizardPage.getValidityEnd();
@@ -581,9 +572,7 @@ public class ProcessSetupTest extends BaseUITestClass {
         processCluster.setName(firstClusterName);
         processCluster.setValidity(xmlPreview.getClusters().getClusters().get(0).getValidity());
         process.addProcessCluster(processCluster);
-        processWizardPage.clickEditXml();
-        processWizardPage.setProcessXml(xmlPreview.toString());
-        processWizardPage.clickEditXml();
+        processWizardPage.setXmlPreview(xmlPreview.toString());
 
         //check that changes are reflected on wizard
         int finalCount = processWizardPage.getWizardClusterCount();
@@ -797,7 +786,7 @@ public class ProcessSetupTest extends BaseUITestClass {
             "Unexpected Input End on the Wizard window");
 
         // Get process from XML Preview
-        ProcessMerlin processFromXML = processWizardPage.getProcessMerlinFromProcessXml();
+        ProcessMerlin processFromXML = processWizardPage.getEntityFromXMLPreview();
 
         // Assert Input values on the XML Preview
         LOGGER.info(String.format("Comparing source process: %n%s%n and preview: %n%s%n.", process, processFromXML));
@@ -808,10 +797,8 @@ public class ProcessSetupTest extends BaseUITestClass {
         processFromXML.setOutputs(process.getOutputs());
 
         // Now click EditXML and set the updated XML here
-        processWizardPage.clickEditXml();
         String xmlToString = processFromXML.toString();
-        processWizardPage.setProcessXml(xmlToString);
-        processWizardPage.clickEditXml();
+        processWizardPage.setXmlPreview(xmlToString);
 
         // Assert Input Name and Output values on Wizard
         Assert.assertEquals(processWizardPage.getInputNameText(0), "newInputData",
@@ -867,7 +854,7 @@ public class ProcessSetupTest extends BaseUITestClass {
             "Unexpected Input End on the Wizard window");
 
         // Get process from XML Preview
-        ProcessMerlin processFromXML = processWizardPage.getProcessMerlinFromProcessXml();
+        ProcessMerlin processFromXML = processWizardPage.getEntityFromXMLPreview();
 
         // Assert Input values on the XML Preview
         LOGGER.info(String.format("Comparing source process: %n%s%n and preview: %n%s%n.", process, processFromXML));
@@ -894,7 +881,7 @@ public class ProcessSetupTest extends BaseUITestClass {
             "Unexpected Output Instance on the Wizard window");
 
         // Get process from XML Preview
-        processFromXML = processWizardPage.getProcessMerlinFromProcessXml();
+        processFromXML = processWizardPage.getEntityFromXMLPreview();
 
         // Assert Output values on the XML Preview
         LOGGER.info(String.format("Comparing source process : %n%s%n and preview: %n%s%n.", process, processFromXML));
@@ -1009,7 +996,7 @@ public class ProcessSetupTest extends BaseUITestClass {
         //get process from summary and from xml and compare them
         ProcessMerlin summaryProcess = ProcessMerlin.getEmptyProcess(process);
         summaryProcess = processWizardPage.getProcessFromSummaryBox(summaryProcess);
-        ProcessMerlin previewProcess = processWizardPage.getProcessMerlinFromProcessXml();
+        ProcessMerlin previewProcess = processWizardPage.getEntityFromXMLPreview();
         summaryProcess.assertEquals(previewProcess);
 
         //add input to preview cluster
@@ -1022,9 +1009,7 @@ public class ProcessSetupTest extends BaseUITestClass {
         previewProcess.getInputs().getInputs().add(newInput);
 
         //push new process to xml preview
-        processWizardPage.clickEditXml();
-        processWizardPage.setProcessXml(previewProcess.toString());
-        processWizardPage.clickEditXml();
+        processWizardPage.setXmlPreview(previewProcess.toString());
 
         //get process from summary and check that new input is available
         summaryProcess = processWizardPage.getProcessFromSummaryBox(ProcessMerlin.getEmptyProcess(summaryProcess));
@@ -1062,17 +1047,15 @@ public class ProcessSetupTest extends BaseUITestClass {
         processWizardPage.clickNext();
 
         //get process from xml preview
-        ProcessMerlin previewProcess1 = processWizardPage.getProcessMerlinFromProcessXml();
+        ProcessMerlin previewProcess1 = processWizardPage.getEntityFromXMLPreview();
         String processString = previewProcess1.toString();
 
         //damage the xml and populate it back to preview
         processString = processString.substring(0, processString.length() - 3);
-        processWizardPage.clickEditXml();
-        processWizardPage.setProcessXml(processString);
-        processWizardPage.clickEditXml();
+        processWizardPage.setXmlPreview(processString);
 
         //get xml preview and compare with initial state
-        ProcessMerlin previewProcess2 = processWizardPage.getProcessMerlinFromProcessXml();
+        ProcessMerlin previewProcess2 = processWizardPage.getEntityFromXMLPreview();
         previewProcess2.assertEquals(previewProcess1);
     }
 }

http://git-wip-us.apache.org/repos/asf/falcon/blob/9e6d5a6c/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FalconClientTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FalconClientTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FalconClientTest.java
index d11411b..73273f9 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FalconClientTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FalconClientTest.java
@@ -25,6 +25,7 @@ import org.apache.falcon.regression.core.supportClasses.ExecResult;
 import org.apache.falcon.regression.core.util.AssertUtil;
 import org.apache.falcon.regression.core.util.BundleUtil;
 import org.apache.falcon.regression.core.util.HadoopUtil;
+import org.apache.falcon.regression.core.util.KerberosHelper;
 import org.apache.falcon.regression.core.util.OSUtil;
 import org.apache.falcon.regression.testHelper.BaseTestClass;
 import org.apache.hadoop.fs.FileSystem;
@@ -80,9 +81,13 @@ public class FalconClientTest extends BaseTestClass {
      * able to delete
      * @throws Exception
      */
-    @Test(enabled = false)
+    @Test(enabled = true)
     public void badClusterDelete() throws Exception {
         bundles[0].submitClusters(prism);
+        //switch user
+        if (MerlinConstants.IS_SECURE) {
+            KerberosHelper.initUserWithKeytab(MerlinConstants.DIFFERENT_USER_NAME);
+        }
         final String clusterXml = bundles[0].getClusters().get(0);
         final ExecResult execResult =
             prism.getClusterHelper().clientDelete(clusterXml, MerlinConstants.DIFFERENT_USER_NAME);