001package com.thed.zblast.launcher; 002 003import com.google.gson.Gson; 004import com.thed.launcher.InputStreamHandler; 005import com.thed.model.AutomationJobDetail; 006import com.thed.model.ExecutionRequest; 007import com.thed.model.ZblastScriptExecutionResult; 008import com.thed.parser.ParserUtil; 009import com.thed.util.Utils; 010import com.thed.util.ZeeConstants; 011import com.thed.util.gson.GsonUtil; 012import com.thed.zblast.parser.EggplantParser; 013import com.thed.zblast.parser.JUnitResultParser; 014import com.thed.zblast.parser.TestNGXMLResultParserImpl; 015import com.thed.zblast.parser.jaxb.junit.Failure; 016import com.thed.zblast.parser.jaxb.junit.Testcase; 017import com.thed.zblast.parser.jaxb.junit.Testsuite; 018import com.thed.zblast.parser.model.EggPlantResult; 019import com.thed.zblast.parser.model.TestCase; 020import com.thed.zblast.parser.model.TestngResults; 021import com.thed.zblast.parser.model.TestngResults.Testsuite.Test.Class; 022import com.thed.zblast.parser.model.TestngResults.Testsuite.Test.Class.TestMethod; 023import org.apache.commons.configuration.PropertiesConfiguration; 024import org.apache.commons.io.FilenameUtils; 025import org.apache.commons.lang.StringUtils; 026import org.apache.commons.lang.SystemUtils; 027import org.xml.sax.SAXException; 028 029import javax.xml.parsers.ParserConfigurationException; 030import java.io.*; 031import java.math.BigDecimal; 032import java.util.*; 033import java.util.concurrent.TimeUnit; 034import java.util.logging.Level; 035import java.util.logging.Logger; 036import java.util.stream.Collectors; 037 038public class ZblastLauncher { 039 040 private final Logger logger = Logger.getLogger(ZblastLauncher.class.getName()); 041 String logstatus; 042 043 public void invoke(AutomationJobDetail automationJobDetail, ZblastScriptExecutionResult executionResult) { 044 String frameworkSelected = automationJobDetail.getAutomationFramework().toLowerCase(); 045 046 PropertiesConfiguration props = Utils.getZbotProperties(); 047 String useGenericParser=props.getString("use_generic_parser"); 048 Boolean isGenericParserUsed = Boolean.valueOf((useGenericParser==null)?"false":useGenericParser); 049 050 if (automationJobDetail.isInvokeScript()) 051 testcaseExecutionRun(automationJobDetail, executionResult); 052 053 if (automationJobDetail.isInvokeScript() && !executionResult.isScriptExecutionSatus()) 054 return; 055 if (frameworkSelected.equalsIgnoreCase(ZeeConstants.SELENIUM) || frameworkSelected.equalsIgnoreCase(ZeeConstants.UFT) || frameworkSelected.contains(ZeeConstants.TOSCA) 056 || frameworkSelected.equalsIgnoreCase(ZeeConstants.JUNIT)|| frameworkSelected.equalsIgnoreCase(ZeeConstants.CUCUMBER) 057 || frameworkSelected.equalsIgnoreCase(ZeeConstants.SOAP_UI_PRO) ||frameworkSelected.equalsIgnoreCase(ZeeConstants.SOAPUI_PRO) || frameworkSelected.equalsIgnoreCase(ZeeConstants.TESTCOMPLETE)) { 058 List<Testsuite> testsuites=null; 059 if(isGenericParserUsed){ 060 testsuites=getTestSuitesFromGenericParser(automationJobDetail.getResultPath(),automationJobDetail.getParserTemplate()); 061 }else{ 062 testsuites = JUnitResultParser.parseResults(automationJobDetail.getResultPath()); 063 } 064 executionResult.setTestSuite(testsuites); 065 } else if (frameworkSelected.equalsIgnoreCase(ZeeConstants.EGG_PLANT)) { 066 try { 067 // TODO : sut and image url support implementation if required by customers 068 EggplantParser eggplantParser = new EggplantParser("unknownSUT", "url"); 069 // result path must point to RunHistory.csv (Ex. D:\\eggPlant\\Untitled\\RunHistory.csv) 070 ArrayList<EggPlantResult> eggPlantResults = eggplantParser.invoke(new File(FilenameUtils.separatorsToSystem(automationJobDetail.getResultPath()))); 071 List<Testsuite> testSuite=getTestsSuitsForEggplant(eggPlantResults,automationJobDetail,isGenericParserUsed); 072 executionResult.setTestSuite(testSuite); 073 } catch (Exception e) { 074 logger.info("exception parsing eggPlant results: " + e.getMessage()); 075 } 076 } 077 else if( frameworkSelected.equalsIgnoreCase(ZeeConstants.TEST_NG) ) { 078 List<Testsuite> testSuite=getSuiteForTestNg(automationJobDetail,isGenericParserUsed); 079 executionResult.setTestSuite(testSuite); 080 } else if(isGenericParserUsed) { 081 List<Testsuite> testsuites=getTestSuitesFromGenericParser(automationJobDetail.getResultPath(),automationJobDetail.getParserTemplate()); 082 executionResult.setTestSuite(testsuites); 083 } 084 } 085 086 private List<Testsuite> getSuiteForTestNg(AutomationJobDetail automationJobDetail, Boolean isGenericParserUsed) { 087 List<Testsuite> testsuites=new ArrayList<>(); 088 if(isGenericParserUsed){ 089 testsuites=getTestSuitesFromGenericParser(automationJobDetail.getResultPath(),automationJobDetail.getParserTemplate()); 090 }else{ 091 testsuites=getResultForTestNg(automationJobDetail); 092 } 093 return testsuites; 094 } 095 096 private List<Testsuite> getResultForTestNg(AutomationJobDetail automationJobDetail) { 097 List<Testsuite> testSuite=new ArrayList<>(); 098 List<com.thed.zblast.parser.model.TestngResults.Testsuite> testNgResults=TestNGXMLResultParserImpl.parseResults(automationJobDetail.getResultPath()); 099 for(com.thed.zblast.parser.model.TestngResults.Testsuite suite: testNgResults) { 100 Testsuite tests=new Testsuite(); 101 List<TestngResults.Testsuite.Test> test1 = suite.getTest(); 102 List<Class> testClass = new ArrayList<>(); 103 test1.stream().forEach(t->testClass.addAll(t.getClazz())); 104 List<TestMethod> testMethods=new ArrayList<>(); 105 List<List<TestMethod>> testMethodsList = testClass.stream().map(s -> s.getTestMethod()).collect(Collectors.toList()); 106 testMethodsList.forEach(su-> {testMethods.addAll(su);}); 107 List<Testcase> testcases=new ArrayList<>(); 108 for (TestMethod testcase : testMethods) { 109 String name = testcase.getName(); 110 Testcase test=new Testcase(); 111 112 if (name.equals(ZeeConstants.BEFORE_CLASS) || name.equals(ZeeConstants.AFTER_CLASS) || name.equals(ZeeConstants.BEFORE_SUITE) 113 || name.equals(ZeeConstants.AFTER_SUITE) || name.equals(ZeeConstants.BEFORE_METHOD) || name.equals(ZeeConstants.AFTER_METHOD)) { 114 continue; 115 } 116 String status = testcase.getStatus(); 117 test.setName(name); 118 test.setStatus(status); 119 Failure failure=new Failure(); 120 if(testcase.getException()!=null) { 121 failure.setContent(testcase.getException().getMessage()+SystemUtils.LINE_SEPARATOR+testcase.getException().getFullStacktrace()); 122 test.getFailure().add(failure); 123 } 124 testcases.add(test); 125 } 126 tests.getTestcase().addAll(testcases); 127 testSuite.add(tests); 128 } 129 return testSuite; 130 } 131 132 private List<Testsuite> getTestSuitesFromGenericParser(String resultPath,String parserTemplate) { 133 File result = new File(resultPath); 134 List<Testsuite> testsuites=new ArrayList<>(); 135 List<String> xmlResultFile = new ArrayList<>(); 136 if(result.exists()){ 137 if(result.isDirectory()){ 138 //get all .xml files 139 File[] resultFiles = result.listFiles((file, name) -> name.endsWith(".xml")); 140 List<String> files=Arrays.asList(resultFiles).stream().map(file -> file.getAbsolutePath()).collect(Collectors.toList()); 141 xmlResultFile.addAll(files); 142 }else{ 143 // add the file to the list of files 144 xmlResultFile.add(resultPath); 145 } 146 } 147 148 xmlResultFile.forEach((resultFile)->{ 149 try { 150 List<Map> dataMap = new ParserUtil().parseXmlLang(resultFile, parserTemplate); 151 Testsuite testsuite=getTestSuiteFromDataMap(dataMap); 152 //required for Eggplant, ignoring for other frameworks 153 testsuite.setAttachmentFile(resultFile); 154 testsuites.add(testsuite); 155 } catch (IOException e) { 156 e.printStackTrace(); 157 } catch (SAXException e) { 158 e.printStackTrace(); 159 } catch (ParserConfigurationException e) { 160 e.printStackTrace(); 161 } 162 }); 163 return testsuites; 164 } 165 166 private Testsuite getTestSuiteFromDataMap(List<Map> dataMapList) { 167 Testsuite testsuite=new Testsuite(); 168 List<Testcase> testcaseList=getTestcaseFromDataMap(dataMapList); 169 Map map = dataMapList.get(0); 170 if(map.containsKey("timestamp")){ 171 String timestamp = (String) map.get("timestamp"); 172 testsuite.setTimestamp(timestamp); 173 } 174 testsuite.setTestcase(testcaseList); 175 return testsuite; 176 } 177 178 private List<Testcase> getTestcaseFromDataMap(List<Map> dataMapList) { 179 List<Testcase> testcaseList=new ArrayList<>(); 180 for (Map map : dataMapList) { 181 Testcase tc=extractTestcase(map); 182 if(tc!=null){ 183 testcaseList.add(tc); 184 } 185 } 186 return testcaseList; 187 } 188 189 private Testcase extractTestcase(Map dataMap) { 190 //implement here 191 Testcase tc=new Testcase(); 192 Set<String> requirementIds = new HashSet<>(); 193 Set<String> packageNames = new HashSet<>(); 194 List<String> attachments = new ArrayList<>(); 195 packageNames.add(dataMap.get("packageName").toString()); 196 Map testcaseMap = (Map) dataMap.get("testcase"); 197 198 String testcaseJson = new Gson().toJson(testcaseMap); 199 TestCase testcase = new Gson().fromJson(testcaseJson, TestCase.class); 200 201 if(testcase.getName().isEmpty()) { 202 return null; 203 } 204 205 if(dataMap.containsKey("skipTestcaseNames")) { 206 boolean isSkipTestcase=false; 207 String[] skipTestcaseNames = dataMap.get("skipTestcaseNames").toString().split(","); 208 for (String testcaseName : skipTestcaseNames) { 209 if(testcase.getName().equals(testcaseName)) { 210 //name matches, skip this testcase 211 isSkipTestcase=true; 212 continue; 213 } 214 } 215 if(isSkipTestcase){ 216 return null; 217 } 218 } 219 220 String packageName = dataMap.get("packageName").toString(); 221 222 Map<String, String> statusCondition = new HashMap<>(); 223 if(dataMap.containsKey("statuses") && dataMap.get("statuses") != null) { 224 List<Map> statuses = (List) dataMap.get("statuses"); 225 boolean matched = false; 226 for(Map sc : statuses) { 227 if((sc.get("statusString") == null && sc.get("status") != null && StringUtils.isNotEmpty(sc.get("status").toString())) //status is not empty 228 || (sc.get("statusString") != null && sc.get("statusString").equals(sc.get("status")))) { //status matches statusString 229 statusCondition = sc; 230 matched = true; 231 break; 232 } 233 } 234 if(!matched) { 235 //none of the status condition satisfied, search for default 236 for(Map sc : statuses) { 237 if(sc.get("default") != null && Boolean.valueOf(sc.get("default").toString())) { //default status 238 Object val = dataMap.get("stepText"); 239 if (val != null && !val.toString().isEmpty() && val.toString().contains("skipped")) { 240 sc.put("statusId", "10"); 241 statusCondition = sc; 242 } else { 243 statusCondition = sc; 244 break; 245 } 246 } 247 } 248 } 249 } 250 251 //get requirement from datamap 252 if(dataMap.containsKey("requirements")) { 253 List<Map> requirements = (List) dataMap.get("requirements"); 254 for (Map requirement : requirements) { 255 String id = requirement.get("id").toString(); 256 String[] splitRequirementId = id.split("_"); 257 if(id.startsWith("ID_") || id.startsWith("AltID_")) { 258 requirementIds.add(id); 259 } 260 } 261 } 262 //fetch attachment tags 263 264 if(dataMap.containsKey("attachments")) { 265 List<Map> attachmentFilePaths = (List) dataMap.get("attachments"); 266 for(Map attachment : attachmentFilePaths) { 267 String filePath = attachment.get("filePath").toString(); 268 attachments.add(filePath); 269 } 270 } 271 272 if(statusCondition.containsKey("attachmentText")) { 273 String attachmentText = statusCondition.get("attachmentText"); 274 tc.setStatusAttachment(attachmentText); 275 } 276 277 if(dataMap.containsKey("stepText")) { 278 String stepStr = dataMap.get("stepText").toString(); 279 tc.setSystemOut(Arrays.asList(stepStr)); 280 System.out.println("system-out: "+stepStr); 281 } 282 283 if(dataMap.containsKey("execution")) { 284 Map<String, Object> executionDataMap = (Map<String, Object>) dataMap.get("execution"); 285 Object actualTimeObj = executionDataMap.get("actualTime"); 286 Object actualTimeUnitObj = executionDataMap.get("actualTimeUnit"); 287 executionDataMap.remove("actualTime"); 288 ExecutionRequest executionRequest = GsonUtil.CUSTOM_GSON.fromJson(GsonUtil.CUSTOM_GSON.toJson(executionDataMap), ExecutionRequest.class); 289 if(executionRequest == null) { 290 executionRequest = new ExecutionRequest(); 291 } 292 if(actualTimeObj != null && StringUtils.isNotBlank(actualTimeObj.toString())) { 293 BigDecimal actualTimeSrc = new BigDecimal(actualTimeObj.toString()); 294 TimeUnit actualTimeUnit = null; 295 try { 296 actualTimeUnit = actualTimeUnitObj != null 297 ? TimeUnit.valueOf(actualTimeUnitObj.toString()) 298 : TimeUnit.SECONDS; 299 } catch (Exception e) { 300 logger.warning(ZeeConstants.ERROR_MESSAGE_ACTUAL_TIME_UNIT.formatted(actualTimeUnitObj.toString())); 301 actualTimeUnit = TimeUnit.SECONDS; 302 } 303 switch (actualTimeUnit) { 304 case MILLISECONDS: executionRequest.setActualTime(actualTimeSrc.longValue()); 305 break; 306 307 case SECONDS: 308 default: 309 actualTimeSrc = actualTimeSrc.multiply(new BigDecimal("1000")); 310 executionRequest.setActualTime(actualTimeSrc.longValue()); 311 break; 312 313 } 314 } 315 if(statusCondition.containsKey("statusId")) { 316 executionRequest.setStatus(statusCondition.get("statusId")); 317 } 318 tc.setExecutionRequest(executionRequest); 319 } else { 320 ExecutionRequest executionRequest = new ExecutionRequest(); 321 if(statusCondition.containsKey("statusId")) { 322 executionRequest.setStatus(statusCondition.get("statusId")); 323 tc.setExecutionRequest(executionRequest); 324 } 325 } 326 327 tc.setName(testcase.getName()); 328 tc.setTag(testcase.getTag()); 329 tc.setClassname(packageName); 330 tc.setRequirementIds(requirementIds); 331 tc.setAttachmentList(attachments); 332 return tc; 333 } 334 335 336 private List<Testsuite> getTestsSuitsForEggplant(ArrayList<EggPlantResult> invoke, AutomationJobDetail automationJobDetail, Boolean isGenericParserUsed) { 337 List<Testsuite> testSuits=new ArrayList<>(); 338 Map<String,Testsuite> eggPlantSuite=new HashMap<>(); 339 for(EggPlantResult eggPlant:invoke){ 340 List<Testsuite> suiteList=null; 341 if(isGenericParserUsed){ 342 suiteList=getTestSuitesFromGenericParser(eggPlant.getXmlResultFile(),automationJobDetail.getParserTemplate()); 343 }else{ 344 suiteList=JUnitResultParser.parseResults(eggPlant.getXmlResultFile()); 345 } 346 if(!suiteList.isEmpty()){ 347 Testsuite suite=null; 348 String testCaseName=null; 349 if(isGenericParserUsed){ 350 testCaseName=suiteList.get(0).getTestcase().get(0).getName(); 351 }else{ 352 testCaseName=suiteList.get(0).getName(); 353 } 354 suite=eggPlantSuite.get(testCaseName); 355 356 if(suite==null){ 357 eggPlantSuite.put(testCaseName,suiteList.get(0)); 358 }else{ 359 if(suite.getTimeInDate().before(suiteList.get(0).getTimeInDate())){ 360 eggPlantSuite.put(testCaseName,suiteList.get(0)); 361 } 362 } 363 } 364 } 365 eggPlantSuite.forEach((key,value)->{ 366 testSuits.add(value); 367 }); 368 return testSuits; 369 } 370 371 public void testcaseExecutionRun(AutomationJobDetail automationJobDetail, ZblastScriptExecutionResult executionResult) { 372 373 int status = 0; 374 try { 375 logger.info("about to run script with path: " + automationJobDetail.getScriptPath()); 376 StringBuilder command = new StringBuilder(automationJobDetail.getScriptPath()); 377 final Process process = Runtime.getRuntime().exec(command.toString()); 378 logger.info("Waiting for execution completion..."); 379 StringBuffer inBuffer = new StringBuffer(); 380 InputStream inStream = process.getInputStream(); 381 new InputStreamHandler( inBuffer, inStream ); 382 383 StringBuffer errBuffer = new StringBuffer(); 384 InputStream errStream = process.getErrorStream(); 385 new InputStreamHandler( errBuffer , errStream ); 386 status = process.waitFor(); 387 388 if(status!=0){ 389 logger.log(Level.SEVERE,"Script execution failed. Error : "+errBuffer.toString()); 390 }else{ 391 logger.info("Script successfully executed "); 392 } 393 394 executionResult.setExitCode(status); 395 executionResult.setScriptExecutionSatus(true); 396 executionResult.setScriptExecutionSatusMsg("Script Executed Successfully"); 397 398 } catch (Exception e) { 399 logger.info(""" 400 Automation Job Id : %s: STATUS: Execution Error %s""".formatted(automationJobDetail.getId(), e.getMessage())); 401 logger.info("Script run exit code: " + status); 402 executionResult.setExitCode(status); 403 executionResult.setScriptExecutionSatus(false); 404 executionResult.setScriptExecutionSatusMsg(e.getMessage()); 405 e.printStackTrace(); 406 } 407 408 } 409 410 static class ProcessStreamReader extends Thread { 411 BufferedReader br; 412 private final Logger logger = Logger.getLogger(this.getClass().getName()); 413 414 public ProcessStreamReader(InputStream in) { 415 super(); 416 br = new BufferedReader(new InputStreamReader(in)); 417 } 418 419 @Override 420 public void run() { 421 String line; 422 try { 423 while ((line = br.readLine()) != null) { 424 logger.info(Thread.currentThread().getName() + " | Read output..." + line); 425 } 426 } catch (IOException e) { 427 logger.log(Level.SEVERE, "Error in reading process steams \n", e); 428 } finally { 429 if (br != null) { 430 try { 431 br.close(); 432 } catch (IOException e) { 433 } 434 } 435 } 436 logger.info(Thread.currentThread().getName() + " | Done reading process log input stream"); 437 } 438 } 439 440}