http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OozieUtil.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OozieUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OozieUtil.java deleted file mode 100644 index 4c609b3..0000000 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OozieUtil.java +++ /dev/null @@ -1,855 +0,0 @@ -/** - * 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.falcon.entity.v0.EntityType; -import org.apache.falcon.regression.core.helpers.ColoHelper; -import org.apache.falcon.regression.core.helpers.entity.AbstractEntityHelper; -import org.apache.hadoop.conf.Configuration; -import org.apache.oozie.client.AuthOozieClient; -import org.apache.oozie.client.BundleJob; -import org.apache.oozie.client.OozieClient; -import org.apache.oozie.client.OozieClientException; -import org.apache.oozie.client.Job; -import org.apache.oozie.client.CoordinatorAction; -import org.apache.oozie.client.CoordinatorJob; -import org.apache.oozie.client.WorkflowAction; -import org.apache.oozie.client.WorkflowJob; -import org.joda.time.DateTime; -import org.apache.log4j.Logger; -import org.joda.time.DateTimeZone; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; -import org.json.JSONException; -import org.testng.Assert; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -/** - * helper methods for oozie . - */ -public final class OozieUtil { - - public static final String FAIL_MSG = "NO_such_workflow_exists"; - private OozieUtil() { - throw new AssertionError("Instantiating utility class..."); - } - - private static final Logger LOGGER = Logger.getLogger(OozieUtil.class); - - public static AuthOozieClient getClient(String url) { - return new AuthOozieClient(url); - } - - public static List<BundleJob> getBundles(OozieClient client, String filter, int start, int len) - throws OozieClientException { - LOGGER.info("Connecting to oozie: " + client.getOozieUrl()); - return client.getBundleJobsInfo(filter, start, len); - } - - public static List<String> getBundleIds(List<BundleJob> bundles) { - List<String> ids = new ArrayList<>(); - for (BundleJob bundle : bundles) { - LOGGER.info("Bundle Id: " + bundle.getId()); - ids.add(bundle.getId()); - } - return ids; - } - - public static List<Job.Status> getBundleStatuses(List<BundleJob> bundles) { - List<Job.Status> statuses = new ArrayList<>(); - for (BundleJob bundle : bundles) { - LOGGER.info("bundle: " + bundle); - statuses.add(bundle.getStatus()); - } - return statuses; - } - - public static String getMaxId(List<String> ids) { - String oozieId = ids.get(0); - int maxInt = Integer.valueOf(oozieId.split("-")[0]); - for (int i = 1; i < ids.size(); i++) { - String currentId = ids.get(i); - int currInt = Integer.valueOf(currentId.split("-")[0]); - if (currInt > maxInt) { - oozieId = currentId; - } - } - return oozieId; - } - - public static String getMinId(List<String> ids) { - String oozieId = ids.get(0); - int minInt = Integer.valueOf(oozieId.split("-")[0]); - for (int i = 1; i < ids.size(); i++) { - String currentId = ids.get(i); - int currInt = Integer.valueOf(currentId.split("-")[0]); - if (currInt < minInt) { - oozieId = currentId; - } - } - return oozieId; - } - - /** - * @param bundleID bundle number - * @param oozieClient oozie client - * @return list of action ids of the succeeded retention workflow - * @throws OozieClientException - */ - public static List<String> waitForRetentionWorkflowToSucceed(String bundleID, - OozieClient oozieClient) - throws OozieClientException { - LOGGER.info("Connecting to oozie: " + oozieClient.getOozieUrl()); - List<String> jobIds = new ArrayList<>(); - LOGGER.info("using bundleId:" + bundleID); - waitForCoordinatorJobCreation(oozieClient, bundleID); - final String coordinatorId = - oozieClient.getBundleJobInfo(bundleID).getCoordinators().get(0).getId(); - LOGGER.info("using coordinatorId: " + coordinatorId); - - for (int i = 0; - i < 120 && oozieClient.getCoordJobInfo(coordinatorId).getActions().isEmpty(); ++i) { - TimeUtil.sleepSeconds(4); - } - Assert.assertFalse(oozieClient.getCoordJobInfo(coordinatorId).getActions().isEmpty(), - "Coordinator actions should have got created by now."); - - CoordinatorAction action = oozieClient.getCoordJobInfo(coordinatorId).getActions().get(0); - for (int i = 0; i < 180; ++i) { - CoordinatorAction actionInfo = oozieClient.getCoordActionInfo(action.getId()); - LOGGER.info("actionInfo: " + actionInfo); - if (EnumSet.of(CoordinatorAction.Status.SUCCEEDED, CoordinatorAction.Status.KILLED, - CoordinatorAction.Status.FAILED).contains(actionInfo.getStatus())) { - break; - } - TimeUtil.sleepSeconds(10); - } - Assert.assertEquals( - oozieClient.getCoordActionInfo(action.getId()).getStatus(), - CoordinatorAction.Status.SUCCEEDED, - "Action did not succeed."); - jobIds.add(action.getId()); - - return jobIds; - } - - public static void waitForCoordinatorJobCreation(OozieClient oozieClient, String bundleID) - throws OozieClientException { - LOGGER.info("Connecting to oozie: " + oozieClient.getOozieUrl()); - for (int i = 0; - i < 60 && oozieClient.getBundleJobInfo(bundleID).getCoordinators().isEmpty(); ++i) { - TimeUtil.sleepSeconds(2); - } - Assert.assertFalse(oozieClient.getBundleJobInfo(bundleID).getCoordinators().isEmpty(), - "Coordinator job should have got created by now."); - } - - public static Job.Status getOozieJobStatus(OozieClient client, String processName, - EntityType entityType) - throws OozieClientException { - String filter = String.format("name=FALCON_%s_%s", entityType, processName); - List<Job.Status> statuses = getBundleStatuses(getBundles(client, filter, 0, 10)); - if (statuses.isEmpty()) { - return null; - } else { - return statuses.get(0); - } - } - - public static List<String> getBundles(OozieClient client, String entityName, - EntityType entityType) - throws OozieClientException { - String filter = "name=FALCON_" + entityType + "_" + entityName; - return getBundleIds(getBundles(client, filter, 0, 10)); - } - - public static List<DateTime> getStartTimeForRunningCoordinators(ColoHelper prismHelper, - String bundleID) - throws OozieClientException { - List<DateTime> startTimes = new ArrayList<>(); - - OozieClient oozieClient = prismHelper.getClusterHelper().getOozieClient(); - BundleJob bundleJob = oozieClient.getBundleJobInfo(bundleID); - CoordinatorJob jobInfo; - - - for (CoordinatorJob job : bundleJob.getCoordinators()) { - - if (job.getAppName().contains("DEFAULT")) { - jobInfo = oozieClient.getCoordJobInfo(job.getId()); - for (CoordinatorAction action : jobInfo.getActions()) { - DateTime temp = new DateTime(action.getCreatedTime(), DateTimeZone.UTC); - LOGGER.info(temp); - startTimes.add(temp); - } - } - - Collections.sort(startTimes); - - if (!(startTimes.isEmpty())) { - return startTimes; - } - } - - return null; - } - - public static boolean verifyOozieJobStatus(OozieClient client, String processName, - EntityType entityType, Job.Status expectedStatus) - throws OozieClientException { - for (int seconds = 0; seconds < 100; seconds+=5) { - Job.Status status = getOozieJobStatus(client, processName, entityType); - LOGGER.info("Current status: " + status); - if (status == expectedStatus) { - return true; - } - TimeUtil.sleepSeconds(5); - } - return false; - } - - - public static List<String> getMissingDependencies(OozieClient oozieClient, String bundleID) - throws OozieClientException { - CoordinatorJob jobInfo; - jobInfo = null; - BundleJob bundleJob = oozieClient.getBundleJobInfo(bundleID); - List<CoordinatorJob> coordinatorJobList = bundleJob.getCoordinators(); - if (coordinatorJobList.size() > 1) { - - for (CoordinatorJob coord : bundleJob.getCoordinators()) { - LOGGER.info("Appname is : " + coord.getAppName()); - if ((coord.getAppName().contains("DEFAULT") - && coord.getAppName().contains("PROCESS")) - || - (coord.getAppName().contains("REPLICATION") - && coord.getAppName().contains("FEED"))) { - jobInfo = oozieClient.getCoordJobInfo(coord.getId()); - } else { - LOGGER.info("Desired coord does not exists on " + oozieClient.getOozieUrl()); - } - } - - } else { - jobInfo = oozieClient.getCoordJobInfo(bundleJob.getCoordinators().get(0).getId()); - } - - LOGGER.info("Coordinator id : " + jobInfo); - List<CoordinatorAction> actions = null; - if (jobInfo != null) { - actions = jobInfo.getActions(); - } - - if (actions != null) { - if (actions.size() < 1) { - return null; - } - } - if (actions != null) { - LOGGER.info("conf from event: " + actions.get(0).getMissingDependencies()); - } - - String[] missingDependencies = new String[0]; - if (actions != null) { - missingDependencies = actions.get(0).getMissingDependencies().split("#"); - } - return new ArrayList<>(Arrays.asList(missingDependencies)); - } - - public static List<String> getWorkflowJobs(OozieClient oozieClient, String bundleID) - throws OozieClientException { - waitForCoordinatorJobCreation(oozieClient, bundleID); - List<String> workflowIds = new ArrayList<>(); - List<CoordinatorJob> coordJobs = oozieClient.getBundleJobInfo(bundleID).getCoordinators(); - CoordinatorJob coordJobInfo = oozieClient.getCoordJobInfo(coordJobs.get(0).getId()); - - for (CoordinatorAction action : coordJobInfo.getActions()) { - workflowIds.add(action.getExternalId()); - } - return workflowIds; - } - - public static List<String> getWorkflow(OozieClient oozieClient, String bundleID) - throws OozieClientException { - waitForCoordinatorJobCreation(oozieClient, bundleID); - List<String> workflowIds = new ArrayList<>(); - String coordId = getDefaultCoordIDFromBundle(oozieClient, bundleID); - CoordinatorJob coordJobInfo = oozieClient.getCoordJobInfo(coordId); - for (CoordinatorAction action : coordJobInfo.getActions()) { - if (action.getStatus().name().equals("RUNNING") || action.getStatus().name().equals("SUCCEEDED")) { - workflowIds.add(action.getExternalId()); - } - if (action.getStatus().name().equals("KILLED") || action.getStatus().name().equals("WAITING")) { - Assert.assertNull(action.getExternalId()); - } - } - return workflowIds; - } - - public static Date getNominalTime(OozieClient oozieClient, String bundleID) - throws OozieClientException { - BundleJob bundleJob = oozieClient.getBundleJobInfo(bundleID); - CoordinatorJob jobInfo = - oozieClient.getCoordJobInfo(bundleJob.getCoordinators().get(0).getId()); - List<CoordinatorAction> actions = jobInfo.getActions(); - return actions.get(0).getNominalTime(); - } - - public static CoordinatorJob getDefaultOozieCoord(OozieClient oozieClient, String bundleId, - EntityType type) - throws OozieClientException { - BundleJob bundlejob = oozieClient.getBundleJobInfo(bundleId); - for (CoordinatorJob coord : bundlejob.getCoordinators()) { - if ((coord.getAppName().contains("DEFAULT") && EntityType.PROCESS == type) - || - (coord.getAppName().contains("REPLICATION") && EntityType.FEED == type)) { - return oozieClient.getCoordJobInfo(coord.getId()); - } else { - LOGGER.info("Desired coord does not exists on " + oozieClient.getOozieUrl()); - } - } - return null; - } - - public static int getNumberOfWorkflowInstances(OozieClient oozieClient, String bundleId) - throws OozieClientException { - return getDefaultOozieCoord(oozieClient, bundleId, EntityType.PROCESS).getActions().size(); - } - - public static List<String> getActionsNominalTime(OozieClient oozieClient, - String bundleId, EntityType type) - throws OozieClientException { - Map<Date, CoordinatorAction.Status> actions = getActionsNominalTimeAndStatus(oozieClient, bundleId, type); - List<String> nominalTime = new ArrayList<>(); - for (Date date : actions.keySet()) { - nominalTime.add(date.toString()); - } - return nominalTime; - } - - public static Map<Date, CoordinatorAction.Status> getActionsNominalTimeAndStatus(OozieClient oozieClient, - String bundleId, EntityType type) throws OozieClientException { - Map<Date, CoordinatorAction.Status> result = new TreeMap<>(); - List<CoordinatorAction> actions = getDefaultOozieCoord(oozieClient, bundleId, type).getActions(); - for (CoordinatorAction action : actions) { - result.put(action.getNominalTime(), action.getStatus()); - } - return result; - } - - public static boolean isBundleOver(ColoHelper coloHelper, String bundleId) - throws OozieClientException { - OozieClient client = coloHelper.getClusterHelper().getOozieClient(); - - BundleJob bundleJob = client.getBundleJobInfo(bundleId); - - if (EnumSet.of(BundleJob.Status.DONEWITHERROR, BundleJob.Status.FAILED, - BundleJob.Status.SUCCEEDED, BundleJob.Status.KILLED).contains(bundleJob.getStatus())) { - return true; - } - TimeUtil.sleepSeconds(20); - return false; - } - - public static void verifyNewBundleCreation(OozieClient oozieClient, String originalBundleId, - List<String> initialNominalTimes, String entity, - boolean shouldBeCreated, boolean matchInstances) - throws OozieClientException { - String entityName = Util.readEntityName(entity); - EntityType entityType = Util.getEntityType(entity); - String newBundleId = getLatestBundleID(oozieClient, entityName, entityType); - if (shouldBeCreated) { - Assert.assertTrue(!newBundleId.equalsIgnoreCase(originalBundleId), - "eeks! new bundle is not getting created!!!!"); - LOGGER.info("old bundleId=" + originalBundleId + " on oozie: " + oozieClient); - LOGGER.info("new bundleId=" + newBundleId + " on oozie: " + oozieClient); - if (matchInstances) { - validateNumberOfWorkflowInstances(oozieClient, - initialNominalTimes, originalBundleId, newBundleId, entityType); - } - } else { - Assert.assertEquals(newBundleId, originalBundleId, "eeks! new bundle is getting created!!!!"); - } - } - - private static void validateNumberOfWorkflowInstances(OozieClient oozieClient, - List<String> initialNominalTimes, - String originalBundleId, - String newBundleId, EntityType type) - throws OozieClientException { - List<String> nominalTimesOriginalAndNew = getActionsNominalTime(oozieClient, originalBundleId, type); - nominalTimesOriginalAndNew.addAll(getActionsNominalTime(oozieClient, newBundleId, type)); - initialNominalTimes.removeAll(nominalTimesOriginalAndNew); - if (initialNominalTimes.size() != 0) { - LOGGER.info("Missing instance are : " + initialNominalTimes); - LOGGER.debug("Original Bundle ID : " + originalBundleId); - LOGGER.debug("New Bundle ID : " + newBundleId); - Assert.fail("some instances have gone missing after update"); - } - } - - public static String getCoordStartTime(OozieClient oozieClient, String entity, int bundleNo) - throws OozieClientException { - String bundleID = getSequenceBundleID(oozieClient, - Util.readEntityName(entity), Util.getEntityType(entity), bundleNo); - CoordinatorJob coord = getDefaultOozieCoord(oozieClient, bundleID, - Util.getEntityType(entity)); - return TimeUtil.dateToOozieDate(coord.getStartTime()); - } - - public static DateTimeFormatter getOozieDateTimeFormatter() { - return DateTimeFormat.forPattern("yyyy'-'MM'-'dd'T'HH':'mm'Z'"); - } - - public static int getNumberOfBundle(OozieClient oozieClient, EntityType type, String entityName) - throws OozieClientException { - return OozieUtil.getBundles(oozieClient, entityName, type).size(); - } - - public static void createMissingDependencies(ColoHelper helper, EntityType type, - String entityName, int bundleNumber, - int instanceNumber) - throws OozieClientException, IOException { - final OozieClient oozieClient = helper.getClusterHelper().getOozieClient(); - String bundleID = getSequenceBundleID(oozieClient, entityName, type, bundleNumber); - List<CoordinatorJob> coords = oozieClient.getBundleJobInfo(bundleID).getCoordinators(); - final List<String> missingDependencies = getMissingDependenciesForInstance(oozieClient, coords, instanceNumber); - HadoopUtil.createFolders(helper.getClusterHelper().getHadoopFS(), helper.getPrefix(), missingDependencies); - } - - private static List<String> getMissingDependenciesForInstance(OozieClient oozieClient, - List<CoordinatorJob> coords, int instanceNumber) - throws OozieClientException { - ArrayList<String> missingPaths = new ArrayList<>(); - for (CoordinatorJob coord : coords) { - CoordinatorJob temp = oozieClient.getCoordJobInfo(coord.getId()); - CoordinatorAction instance = temp.getActions().get(instanceNumber); - missingPaths.addAll(Arrays.asList(instance.getMissingDependencies().split("#"))); - } - return missingPaths; - } - - public static List<List<String>> createMissingDependencies(ColoHelper helper, EntityType type, - String entityName, int bundleNumber) - throws OozieClientException, IOException { - final OozieClient oozieClient = helper.getClusterHelper().getOozieClient(); - String bundleID = getSequenceBundleID(oozieClient, entityName, type, bundleNumber); - return createMissingDependenciesForBundle(helper, bundleID); - } - - public static List<List<String>> createMissingDependenciesForBundle(ColoHelper helper, String bundleId) - throws OozieClientException, IOException { - OozieClient oozieClient = helper.getClusterHelper().getOozieClient(); - List<CoordinatorJob> coords = oozieClient.getBundleJobInfo(bundleId).getCoordinators(); - List<List<String>> missingDependencies = getMissingDependenciesForBundle(oozieClient, coords); - for (List<String> missingDependencyPerInstance : missingDependencies) { - HadoopUtil.createFolders(helper.getClusterHelper().getHadoopFS(), helper.getPrefix(), - missingDependencyPerInstance); - } - return missingDependencies; - } - - private static List<List<String>> getMissingDependenciesForBundle(OozieClient oozieClient, - List<CoordinatorJob> coords) - throws OozieClientException, IOException { - List<List<String>> missingDependencies = new ArrayList<>(); - for (CoordinatorJob coord : coords) { - CoordinatorJob temp = oozieClient.getCoordJobInfo(coord.getId()); - for (int instanceNumber = 0; instanceNumber < temp.getActions().size(); - instanceNumber++) { - CoordinatorAction instance = temp.getActions().get(instanceNumber); - missingDependencies.add(Arrays.asList(instance.getMissingDependencies().split("#"))); - } - } - return missingDependencies; - } - - public static void validateRetryAttempts(OozieClient oozieClient, String bundleId, EntityType type, - int attempts) throws OozieClientException { - CoordinatorJob coord = getDefaultOozieCoord(oozieClient, bundleId, type); - int actualRun = oozieClient.getJobInfo(coord.getActions().get(0).getExternalId()).getRun(); - LOGGER.info("Actual run count: " + actualRun); // wrt 0 - Assert.assertEquals(actualRun, attempts, "Rerun attempts did not match"); - } - - /** - * Try to find feed coordinators of given type. - */ - public static int checkIfFeedCoordExist(OozieClient oozieClient, - String feedName, String coordType) throws OozieClientException { - return checkIfFeedCoordExist(oozieClient, feedName, coordType, 5); - } - - /** - * Try to find feed coordinators of given type given number of times. - */ - public static int checkIfFeedCoordExist(OozieClient oozieClient, - String feedName, String coordType, int numberOfRetries) throws OozieClientException { - LOGGER.info("feedName: " + feedName); - for (int retryAttempt = 0; retryAttempt < numberOfRetries; retryAttempt++) { - int numberOfCoord = 0; - List<String> bundleIds = getBundles(oozieClient, feedName, EntityType.FEED); - if (bundleIds.size() == 0) { - TimeUtil.sleepSeconds(4); - continue; - } - LOGGER.info("bundleIds: " + bundleIds); - for (String aBundleId : bundleIds) { - LOGGER.info("aBundleId: " + aBundleId); - waitForCoordinatorJobCreation(oozieClient, aBundleId); - List<CoordinatorJob> coords = getBundleCoordinators(oozieClient, aBundleId); - LOGGER.info("coords: " + coords); - for (CoordinatorJob coord : coords) { - if (coord.getAppName().contains(coordType)) { - numberOfCoord++; - } - } - } - if (numberOfCoord > 0) { - return numberOfCoord; - } - TimeUtil.sleepSeconds(4); - } - return 0; - } - - /** - * Retrieves replication coordinatorID from bundle of coordinators. - */ - public static List<String> getReplicationCoordID(String bundleId, AbstractEntityHelper helper) - throws OozieClientException { - final OozieClient oozieClient = helper.getOozieClient(); - List<CoordinatorJob> coords = getBundleCoordinators(oozieClient, bundleId); - List<String> replicationCoordID = new ArrayList<>(); - for (CoordinatorJob coord : coords) { - if (coord.getAppName().contains("FEED_REPLICATION")) { - replicationCoordID.add(coord.getId()); - } - } - return replicationCoordID; - } - - /** - * Retrieves ID of bundle related to some process/feed using its ordinal number. - * - * @param entityName - name of entity bundle is related to - * @param entityType - feed or process - * @param bundleNumber - ordinal number of bundle - * @return bundle ID - * @throws org.apache.oozie.client.OozieClientException - */ - public static String getSequenceBundleID(OozieClient oozieClient, String entityName, - EntityType entityType, int bundleNumber) throws OozieClientException { - //sequence start from 0 - List<String> bundleIds = getBundles(oozieClient, entityName, entityType); - Collections.sort(bundleIds); - if (bundleNumber < bundleIds.size()) { - return bundleIds.get(bundleNumber); - } - return null; - } - - /** - * Retrieves the latest bundle ID. - * - * @param oozieClient where job is running - * @param entityName name of entity job is related to - * @param entityType type of entity - feed or process expected - * @return latest bundle ID - * @throws org.apache.oozie.client.OozieClientException - */ - public static String getLatestBundleID(OozieClient oozieClient, - String entityName, EntityType entityType) throws OozieClientException { - List<String> bundleIds = getBundles(oozieClient, entityName, entityType); - String max = "0"; - int maxID = -1; - for (String strID : bundleIds) { - if (maxID < Integer.parseInt(strID.substring(0, strID.indexOf('-')))) { - maxID = Integer.parseInt(strID.substring(0, strID.indexOf('-'))); - max = strID; - } - } - return max; - } - - /** - * Retrieves all coordinators of bundle. - * - * @param oozieClient Oozie client to use for fetching info. - * @param bundleID specific bundle ID - * @return list of bundle coordinators - * @throws org.apache.oozie.client.OozieClientException - */ - public static List<CoordinatorJob> getBundleCoordinators(OozieClient oozieClient, String bundleID) - throws OozieClientException { - BundleJob bundleInfo = oozieClient.getBundleJobInfo(bundleID); - return bundleInfo.getCoordinators(); - } - - public static Job.Status getDefaultCoordinatorStatus(OozieClient oozieClient, String processName, - int bundleNumber) throws OozieClientException { - String bundleID = getSequenceBundleID(oozieClient, processName, EntityType.PROCESS, bundleNumber); - String coordId = getDefaultCoordIDFromBundle(oozieClient, bundleID); - return oozieClient.getCoordJobInfo(coordId).getStatus(); - } - - public static String getDefaultCoordIDFromBundle(OozieClient oozieClient, String bundleId) - throws OozieClientException { - waitForCoordinatorJobCreation(oozieClient, bundleId); - BundleJob bundleInfo = oozieClient.getBundleJobInfo(bundleId); - List<CoordinatorJob> coords = bundleInfo.getCoordinators(); - int min = 100000; - String minString = ""; - for (CoordinatorJob coord : coords) { - String strID = coord.getId(); - if (min > Integer.parseInt(strID.substring(0, strID.indexOf('-')))) { - min = Integer.parseInt(strID.substring(0, strID.indexOf('-'))); - minString = coord.getId(); - } - } - LOGGER.info("function getDefaultCoordIDFromBundle: minString: " + minString); - return minString; - } - - public static String getLatestCoordinatorID(OozieClient oozieClient, String processName, - EntityType entityType) throws OozieClientException { - final String latestBundleID = getLatestBundleID(oozieClient, processName, entityType); - return getDefaultCoordIDFromBundle(oozieClient, latestBundleID); - } - - /** - * Waits till bundle job will reach expected status. - * Generates time according to expected status. - * - * @param oozieClient oozieClient of cluster job is running on - * @param processName name of process which job is being analyzed - * @param expectedStatus job status we are waiting for - * @throws org.apache.oozie.client.OozieClientException - */ - public static void waitForBundleToReachState(OozieClient oozieClient, - String processName, Job.Status expectedStatus) throws OozieClientException { - int totalMinutesToWait = getMinutesToWait(expectedStatus); - waitForBundleToReachState(oozieClient, processName, expectedStatus, totalMinutesToWait); - } - - /** - * Waits till bundle job will reach expected status during specific time. - * Use it directly in test cases when timeouts are different from trivial, in other cases use - * waitForBundleToReachState(OozieClient, String, Status) - * - * @param oozieClient oozie client of cluster job is running on - * @param processName name of process which job is being analyzed - * @param expectedStatus job status we are waiting for - * @param totalMinutesToWait specific time to wait expected state - * @throws org.apache.oozie.client.OozieClientException - */ - public static void waitForBundleToReachState(OozieClient oozieClient, String processName, - Job.Status expectedStatus, int totalMinutesToWait) throws OozieClientException { - int sleep = totalMinutesToWait * 60 / 20; - for (int sleepCount = 0; sleepCount < sleep; sleepCount++) { - String bundleID = - getLatestBundleID(oozieClient, processName, EntityType.PROCESS); - BundleJob j = oozieClient.getBundleJobInfo(bundleID); - LOGGER.info(sleepCount + ". Current status: " + j.getStatus() - + "; expected: " + expectedStatus); - if (j.getStatus() == expectedStatus) { - return; - } - TimeUtil.sleepSeconds(20); - } - Assert.fail("State " + expectedStatus + " wasn't reached in " + totalMinutesToWait + " mins"); - } - - /** - * Generates time which is presumably needed for bundle job to reach particular state. - * - * @param expectedStatus status which we are expect to get from bundle job - * @return minutes to wait for expected status - */ - private static int getMinutesToWait(Job.Status expectedStatus) { - switch (expectedStatus) { - case DONEWITHERROR: - case SUCCEEDED: - return OSUtil.IS_WINDOWS ? 40 : 20; - case KILLED: - return OSUtil.IS_WINDOWS ? 30 : 15; - default: - return OSUtil.IS_WINDOWS ? 60 : 30; - } - } - - public static String getActionStatus(OozieClient oozieClient, String workflowId, String actionName) - throws OozieClientException { - List<WorkflowAction> wfAction = oozieClient.getJobInfo(workflowId).getActions(); - for (WorkflowAction wf : wfAction) { - if (wf.getName().contains(actionName)) { - return wf.getExternalStatus(); - } - } - return ""; - } - - public static String getWorkflowActionStatus(OozieClient oozieClient, String bundleId, String actionName) - throws OozieClientException { - List<String> workflowIds = getWorkflowJobs(oozieClient, bundleId); - if (workflowIds.get(0).isEmpty()) { - return FAIL_MSG; - } - return getActionStatus(oozieClient, workflowIds.get(0), actionName); - } - - public static String getSubWorkflowActionStatus(OozieClient oozieClient, String bundleId, - String actionName, String subAction) - throws OozieClientException { - List<String> workflowIds = getWorkflowJobs(oozieClient, bundleId); - if (workflowIds.get(0).isEmpty()) { - return FAIL_MSG; - } - - String wid=""; - List<WorkflowAction> wfAction = oozieClient.getJobInfo(workflowIds.get(0)).getActions(); - for (WorkflowAction wf : wfAction) { - if (wf.getName().contains(actionName)) { - wid = wf.getExternalId(); - } - } - - if (!wid.isEmpty()) { - return getActionStatus(oozieClient, wid, subAction); - } - return FAIL_MSG; - } - - /** - * Returns configuration object of a given bundleID for a given instanceTime. - * - * @param oozieClient oozie client of cluster job is running on - * @param bundleID bundleID of given cluster - * @param time instanceTime - * @throws org.apache.oozie.client.OozieClientException - * @throws org.json.JSONException - */ - public static Configuration getProcessConf(OozieClient oozieClient, String bundleID, String time) - throws OozieClientException, JSONException { - waitForCoordinatorJobCreation(oozieClient, bundleID); - List<CoordinatorJob> coordJobs = oozieClient.getBundleJobInfo(bundleID).getCoordinators(); - CoordinatorJob coordJobInfo = oozieClient.getCoordJobInfo(coordJobs.get(0).getId()); - - Configuration conf = new Configuration(); - for (CoordinatorAction action : coordJobInfo.getActions()) { - String dateStr = (new DateTime(action.getNominalTime(), DateTimeZone.UTC)).toString(); - if (!dateStr.isEmpty() && dateStr.contains(time.replace("Z", ""))) { - conf.addResource(new ByteArrayInputStream(oozieClient.getJobInfo(action.getExternalId()). - getConf().getBytes())); - } - } - return conf; - } - - /** - * Method retrieves and parses replication coordinator action workflow definition and checks whether specific - * properties are present in list of workflow args or not. - * @param workflowDefinition workflow definition - * @param actionName action within workflow, e.g pre-processing, replication etc. - * @param propMap specific properties which are expected to be in arg list - * @return true if all keys and values are present, false otherwise - */ - public static boolean propsArePresentInWorkflow(String workflowDefinition, String actionName, - HashMap<String, String> propMap) { - //get action definition - Document definition = Util.convertStringToDocument(workflowDefinition); - Assert.assertNotNull(definition, "Workflow definition shouldn't be null."); - NodeList actions = definition.getElementsByTagName("action"); - Element action = null; - for (int i = 0; i < actions.getLength(); i++) { - Node node = actions.item(i); - if (node.getNodeType() == Node.ELEMENT_NODE) { - action = (Element) node; - if (action.getAttribute("name").equals(actionName)) { - break; - } - action = null; - } - } - Assert.assertNotNull(action, actionName + " action not found."); - - //retrieve and checks whether properties are present in workflow args - Element javaElement = (Element) action.getElementsByTagName("java").item(0); - NodeList args = javaElement.getElementsByTagName("arg"); - int counter = 0; - String key = null; - for (int i = 0; i < args.getLength(); i++) { - Node node = args.item(i); - if (node.getNodeType() == Node.ELEMENT_NODE) { - String argKey = node.getTextContent().replace("-", ""); - if (key != null && propMap.get(key).equals(argKey)) { - counter++; - key = null; - } else if (key == null && propMap.containsKey(argKey)) { - key = argKey; - } - } - } - return counter == propMap.size(); - } - - /** - * Returns configuration object of a given bundleID for a given retentionFeed. - * - * @param oozieClient oozie client of cluster job is running on - * @param bundleID bundleID of given cluster - * @throws OozieClientException - */ - public static Configuration getRetentionConfiguration(OozieClient oozieClient, String bundleID) - throws OozieClientException { - waitForCoordinatorJobCreation(oozieClient, bundleID); - CoordinatorJob coord = null; - List<CoordinatorJob> coordJobs = oozieClient.getBundleJobInfo(bundleID).getCoordinators(); - for (CoordinatorJob coordinatorJob : coordJobs) { - if (coordinatorJob.getAppName().startsWith("FALCON_FEED_RETENTION")) { - coord = oozieClient.getCoordJobInfo(coordinatorJob.getId()); - } - } - - Configuration configuration = new Configuration(); - if (coord != null) { - WorkflowJob wid = oozieClient.getJobInfo(coord.getActions().get(0).getExternalId()); - configuration.addResource(new ByteArrayInputStream(wid.getConf().getBytes())); - } else { - configuration = null; - } - - return configuration; - } -}
http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/TimeUtil.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/TimeUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/TimeUtil.java deleted file mode 100644 index 292a516..0000000 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/TimeUtil.java +++ /dev/null @@ -1,301 +0,0 @@ -/** - * 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.falcon.regression.core.enumsAndConstants.FreqType; -import org.apache.log4j.Logger; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.concurrent.TimeUnit; - - -/** -All time / date related util methods for merlin . need to move methods from -instanceUtil to here , pending item. - */ - -public final class TimeUtil { - - private TimeUtil() { - throw new AssertionError("Instantiating utility class..."); - } - private static final Logger LOGGER = Logger.getLogger(TimeUtil.class); - - public static void sleepSeconds(double seconds) { - long ms = (long) (seconds * 1000); - try { - TimeUnit.MILLISECONDS.sleep(ms); - } catch (InterruptedException e) { - LOGGER.info("Sleep was interrupted"); - } - } - - public static String get20roundedTime(String oozieBaseTime) { - DateTime startTime = - new DateTime(oozieDateToDate(oozieBaseTime), DateTimeZone.UTC); - if (startTime.getMinuteOfHour() < 20) { - startTime = startTime.minusMinutes(startTime.getMinuteOfHour()); - } else if (startTime.getMinuteOfHour() < 40) { - startTime = startTime.minusMinutes(startTime.getMinuteOfHour() + 20); - } else { - startTime = startTime.minusMinutes(startTime.getMinuteOfHour() + 40); - } - return dateToOozieDate(startTime.toDate()); - } - - public static List<String> getMinuteDatesOnEitherSide(int interval, int minuteSkip) { - DateTime today = new DateTime(DateTimeZone.UTC); - LOGGER.info("today is: " + today.toString()); - return getMinuteDatesOnEitherSide(today.minusMinutes(interval), - today.plusMinutes(interval), minuteSkip); - } - - public static List<String> getMinuteDatesOnEitherSide(String startOozieDate, String endOozieDate, - int minuteSkip) { - DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy/MM/dd/HH/mm"); - formatter.withZoneUTC(); - return getMinuteDatesOnEitherSide(TimeUtil.oozieDateToDate(startOozieDate), - TimeUtil.oozieDateToDate(endOozieDate), minuteSkip, formatter); - } - - public static List<String> getMinuteDatesOnEitherSide(DateTime startDate, DateTime endDate, - int minuteSkip) { - DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy/MM/dd/HH/mm"); - formatter.withZoneUTC(); - return getMinuteDatesOnEitherSide(startDate, endDate, minuteSkip, formatter); - } - - public static List<String> getMinuteDatesOnEitherSide(String startOozieDate, String endOozieDate, - int minuteSkip, - DateTimeFormatter formatter) { - return getMinuteDatesOnEitherSide(TimeUtil.oozieDateToDate(startOozieDate), - TimeUtil.oozieDateToDate(endOozieDate), minuteSkip, formatter); - } - - public static List<String> getMinuteDatesOnEitherSide(DateTime startDate, DateTime endDate, - int minuteSkip, - DateTimeFormatter formatter) { - LOGGER.info("generating data between " + formatter.print(startDate) + " and " - + formatter.print(endDate)); - if (minuteSkip == 0) { - minuteSkip = 1; - } - List<String> dates = new ArrayList<>(); - while (!startDate.isAfter(endDate)) { - dates.add(formatter.print(startDate)); - startDate = startDate.plusMinutes(minuteSkip); - } - return dates; - } - - /** - * Convert list of dates to list of string according to the supplied format. - * - * @param dates list of dates - * @param formatter formatter to be used for converting dates - * @return list of strings corresponding to given dates - */ - public static List<String> convertDatesToString(List<DateTime> dates, - DateTimeFormatter formatter) { - List<String> dateString = new ArrayList<>(); - formatter.withZoneUTC(); - for (DateTime date : dates) { - dateString.add(formatter.print(date)); - } - return dateString; - } - - /** - * Get all possible dates between start and end date gap between subsequent dates be one unit. - * of freqType - * - * @param startDate start date - * @param endDate end date - * @param freqType type of the feed - * @return list of dates - */ - public static List<DateTime> getDatesOnEitherSide(DateTime startDate, DateTime endDate, - FreqType freqType) { - return getDatesOnEitherSide(startDate, endDate, 1, freqType); - } - - /** - * Get all possible dates between start and end date gap between subsequent dates be one unit. - * of freqType - * - * @param startDate start date - * @param endDate end date - * @param skip amount of skipping - * @param freqType type of the feed - * @return list of dates - */ - public static List<DateTime> getDatesOnEitherSide(DateTime startDate, DateTime endDate, - int skip, FreqType freqType) { - final List<DateTime> dates = new ArrayList<>(); - if (!startDate.isAfter(endDate)) { - dates.add(startDate); - } - for (int counter = 0; !startDate.isAfter(endDate) && counter < 1000; ++counter) { - startDate = freqType.addTime(startDate, skip); - dates.add(startDate); - } - return dates; - } - - public static String getTimeWrtSystemTime(int minutes) { - - DateTime jodaTime = new DateTime(DateTimeZone.UTC); - if (minutes > 0) { - jodaTime = jodaTime.plusMinutes(minutes); - } else { - jodaTime = jodaTime.minusMinutes(-1 * minutes); - } - DateTimeFormatter fmt = OozieUtil.getOozieDateTimeFormatter(); - DateTimeZone tz = DateTimeZone.getDefault(); - return fmt.print(tz.convertLocalToUTC(jodaTime.getMillis(), false)); - } - - public static String addMinsToTime(String time, int minutes) { - - DateTimeFormatter fmt = OozieUtil.getOozieDateTimeFormatter(); - DateTime jodaTime = fmt.parseDateTime(time); - jodaTime = jodaTime.plusMinutes(minutes); - return fmt.print(jodaTime); - } - - public static DateTime oozieDateToDate(String time) { - DateTimeFormatter fmt = OozieUtil.getOozieDateTimeFormatter(); - fmt = fmt.withZoneUTC(); - return fmt.parseDateTime(time); - } - - public static String dateToOozieDate(Date dt) { - - DateTime jodaTime = new DateTime(dt, DateTimeZone.UTC); - LOGGER.info("SystemTime: " + jodaTime); - DateTimeFormatter fmt = OozieUtil.getOozieDateTimeFormatter(); - return fmt.print(jodaTime); - } - - public static void sleepTill(String startTimeOfLateCoord) { - - DateTime finalDate = new DateTime(oozieDateToDate(startTimeOfLateCoord)); - while (true) { - DateTime sysDate = oozieDateToDate(getTimeWrtSystemTime(0)); - LOGGER.info("sysDate: " + sysDate + " finalDate: " + finalDate); - if (sysDate.compareTo(finalDate) > 0) { - break; - } - TimeUtil.sleepSeconds(15); - } - } - - public static Date getMinutes(String expression, Calendar time) { - int hr; - int mins; - int day; - int month; - Calendar cal = Calendar.getInstance(); - cal.setTime(time.getTime()); - if (expression.contains("now")) { - hr = getInt(expression, 0); - mins = getInt(expression, 1); - cal.add(Calendar.HOUR, hr); - cal.add(Calendar.MINUTE, mins); - } else if (expression.contains("today")) { - hr = getInt(expression, 0); - mins = getInt(expression, 1); - cal.add(Calendar.HOUR, hr - (cal.get(Calendar.HOUR_OF_DAY))); - cal.add(Calendar.MINUTE, mins); - } else if (expression.contains("yesterday")) { - hr = getInt(expression, 0); - mins = getInt(expression, 1); - cal.add(Calendar.HOUR, hr - (cal.get(Calendar.HOUR_OF_DAY)) - 24); - cal.add(Calendar.MINUTE, mins); - } else if (expression.contains("currentMonth")) { - day = getInt(expression, 0); - hr = getInt(expression, 1); - mins = getInt(expression, 2); - cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 1, 0, 0); - cal.add(Calendar.HOUR, 24 * day + hr); - cal.add(Calendar.MINUTE, mins); - } else if (expression.contains("lastMonth")) { - day = getInt(expression, 0); - hr = getInt(expression, 1); - mins = getInt(expression, 2); - cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) - 1, 1, 0, 0); - cal.add(Calendar.HOUR, 24 * day + hr); - cal.add(Calendar.MINUTE, mins); - } else if (expression.contains("currentYear")) { - month = getInt(expression, 0); - day = getInt(expression, 1); - hr = getInt(expression, 2); - mins = getInt(expression, 3); - cal.set(cal.get(Calendar.YEAR), 1, 1, 0, 0); - cal.add(Calendar.MONTH, month - 1); - cal.add(Calendar.HOUR, 24 * day + hr); - cal.add(Calendar.MINUTE, mins); - } else if (expression.contains("lastYear")) { - month = getInt(expression, 0); - day = getInt(expression, 1); - hr = getInt(expression, 2); - mins = getInt(expression, 3); - cal.set(cal.get(Calendar.YEAR) - 1, 1, 1, 0, 0); - cal.add(Calendar.MONTH, month - 1); - cal.add(Calendar.HOUR, 24 * day + hr); - cal.add(Calendar.MINUTE, mins); - } - return cal.getTime(); - } - - private static int getInt(String expression, int position) { - String numbers = expression.substring(expression.indexOf('(') + 1, expression.indexOf(')')); - return Integer.parseInt(numbers.split(",")[position]); - } - - /** - * Converts given date from one format to another. - * - * @param date input date - * @param myFormat input date format - * @param userFormat required format - * @return date in userFormat - */ - public static String parseDate(String date, String myFormat, String userFormat) throws ParseException { - SimpleDateFormat formatter = new SimpleDateFormat(myFormat); - SimpleDateFormat fromUser = new SimpleDateFormat(userFormat); - String reformattedStr=""; - try { - reformattedStr = formatter.format(fromUser.parse(date)); - LOGGER.info(reformattedStr); - } catch (ParseException e) { - e.printStackTrace(); - } - return reformattedStr; - } -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java deleted file mode 100644 index c86fb4b..0000000 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * 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.log4j.Logger; -import org.openqa.selenium.WebElement; -import org.testng.Assert; - -/** - * Assertion related to UI testing. - */ -public final class UIAssert { - private UIAssert() { - throw new AssertionError("Instantiating utility class..."); - } - private static final Logger LOGGER = Logger.getLogger(UIAssert.class); - - public static void assertDisplayed(WebElement element, String webElementName) { - LOGGER.info(String.format("Checking if WebElement '%s' is displayed", webElementName)); - int timeoutSeconds = 2; - for (int i = 0; !element.isDisplayed() && i < timeoutSeconds * 10; i++) { - TimeUtil.sleepSeconds(0.1); - } - Assert.assertTrue(element.isDisplayed(), - String.format("WebElement '%s' should have been displayed", webElementName)); - LOGGER.info(String.format("WebElement '%s' is displayed", webElementName)); - } - - public static void assertNotDisplayed(WebElement clusterForm, String webElementName) { - LOGGER.info(String.format("Checking if WebElement '%s' is displayed", webElementName)); - Assert.assertFalse(clusterForm.isDisplayed(), - String.format("WebElement '%s' should NOT have been displayed", webElementName)); - LOGGER.info(String.format("WebElement '%s' is not displayed", webElementName)); - } -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UiUtil.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UiUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UiUtil.java deleted file mode 100644 index 6142332..0000000 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UiUtil.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * 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.StringEscapeUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; -import org.openqa.selenium.By; -import org.openqa.selenium.JavascriptExecutor; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -import java.util.ArrayList; -import java.util.List; - -/** - * Utility class for UI related tasks. - */ -public final class UiUtil { - private UiUtil() { - throw new AssertionError("Instantiating utility class..."); - } - private static final Logger LOGGER = Logger.getLogger(UiUtil.class); - - /** - * Convert the element to string representation. Useful for debugging/development. - * @param element element to be converted - * @param limitDepth the depth to traverse. Typically <=3 is good value. - * @return - */ - protected static String elementToString(WebElement element, Integer limitDepth) { - final StringBuilder retVal = - new StringBuilder("String representation of the element(first line is format):\n"); - retVal.append("-> tagname") - .append("(id)") - .append("(classes)") - .append("[extra-info]") - .append("\t") - .append("text") - .append("\n"); - retVal.append(elementToString("", element, limitDepth)); - return retVal.toString(); - } - - private static StringBuilder elementToString(String prefix, WebElement element, Integer - limitDepth) { - if (limitDepth != null && limitDepth == 0) { - return new StringBuilder(); - } - final Integer newDepth = limitDepth == null ? null : limitDepth - 1; - final StringBuilder elementStr = new StringBuilder(prefix); - List<String> extraInfo = new ArrayList<>(); - if (StringUtils.isNotBlank(element.getAttribute("ng-repeat"))) { - extraInfo.add("array"); - } - elementStr.append("-> ") - .append(element.getTagName()) - .append("(").append(element.getAttribute("id")).append(")") - .append("(").append(element.getAttribute("class")).append(")") - .append(extraInfo) - .append("\t").append(StringEscapeUtils.escapeJava(element.getText())); - final String childPrefix = prefix + "\t"; - final List<WebElement> childElements = element.findElements(By.xpath("./*")); - for (WebElement oneChildElement : childElements) { - StringBuilder childStr = elementToString(childPrefix, oneChildElement, newDepth); - if (childStr.length() > 0) { - elementStr.append("\n").append(childStr); - } - } - return elementStr; - } - - /** - * Highlight the element in the UI. Useful for development/debugging. - * Copied from http://www.testingdiaries.com/highlight-element-using-selenium-webdriver/ - * @param element the element to highlight - * @param driver the web driver in use - */ - public static void elementHighlight(WebElement element, WebDriver driver) { - for (int i = 0; i < 2; i++) { - JavascriptExecutor js = (JavascriptExecutor) driver; - js.executeScript( - "arguments[0].setAttribute('style', arguments[1]);", - element, "color: red; border: 3px solid red;"); - js.executeScript( - "arguments[0].setAttribute('style', arguments[1]);", - element, ""); - } - } -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Util.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Util.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Util.java deleted file mode 100644 index 452effa..0000000 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Util.java +++ /dev/null @@ -1,607 +0,0 @@ -/** - * 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 com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.jcraft.jsch.JSchException; -import org.apache.falcon.entity.v0.EntityType; -import org.apache.falcon.entity.v0.feed.LocationType; -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.enumsAndConstants.MerlinConstants; -import org.apache.falcon.regression.core.helpers.ColoHelper; -import org.apache.falcon.regression.core.helpers.entity.AbstractEntityHelper; -import org.apache.falcon.regression.core.response.ServiceResponse; -import org.apache.falcon.regression.core.supportClasses.JmsMessageConsumer; -import org.apache.falcon.request.BaseRequest; -import org.apache.falcon.request.RequestKeys; -import org.apache.falcon.resource.APIResult; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.security.authentication.client.AuthenticationException; -import org.apache.http.HttpResponse; -import org.apache.log4j.Logger; -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; -import org.testng.Assert; -import org.w3c.dom.Document; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -import javax.jms.JMSException; -import javax.jms.MapMessage; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Source; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.stream.StreamResult; -import javax.xml.transform.stream.StreamSource; -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; - -/** - * util methods used across test. - */ -public final class Util { - - private Util() { - throw new AssertionError("Instantiating utility class..."); - } - private static final Logger LOGGER = Logger.getLogger(Util.class); - - /** - * Sends request without data and user. - */ - public static ServiceResponse sendRequest(String url, String method) - throws IOException, URISyntaxException, AuthenticationException, InterruptedException { - return sendRequest(url, method, null, null); - } - - /** - * Sends api request without data. - */ - public static ServiceResponse sendRequest(String url, String method, String user) - throws IOException, URISyntaxException, AuthenticationException, InterruptedException { - return sendRequest(url, method, null, user); - } - - /** - * Sends api requests. - * @param url target url - * @param method request method - * @param data data to be places in body of request - * @param user user to be used to send request - * @return api response - * @throws IOException - * @throws URISyntaxException - * @throws AuthenticationException - */ - public static ServiceResponse sendRequest(String url, String method, String data, String user) - throws IOException, URISyntaxException, AuthenticationException, InterruptedException { - BaseRequest request = new BaseRequest(url, method, user, data); - request.addHeader(RequestKeys.CONTENT_TYPE_HEADER, RequestKeys.XML_CONTENT_TYPE); - HttpResponse response = request.run(); - return new ServiceResponse(response); - } - - /** - * @param data string data - * @return is data should be considered as XMl - */ - private static boolean isXML(String data) { - return data != null && data.trim().length() > 0 && data.trim().startsWith("<"); - } - - /** - * Converts service response to api result form. - * @param response service response - * @return api result - * @throws JAXBException - */ - public static APIResult parseResponse(ServiceResponse response) throws JAXBException { - if (!isXML(response.getMessage())) { - return new APIResult(APIResult.Status.FAILED, response.getMessage()); - } - JAXBContext jc = JAXBContext.newInstance(APIResult.class); - Unmarshaller u = jc.createUnmarshaller(); - if (response.getMessage().contains("requestId")) { - return (APIResult) u - .unmarshal(new InputSource(new StringReader(response.getMessage()))); - } else { - return new APIResult(response.getCode() == 200 - ? APIResult.Status.SUCCEEDED : APIResult.Status.FAILED, response.getMessage()); - } - } - - /** - * Lists all directories contained in a store by sub-path. - * @param helper cluster where store is present - * @param subPath sub-path - * @return list of all directories in the sub-path - * @throws IOException - * @throws JSchException - */ - public static List<String> getStoreInfo(AbstractEntityHelper helper, String subPath) - throws IOException, JSchException { - if (helper.getStoreLocation().startsWith("hdfs:")) { - return HadoopUtil.getAllFilesHDFS(helper.getHadoopFS(), - new Path(helper.getStoreLocation() + subPath)); - } else { - return ExecUtil.runRemoteScriptAsSudo(helper.getQaHost(), helper.getUsername(), - helper.getPassword(), "ls " + helper.getStoreLocation() + subPath, - helper.getUsername(), helper.getIdentityFile()); - } - } - - /** - * @param data entity definition - * @return entity name - */ - public static String readEntityName(String data) { - if (data.contains("uri:falcon:feed")) { - return new FeedMerlin(data).getName(); - } else if (data.contains("uri:falcon:process")) { - return new ProcessMerlin(data).getName(); - } else { - return new ClusterMerlin(data).getName(); - } - } - - /** - * Retrieves all hadoop data directories from a specific data path. - * @param fs filesystem - * @param feed feed definition - * @param dir specific directory - * @return all - * @throws IOException - */ - public static List<String> getHadoopDataFromDir(FileSystem fs, String feed, String dir) - throws IOException { - List<String> finalResult = new ArrayList<>(); - String feedPath = new FeedMerlin(feed).getFeedPath(LocationType.DATA); - int depth = feedPath.split(dir)[1].split("/").length - 1; - List<Path> results = HadoopUtil.getAllDirsRecursivelyHDFS(fs, new Path(dir), depth); - for (Path result : results) { - int pathDepth = result.toString().split(dir)[1].split("/").length - 1; - if (pathDepth == depth) { - finalResult.add(result.toString().split(dir)[1]); - } - } - return finalResult; - } - - /** - * Finds first folder within a date range. - * @param startTime start date - * @param endTime end date - * @param folderList list of folders which are under analysis - * @return first matching folder or null if not present in a list - */ - public static String findFolderBetweenGivenTimeStamps(DateTime startTime, DateTime endTime, - List<String> folderList) { - DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy/MM/dd/HH/mm"); - for (String folder : folderList) { - if (folder.compareTo(formatter.print(startTime)) >= 0 - && - folder.compareTo(formatter.print(endTime)) <= 0) { - return folder; - } - } - return null; - } - - public static List<String> getInstanceFinishTimes(ColoHelper coloHelper, String workflowId) - throws IOException, JSchException { - List<String> raw = ExecUtil.runRemoteScriptAsSudo(coloHelper.getProcessHelper() - .getQaHost(), coloHelper.getProcessHelper().getUsername(), - coloHelper.getProcessHelper().getPassword(), - "cat /var/log/falcon/application.* | grep \"" + workflowId + "\" | grep " - + "\"Received\" | awk '{print $2}'", - coloHelper.getProcessHelper().getUsername(), - coloHelper.getProcessHelper().getIdentityFile() - ); - List<String> finalList = new ArrayList<>(); - for (String line : raw) { - finalList.add(line.split(",")[0]); - } - return finalList; - } - - public static List<String> getInstanceRetryTimes(ColoHelper coloHelper, String workflowId) - throws IOException, JSchException { - List<String> raw = ExecUtil.runRemoteScriptAsSudo(coloHelper.getProcessHelper() - .getQaHost(), coloHelper.getProcessHelper().getUsername(), - coloHelper.getProcessHelper().getPassword(), - "cat /var/log/falcon/application.* | grep \"" + workflowId + "\" | grep " - + - "\"Retrying attempt\" | awk '{print $2}'", - coloHelper.getProcessHelper().getUsername(), - coloHelper.getProcessHelper().getIdentityFile() - ); - List<String> finalList = new ArrayList<>(); - for (String line : raw) { - finalList.add(line.split(",")[0]); - } - return finalList; - } - - /** - * Shuts down falcon server on a given host using sudo credentials. - * @param helper given host - * @throws IOException - * @throws JSchException - */ - public static void shutDownService(AbstractEntityHelper helper) - throws IOException, JSchException { - ExecUtil.runRemoteScriptAsSudo(helper.getQaHost(), helper.getUsername(), - helper.getPassword(), helper.getServiceStopCmd(), - helper.getServiceUser(), helper.getIdentityFile()); - TimeUtil.sleepSeconds(10); - } - - /** - * Start falcon server on a given host using sudo credentials and checks if it succeeds. - * @param helper given host - * @throws IOException - * @throws JSchException - * @throws AuthenticationException - * @throws URISyntaxException - */ - public static void startService(AbstractEntityHelper helper) - throws IOException, JSchException, AuthenticationException, URISyntaxException, - InterruptedException { - ExecUtil.runRemoteScriptAsSudo(helper.getQaHost(), helper.getUsername(), - helper.getPassword(), helper.getServiceStartCmd(), helper.getServiceUser(), - helper.getIdentityFile()); - int statusCode = 0; - for (int tries = 20; tries > 0; tries--) { - try { - statusCode = Util.sendRequest(helper.getHostname(), "get").getCode(); - } catch (IOException e) { - LOGGER.info(e.getMessage()); - } - if (statusCode == 200) { - return; - } - TimeUtil.sleepSeconds(5); - } - throw new RuntimeException("Service on" + helper.getHostname() + " did not start!"); - } - - /** - * Stops and starts falcon service for a given host using sudo credentials. - * @param helper given host - * @throws IOException - * @throws JSchException - * @throws AuthenticationException - * @throws URISyntaxException - */ - public static void restartService(AbstractEntityHelper helper) - throws IOException, JSchException, AuthenticationException, URISyntaxException, - InterruptedException { - LOGGER.info("restarting service for: " + helper.getQaHost()); - shutDownService(helper); - startService(helper); - } - - /** - * Prints JMSConsumer messages content. - * @param messageConsumer the source JMSConsumer - * @throws JMSException - */ - public static void printMessageData(JmsMessageConsumer messageConsumer) throws JMSException { - LOGGER.info("dumping all queue data:"); - for (MapMessage mapMessage : messageConsumer.getReceivedMessages()) { - StringBuilder stringBuilder = new StringBuilder(); - final Enumeration mapNames = mapMessage.getMapNames(); - while (mapNames.hasMoreElements()) { - final String propName = mapNames.nextElement().toString(); - final String propValue = mapMessage.getString(propName); - stringBuilder.append(propName).append('=').append(propValue).append(' '); - } - LOGGER.info(stringBuilder); - } - } - - /** - * Get entity type according to its definition. - * @param entity entity which is under analysis - * @return entity type - */ - public static EntityType getEntityType(String entity) { - if (entity.contains("uri:falcon:process:0.1")) { - return EntityType.PROCESS; - } else if (entity.contains("uri:falcon:cluster:0.1")) { - return EntityType.CLUSTER; - } else if (entity.contains("uri:falcon:feed:0.1")) { - return EntityType.FEED; - } - return null; - } - - /** - * Compares two definitions. - * @param server1 server where 1st definition is stored - * @param server2 server where 2nd definition is stored - * @param entity entity which is under analysis - * @return are definitions identical - */ - public static boolean isDefinitionSame(ColoHelper server1, ColoHelper server2, - String entity) - throws URISyntaxException, IOException, AuthenticationException, JAXBException, - SAXException, InterruptedException { - return XmlUtil.isIdentical(getEntityDefinition(server1, entity, true), - getEntityDefinition(server2, entity, true)); - } - - /** - * enums used for instance api. - */ - public enum URLS { - LIST_URL("/api/entities/list"), - SUBMIT_URL("/api/entities/submit"), - GET_ENTITY_DEFINITION("/api/entities/definition"), - DEPENDENCIES("/api/entities/dependencies"), - DELETE_URL("/api/entities/delete"), - SCHEDULE_URL("/api/entities/schedule"), - VALIDATE_URL("/api/entities/validate"), - SUSPEND_URL("/api/entities/suspend"), - RESUME_URL("/api/entities/resume"), - UPDATE("/api/entities/update"), - STATUS_URL("/api/entities/status"), - ENTITY_SUMMARY("/api/entities/summary"), - SUBMIT_AND_SCHEDULE_URL("/api/entities/submitAndSchedule"), - SLA("/api/entities/sla-alert"), - ENTITY_LINEAGE("/api/metadata/lineage/entities"), - INSTANCE_RUNNING("/api/instance/running"), - INSTANCE_STATUS("/api/instance/status"), - INSTANCE_KILL("/api/instance/kill"), - INSTANCE_RESUME("/api/instance/resume"), - INSTANCE_SUSPEND("/api/instance/suspend"), - INSTANCE_RERUN("/api/instance/rerun"), - INSTANCE_SUMMARY("/api/instance/summary"), - INSTANCE_PARAMS("/api/instance/params"), - INSTANCE_TRIAGE("/api/instance/triage"), - INSTANCE_LIST("/api/instance/list"), - INSTANCE_LISTING("/api/instance/listing"), - INSTANCE_LOGS("/api/instance/logs"), - INSTANCE_DEPENDENCIES("/api/instance/dependencies"), - TOUCH_URL("/api/entities/touch"); - - private final String url; - - URLS(String url) { - this.url = url; - } - - public String getValue() { - return this.url; - } - } - - /** - * @param pathString whole path. - * @return path to basic data folder - */ - public static String getPathPrefix(String pathString) { - return pathString.substring(0, pathString.indexOf('$')); - } - - /** - * @param path whole path. - * @return file name which is retrieved from a path - */ - public static String getFileNameFromPath(String path) { - return path.substring(path.lastIndexOf('/') + 1, path.length()); - } - - /** - * Defines request type according to request url. - * @param url request url - * @return request type - */ - public static String getMethodType(String url) { - List<String> postList = new ArrayList<>(); - postList.add("/entities/validate"); - postList.add("/entities/submit"); - postList.add("/entities/submitAndSchedule"); - postList.add("/entities/suspend"); - postList.add("/entities/resume"); - postList.add("/instance/kill"); - postList.add("/instance/suspend"); - postList.add("/instance/resume"); - postList.add("/instance/rerun"); - for (String item : postList) { - if (url.toLowerCase().contains(item)) { - return "post"; - } - } - List<String> deleteList = new ArrayList<>(); - deleteList.add("/entities/delete"); - for (String item : deleteList) { - if (url.toLowerCase().contains(item)) { - return "delete"; - } - } - return "get"; - } - - /** - * Prints xml in readable form. - * @param xmlString xmlString - * @return formatted xmlString - */ - public static String prettyPrintXml(final String xmlString) { - if (xmlString == null) { - return null; - } - try { - Source xmlInput = new StreamSource(new StringReader(xmlString)); - StringWriter stringWriter = new StringWriter(); - StreamResult xmlOutput = new StreamResult(stringWriter); - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - transformerFactory.setAttribute("indent-number", "2"); - Transformer transformer = transformerFactory.newTransformer(); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.transform(xmlInput, xmlOutput); - return xmlOutput.getWriter().toString(); - } catch (TransformerConfigurationException e) { - return xmlString; - } catch (TransformerException e) { - return xmlString; - } - } - - /** - * Converts json string to readable form. - * @param jsonString json string - * @return formatted string - */ - public static String prettyPrintJson(final String jsonString) { - if (jsonString == null) { - return null; - } - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - JsonElement json = new JsonParser().parse(jsonString); - return gson.toJson(json); - } - - /** - * Prints xml or json in pretty and readable format. - * @param str xml or json string - * @return converted xml or json - */ - public static String prettyPrintXmlOrJson(final String str) { - if (str == null) { - return null; - } - String cleanStr = str.trim(); - //taken from http://stackoverflow.com/questions/7256142/way-to-quickly-check-if-string-is-xml-or-json-in-c-sharp - if (cleanStr.startsWith("{") || cleanStr.startsWith("[")) { - return prettyPrintJson(cleanStr); - } - if (cleanStr.startsWith("<")) { - return prettyPrintXml(cleanStr); - } - LOGGER.warn("The string does not seem to be either json or xml: " + cleanStr); - return str; - } - - /** - * Tries to get entity definition. - * @param cluster cluster where definition is stored - * @param entity entity for which definition is required - * @param shouldReturn should the definition be successfully retrieved or not - * @return entity definition - */ - public static String getEntityDefinition(ColoHelper cluster, - String entity, - boolean shouldReturn) throws - JAXBException, - IOException, URISyntaxException, AuthenticationException, InterruptedException { - EntityType type = getEntityType(entity); - AbstractEntityHelper helper; - if (EntityType.PROCESS == type) { - helper = cluster.getProcessHelper(); - } else if (EntityType.FEED == type) { - helper = cluster.getFeedHelper(); - } else { - helper = cluster.getClusterHelper(); - } - ServiceResponse response = helper.getEntityDefinition(entity); - if (shouldReturn) { - AssertUtil.assertSucceeded(response); - } else { - AssertUtil.assertFailed(response); - } - String result = response.getMessage(); - Assert.assertNotNull(result); - return result; - } - - /** - * Get prefix for test entities. - * @param testClass object of test class - * @return test class name if is_deprecate=false or 'A' and hash if is_deprecate=true - */ - public static String getEntityPrefix(Object testClass) { - String className = testClass.getClass().getSimpleName(); - if (MerlinConstants.IS_DEPRECATE) { - return 'A' + Integer.toHexString(className.hashCode()); - } else { - return className; - } - } - - /** - * Converts string to xml document. - * @param xmlStr string representation - * @return document representation. - */ - public static Document convertStringToDocument(String xmlStr) { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder; - try { - builder = factory.newDocumentBuilder(); - Document doc = builder.parse(new InputSource(new StringReader(xmlStr))); - return doc; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - /** - * Sends api requests. - * @param url target url - * @param method request method - * @param data data to be places in body of request - * @param user user to be used to send request - * @return api response - * @throws IOException - * @throws URISyntaxException - * @throws AuthenticationException - */ - public static ServiceResponse sendJSONRequest(String url, String method, String data, String user) - throws IOException, URISyntaxException, AuthenticationException, InterruptedException { - BaseRequest request = new BaseRequest(url, method, user, data); - request.addHeader(RequestKeys.CONTENT_TYPE_HEADER, RequestKeys.JSON_CONTENT_TYPE); - HttpResponse response = request.run(); - return new ServiceResponse(response); - } - -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/XmlUtil.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/XmlUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/XmlUtil.java deleted file mode 100644 index 1041910..0000000 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/XmlUtil.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * 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.custommonkey.xmlunit.Diff; -import org.custommonkey.xmlunit.XMLUnit; -import org.apache.log4j.Logger; -import org.xml.sax.SAXException; - -import java.io.IOException; - -/** - * Util methods for XML. - */ -public final class XmlUtil { - - private XmlUtil() { - throw new AssertionError("Instantiating utility class..."); - } - private static final Logger LOGGER = Logger.getLogger(XmlUtil.class); - - public static boolean isIdentical(String expected, String actual) - throws IOException, SAXException { - XMLUnit.setIgnoreWhitespace(true); - XMLUnit.setIgnoreAttributeOrder(true); - Diff diff = XMLUnit.compareXML(expected, actual); - LOGGER.info(diff); - return diff.identical(); - } -}
