/** * 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.core.util; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.falcon.entity.v0.EntityType; import org.apache.falcon.regression.core.bundle.Bundle; import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants; import org.apache.falcon.regression.core.response.ServiceResponse; import org.apache.falcon.regression.core.supportClasses.ExecResult; import org.apache.falcon.resource.APIResult; import org.apache.hadoop.fs.ContentSummary; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.log4j.Logger; import org.apache.oozie.client.Job; import org.apache.oozie.client.OozieClient; import org.apache.oozie.client.OozieClientException; import org.json.JSONArray; import org.json.JSONObject; import org.testng.Assert; import javax.xml.bind.JAXBException; import java.io.IOException; import java.util.Collection; import java.util.List; /** * Util methods for assert. */ public final class AssertUtil { private AssertUtil() { throw new AssertionError("Instantiating utility class..."); } private static final Logger LOGGER = Logger.getLogger(AssertUtil.class); /** * Asserts correctness of CLI metrics for recipe based process or feed replication. * @param execResult CLI metrics exec result to be checked * @param entityName name of recipe process or replication feed * @param instanceNum expected number of process/feed instances in metrics output * @param withData is data expected to be replicated * @throws Exception */ public static void assertCLIMetrics(ExecResult execResult, String entityName, int instanceNum, boolean withData) throws Exception { String output = execResult.getOutput(); Assert.assertTrue(StringUtils.isNotBlank(output), "Exec result output is blank."); JSONObject jsonObject = new JSONObject(output); int totalSize = jsonObject.getInt("totalSize"); Assert.assertEquals(totalSize, instanceNum); JSONArray array = jsonObject.getJSONArray("results"); for (int i = 0; i < array.length(); i++) { String name = array.getJSONObject(i).getString("name"); Assert.assertTrue(name.contains(entityName)); int timeTaken = array.getJSONObject(i).getInt("TIMETAKEN"); Assert.assertTrue(timeTaken > 0, "TIMETAKEN metric should be greater then zero."); int bytescopied = array.getJSONObject(i).getInt("BYTESCOPIED"); Assert.assertTrue(bytescopied >= 0, "BYTESCOPIED metric should be greater or equal to zero."); int copy = array.getJSONObject(i).getInt("COPY"); if (withData) { Assert.assertTrue(copy > 0, "COPY metric should be greater then zero."); } else { Assert.assertEquals(copy, 0, "COPY metric should be equal to zero as data was absent."); } } } /** * Checks that any path in list doesn't contains a string. * * @param paths list of paths * @param shouldNotBePresent string that shouldn't be present */ public static void failIfStringFoundInPath( List<Path> paths, String... shouldNotBePresent) { for (Path path : paths) { for (String aShouldNotBePresent : shouldNotBePresent) { if (path.toUri().toString().contains(aShouldNotBePresent)) { Assert.fail("String " + aShouldNotBePresent + " was not expected in path " + path.toUri().toString()); } } } } /** * Checks that two lists have same size. * * @param expected expected list * @param actual actual list */ public static void checkForListSizes(List<?> expected, List<?> actual) { if (expected.size() != actual.size()) { LOGGER.info("expected = " + expected); } checkForListSize(actual, expected.size()); } /** * Checks that two lists have same size. * * @param elements list of elements * @param expectedSize expected size of the list */ public static void checkForListSize(List<?> elements, int expectedSize) { if (elements.size() != expectedSize) { LOGGER.info("expectedSize = " + expectedSize); LOGGER.info("elements.size() = " + elements.size()); LOGGER.info("elements = " + elements); } Assert.assertEquals(elements.size(), expectedSize, "Size of expected and actual list don't match."); } /** * Checks that two lists has expected diff element. * * @param initialState first list * @param finalState second list * @param filename expected diff element * @param expectedDiff diff count (positive for new elements) */ public static void compareDataStoreStates(List<String> initialState, List<String> finalState, String filename, int expectedDiff) { if (expectedDiff > -1) { finalState.removeAll(initialState); Assert.assertEquals(finalState.size(), expectedDiff); if (expectedDiff != 0) { Assert.assertTrue(finalState.get(0).contains(filename)); } } else { expectedDiff = expectedDiff * -1; initialState.removeAll(finalState); Assert.assertEquals(initialState.size(), expectedDiff); if (expectedDiff != 0) { Assert.assertTrue(initialState.get(0).contains(filename)); } } } /** * Checks that two lists has expected diff element. * * @param initialState first list * @param finalState second list * @param expectedDiff diff count (positive for new elements) */ public static void compareDataStoreStates(List<String> initialState, List<String> finalState, int expectedDiff) { if (expectedDiff > -1) { finalState.removeAll(initialState); Assert.assertEquals(finalState.size(), expectedDiff); } else { expectedDiff = expectedDiff * -1; initialState.removeAll(finalState); Assert.assertEquals(initialState.size(), expectedDiff); } } /** * Checks that ServiceResponse status is SUCCEEDED. * * @param response ServiceResponse * @throws JAXBException */ public static void assertSucceeded(ServiceResponse response) throws JAXBException { final APIResult apiResult = Util.parseResponse(response); Assert.assertNotNull(apiResult.getMessage(), "Status message is null"); Assert.assertEquals(apiResult.getStatus(), APIResult.Status.SUCCEEDED, "Status should be SUCCEEDED. Message: " + apiResult.getMessage()); Assert.assertEquals(response.getCode(), 200, "Status code should be 200. Message: " + apiResult.getMessage()); } /** * Checks that ServiceResponse status is SUCCEEDED. * * @param response ServiceResponse * @return if the response was a success or not */ public static boolean checkSucceeded(ServiceResponse response) { final APIResult apiResult; try { apiResult = Util.parseResponse(response); } catch (JAXBException e) { return false; } return apiResult.getStatus() == APIResult.Status.SUCCEEDED && response.getCode() == 200 && apiResult.getMessage() != null; } /** * Checks that ProcessInstancesResult status is SUCCEEDED. * * @param response ProcessInstancesResult */ public static void assertSucceeded(APIResult response) { Assert.assertNotNull(response.getMessage(), "Status message is null"); Assert.assertEquals(response.getStatus(), APIResult.Status.SUCCEEDED, "Status should be SUCCEEDED. Message: " + response.getMessage()); } /** * Checks that ServiceResponse status is status FAILED. * * @param response ServiceResponse * @param message message for exception * @throws JAXBException */ public static void assertFailed(final ServiceResponse response, final String message) throws JAXBException { assertFailedWithStatus(response, 400, message); } /** * Assert that command executed unsuccessfully. * * @param execResult ExecResult of the command execution */ public static void assertFailed(ExecResult execResult, String expectedMessage) { Assert.assertFalse(execResult.hasSuceeded(), "Unexpectedly succeeded execResult: " + execResult); Assert.assertTrue((execResult.getError() + execResult.getOutput()).contains(expectedMessage), "Expected error: " + expectedMessage + " in execResult: " + execResult); } /** * Checks that ServiceResponse status is status FAILED with some status code. * * @param response ServiceResponse * @param statusCode expected status code * @param message message for exception * @throws JAXBException */ public static void assertFailedWithStatus(final ServiceResponse response, final int statusCode, final String message) throws JAXBException { Assert.assertNotEquals(response.getMessage(), "null", "response message should not be null"); Assert.assertEquals(Util.parseResponse(response).getStatus(), APIResult.Status.FAILED, message); Assert.assertEquals(response.getCode(), statusCode, message); Assert.assertNotNull(Util.parseResponse(response).getRequestId(), "RequestId is null"); } /** * Checks that ServiceResponse status is status PARTIAL. * * @param response ServiceResponse * @throws JAXBException */ public static void assertPartial(ServiceResponse response) throws JAXBException { Assert.assertEquals(Util.parseResponse(response).getStatus(), APIResult.Status.PARTIAL); Assert.assertEquals(response.getCode(), 200); Assert.assertNotNull(Util.parseResponse(response).getMessage()); } /** * Checks that ServiceResponse status is status FAILED with status code 400. * * @param response ServiceResponse * @throws JAXBException */ public static void assertFailed(ServiceResponse response) throws JAXBException { Assert.assertNotEquals(response.getMessage(), "null", "response message should not be null"); Assert.assertEquals(Util.parseResponse(response).getStatus(), APIResult.Status.FAILED); Assert.assertEquals(response.getCode(), 400); } /** * Checks that ServiceResponse status is status FAILED with expectedMessage. * * @param response ServiceResponse * @param expectedMessage expected message * @throws JAXBException */ public static void assertFailedWithMessage(ServiceResponse response, String expectedMessage) throws JAXBException { assertFailed(response); Assert.assertTrue(response.getMessage().contains(expectedMessage), "Incorrect message in response"); } /** * Checks that Instance/Triage result status is FAILED. * * @param response APIResult response */ public static void assertFailed(APIResult response) { Assert.assertNotEquals(response.getMessage(), "null", "response message should not be null"); Assert.assertEquals(response.getStatus(), APIResult.Status.FAILED, "Status should be FAILED. Message: " + response.getMessage()); } /** * Checks that ServiceResponse status is status FAILED with status code 403. * * @param response ServiceResponse * @throws JAXBException */ public static void assertFailedWith403(ServiceResponse response) throws JAXBException { Assert.assertNotEquals(response.getMessage(), "null", "response message should not be null"); Assert.assertEquals(Util.parseResponse(response).getStatus(), APIResult.Status.FAILED); Assert.assertEquals(response.getCode(), 403); } /** * Checks that status of some entity job is equal to expected. Method can wait * 100 seconds for expected status. * * @param oozieClient OozieClient * @param entityType FEED or PROCESS * @param data feed or proceess XML * @param expectedStatus expected Job.Status of entity * @throws OozieClientException */ public static void checkStatus(OozieClient oozieClient, EntityType entityType, String data, Job.Status expectedStatus) throws OozieClientException { String name = null; if (entityType == EntityType.FEED) { name = Util.readEntityName(data); } else if (entityType == EntityType.PROCESS) { name = Util.readEntityName(data); } Assert.assertEquals( OozieUtil.verifyOozieJobStatus(oozieClient, name, entityType, expectedStatus), true, "Status should be " + expectedStatus); } /** * Checks that status of some entity job is equal to expected. Method can wait * 100 seconds for expected status. * * @param oozieClient OozieClient * @param entityType FEED or PROCESS * @param bundle Bundle with feed or process data * @param expectedStatus expected Job.Status of entity * @throws OozieClientException */ public static void checkStatus(OozieClient oozieClient, EntityType entityType, Bundle bundle, Job.Status expectedStatus) throws OozieClientException { String data = null; if (entityType == EntityType.FEED) { data = bundle.getDataSets().get(0); } else if (entityType == EntityType.PROCESS) { data = bundle.getProcessData(); } checkStatus(oozieClient, entityType, data, expectedStatus); } /** * Checks that status of some entity job is NOT equal to expected. * * @param oozieClient OozieClient * @param entityType FEED or PROCESS * @param data feed or proceess XML * @param expectedStatus expected Job.Status of entity * @throws OozieClientException */ public static void checkNotStatus(OozieClient oozieClient, EntityType entityType, String data, Job.Status expectedStatus) throws OozieClientException { String processName = null; if (entityType == EntityType.FEED) { processName = Util.readEntityName(data); } else if (entityType == EntityType.PROCESS) { processName = Util.readEntityName(data); } Assert.assertNotEquals(OozieUtil.getOozieJobStatus(oozieClient, processName, entityType), expectedStatus, "Status should not be " + expectedStatus); } /** * Checks that status of some entity job is NOT equal to expected. * * @param oozieClient OozieClient * @param entityType FEED or PROCESS * @param bundle Bundle with feed or process data * @param expectedStatus expected Job.Status of entity * @throws OozieClientException */ public static void checkNotStatus(OozieClient oozieClient, EntityType entityType, Bundle bundle, Job.Status expectedStatus) throws OozieClientException { String data = null; if (entityType == EntityType.FEED) { data = bundle.getDataSets().get(0); } else if (entityType == EntityType.PROCESS) { data = bundle.getProcessData(); } checkNotStatus(oozieClient, entityType, data, expectedStatus); } /** * Checks size of the content a two locations. * * @param firstPath path to the first location * @param secondPath path to the second location * @param fs hadoop file system for the locations * @throws IOException */ public static void checkContentSize(String firstPath, String secondPath, FileSystem fs) throws IOException { final ContentSummary firstSummary = fs.getContentSummary(new Path(firstPath)); final ContentSummary secondSummary = fs.getContentSummary(new Path(secondPath)); LOGGER.info(firstPath + " : firstSummary = " + firstSummary.toString(false)); LOGGER.info(secondPath + " : secondSummary = " + secondSummary.toString(false)); Assert.assertEquals(firstSummary.getLength(), secondSummary.getLength(), "Contents at the two locations don't have same size."); } /** * Fail the test because of the supplied exception. * @param e exception */ public static void fail(Exception e) { LOGGER.info("Got exception: " + ExceptionUtils.getStackTrace(e)); Assert.fail("Failing because of exception."); } public static void assertEmpty(String str, String message) { if (StringUtils.isNotEmpty(str)) { Assert.fail(String.format("%s expected [empty string/null] found [%s]", message, str)); } } public static <E> void assertEmpty(Collection<E> collection, String message) { if (!collection.isEmpty()) { Assert.fail( String.format("%s expected [empty collection] found [%s]", message, collection)); } } public static void assertNotEmpty(String str, String message) { if (StringUtils.isEmpty(str)) { Assert.fail(String.format("%s expected non-empty string found [%s]", message, str)); } } /** * Checks that job logs are copied to user defined cluster staging path. * * @param logFlag denotes whether is is failed/succeeded log * @param entityName name of entity * @param clusterFS hadoop file system for the locations * @param entityType feed or process */ public static boolean assertPath(boolean logFlag, String entityName, FileSystem clusterFS, String entityType) throws Exception { String stagingDir= MerlinConstants.STAGING_LOCATION; String path=stagingDir+"/falcon/workflows/"+ entityType + "/" + entityName +"/logs"; List<Path> logmoverPaths = HadoopUtil .getAllFilesRecursivelyHDFS(clusterFS, new Path(HadoopUtil.cutProtocol(path))); String part = logFlag ? "SUCCEEDED" : "FAILED"; for (Path logmoverPath : logmoverPaths) { if (logmoverPath.toString().contains(part)) { return true; } } return false; } /** * Checks that job logs are copied to user defined cluster staging path. * * @param logFlag denotes whether is is failed/succeeded log * @param entityName name of entity * @param clusterFS hadoop file system for the locations * @param entityType feed or process * @param message message returned if assert fails */ public static void assertLogMoverPath(boolean logFlag, String entityName, FileSystem clusterFS, String entityType, String message) throws Exception { Assert.assertTrue(assertPath(logFlag, entityName, clusterFS, entityType), message); } /** * Checks that API Response status is FAILED. * * @param response APIResult * @throws JAXBException */ public static void assertFailedInstance(APIResult response) throws JAXBException { Assert.assertEquals(response.getStatus(), APIResult.Status.FAILED, "Status should be FAILED. Message: " + response.getMessage()); Assert.assertNotNull(response.getMessage(), "response message should not be null"); } }