/** * 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.commons.lang.StringUtils; 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.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. */ @Test(groups = "search-api") 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 { Assert.assertFalse(clusterSetup.isXmlPreviewExpanded(), "Xml preview should be collapsed by default."); 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()); //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 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.getEntityFromXMLPreview(); cleanGeneralPreview(generalStepPreview); sourceCluster.assertEquals(generalStepPreview); clusterSetup.clickNext(); ClusterMerlin summaryStepPreview = clusterSetup.getEntityFromXMLPreview(); 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.getEntityFromXMLPreview(); 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.getEntityFromXMLPreview(); 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.getEntityFromXMLPreview(); 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.getEntityFromXMLPreview(); 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.getEntityFromXMLPreview(); 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.getEntityFromXMLPreview(); 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(true); Assert.assertTrue(clusterSetup.isRegistryEnabled(), "Registry should be enabled."); clusterSetup.checkRegistry(false); Assert.assertFalse(clusterSetup.isRegistryEnabled(), "Registry should be disabled again."); } /** * Check that interface version with different length and parts is allowed. */ @Test public void testDifferentInterfaceVersions() { sourceCluster.addInterface(Interfacetype.REGISTRY, "http://colo-1.example.com:15000", "1.1.1"); clusterSetup.checkRegistry(true); clusterSetup.fillForm(sourceCluster); StringBuilder partialVersion = new StringBuilder(""); for (String c : new String[]{"3", ".", "2", ".", "0"}) { partialVersion.append(c); for (Interface inface : sourceCluster.getInterfaces().getInterfaces()) { inface.setVersion(partialVersion.toString()); clusterSetup.setInterfaceVersion(inface); } clusterSetup.clickNext(); clusterSetup.clickPrevious(); } } /** * 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).getPath(); String working = sourceCluster.getLocation(ClusterLocationType.WORKING).getPath(); //set working to dir which has 777 permissions sourceCluster.getLocation(ClusterLocationType.WORKING).setPath(staging); //set staging to dir which has 755 permissions sourceCluster.getLocation(ClusterLocationType.STAGING).setPath(working); clusterSetup.fillForm(sourceCluster); clusterSetup.clickNext(); clusterSetup.clickSave(); String alertMessage = clusterSetup.getActiveAlertText(); Assert.assertEquals(alertMessage, String.format("Path %s has permissions: rwxr-xr-x, should be rwxrwxrwx", working)); } /** * 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).setPath(nonExistent); clusterSetup.fillForm(sourceCluster); clusterSetup.clickNext(); clusterSetup.clickSave(); String alertMessage = clusterSetup.getActiveAlertText(); 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())); } /** * Specify the same directory locations for staging and working location. * Check that user is not allowed to create a cluster with same directory for both with proper error message. */ @Test public void testSameLocations() throws IOException { //get the staging directory location String staging = sourceCluster.getLocation(ClusterLocationType.STAGING).getPath(); //set the working directory to staging directory sourceCluster.getLocation(ClusterLocationType.WORKING).setPath(staging); clusterSetup.fillForm(sourceCluster); clusterSetup.clickJustNext(); clusterSetup.assertLocationsEqualError(); } /** * Default cluster creation scenario with Optional fields set with Empty 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 testOptionalfields() throws URISyntaxException, AuthenticationException, InterruptedException, IOException { // Set the Description value to empty sourceCluster.setDescription(""); // Set the temp location value to empty sourceCluster.getLocation(ClusterLocationType.TEMP).setPath(""); // Now fill the form with the above values for optional fields 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()); //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 sourceCluster.assertEquals(definition); } /** * 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. */ @Test public void testEditXml() { clusterSetup.fillForm(sourceCluster); //check that registry is empty String registryEndpoint = clusterSetup.getInterfaceEndpointValue(Interfacetype.REGISTRY); Assert.assertTrue(StringUtils.isEmpty(registryEndpoint), "Registry endpoint should be empty"); String registryVersion = clusterSetup.getInterfaceVersionValue(Interfacetype.REGISTRY); Assert.assertTrue(StringUtils.isEmpty(registryVersion), "Registry version should be empty"); Assert.assertFalse(clusterSetup.isRegistryEnabled(), "Registry should be disabled."); //change cluster xml sourceCluster.setName(sourceCluster.getName() + "-new"); sourceCluster.setDescription("newDescription"); Interface iFace = new Interface(); iFace.setEndpoint(cluster.getClusterHelper().getHostname()); iFace.setVersion("1.0.0"); iFace.setType(Interfacetype.REGISTRY); sourceCluster.getInterfaces().getInterfaces().add(iFace); //populate it to xmlPreview clusterSetup.setXmlPreview(sourceCluster.toString()); //check values on wizard registryEndpoint = clusterSetup.getInterfaceEndpointValue(Interfacetype.REGISTRY); Assert.assertEquals(registryEndpoint, sourceCluster.getInterfaces().getInterfaces().get(5).getEndpoint(), "Registry endpoint on wizard should match to endpoint on preview xml."); registryVersion = clusterSetup.getInterfaceVersionValue(Interfacetype.REGISTRY); Assert.assertEquals(registryVersion, sourceCluster.getInterfaces().getInterfaces().get(5).getVersion(), "Registry version on wizard should match to endpoint on preview xml."); Assert.assertTrue(clusterSetup.isRegistryEnabled(), "Registry should be enabled."); } /** * Populate cluster with properties. Click Edit XML. Break the XML (delete closing tag). * Check that malformed cluster is not accepted by the form. * Undo the change. Change cluster name to malformed one. * Check that value is accepted. */ @Test public void testEditXmlInvalidValues(){ clusterSetup.fillForm(sourceCluster); 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.setXmlPreview(brokenXml); //compare preview before and after changes 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.setXmlPreview(sourceCluster.toString()); //check the value on a wizard Assert.assertEquals(clusterSetup.getName(), sourceCluster.getName(), "Malformed name should be accepted."); } @AfterMethod(alwaysRun = true) public void tearDown() throws IOException { removeTestClassEntities(); closeBrowser(); } }