/**
* 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.lineage;
import org.apache.falcon.regression.core.bundle.Bundle;
import org.apache.falcon.regression.core.helpers.ColoHelper;
import org.apache.falcon.regression.core.response.ServiceResponse;
import org.apache.falcon.regression.core.util.AssertUtil;
import org.apache.falcon.regression.core.util.BundleUtil;
import org.apache.falcon.regression.core.util.OSUtil;
import org.apache.falcon.regression.core.util.Util;
import org.apache.falcon.regression.core.util.XmlUtil;
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.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.xml.sax.SAXException;
import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Submitting and listing processes with different pipeline names.
*/
@Test(groups = { "distributed", "embedded", "sanity" })
public class ProcessPipelineTest extends BaseTestClass{
private static final Logger LOGGER = Logger.getLogger(ProcessPipelineTest.class);
private ColoHelper cluster = servers.get(0);
private String baseTestHDFSDir = cleanAndGetTestDir();
private String aggregateWorkflowDir = baseTestHDFSDir + "/aggregator";
@BeforeClass(alwaysRun = true)
public void setUp() throws IOException {
uploadDirToClusters(aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE);
}
@BeforeMethod(alwaysRun = true)
public void prepareData() throws IOException {
bundles[0] = BundleUtil.readELBundle();
bundles[0] = new Bundle(bundles[0], servers.get(0));
bundles[0].generateUniqueBundle(this);
bundles[0].setProcessWorkflow(aggregateWorkflowDir);
}
@AfterMethod(alwaysRun = true)
public void tearDown(){
removeTestClassEntities();
}
/**
* Submit List of processes with a given pipeline tag. There are few pipelines and for each
* pipeline there is different number of processes. Test expects an appropriate list of
* processes for each given pipeline tag.
*/
@Test
public void listPipeline()
throws URISyntaxException, IOException, AuthenticationException, JAXBException,
InterruptedException {
//match processes to pipelines
HashMap<String, List<String>> map = new HashMap<>();
//index for few different pipelines
for(int p = 0, i = 0, n = 0, d = 3; p < 3; p++, d++){
n += d + 1;
String pipeline = "pipeline" + p;
map.put(pipeline, new ArrayList<String>());
//index for new processes for current pipeline
for(; i < n; i++){
String processName = Util.getEntityPrefix(this) + "-process-" + i;
bundles[0].setProcessName(processName);
bundles[0].setProcessPipeline(pipeline);
bundles[0].submitProcess(true);
map.get(pipeline).add(processName);
}
}
LOGGER.info("Expected set of processes: " + map);
//now go through pipelines and check that their processes lists match to expected
for(int p = 0, n = 3; p < 3; p++, n++){
String pipeline = "pipeline" + p;
ServiceResponse response = prism.getProcessHelper().getListByPipeline(pipeline);
EntityElement[] processes = response.getEntityList().getElements();
//check that all retrieved processes match to expected list
List<String> expected = map.get(pipeline);
Assert.assertEquals(processes.length, expected.size(),
String.format("Invalid number of processes for pipeline [%s].", pipeline));
for(EntityElement process : processes){
Assert.assertTrue(expected.contains(process.name), String.format("Expected "
+ "list %s doesn't contain %s for %s.", expected, process.name, pipeline));
}
}
}
/**
* Submit a process with pipeline element, get process definition expecting retrieved xml to
* be the same.
*/
@Test
public void testProcessWithPipeline()
throws URISyntaxException, IOException, AuthenticationException, JAXBException,
SAXException, InterruptedException {
String pipeline = "samplePipeline";
bundles[0].setProcessPipeline(pipeline);
bundles[0].submitProcess(true);
String process = bundles[0].getProcessData();
String processDef = prism.getProcessHelper().getEntityDefinition(process).getMessage();
Assert.assertTrue(XmlUtil.isIdentical(process, processDef), "Definitions are not equal.");
}
/**
* Test cases:
* -list processes with pipeline name having special or UTF-8 chars expecting request to fail.
* -list processes with invalid or long pipeline name expecting request to pass.
* -submit a process with pipeline name with special or UTF-8 chars expecting submission to fail.
* -submit a process with a long pipeline name or many comma separated names process submission
* to go through.
*
* @param pipeline pipeline name
* @param action list or submit entities
* @param shouldSucceed should action succeed or not
*/
@Test(dataProvider = "data")
public void testPipelines(String pipeline, String action, boolean shouldSucceed)
throws URISyntaxException, IOException, AuthenticationException, JAXBException,
InterruptedException {
bundles[0].setProcessPipeline(pipeline);
if (action.equals("list")){
if (shouldSucceed){
AssertUtil.assertSucceeded(cluster.getProcessHelper().getListByPipeline(pipeline));
}else {
AssertUtil.assertFailed(cluster.getProcessHelper().getListByPipeline(pipeline));
}
} else {
bundles[0].submitProcess(shouldSucceed);
}
}
@DataProvider(name = "data")
public Object[][] getTestData(){
String specialName = "$pec!alN@me#1";
String utf8Name = "UTF8Pipelin" + "\u20AC"; //euro symbol added to name
String longName = "TestItWithPipelineNameWhichIsLongEnough";
return new Object[][]{//{specialName, "list", false},
//{utf8Name, "list", false},
{"nonexistentPipeline", "list", true}, //expecting blank response
{longName, "list", true}, //expecting blank response
//{specialName, "submit", false}, {utf8Name, "submit", false},
{longName, "submit", true},
{"pipeline0,pipeline1,pipeline2,pipeline3,pipeline4,pipeline5,pipeline6,pipeline7,"
+ "pipeline8,pipeline9,pipeline10,pipeline11", "submit", true,
},
};
}
}