You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@falcon.apache.org by ro...@apache.org on 2015/05/20 16:20:37 UTC
falcon git commit: FALCON-1216 Cluster setup wizard multiple tests.
Contributed by Paul Isaychuk
Repository: falcon
Updated Branches:
refs/heads/master ea30dc410 -> 24d28a71b
FALCON-1216 Cluster setup wizard multiple tests. Contributed by Paul Isaychuk
Project: http://git-wip-us.apache.org/repos/asf/falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/falcon/commit/24d28a71
Tree: http://git-wip-us.apache.org/repos/asf/falcon/tree/24d28a71
Diff: http://git-wip-us.apache.org/repos/asf/falcon/diff/24d28a71
Branch: refs/heads/master
Commit: 24d28a71be00935d29e1f7e6bcab816d8de66571
Parents: ea30dc4
Author: Ruslan Ostafiychuk <ro...@apache.org>
Authored: Wed May 20 17:19:30 2015 +0300
Committer: Ruslan Ostafiychuk <ro...@apache.org>
Committed: Wed May 20 17:19:30 2015 +0300
----------------------------------------------------------------------
falcon-regression/CHANGES.txt | 4 +-
.../regression/Entities/ClusterMerlin.java | 158 ++++++-
.../core/enumsAndConstants/MerlinConstants.java | 1 +
.../falcon/regression/core/util/BundleUtil.java | 4 +
.../falcon/regression/core/util/UIAssert.java | 1 -
.../ui/search/AbstractSearchPage.java | 13 +
.../regression/ui/search/ClusterWizardPage.java | 449 +++++++++++++++++++
.../regression/ui/search/NewClusterPage.java | 44 --
.../falcon/regression/ui/search/PageHeader.java | 4 +-
.../falcon/regression/ui/search/SearchPage.java | 12 -
.../regression/searchUI/ClusterSetupTest.java | 261 +++++++++++
.../src/test/resources/ELbundle/cluster-0.1.xml | 2 +-
12 files changed, 891 insertions(+), 62 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/CHANGES.txt
----------------------------------------------------------------------
diff --git a/falcon-regression/CHANGES.txt b/falcon-regression/CHANGES.txt
index 5e2d0f9..c6da36d 100644
--- a/falcon-regression/CHANGES.txt
+++ b/falcon-regression/CHANGES.txt
@@ -5,6 +5,8 @@ Trunk (Unreleased)
INCOMPATIBLE CHANGES
NEW FEATURES
+ FALCON-1216 Cluster setup wizard multiple tests (Paul Isaychuk via Ruslan Ostafiychuk)
+
FALCON-1202 Add tests for EntityPage (Raghav Kumar Gautam)
FALCON-1210 Process Setup tests for testing header and general step default scenario (Raghav Kumar Gautam)
@@ -79,7 +81,7 @@ Trunk (Unreleased)
via Samarth Gupta)
IMPROVEMENTS
- FALCON-1226 Stabilize testActionsPauseResume()
+ FALCON-1226 Stabilize testActionsPauseResume() (Ruslan Ostafiychuk)
FALCON-1225 remove text line containing "Copyright" from regression
log4j.properties(Samarth Gupta)
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ClusterMerlin.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ClusterMerlin.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ClusterMerlin.java
index d8305c8..4912be9 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ClusterMerlin.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ClusterMerlin.java
@@ -28,17 +28,24 @@ import org.apache.falcon.entity.v0.cluster.Interface;
import org.apache.falcon.entity.v0.cluster.Interfaces;
import org.apache.falcon.entity.v0.cluster.Interfacetype;
import org.apache.falcon.entity.v0.cluster.Location;
+import org.apache.falcon.entity.v0.cluster.Locations;
+import org.apache.falcon.entity.v0.cluster.Properties;
+import org.apache.falcon.entity.v0.cluster.Property;
+import org.apache.falcon.regression.core.util.Util;
+import org.apache.log4j.Logger;
import org.testng.Assert;
+import org.testng.asserts.SoftAssert;
import javax.xml.bind.JAXBException;
import java.io.StringWriter;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** Class for representing a cluster xml. */
public class ClusterMerlin extends Cluster {
-
+ private static final Logger LOGGER = Logger.getLogger(ClusterMerlin.class);
public ClusterMerlin(String clusterData) {
final Cluster cluster = (Cluster) TestEntityUtil.fromString(EntityType.CLUSTER,
clusterData);
@@ -104,6 +111,155 @@ public class ClusterMerlin extends Cluster {
}
}
+ /**
+ * Cleans all properties and returns empty cluster as a draft (as we can't create cluster e.g from empty string).
+ */
+ public ClusterMerlin getEmptyCluster() {
+ ClusterMerlin clusterMerlin = new ClusterMerlin(this.toString());
+ clusterMerlin.setName("");
+ clusterMerlin.setDescription(null);
+ clusterMerlin.setColo(null);
+ clusterMerlin.setTags(null);
+ clusterMerlin.setInterfaces(new Interfaces());
+ clusterMerlin.setLocations(new Locations());
+ clusterMerlin.getACL().setGroup("");
+ clusterMerlin.getACL().setOwner("");
+ clusterMerlin.setProperties(new Properties());
+ return clusterMerlin;
+ }
+
+ public void addLocation(ClusterLocationType type, String path) {
+ Location newLocation = new Location();
+ newLocation.setName(type);
+ newLocation.setPath(path);
+ getLocations().getLocations().add(newLocation);
+ }
+
+ public void addProperty(String name, String value) {
+ Property property = new Property();
+ property.setName(name);
+ property.setValue(value);
+ getProperties().getProperties().add(property);
+ }
+
+ public void addInterface(Interfacetype type, String endpoint, String version) {
+ Interface iface = new Interface();
+ iface.setType(type);
+ iface.setEndpoint(endpoint);
+ iface.setVersion(version);
+ getInterfaces().getInterfaces().add(iface);
+ }
+
+ public void assertEquals(ClusterMerlin cluster) {
+ LOGGER.info(String.format("Comparing : source: %n%s%n and cluster: %n%n%s",
+ Util.prettyPrintXml(toString()), Util.prettyPrintXml(cluster.toString())));
+ SoftAssert softAssert = new SoftAssert();
+ softAssert.assertEquals(name, cluster.getName(), "Cluster name is different.");
+ softAssert.assertEquals(colo, cluster.getColo(), "Cluster colo is different.");
+ softAssert.assertEquals(description, cluster.getDescription(), "Cluster description is different.");
+ softAssert.assertEquals(tags, cluster.getTags(), "Cluster tags are different.");
+ softAssert.assertTrue(interfacesEqual(interfaces.getInterfaces(), cluster.getInterfaces().getInterfaces()),
+ "Cluster interfaces are different");
+ softAssert.assertTrue(locationsEqual(locations.getLocations(), cluster.getLocations().getLocations()),
+ "Cluster locations are different");
+ softAssert.assertEquals(acl.getGroup(), cluster.getACL().getGroup(), "Cluster acl group is different.");
+ softAssert.assertEquals(acl.getOwner(), cluster.getACL().getOwner(), "Cluster acl owner is different.");
+ softAssert.assertEquals(acl.getPermission(), cluster.getACL().getPermission(),
+ "Cluster acl permissions is different.");
+ softAssert.assertTrue(propertiesEqual(properties.getProperties(), cluster.getProperties().getProperties()),
+ "Cluster properties are different.");
+ softAssert.assertAll();
+ }
+
+ private static boolean checkEquality(String str1, String str2, String message){
+ if (!str1.equals(str2)) {
+ LOGGER.info(String.format("Cluster %s are different: %s and %s.", message, str1, str2));
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean interfacesEqual(List<Interface> srcInterfaces, List<Interface> trgInterfaces) {
+ if (srcInterfaces.size() == trgInterfaces.size()) {
+ boolean equality = false;
+ for(Interface iface1: srcInterfaces){
+ for(Interface iface2 : trgInterfaces) {
+ if (iface2.getType().value().equals(iface1.getType().value())) {
+ equality = checkEquality(iface1.getEndpoint(), iface2.getEndpoint(),
+ iface1.getType().value() + " interface endpoints");
+ equality &= checkEquality(iface1.getVersion(), iface2.getVersion(),
+ iface1.getType().value() + " interface versions");
+ }
+ }
+ }
+ return equality;
+ } else {
+ return false;
+ }
+ }
+
+ private static boolean propertiesEqual(List<Property> srcProps, List<Property> trgProps) {
+ if (srcProps.size() == trgProps.size()) {
+ boolean equality = true;
+ for(Property prop1: srcProps){
+ for(Property prop2 : trgProps) {
+ if (prop2.getName().equals(prop1.getName())) {
+ equality &= checkEquality(prop1.getValue(), prop2.getValue(),
+ prop1.getName() + " property values");
+ }
+ }
+ }
+ return equality;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Compares two lists of locations.
+ */
+ private static boolean locationsEqual(List<Location> srcLocations, List<Location> objLocations) {
+ if (srcLocations.size() != objLocations.size()) {
+ return false;
+ }
+ nextType:
+ for (ClusterLocationType type : ClusterLocationType.values()) {
+ List<Location> locations1 = new ArrayList<>();
+ List<Location> locations2 = new ArrayList<>();
+ //get locations of the same type
+ for (int i = 0; i < srcLocations.size(); i++) {
+ if (srcLocations.get(i).getName() == type) {
+ locations1.add(srcLocations.get(i));
+ }
+ if (objLocations.get(i).getName() == type) {
+ locations2.add(objLocations.get(i));
+ }
+ }
+ //compare locations of the same type. At least 1 match should be present.
+ if (locations1.size() != locations2.size()) {
+ return false;
+ }
+ for (Location location1 : locations1) {
+ for (Location location2 : locations2) {
+ if (location1.getPath().equals(location2.getPath())) {
+ continue nextType;
+ }
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
+ public List<Location> getLocation(ClusterLocationType type) {
+ List<Location> locationsOfType = new ArrayList<>();
+ for(Location location : locations.getLocations()) {
+ if (location.getName() == type) {
+ locationsOfType.add(location);
+ }
+ }
+ return locationsOfType;
+ }
@Override
public EntityType getEntityType() {
return EntityType.CLUSTER;
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java
index 299be67..4682b6b 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java
@@ -48,6 +48,7 @@ public final class MerlinConstants {
/** Working location to use in cluster xml. */
public static final String WORKING_LOCATION = Config.getProperty("merlin.working.location",
"/tmp/falcon-regression-working");
+ public static final String TEMP_LOCATION = Config.getProperty("merlin.temp.location", "/tmp");
public static final String OOZIE_EXAMPLE_LIB = Config.getProperty("merlin.oozie_example_lib",
"https://repo1.maven.org/maven2/org/apache/oozie/oozie-examples/4.1.0/oozie-examples-4.1.0.jar");
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/BundleUtil.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/BundleUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/BundleUtil.java
index 7baa7dd..761ebe7 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/BundleUtil.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/BundleUtil.java
@@ -125,6 +125,10 @@ public final class BundleUtil {
working.setName(ClusterLocationType.WORKING);
working.setPath(MerlinConstants.WORKING_LOCATION);
clusterMerlin.getLocations().getLocations().add(working);
+ final Location temp = new Location();
+ temp.setName(ClusterLocationType.TEMP);
+ temp.setPath(MerlinConstants.TEMP_LOCATION);
+ clusterMerlin.getLocations().getLocations().add(temp);
final String protectionPropName = "hadoop.rpc.protection";
final String protectionPropValue = Config.getProperty(protectionPropName);
if (StringUtils.isNotEmpty(protectionPropValue)) {
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java
index f4befd4..c86fb4b 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java
@@ -31,7 +31,6 @@ public final class UIAssert {
}
private static final Logger LOGGER = Logger.getLogger(UIAssert.class);
-
public static void assertDisplayed(WebElement element, String webElementName) {
LOGGER.info(String.format("Checking if WebElement '%s' is displayed", webElementName));
int timeoutSeconds = 2;
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/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 3550604..2778dcc 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
@@ -29,6 +29,8 @@ import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
+import java.util.List;
+
/** Parent page object for all the search ui pages. */
public abstract class AbstractSearchPage extends Page {
@@ -82,4 +84,15 @@ public abstract class AbstractSearchPage extends Page {
LOGGER.info("angular is done continuing...");
}
+ public String getActiveAlertText() {
+ WebElement alertsBlock = driver.findElement(By.className("messages-to-show"));
+ List<WebElement> alerts = alertsBlock.findElements(By.className("ng-animate"));
+ if (!alerts.isEmpty()) {
+ WebElement last = alerts.get(alerts.size() - 1);
+ if (last.isDisplayed()) {
+ return last.getText();
+ }
+ }
+ return null;
+ }
}
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/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
new file mode 100644
index 0000000..300a3d6
--- /dev/null
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ClusterWizardPage.java
@@ -0,0 +1,449 @@
+/**
+ * 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.commons.lang.StringUtils;
+import org.apache.falcon.entity.v0.cluster.ACL;
+import org.apache.falcon.entity.v0.cluster.ClusterLocationType;
+import org.apache.falcon.entity.v0.cluster.Interface;
+import org.apache.falcon.entity.v0.cluster.Interfacetype;
+import org.apache.falcon.entity.v0.cluster.Location;
+import org.apache.falcon.entity.v0.cluster.Property;
+import org.apache.falcon.regression.Entities.ClusterMerlin;
+import org.apache.falcon.regression.core.util.TimeUtil;
+import org.apache.falcon.regression.core.util.UIAssert;
+import org.apache.log4j.Logger;
+import org.openqa.selenium.By;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+import org.openqa.selenium.support.FindBys;
+import org.testng.Assert;
+
+import java.util.List;
+
+/** Page object of the Cluster creation page. */
+public class ClusterWizardPage extends AbstractSearchPage {
+ private static final Logger LOGGER = Logger.getLogger(ClusterWizardPage.class);
+ @FindBys({
+ @FindBy(className = "mainUIView"),
+ @FindBy(className = "clusterForm")
+ })
+ private WebElement clusterBox;
+ @FindBy(id = "cluster.step1")
+ private WebElement next;
+ @FindBy(id = "cluster.step2")
+ private WebElement save;
+ @FindBy(id = "cluster.backToStep1")
+ 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);
+ }
+
+ @Override
+ public void checkPage() {
+ UIAssert.assertDisplayed(clusterBox, "Cluster box");
+ }
+
+ /**
+ * Fills cluster setup forms with values retrieved from Filling object.
+ */
+ public void fillForm(ClusterMerlin cluster) {
+ setName(cluster.getName());
+ setColo(cluster.getColo());
+ setDescription(cluster.getDescription());
+ setTags(cluster.getTags());
+ ACL acl = cluster.getACL();
+ setOwner(acl.getOwner());
+ setGroup(acl.getGroup());
+ setPermissions(acl.getPermission());
+ for(Interface iface : cluster.getInterfaces().getInterfaces()) {
+ setInterface(iface);
+ }
+ for (Property property : cluster.getProperties().getProperties()) {
+ addProperty(property.getName(), property.getValue());
+ }
+ setLocations(cluster.getLocations().getLocations());
+ }
+
+ /**
+ * Methods to fill specific wizard fields.
+ */
+ public void setName(String name) {
+ WebElement nameInput = driver.findElement(By.xpath("//div[label[text()='Name']]/input"));
+ nameInput.clear();
+ sendKeysSlowly(nameInput, name);
+ }
+
+ public void setColo(String colo) {
+ WebElement coloInput = clusterBox.findElement(By.xpath("//div[label[text()='Colo']]/input"));
+ coloInput.clear();
+ sendKeysSlowly(coloInput, colo);
+ }
+
+ public void setDescription(String description) {
+ WebElement descriptionInput = clusterBox.findElement(By.xpath("//div[label[text()='Description']]/input"));
+ descriptionInput.clear();
+ sendKeysSlowly(descriptionInput, description);
+ }
+
+ public void setOwner(String owner) {
+ WebElement ownerInput = clusterBox.findElement(By.xpath("//div[label[text()='Owner']]/input"));
+ ownerInput.clear();
+ sendKeysSlowly(ownerInput, owner);
+ }
+
+ public void setGroup(String group) {
+ WebElement groupInput = clusterBox.findElement(By.xpath("//div[label[text()='Group']]/input"));
+ groupInput.clear();
+ sendKeysSlowly(groupInput, group);
+ }
+
+ public void setPermissions(String permissions) {
+ WebElement permissionsInput = clusterBox.findElement(By.xpath("//div[label[text()='Permissions']]/input"));
+ permissionsInput.clear();
+ sendKeysSlowly(permissionsInput, permissions);
+ }
+
+ /**
+ * Common method to fill interfaces.
+ */
+ public void setInterface(Interface iface) {
+ String root = String.format("//div[contains(., '%s')]", iface.getType().value());
+ String xpath = root + "/div/input[contains(@ng-model, '%s')]";
+ WebElement ifaceEndpoint = clusterBox.findElement(By.xpath(String.format(xpath, "_interface._endpoint")));
+ WebElement ifaceVersion = clusterBox.findElement(By.xpath(String.format(xpath, "_interface._version")));
+ ifaceEndpoint.clear();
+ sendKeysSlowly(ifaceEndpoint, iface.getEndpoint());
+ if (iface.getVersion() != null) {
+ ifaceVersion.clear();
+ sendKeysSlowly(ifaceVersion, iface.getVersion());
+ }
+ }
+
+ /**
+ * Populates form with tags.
+ */
+ public void setTags(String tagsStr){
+ if (!StringUtils.isEmpty(tagsStr)) {
+ String [] tags = tagsStr.split(",");
+ for (int i = 0; i < tags.length; i++) {
+ if (i > 0){
+ clickAddTag();
+ }
+ String key = tags[i].trim().split("=")[0];
+ String value = tags[i].trim().split("=")[1];
+ addTag(key, value);
+ }
+ }
+ }
+
+ /**
+ * Populates last (empty) tag and value fields and creates new fields.
+ * @param key tag key
+ * @param value tag value
+ */
+ public void addTag(String key, String value) {
+ List<WebElement> tagInputs = clusterBox.findElements(By.xpath("//input[@ng-model='tag.key']"));
+ List<WebElement> valueInputs = clusterBox.findElements(By.xpath("//input[@ng-model='tag.value']"));
+ WebElement tagInput = tagInputs.get(tagInputs.size()-1);
+ sendKeysSlowly(tagInput, key);
+ WebElement valueInput = valueInputs.get(valueInputs.size() - 1);
+ sendKeysSlowly(valueInput, value);
+ }
+
+ public void clickAddTag() {
+ clusterBox.findElement(By.xpath("//button[contains(., 'add tag')]")).click();
+ }
+
+ public void clickDeleteTag() {
+ List<WebElement> buttons = clusterBox
+ .findElements(By.xpath("//div[@class='row dynamic-table-spacer ng-scope']//button[contains(.,'delete')]"));
+ buttons.get(buttons.size() - 1).click();
+ }
+
+ /**
+ * Fills property fields and creates new empty property fields.
+ */
+ public void addProperty(String name, String value) {
+ List<WebElement> propInputs = clusterBox.findElements(By.xpath("//input[@ng-model='property._name']"));
+ List<WebElement> valueInputs = clusterBox.findElements(By.xpath("//input[@ng-model='property._value']"));
+ WebElement propInput = propInputs.get(propInputs.size()-1);
+ sendKeysSlowly(propInput, name);
+ WebElement valueInput = valueInputs.get(valueInputs.size()-1);
+ sendKeysSlowly(valueInput, value);
+ clickAddProperty();
+ }
+
+ public void clickAddProperty() {
+ clusterBox.findElement(By.xpath("//button[contains(., 'add property')]")).click();
+ }
+
+ /**
+ * Method to set locations. Location can be only one of ClusterLocationType. So adding new location only after
+ * respective compulsory location was filled.
+ * @param locations locations
+ */
+ public void setLocations(List<Location> locations) {
+ boolean staging = false, temp = false, working = false;
+ for(Location location : locations) {
+ WebElement pathInput = null;
+ if (location.getName() == ClusterLocationType.STAGING && !staging) {
+ pathInput = clusterBox.findElement(By.id("location.staging"));
+ staging = true;
+ } else if (location.getName() == ClusterLocationType.TEMP && !temp) {
+ pathInput = clusterBox.findElement(By.id("location.temp"));
+ temp = true;
+ } else if (location.getName() == ClusterLocationType.WORKING && !working) {
+ pathInput = clusterBox.findElement(By.id("location.working"));
+ working = true;
+ } else {
+ fillAdditionalLocation(location);
+ }
+ if (pathInput != null) {
+ pathInput.clear();
+ sendKeysSlowly(pathInput, location.getPath());
+ }
+ }
+ }
+
+ /**
+ * Method populates last location fields with values and creates new fields.
+ */
+ public void fillAdditionalLocation(Location location) {
+ List<WebElement> allNameInputs = clusterBox
+ .findElements(By.xpath("//input[contains(@ng-model, 'location._name')]"));
+ sendKeysSlowly(allNameInputs.get(allNameInputs.size() - 1), location.getName().value());
+ List<WebElement> allPathInputs = clusterBox
+ .findElements(By.xpath("//input[contains(@ng-model, 'location._path')]"));
+ sendKeysSlowly(allPathInputs.get(allPathInputs.size() - 1), location.getPath());
+ }
+
+ public void clickAddLocation() {
+ clusterBox.findElement(By.xpath("//button[contains(., 'add location')]")).click();
+ }
+
+ public void clickDeleteLocation() {
+ List<WebElement> buttons = clusterBox
+ .findElements(By.xpath("//div[@class='row ng-scope']//button[contains(.,'delete')]"));
+ Assert.assertFalse(buttons.isEmpty(), "Delete button should be present.");
+ buttons.get(buttons.size() - 1).click();
+ }
+
+ public boolean checkElementByContent(String elementTag, String content) {
+ List<WebElement> elements = clusterBox.findElements(By.xpath("//" + elementTag));
+ for(WebElement element : elements) {
+ if (element.getAttribute("value").equals(content)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public ClusterMerlin getXmlPreview() {
+ //preview block fetches changes slower then they appear on the form
+ TimeUtil.sleepSeconds(1);
+ String previewData = xmlPreview.getAttribute("value");
+ return new ClusterMerlin(previewData);
+ }
+
+ /**
+ * Retrieves hte value of the summary box and parses it to cluster properties.
+ * @param draft empty cluster to contain all properties.
+ * @return cluster filled with properties from the summary.
+ */
+ public ClusterMerlin getSummary(ClusterMerlin draft) {
+ ClusterMerlin cluster = new ClusterMerlin(draft.toString());
+ String summaryBoxText = summaryBox.getText();
+ LOGGER.info("Summary block text : " + summaryBoxText);
+
+ String[] slices;
+ //retrieve basic properties
+ String basicProps = summaryBoxText.split("ACL")[0];
+ for (String line : basicProps.split("\\n")) {
+ slices = line.split(" ");
+ String label = slices[0].replace(":", "").trim();
+ String value = slices[1].trim();
+ switch (label) {
+ case "Name":
+ cluster.setName(value);
+ break;
+ case "Colo":
+ cluster.setColo(value);
+ break;
+ case "Description":
+ cluster.setDescription(value);
+ break;
+ case "Tags":
+ cluster.setTags(value);
+ break;
+ default:
+ break;
+ }
+ }
+ //retrieve ALC
+ String propsLeft = summaryBoxText.split("ACL")[1];
+ String[] acl = propsLeft.split("Interfaces")[0].split(" ");
+ cluster.getACL().setOwner(acl[1]);
+ cluster.getACL().setGroup(acl[3]);
+ cluster.getACL().setPermission(acl[5].trim());
+
+ //retrieve interfaces
+ propsLeft = propsLeft.split("Interfaces")[1];
+ boolean propertiesPresent = propsLeft.contains("Properties");
+ String nextLabel = propertiesPresent ? "Properties" : "Locations";
+ String interfaces = propsLeft.split(nextLabel)[0].trim();
+ for (String line : interfaces.split("\\n")) {
+ slices = line.split(" ");
+ String label = slices[0].replace(":", "").trim();
+ String endpoint = slices[1].trim();
+ String version = slices[3].trim();
+ switch (label) {
+ case "readonly":
+ cluster.addInterface(Interfacetype.READONLY, endpoint, version);
+ break;
+ case "write":
+ cluster.addInterface(Interfacetype.WRITE, endpoint, version);
+ break;
+ case "execute":
+ cluster.addInterface(Interfacetype.EXECUTE, endpoint, version);
+ break;
+ case "workflow":
+ cluster.addInterface(Interfacetype.WORKFLOW, endpoint, version);
+ break;
+ case "messaging":
+ cluster.addInterface(Interfacetype.MESSAGING, endpoint, version);
+ break;
+ case "registry":
+ cluster.addInterface(Interfacetype.REGISTRY, endpoint, version);
+ break;
+ default:
+ break;
+ }
+ }
+ //retrieve properties
+ if (propertiesPresent) {
+ propsLeft = propsLeft.split("Properties")[1];
+ String properties = propsLeft.split("Locations")[0].trim();
+ for (String line : properties.split("\\n")) {
+ slices = line.split(":");
+ cluster.addProperty(slices[0].trim(), slices[1].trim());
+ }
+ }
+ //retrieve locations
+ propsLeft = propsLeft.split("Locations")[1].trim();
+ for (String line : propsLeft.split("\\n")) {
+ slices = line.split(":");
+ String label = slices[0].trim();
+ String path = slices[1].trim();
+ switch (label) {
+ case "staging":
+ cluster.addLocation(ClusterLocationType.STAGING, path);
+ break;
+ case "temp":
+ cluster.addLocation(ClusterLocationType.TEMP, path);
+ break;
+ default:
+ cluster.addLocation(ClusterLocationType.WORKING, path);
+ break;
+ }
+ }
+ return cluster;
+ }
+
+ /**
+ * Clicks on cancel button.
+ */
+ public void cancel() {
+ cancel.click();
+ }
+
+ /**
+ * Clicks on editXml button.
+ */
+ private void clickEditXml() {
+ editXML.click();
+ String disabled = xmlPreview.getAttribute("disabled");
+ Assert.assertEquals(disabled, null, "Xml preview should be enabled.");
+ }
+
+ /**
+ * Click on next button which is the same as finish step 1.
+ */
+ public void clickNext() {
+ next.click();
+ Assert.assertTrue(summaryBox.isDisplayed(), "Summary box should be displayed.");
+ }
+
+ /**
+ * Click on save button.
+ */
+ public void clickSave() {
+ save.click();
+ }
+
+ /**
+ * Checks whether alert has appeared and does it contains expected message.
+ * @param alertMessage expected message
+ */
+ public void checkSubmissionAlert(boolean shouldSucceed, String alertMessage) {
+ String className = "alert ng-binding bg-danger";
+ if (shouldSucceed) {
+ className = "alert ng-binding bg-success";
+ }
+ waitForElement(String.format("//div[contains(@class, '%s')]", className), DEFAULT_TIMEOUT, "Alert not found.");
+ //alert message is not a content of a div, but is product of the script
+ //so we can't just retrieve it as usually
+ String alertText = ((JavascriptExecutor)driver).executeScript(String.format(
+ "return (function(){return document.getElementsByClassName('%s')[0].textContent;})();",
+ className)).toString().trim();
+ Assert.assertEquals(alertText, alertMessage);
+ }
+
+ /**
+ * Clicks on previous button.
+ */
+ public void clickPrevious() {
+ previous.click();
+ UIAssert.assertDisplayed(clusterBox, "Cluster box");
+ }
+
+ public void checkRegistry() {
+ clusterBox.findElement(By.xpath("//input[@type='checkbox']")).click();
+ }
+
+ /**
+ * Checks whether registry interface is enabled for input or not.
+ */
+ public boolean isRegistryEnabled() {
+ WebElement endpoint = clusterBox.findElement(By.xpath("(//input[@ng-model='_interface._endpoint'])[6]"));
+ WebElement version = clusterBox.findElement(By.xpath("(//input[@ng-model='_interface._version'])[6]"));
+ return endpoint.isEnabled() && version.isEnabled();
+ }
+}
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/NewClusterPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/NewClusterPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/NewClusterPage.java
deleted file mode 100644
index fa8349b..0000000
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/NewClusterPage.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * 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.regression.core.util.UIAssert;
-import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.FindBy;
-import org.openqa.selenium.support.FindBys;
-
-/** Page object of the Cluster creation page. */
-public class NewClusterPage extends AbstractSearchPage {
-
- @FindBys({
- @FindBy(className = "mainUIView"),
- @FindBy(className = "clusterForm")
- })
- private WebElement clusterBox;
-
- public NewClusterPage(WebDriver driver) {
- super(driver);
- }
-
- @Override
- public void checkPage() {
- UIAssert.assertDisplayed(clusterBox, "Cluster box");
- }
-}
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/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 8af6101..c84cfe5 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
@@ -180,12 +180,12 @@ public class PageHeader {
driver.get(oldUrl);
}
- public NewClusterPage doCreateCluster() {
+ public ClusterWizardPage doCreateCluster() {
UIAssert.assertDisplayed(clusterCreateButton, "Cluster create button");
Assert.assertEquals(clusterCreateButton.getText(), "Cluster",
"Unexpected text on create cluster button");
clusterCreateButton.click();
- final NewClusterPage clusterPage = PageFactory.initElements(driver, NewClusterPage.class);
+ final ClusterWizardPage clusterPage = PageFactory.initElements(driver, ClusterWizardPage.class);
clusterPage.checkPage();
return clusterPage;
}
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/SearchPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/SearchPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/SearchPage.java
index 14f0d6c..b3bbeab 100644
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/SearchPage.java
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/SearchPage.java
@@ -158,18 +158,6 @@ public class SearchPage extends AbstractSearchPage {
}
- private String getActiveAlertText() {
- WebElement alertsBlock = driver.findElement(By.className("messages-to-show"));
- List<WebElement> alerts = alertsBlock.findElements(By.className("ng-animate"));
- if (!alerts.isEmpty()) {
- WebElement last = alerts.get(alerts.size() - 1);
- if (last.isDisplayed()) {
- return last.getText();
- }
- }
- return null;
- }
-
public SearchQuery getSearchQuery() {
return new SearchQuery(searchBlock);
}
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/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
new file mode 100644
index 0000000..95854ca
--- /dev/null
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ClusterSetupTest.java
@@ -0,0 +1,261 @@
+/**
+ * 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.searchUI;
+
+import org.apache.falcon.entity.v0.cluster.ClusterLocationType;
+import org.apache.falcon.entity.v0.cluster.Interface;
+import org.apache.falcon.entity.v0.cluster.Location;
+import org.apache.falcon.entity.v0.cluster.Property;
+import org.apache.falcon.regression.Entities.ClusterMerlin;
+import org.apache.falcon.regression.core.bundle.Bundle;
+import org.apache.falcon.regression.core.helpers.ColoHelper;
+import org.apache.falcon.regression.core.util.BundleUtil;
+import org.apache.falcon.regression.testHelper.BaseUITestClass;
+import org.apache.falcon.regression.ui.search.ClusterWizardPage;
+import org.apache.falcon.regression.ui.search.LoginPage;
+import org.apache.falcon.regression.ui.search.SearchPage;
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.List;
+
+/**
+ * Tests for cluster setup page.
+ */
+public class ClusterSetupTest extends BaseUITestClass{
+ private ClusterWizardPage clusterSetup = null;
+ private ColoHelper cluster = servers.get(0);
+ private ClusterMerlin sourceCluster;
+
+ @BeforeClass(alwaysRun = true)
+ public void prepareCluster() throws IOException {
+ bundles[0] = BundleUtil.readELBundle();
+ bundles[0] = new Bundle(bundles[0], cluster);
+ bundles[0].generateUniqueBundle(this);
+ }
+
+ @BeforeMethod(alwaysRun = true)
+ public void setup() {
+ openBrowser();
+ SearchPage homePage = LoginPage.open(getDriver()).doDefaultLogin();
+ clusterSetup = homePage.getPageHeader().doCreateCluster();
+ clusterSetup.checkPage();
+ sourceCluster = bundles[0].getClusterElement();
+ //add custom cluster properties
+ sourceCluster.setTags("myTag1=myValue1");
+ sourceCluster.setDescription("description");
+ }
+
+ @Test
+ public void testHeader() {
+ clusterSetup.getPageHeader().checkHeader();
+ }
+
+ /**
+ * Default cluster creation scenario. Populate fields with valid values. Click next. Return back and click
+ * next again. Check that all values are present on Summary page. Save cluster.
+ * Check the cluster definition trough /definition API.
+ */
+ @Test
+ public void testDefaultScenario()
+ throws URISyntaxException, AuthenticationException, InterruptedException, IOException {
+ clusterSetup.fillForm(sourceCluster);
+ clusterSetup.clickNext();
+ clusterSetup.clickPrevious();
+ clusterSetup.clickNext();
+ ClusterMerlin summaryBlock = clusterSetup.getSummary(sourceCluster.getEmptyCluster());
+ //summary block should contain the same info as source
+ sourceCluster.assertEquals(summaryBlock);
+ clusterSetup.clickSave();
+ String alertText = clusterSetup.getActiveAlertText();
+ Assert.assertEquals(alertText, "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
+ sourceCluster.assertEquals(definition);
+ }
+
+ /**
+ * Populate fields with valid values. Check that changes are reflected on XMLPreview block. Click next.
+ * Check that XML is what we have populated on the previous step.
+ */
+ @Test
+ public void testXmlPreview() {
+ clusterSetup.fillForm(sourceCluster);
+ ClusterMerlin generalStepPreview = clusterSetup.getXmlPreview();
+ cleanGeneralPreview(generalStepPreview);
+ sourceCluster.assertEquals(generalStepPreview);
+ clusterSetup.clickNext();
+ ClusterMerlin summaryStepPreview = clusterSetup.getXmlPreview();
+ sourceCluster.assertEquals(summaryStepPreview);
+ generalStepPreview.assertEquals(summaryStepPreview);
+ }
+
+ private void cleanGeneralPreview(ClusterMerlin clusterMerlin) {
+ //On general step xml preview has extra empty values which should be removed to compare data.
+ List<Location> locations = clusterMerlin.getLocations().getLocations();
+ int last = locations.size() - 1;
+ if (locations.get(last).getName() == null && locations.get(last).getPath().isEmpty()) {
+ locations.remove(last);
+ }
+ List<Interface> interfaces = clusterMerlin.getInterfaces().getInterfaces();
+ last = interfaces.size() - 1;
+ if (interfaces.get(last).getEndpoint().isEmpty() && interfaces.get(last).getVersion().isEmpty()) {
+ interfaces.remove(last);
+ }
+ List<Property> properties = clusterMerlin.getProperties().getProperties();
+ last = properties.size() - 1;
+ if (properties.get(last).getName().isEmpty() && properties.get(last).getValue().isEmpty()) {
+ properties.remove(last);
+ }
+ }
+
+ /**
+ * Add location to cluster. Check that it is present. Check XML preview has it.
+ * Delete the location. Check that it has been deleted from wizard window.
+ */
+ @Test
+ public void testAddDeleteLocation() {
+ //to make addLocation button enabled
+ sourceCluster.addLocation(ClusterLocationType.WORKING, "/one-another-temp");
+ clusterSetup.fillForm(sourceCluster);
+
+ //check without extra location
+ ClusterMerlin preview = clusterSetup.getXmlPreview();
+ cleanGeneralPreview(preview);
+ sourceCluster.assertEquals(preview);
+
+ //add one more location to the form and check results
+ String path = "/one-extra-working";
+ Location location = new Location();
+ location.setName(ClusterLocationType.WORKING);
+ location.setPath(path);
+ clusterSetup.clickAddLocation();
+ clusterSetup.fillAdditionalLocation(location);
+ Assert.assertTrue(clusterSetup.checkElementByContent("input", path), "Location should be present.");
+ preview = clusterSetup.getXmlPreview();
+ cleanGeneralPreview(preview);
+ //add location to source to compare equality
+ sourceCluster.addLocation(ClusterLocationType.WORKING, path);
+ sourceCluster.assertEquals(preview);
+
+ //delete location and check results
+ clusterSetup.clickDeleteLocation();
+ Assert.assertFalse(clusterSetup.checkElementByContent("input", path), "Location should be absent.");
+ preview = clusterSetup.getXmlPreview();
+ cleanGeneralPreview(preview);
+ //remove location from source to check equality
+ int last = sourceCluster.getLocations().getLocations().size() - 1;
+ sourceCluster.getLocations().getLocations().remove(last);
+ sourceCluster.assertEquals(preview);
+ }
+
+ /**
+ * Add tag to cluster. Check that it is present. Check XML preview has it.
+ * Delete the tag. Check that it has been deleted from wizard window.
+ */
+ @Test
+ public void testAddDeleteTag() {
+ clusterSetup.fillForm(sourceCluster);
+
+ //check without extra tag
+ ClusterMerlin preview = clusterSetup.getXmlPreview();
+ cleanGeneralPreview(preview);
+ sourceCluster.assertEquals(preview);
+
+ //add one more tag to the form and check results
+ clusterSetup.clickAddTag();
+ 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();
+ cleanGeneralPreview(preview);
+ //add tag to source to compare equality
+ sourceCluster.setTags("myTag1=myValue1,myTag2=myValue2");
+ sourceCluster.assertEquals(preview);
+
+ //delete location and check results
+ 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();
+ cleanGeneralPreview(preview);
+ //remove location from source to check equality
+ sourceCluster.setTags("myTag1=myValue1");
+ sourceCluster.assertEquals(preview);
+ }
+
+ /**
+ * Check that staging interface is unavailable by default but becomes available when we set matching checkbox.
+ */
+ @Test
+ public void testRegistryInterface() {
+ Assert.assertFalse(clusterSetup.isRegistryEnabled(), "Registry should be disabled.");
+ clusterSetup.checkRegistry();
+ Assert.assertTrue(clusterSetup.isRegistryEnabled(), "Registry should be enabled.");
+ clusterSetup.checkRegistry();
+ Assert.assertFalse(clusterSetup.isRegistryEnabled(), "Registry should be disabled again.");
+ }
+
+ /**
+ * Populate working location with value pointing to directory with wider permissions then 755.
+ * Check that user is not allowed to create a cluster and is notified with an alert.
+ */
+ @Test
+ public void testLocationsBadPermissions() throws IOException {
+ //reverse staging and working location dirs
+ String staging = sourceCluster.getLocation(ClusterLocationType.STAGING).get(0).getPath();
+ String working = sourceCluster.getLocation(ClusterLocationType.WORKING).get(0).getPath();
+ sourceCluster.getLocation(ClusterLocationType.WORKING).get(0).setPath(staging);
+ sourceCluster.getLocation(ClusterLocationType.STAGING).get(0).setPath(working);
+ clusterSetup.fillForm(sourceCluster);
+ clusterSetup.clickNext();
+ clusterSetup.clickSave();
+ String alertMessage = clusterSetup.getActiveAlertText();
+ Assert.assertEquals(alertMessage,
+ String.format("Path %s has permissions: rwxrwxrwx, should be rwxr-xr-x", staging));
+ }
+
+ /**
+ * Provide locations which are formally correct but don't exist.
+ * Check that user can't create cluster and has been notified with an alert.
+ */
+ @Test
+ public void testLocationsNonExistent() throws IOException {
+ String nonExistent = "/non-existent-directory";
+ sourceCluster.getLocation(ClusterLocationType.STAGING).get(0).setPath(nonExistent);
+ clusterSetup.fillForm(sourceCluster);
+ clusterSetup.clickNext();
+ clusterSetup.clickSave();
+ String alertMessage = clusterSetup.getActiveAlertText();
+ Assert.assertEquals(alertMessage,
+ String.format("Location %s for cluster %s must exist.", nonExistent, sourceCluster.getName()));
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown() throws IOException {
+ removeTestClassEntities();
+ closeBrowser();
+ }
+}
http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin/src/test/resources/ELbundle/cluster-0.1.xml
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/resources/ELbundle/cluster-0.1.xml b/falcon-regression/merlin/src/test/resources/ELbundle/cluster-0.1.xml
index 6478384..5d8a189 100644
--- a/falcon-regression/merlin/src/test/resources/ELbundle/cluster-0.1.xml
+++ b/falcon-regression/merlin/src/test/resources/ELbundle/cluster-0.1.xml
@@ -25,7 +25,7 @@
version="0.20.2" />
<interface type="execute" endpoint="hdfs://host:54311" version="0.20.2" />
<interface type="workflow" endpoint="http://host:11000/oozie/"
- version="3.1" />
+ version="3.1.0" />
<interface type="messaging" endpoint="tcp://host:61616?daemon=true"
version="5.1.6" />
</interfaces>