Repository: falcon Updated Branches: refs/heads/master cecc3b427 -> 0232f1b6b
FALCON-1171: Adding search API 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/0232f1b6 Tree: http://git-wip-us.apache.org/repos/asf/falcon/tree/0232f1b6 Diff: http://git-wip-us.apache.org/repos/asf/falcon/diff/0232f1b6 Branch: refs/heads/master Commit: 0232f1b6bddfc16762357cd0f70b9b89de0c308a Parents: cecc3b4 Author: Raghav Kumar Gautam <[email protected]> Authored: Thu Apr 23 10:31:48 2015 -0700 Committer: Raghav Kumar Gautam <[email protected]> Committed: Thu Apr 23 10:31:48 2015 -0700 ---------------------------------------------------------------------- falcon-regression/CHANGES.txt | 1 + .../helpers/entity/AbstractEntityHelper.java | 14 +- .../apache/falcon/regression/SearchApiTest.java | 497 +++++++++++++++++++ .../regression/entity/ListEntitiesTest.java | 6 +- 4 files changed, 509 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/falcon/blob/0232f1b6/falcon-regression/CHANGES.txt ---------------------------------------------------------------------- diff --git a/falcon-regression/CHANGES.txt b/falcon-regression/CHANGES.txt index 7b56be8..104c01f 100644 --- a/falcon-regression/CHANGES.txt +++ b/falcon-regression/CHANGES.txt @@ -5,6 +5,7 @@ Trunk (Unreleased) INCOMPATIBLE CHANGES NEW FEATURES + FALCON-1171 Adding search API tests (Paul Isaychuk via Raghav Kumar Gautam) FALCON-1167 Homepage & Login test for search-ui (Raghav Kumar Gautam via Ruslan Ostafiychuk) http://git-wip-us.apache.org/repos/asf/falcon/blob/0232f1b6/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 b899f1a..08e11a1 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 @@ -252,14 +252,16 @@ public abstract class AbstractEntityHelper { public ServiceResponse listEntities() throws IOException, URISyntaxException, AuthenticationException, InterruptedException { - return listEntities(null, null); + return listEntities(null, null, null); } - public ServiceResponse listEntities(String params, String user) + public ServiceResponse listEntities(String entityType, String params, String user) throws IOException, URISyntaxException, AuthenticationException, InterruptedException { - LOGGER.info("fetching " + getEntityType() + " list"); - String url = createUrl(this.hostname + URLS.LIST_URL.getValue(), - getEntityType() + colo); + if (StringUtils.isEmpty(entityType)) { + entityType = getEntityType(); + } + LOGGER.info("fetching " + entityType + " list"); + String url = createUrl(this.hostname + URLS.LIST_URL.getValue(), entityType + colo); if (StringUtils.isNotEmpty(params)){ url += colo.isEmpty() ? "?" + params : "&" + params; } @@ -268,7 +270,7 @@ public abstract class AbstractEntityHelper { public ServiceResponse listAllEntities(String params, String user) throws AuthenticationException, IOException, URISyntaxException, InterruptedException { - return listEntities((params == null ? "" : params + '&') + return listEntities(null, (params == null ? "" : params + '&') + "numResults=" + Integer.MAX_VALUE, user); } http://git-wip-us.apache.org/repos/asf/falcon/blob/0232f1b6/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/SearchApiTest.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/SearchApiTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/SearchApiTest.java new file mode 100644 index 0000000..b317944 --- /dev/null +++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/SearchApiTest.java @@ -0,0 +1,497 @@ +/** + * 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 com.google.common.collect.Ordering; +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.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.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.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.ListIterator; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +/** + * Search api tests. + */ +@Test(groups = "search-api") +public class SearchApiTest extends BaseTestClass { + + private static final Logger LOGGER = Logger.getLogger(SearchApiTest.class); + private ColoHelper cluster = servers.get(0); + private String baseTestHDFSDir = cleanAndGetTestDir(); + private String aggregateWorkflowDir = baseTestHDFSDir + "/aggregator"; + private final String base = getClass().getSimpleName(); + private static final Comparator<EntityElement> ASC = new Comparator<EntityElement>() { + @Override + public int compare(EntityElement o1, EntityElement o2) { + return o1.name.compareTo(o2.name); + } + }; + private static final Comparator<EntityElement> DESC = Collections.reverseOrder(ASC); + + /** + * Method creates a set of entities. + * |--------------------------------------------+-----------------------------+-----------------------------| + * | Basic input/output Feeds (without tags) | bundle0-input-feed | bundle0-output-feed | + * |--------------+-----------------------------+-----------------------------+-----------------------------| + * | Feed Name | bundle1-feed | bundle2-feed | bundle3-feed | + * | Tags | specific=bundle1 | specific=bundle2 | specific=bundle3 | + * | | common=common | common=common | common=common | + * | | partial=b1b2 | partial=b1b2 | | + * |--------------+-----------------------------+-----------------------------+-----------------------------| + * | Process Name | bundle1-process | bundle2-process | bundle3-process | + * | Tags | specific=bundle1 | specific=bundle2 | specific=bundle3 | + * | | partial=b1b2 | partial=b1b2 | common=common | + * | | common=common | common=common | | + * |--------------+-----------------------------+-----------------------------+-----------------------------| + * | Mirror Name | bundle1-mirror-process | bundle2-mirror-process | bundle3-mirror-process | + * | Tags | specific=bundle1 | specific=bundle2 | specific=bundle3 | + * | | common=common | common=common | common=common | + * | | partial=b1b2 | partial=b1b2 | _falcon_mirroring_type=HDFS | + * | | _falcon_mirroring_type=HDFS | _falcon_mirroring_type=HIVE | | + * |--------------+-----------------------------+-----------------------------+-----------------------------| + */ + @BeforeClass(alwaysRun = true) + public void prepareData() + throws IOException, URISyntaxException, AuthenticationException, InterruptedException, JAXBException { + uploadDirToClusters(aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE); + + /* Prepare bundle template*/ + bundles[0] = BundleUtil.readELBundle(); + bundles[0] = new Bundle(bundles[0], servers.get(0)); + bundles[0].generateUniqueBundle(this); + bundles[0].submitClusters(cluster); + String prefix = getClass().getSimpleName() + "-bundle"; + + FeedMerlin basicFeed = new FeedMerlin(bundles[0].getInputFeedFromBundle()); + basicFeed.setName(prefix + "0-input-feed"); + AssertUtil.assertSucceeded(cluster.getFeedHelper().submitAndSchedule(basicFeed.toString())); + basicFeed = new FeedMerlin(bundles[0].getOutputFeedFromBundle()); + basicFeed.setName(prefix + "0-output-feed"); + AssertUtil.assertSucceeded(cluster.getFeedHelper().submitAndSchedule(basicFeed.toString())); + + /* Submit 3 bundles of feeds */ + FeedMerlin feed = new FeedMerlin(bundles[0].getInputFeedFromBundle()); + for (int i = 1; i <= 3; i++) { + String feedName = prefix + i + "-feed"; + feed.setName(feedName); + String tags = "specific=bundle" + i + ",common=common"; + if (i <= 2) { + tags += ",partial=b1b2"; + } + feed.setTags(tags); + AssertUtil.assertSucceeded(cluster.getFeedHelper().submitEntity(feed.toString())); + } + + /* Submit 3 bundles of processes */ + ProcessMerlin process = bundles[0].getProcessObject(); + + //replace input and output with feeds of bundle0 + process.addInputFeed("input", prefix + "0-input-feed"); + process.getInputs().getInputs().remove(0); + process.addOutputFeed("output", prefix + "0-output-feed"); + process.getOutputs().getOutputs().remove(0); + process.setWorkflow(aggregateWorkflowDir, null, null); + for (int i = 1; i <= 3; i++) { + process.setName(prefix + i + "-process"); + String tags = "specific=bundle" + i + ",common=common"; + if (i <= 2) { + tags += ",partial=b1b2"; + } + process.setTags(tags); + AssertUtil.assertSucceeded(cluster.getProcessHelper().submitEntity(process.toString())); + + //submit a mirroring process + if (i % 2 == 1) { + tags += ",_falcon_mirroring_type=HDFS"; + } else { + tags += ",_falcon_mirroring_type=HIVE"; + } + process.setName(prefix + i + "-mirror-process"); + process.setTags(tags); + AssertUtil.assertSucceeded(cluster.getProcessHelper().submitEntity(process.toString())); + } + } + + /** + * Test hits API, retrieves entities and validates them based on set of expected conditions. + * @param params object which consists of test case parameters such as type, name sequence, tag keys etc. + * @param result object which contains set of expected conditions. Performs validations of entities. + */ + @Test(dataProvider = "getSearchParams") + public void search(QueryParams params, Result result) + throws URISyntaxException, AuthenticationException, InterruptedException, IOException, JAXBException { + ServiceResponse serviceResponse = cluster.getClusterHelper() + .listEntities(params.getType(), params.getParams(), null); + if (result.getExpError() != null) { + AssertUtil.assertFailed(serviceResponse, result.getExpError()); + } else { + String order = null; + if (params.getParams().contains("orderBy")) { + order = params.getParams().contains("sortOrder=desc") ? "desc" : "asc"; + } + result.validateEntities(serviceResponse.getEntityList().getElements(), order); + } + } + + @DataProvider + private Object[][] getSearchParams() { + return new Object[][]{ + + /*Nameseq test cases*/ + {new QueryParams().withNumResults(12), new Result().withExpBundles(0, 1, 2, 3) + .withExpTypes("feed", "process", "mirror").withExpTotal(11), }, + {new QueryParams().withNameSeq(base + "-bundle1-feed"), new Result().withExpBundles(1) + .withExpTypes("feed").withExpTotal(1), }, + {new QueryParams().withNameSeq(base + "-bundle2-mirror-process"), new Result().withExpBundles(2) + .withExpTypes("process", "mirror").withExpTotal(1), }, + {new QueryParams().withNameSeq(base + "-bUnDlE1-fEeD"), new Result().withExpBundles(1) + .withExpTypes("feed").withExpTotal(1), }, + {new QueryParams().withNameSeq(base + "-bundle1-feed-non"), new Result(), }, + {new QueryParams().withNameSeq(base + "-bundle2-process-non"), new Result(), }, + {new QueryParams().withNameSeq("-bundle2-"), new Result().withExpBundles(2) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + {new QueryParams().withNameSeq(base).withNumResults(12), new Result().withExpBundles(0, 1, 2, 3) + .withExpTypes("feed", "process", "mirror").withExpTotal(11), }, + {new QueryParams().withNameSeq("bundleFeed"), new Result().withExpBundles(0, 1, 2, 3) + .withExpTypes("feed").withExpTotal(5), }, + {new QueryParams().withNameSeq("bundleProcess"), new Result().withExpBundles(1, 2, 3) + .withExpTypes("process", "mirror").withExpTotal(6), }, + {new QueryParams().withNameSeq("bUnDlEfeEd"), new Result().withExpBundles(0, 1, 2, 3) + .withExpTypes("feed").withExpTotal(5), }, + {new QueryParams().withNameSeq("bUnDlEprOCesS"), new Result().withExpBundles(1, 2, 3) + .withExpTypes("process", "mirror").withExpTotal(6), }, + {new QueryParams().withNameSeq(base + "-bundle-nonexistent"), new Result(), }, + //unusual nameseq forms + {new QueryParams().withNameSeq("012345"), new Result(), }, + {new QueryParams().withNameSeq("fâ¬â¬d"), new Result(), }, + {new QueryParams().withNameSeq("_-#$@"), new Result(), }, + {new QueryParams().withNameSeq("").withNumResults(12), new Result().withExpBundles(0, 1, 2, 3) + .withExpTypes("feed", "process", "mirror").withExpTotal(11), }, + + /*Tagkey test cases*/ + /* Full tagkey name*/ + {new QueryParams().withTagkey("bundle1"), new Result().withExpBundles(1) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + {new QueryParams().withTagkey("bundle2"), new Result().withExpBundles(2) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + {new QueryParams().withTagkey("bundle3"), new Result().withExpBundles(3) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + {new QueryParams().withTagkey("bUnDlE1"), new Result().withExpBundles(1) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + {new QueryParams().withTagkey("_falcon_mirroring_type"), new Result().withExpBundles(1, 2, 3) + .withExpTypes("process", "mirror").withExpTotal(3), }, + /* Special, utf-8 symbols*/ + {new QueryParams().withTagkey("bun@le#"), new Result()}, + {new QueryParams().withTagkey("bundlâ¬"), new Result()}, + /* Common for a pair of bundles; use both tag and value as tagkey*/ + {new QueryParams().withTagkey("b1b2"), new Result().withExpBundles(1, 2) + .withExpTypes("feed", "process", "mirror").withExpTotal(6), }, + {new QueryParams().withTagkey("partial"), new Result().withExpBundles(1, 2) + .withExpTypes("feed", "process", "mirror").withExpTotal(6), }, + /* Common for 1,2,3 bundles*/ + {new QueryParams().withTagkey("common"), new Result().withExpBundles(1, 2, 3) + .withExpTypes("feed", "process", "mirror").withExpTotal(9), }, + {new QueryParams().withTagkey("bundle"), new Result().withExpBundles(1, 2, 3) + .withExpTypes("feed", "process", "mirror").withExpTotal(9), }, + {new QueryParams().withTagkey("undle"), new Result().withExpBundles(1, 2, 3) + .withExpTypes("feed", "process", "mirror").withExpTotal(9), }, + {new QueryParams().withTagkey("undle,undle"), new Result().withExpBundles(1, 2, 3) + .withExpTypes("feed", "process", "mirror").withExpTotal(9), }, + /* Multiple full tags*/ + {new QueryParams().withTagkey("common,bundle1"), new Result().withExpBundles(1) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + {new QueryParams().withTagkey("common,bundle2"), new Result().withExpBundles(2) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + {new QueryParams().withTagkey("common,bundle3"), new Result().withExpBundles(3) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + {new QueryParams().withTagkey("common,bundle1,b1b2"), new Result().withExpBundles(1) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + {new QueryParams().withTagkey("common,bundle2,b1b2"), new Result().withExpBundles(2) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + /* Multiple, diff case*/ + {new QueryParams().withTagkey("cOmMoN,bUnDlE2,B1b2"), new Result().withExpBundles(2) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + /* Multiple partial tags*/ + {new QueryParams().withTagkey("common,undle"), new Result().withExpBundles(1, 2, 3) + .withExpTypes("feed", "process", "mirror").withExpTotal(9), }, + {new QueryParams().withTagkey("ommo,undle"), new Result().withExpBundles(1, 2, 3) + .withExpTypes("feed", "process", "mirror").withExpTotal(9), }, + {new QueryParams().withTagkey("ommo,ndle1"), new Result().withExpBundles(1) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + {new QueryParams().withTagkey("oMMon,ndle2"), new Result().withExpBundles(2) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + {new QueryParams().withTagkey("oMMon,b1b"), new Result().withExpBundles(1, 2) + .withExpTypes("feed", "process", "mirror").withExpTotal(6), }, + {new QueryParams().withTagkey("comm,ndle3"), new Result().withExpBundles(3) + .withExpTypes("feed", "process", "mirror").withExpTotal(3), }, + /* Non existent*/ + {new QueryParams().withTagkey("bundle9"), new Result(), }, + {new QueryParams().withTagkey("common,undle,zero"), new Result(), }, + + /*Custom filter test cases*/ + //different types + {new QueryParams().forType("process"), new Result().withExpBundles(1, 2, 3) + .withExpTypes("process", "mirror").withExpTotal(6), }, + {new QueryParams().forType("feed"), new Result().withExpBundles(0, 1, 2, 3) + .withExpTypes("feed").withExpTotal(5), }, + {new QueryParams().forType("FEED"), new Result().withExpBundles(0, 1, 2, 3) + .withExpTypes("feed").withExpTotal(5), }, + {new QueryParams().forType("MEGAFEED"), new Result() + .withExpError("Invalid entity type: MEGAFEED. Expected [feed, process, cluster]"), }, + //custom filters + {new QueryParams().forType("process").withNameSeq("bundle").withTagkey("bundle,b1b2").withNumResults(3) + .withOrder(true).withSortOrder("desc"), new Result().withExpBundles(1, 2) + .withExpTypes("process", "mirror").withExpTotal(3), }, + {new QueryParams().forType("schedulable").withNameSeq("bundle").withTagkey("partial,common") + .withOrder(true), new Result().withExpBundles(1, 2).withExpTypes("feed", "process", "mirror") + .withExpTotal(6), }, + {new QueryParams().forType("feed").withNameSeq("bundlefeed").withNumResults(2).withOrder(true) + .withSortOrder("asc"), new Result().withExpBundles(0, 1, 2, 3) + .withExpTypes("feed").withExpTotal(2), }, + {new QueryParams().forType("schedulable").withNameSeq("bundleproc").withTagkey("_falcon_mirroring_type") + .withOrder(true).withSortOrder("desc"), new Result().withExpBundles(1, 2, 3) + .withExpTypes("process", "mirror").withExpTotal(3), }, + //one option excludes another + {new QueryParams().forType("process").withNameSeq("bundlefeed"), new Result(), }, + {new QueryParams().forType("feed").withNameSeq("bundleprocess"), new Result(), }, + {new QueryParams().forType("schedulable").withNameSeq("bundle3").withTagkey("b1b2").withOrder(true), + new Result(), }, + }; + } + + /** + * Contains all required params for search api request. + */ + private class QueryParams { + private String type = "schedulable"; + private String nameSeq = null; + private String tagKey = null; + private String orderBy = null; + private String sortOrder = null; + private Integer numResults = null; + private String fields = "&fields=tags"; + + public QueryParams forType(String paramType) { + this.type = paramType; + return this; + } + + public QueryParams withNameSeq(String paramNameSeq) { + this.nameSeq = paramNameSeq; + return this; + } + + public QueryParams withTagkey(String paramTagkey) { + this.tagKey = paramTagkey; + return this; + } + + public QueryParams withOrder(boolean ordered) { + if (ordered) { + this.orderBy = "&orderBy=name"; + } + return this; + } + + public QueryParams withSortOrder(String paramSortOrder) { + this.sortOrder = paramSortOrder; + return this; + } + + public QueryParams withNumResults(Integer paramNumResults) { + this.numResults = paramNumResults; + return this; + } + + /** + * @return url param string. + */ + public String getParams() { + return (nameSeq != null ? "&nameseq=" + nameSeq : "") + + (tagKey != null ? "&tagkey=" + tagKey : "") + + (numResults != null ? "&numResults=" + numResults : "") + + (orderBy != null ? "&orderBy=name" + orderBy : "") + + (sortOrder != null ? "&sortOrder=" + sortOrder : "") + fields; + } + + public String getType() { + return this.type; + } + + /** + * Pretty prints params to param string. + */ + @Override + public String toString() { + return "[type: " + type + (nameSeq != null ? "; nseq: " + nameSeq : "") + + (tagKey != null ? "; tagkey: " + tagKey : "") + + (numResults != null ? "; n:" + numResults : "") + + (orderBy != null ? "; ordered" : "") + + (sortOrder != null ? "; " + sortOrder : "") + "]"; + } + } + + /** + * Class for entities response validation. + */ + private class Result { + private List<String> expectedTypes = null; + private String expectedError = null; + private List<String> expectedBundles = null; + private int expectedTotal = 0; + private final List<String> allBundles = Arrays.asList("bundle0", "bundle1", "bundle2", "bundle3"); + private final List<String> allTypes = Arrays.asList("feed", "process", "mirror"); + + public Result withExpBundles(int... bundleNums) { + expectedBundles = new ArrayList<>(); + for (int bundleNum : bundleNums) { + expectedBundles.add("bundle" + bundleNum); + } + return this; + } + + public Result withExpTypes(String... types) { + expectedTypes = Arrays.asList(types); + return this; + } + + public Result withExpError(String message) { + this.expectedError = message; + return this; + } + + public Result withExpTotal(int total) { + this.expectedTotal = total; + return this; + } + + public String getExpError() { + return expectedError; + } + + /** + * Pretty prints params to param string. + */ + @Override + public String toString() { + if (expectedError != null) { + return "Expected: error."; + } else { + return String.format("[Expected: %d %s%s]", expectedTotal, + (expectedTypes != null ? expectedTypes + "s": "entities"), + (expectedBundles != null ? " of " + expectedBundles : "")); + } + } + + /** + * Validates entities number and order. Checks that each entity belongs to expected bundle and type. + * @param entities entities + * @param order expected order + */ + public void validateEntities(EntityElement[] entities, String order) { + //validate number of entities + if (expectedTotal == 0) { + assertNull(entities, "Response shouldn't contain entities."); + } else { + List<EntityElement> entitiesList = new ArrayList<>(Arrays.asList(entities)); + cleanUpResult(entitiesList); + LOGGER.info("Entities after clean up: \n" + entitiesList); + assertEquals(entitiesList.size(), expectedTotal, "Number of entities is not as expected."); + + //Check that each entity belongs to expected bundle and type + for (EntityElement entity : entitiesList) { + assertTrue(matches(entity.name, allBundles, expectedBundles), + entity.name + " doesn't belong to expected bundles: " + expectedBundles); + assertTrue(matches(entity.name, allTypes, expectedTypes), + entity.name + " doesn't belong to expected types: " + expectedTypes); + } + //check the order + if (order != null) { + Assert.assertTrue(Ordering.from(order.equals("desc") ? DESC : ASC).isOrdered(entitiesList), + String.format("Entities are not ordered in %sending order", order)); + } + } + } + + /** + * Checks that entity name corresponds to expected bundle and type. + */ + private boolean matches(String name, List<String> all, List<String> expectedParts) { + boolean matches = false; + for (String expectedPart : expectedParts) { + if (name.contains(expectedPart)) { + matches = true; + break; + } + } + List<String> unexpectedParts = new ArrayList<>(all); + unexpectedParts.removeAll(expectedParts); + for (String unexpectedPart : unexpectedParts) { + if (name.contains(unexpectedPart)) { + matches = false; + break; + } + } + return matches; + } + } + + /** + * Cleans up a result list from items which belong to everything else than current test class. + * @param entityElements result array + */ + private void cleanUpResult(List<EntityElement> entityElements) { + for (ListIterator<EntityElement> iterator = entityElements.listIterator(); iterator.hasNext();) { + String name = iterator.next().name; + if (!name.contains(base)) { + iterator.remove(); + } + } + } + + @AfterClass(alwaysRun = true) + public void tearDown() { + removeTestClassEntities(); + } +} http://git-wip-us.apache.org/repos/asf/falcon/blob/0232f1b6/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/entity/ListEntitiesTest.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/entity/ListEntitiesTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/entity/ListEntitiesTest.java index 3ae44e6..e3fcaf1 100644 --- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/entity/ListEntitiesTest.java +++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/entity/ListEntitiesTest.java @@ -178,7 +178,7 @@ public class ListEntitiesTest extends BaseTestClass { for (int i = 0; i <= allEntitiesCount; i++) { EntityElement[] entities = - helper.listEntities("offset=" + i, null).getEntityList().getElements(); + helper.listEntities(null, "offset=" + i, null).getEntityList().getElements(); LOGGER.info(String.format("%s entities with offset %d: %s", helper.getEntityType(), i, Arrays.toString(entities))); @@ -206,7 +206,7 @@ public class ListEntitiesTest extends BaseTestClass { for (int i = 1; i <= allEntitiesCount; i++) { EntityElement[] entities = - helper.listEntities("numResults=" + i, null).getEntityList().getElements(); + helper.listEntities(null, "numResults=" + i, null).getEntityList().getElements(); Assert.assertEquals(entities.length, i, "Number of entities is not equal to numResults parameter"); for (int j = 0; j < i; j++) { @@ -261,7 +261,7 @@ public class ListEntitiesTest extends BaseTestClass { throws AuthenticationException, IOException, URISyntaxException, InterruptedException { EntityElement[] entities = helper.listEntities( - "numResults=2&fields=status,tags&filterBy=STATUS:SUBMITTED&orderBy=name&tags=" + tags[2], + null, "numResults=2&fields=status,tags&filterBy=STATUS:SUBMITTED&orderBy=name&tags=" + tags[2], null).getEntityList().getElements(); if (entities != null) { SoftAssert softAssert = new SoftAssert();
