/**
* 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.entity;
import org.apache.commons.lang.StringUtils;
import org.apache.falcon.regression.Entities.ClusterMerlin;
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.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.MatrixUtil;
import org.apache.falcon.regression.core.util.OSUtil;
import org.apache.falcon.regression.testHelper.BaseTestClass;
import org.apache.falcon.resource.EntityList.EntityElement;
import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.log4j.Logger;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
/**
* Testing the pattern search of entities. Falcon-914
*/
@Test(groups = { "distributed", "embedded", "sanity" })
public class EntitiesPatternSearchTest extends BaseTestClass {
private static final Logger LOGGER = Logger.getLogger(EntitiesPatternSearchTest.class);
private String baseTestHDFSDir = cleanAndGetTestDir();
private String aggregateWorkflowDir = baseTestHDFSDir + "/aggregator";
/**
* Upload feeds, processes and clusters with different names.
*/
@BeforeClass(alwaysRun = true)
public void prepareData()
throws IOException, URISyntaxException, AuthenticationException, InterruptedException, JAXBException {
uploadDirToClusters(aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE);
removeTestClassEntities();
bundles[0] = BundleUtil.readELBundle();
bundles[0] = new Bundle(bundles[0], servers.get(0));
bundles[0].generateUniqueBundle(this);
bundles[0].setProcessWorkflow(aggregateWorkflowDir);
bundles[0].submitBundle(prism);
//submit different clusters, feeds and processes
FeedMerlin feed = new FeedMerlin(bundles[0].getInputFeedFromBundle());
ProcessMerlin process = bundles[0].getProcessObject();
ClusterMerlin cluster = bundles[0].getClusterElement();
String clusterNamePrefix = bundles[0].getClusterElement().getName() + '-';
String processNamePrefix = bundles[0].getProcessName() + '-';
String feedNamePrefix = bundles[0].getInputFeedNameFromBundle() + '-';
List randomNames = getPatternName();
for (Object randomName : randomNames) {
process.setName(processNamePrefix + randomName);
AssertUtil.assertSucceeded(prism.getProcessHelper().submitAndSchedule(process.toString()));
feed.setName(feedNamePrefix + randomName);
AssertUtil.assertSucceeded(prism.getFeedHelper().submitAndSchedule(feed.toString()));
cluster.setName(clusterNamePrefix + randomName);
AssertUtil.assertSucceeded(prism.getClusterHelper().submitEntity(cluster.toString()));
}
}
@AfterClass(alwaysRun = true)
public void tearDown() throws IOException {
removeTestClassEntities();
}
/**
* Testing entity listing for patterns that match and validating the output for the same.
*/
@Test(dataProvider = "getPattern")
public void listEntitiesWithPattern(AbstractEntityHelper helper, String patternParam)
throws AuthenticationException, IOException, URISyntaxException, InterruptedException {
EntityElement[] entities =
helper.listAllEntities("nameseq=" + patternParam, null).getEntityList().getElements();
LOGGER.info(helper.getEntityType() + " entities: " + Arrays.toString(entities));
validateOutputPatternList(helper.listAllEntities().getEntityList().getElements(), entities, patternParam);
}
/**
* Testing entity listing for patterns that do not match and validating the output for the same.
*/
@Test(dataProvider = "getMismatchPattern")
public void listEntitiesWithPatternMismatch(AbstractEntityHelper helper, String mismatchPatternParam)
throws AuthenticationException, IOException, URISyntaxException, InterruptedException {
mismatchPatternParam = mismatchPatternParam.replaceAll(" ", "%20");
EntityElement[] entities =
helper.listAllEntities("nameseq=" + mismatchPatternParam, null).getEntityList().getElements();
LOGGER.info(helper.getEntityType() + " entities: " + Arrays.toString(entities));
Assert.assertNull(entities, "No pattern matches");
}
@DataProvider
public Object[][] getPattern() {
String[] patternParam =
new String[] {
"new", "defintion", "W-E", "NewEntityDefinition", "ned",
"NED", "NeD", "N-e-D", "N-e-D123", "", };
AbstractEntityHelper[] helper = new AbstractEntityHelper[] {
prism.getProcessHelper(),
prism.getFeedHelper(),
prism.getClusterHelper(),
};
return MatrixUtil.crossProduct(helper, patternParam);
}
@DataProvider
public Object[][] getMismatchPattern(){
String[] mismatchPatternParam = new String[]{"akm", "ne d", "newss", "new*", "NewEntityDefinitions"};
AbstractEntityHelper[] helper = new AbstractEntityHelper[] {
prism.getProcessHelper(),
prism.getFeedHelper(),
prism.getClusterHelper(),
};
return MatrixUtil.crossProduct(helper, mismatchPatternParam);
}
private void validateOutputPatternList(EntityElement[] entityElements,
EntityElement[] outputelements, String pattern) {
List<String> actualOutputElements = new ArrayList<>();
List<String> expectedOutputElements = new ArrayList<>();
for(EntityElement e : entityElements) {
if (getOutputEntity(e.name, pattern)) {
expectedOutputElements.add(e.name);
}
}
for(EntityElement e : outputelements) {
actualOutputElements.add(e.name);
}
LOGGER.debug("actualElement : " + actualOutputElements);
LOGGER.debug("expectedElement : " + expectedOutputElements);
// Checking no of elements present in output.
AssertUtil.checkForListSizes(expectedOutputElements, actualOutputElements);
//Checking expected out and actual output contains same enitities.
Assert.assertTrue(expectedOutputElements.containsAll(actualOutputElements),
"Output list elements are not as expected");
for(String element : expectedOutputElements) {
Assert.assertTrue(actualOutputElements.contains(element),
"Element " + element + "is not present in output");
}
}
private Boolean getOutputEntity(final String entityName, final String userInput) {
final String wildCard = ".*";
final String patternStr = StringUtils.join(userInput.split(""), wildCard) + wildCard;
final Pattern pattern = Pattern.compile(patternStr, Pattern.CASE_INSENSITIVE);
final boolean isMatch = pattern.matcher(entityName).find();
LOGGER.info("patternStr : " + patternStr + " entityName: " + entityName + " isMatch: " + isMatch);
return isMatch;
}
private List<String> getPatternName() {
List<String> nameList = new ArrayList<>();
nameList.add("New-Entity-Definition");
nameList.add("NewEntityDefinition");
nameList.add("newentitydefine");
nameList.add("NEW-ENTITY");
nameList.add("NEW1-ENTITY2-DEFINITION123");
nameList.add("New-definition123");
return nameList;
}
}