/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.poshi.runner.selenium; import com.liferay.poshi.runner.PoshiRunnerGetterUtil; import com.liferay.poshi.runner.exception.PoshiRunnerWarningException; import com.liferay.poshi.runner.util.EmailCommands; import com.liferay.poshi.runner.util.FileUtil; import com.liferay.poshi.runner.util.GetterUtil; import com.liferay.poshi.runner.util.OSDetector; import com.liferay.poshi.runner.util.PropsValues; import com.liferay.poshi.runner.util.StringUtil; import com.liferay.poshi.runner.util.Validator; import java.awt.Rectangle; import java.awt.Robot; import java.awt.Toolkit; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.imageio.ImageIO; import junit.framework.TestCase; import org.apache.tools.ant.DirectoryScanner; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.sikuli.api.ImageTarget; import org.sikuli.api.robot.Keyboard; import org.sikuli.api.robot.desktop.DesktopKeyboard; /** * @author Brian Wing Shun Chan */ @SuppressWarnings("deprecation") public class LiferaySeleniumHelper { public static void addToJavaScriptExceptions(Exception exception) { _javaScriptExceptions.add(exception); } public static void addToJavaScriptExceptions(List<Exception> exceptions) { _javaScriptExceptions.addAll(exceptions); } public static void addToLiferayExceptions(Exception exception) { _liferayExceptions.add(exception); } public static void addToLiferayExceptions(List<Exception> exceptions) { _liferayExceptions.addAll(exceptions); } public static void assertConsoleErrors() throws Exception { if (!PropsValues.TEST_ASSERT_CONSOLE_ERRORS) { return; } String content = getTestConsoleLogFileContent(); if (content.equals("")) { return; } SAXReader saxReader = new SAXReader(); content = "<log4j>" + content + "</log4j>"; content = content.replaceAll("log4j:", ""); InputStream inputStream = new ByteArrayInputStream( content.getBytes("UTF-8")); Document document = saxReader.read(inputStream); Element rootElement = document.getRootElement(); List<Element> eventElements = rootElement.elements("event"); List<Exception> exceptions = new ArrayList<>(); for (Element eventElement : eventElements) { String level = eventElement.attributeValue("level"); if (level.equals("ERROR") || level.equals("FATAL")) { String timestamp = eventElement.attributeValue("timestamp"); if (_errorTimestamps.contains(timestamp)) { continue; } _errorTimestamps.add(timestamp); Element messageElement = eventElement.element("message"); String messageText = messageElement.getText(); if (isIgnorableErrorLine(messageText)) { continue; } StringBuilder sb = new StringBuilder(); sb.append("LIFERAY_ERROR: "); sb.append(messageText); System.out.println(sb.toString()); exceptions.add(new PoshiRunnerWarningException(sb.toString())); } } if (!exceptions.isEmpty()) { addToLiferayExceptions(exceptions); throw exceptions.get(0); } } public static void assertLocation( LiferaySelenium liferaySelenium, String pattern) throws Exception { TestCase.assertEquals(pattern, liferaySelenium.getLocation()); } public static void assertNoJavaScriptExceptions() throws Exception { if (!_javaScriptExceptions.isEmpty()) { StringBuilder sb = new StringBuilder(); sb.append(_javaScriptExceptions.size()); sb.append(" Javascript Exception"); if (_javaScriptExceptions.size() > 1) { sb.append("s were"); } else { sb.append(" was"); } sb.append(" thrown"); System.out.println(); System.out.println("##"); System.out.println("## " + sb.toString()); System.out.println("##"); for (int i = 0; i < _javaScriptExceptions.size(); i++) { Exception liferayException = _javaScriptExceptions.get(i); System.out.println(); System.out.println("##"); System.out.println("## Javascript Exception #" + (i + 1)); System.out.println("##"); System.out.println(); System.out.println(liferayException.getMessage()); System.out.println(); } throw new Exception(sb.toString()); } } public static void assertNoLiferayExceptions() throws Exception { if (!_liferayExceptions.isEmpty()) { StringBuilder sb = new StringBuilder(); sb.append(_liferayExceptions.size()); sb.append(" Liferay Exception"); if (_liferayExceptions.size() > 1) { sb.append("s were"); } else { sb.append(" was"); } sb.append(" thrown"); System.out.println(); System.out.println("##"); System.out.println("## " + sb.toString()); System.out.println("##"); for (int i = 0; i < _liferayExceptions.size(); i++) { Exception liferayException = _liferayExceptions.get(i); System.out.println(); System.out.println("##"); System.out.println("## Liferay Exception #" + (i + 1)); System.out.println("##"); System.out.println(); System.out.println(liferayException.getMessage()); System.out.println(); } throw new Exception(sb.toString()); } } public static void assertNoPoshiWarnings() throws Exception { if (!PropsValues.TEST_ASSERT_WARNING_EXCEPTIONS) { return; } StringBuilder sb = new StringBuilder(); if (!_javaScriptExceptions.isEmpty()) { sb.append("\n"); sb.append("##\n"); sb.append("## "); sb.append(_javaScriptExceptions.size()); sb.append(" Javascript Exception"); if (_javaScriptExceptions.size() > 1) { sb.append("s were"); } else { sb.append(" was"); } sb.append(" thrown\n"); sb.append("##\n"); sb.append("\n"); for (int i = 0; i < _javaScriptExceptions.size(); i++) { Exception exception = _javaScriptExceptions.get(i); sb.append(exception.getMessage()); sb.append("\n"); } sb.append("\n"); } if (!_liferayExceptions.isEmpty()) { sb.append("\n"); sb.append("##\n"); sb.append("## "); sb.append(_liferayExceptions.size()); sb.append(" Liferay Exception"); if (_liferayExceptions.size() > 1) { sb.append("s were"); } else { sb.append(" was"); } sb.append(" thrown\n"); sb.append("##\n"); sb.append("\n"); for (int i = 0; i < _liferayExceptions.size(); i++) { Exception exception = _liferayExceptions.get(i); sb.append(exception.getMessage()); sb.append("\n"); } sb.append("\n"); } if (Validator.isNotNull(sb.toString())) { throw new Exception(sb.toString()); } } public static void captureScreen(String fileName) throws Exception { if (!PropsValues.SAVE_SCREENSHOT) { return; } File file = new File(fileName); file.mkdirs(); Robot robot = new Robot(); Toolkit toolkit = Toolkit.getDefaultToolkit(); Rectangle rectangle = new Rectangle(toolkit.getScreenSize()); BufferedImage bufferedImage = robot.createScreenCapture(rectangle); ImageIO.write(bufferedImage, "jpg", file); } public static void connectToEmailAccount( String emailAddress, String emailPassword) throws Exception { EmailCommands.connectToEmailAccount(emailAddress, emailPassword); } public static void deleteAllEmails() throws Exception { EmailCommands.deleteAllEmails(); } public static void echo(String message) { System.out.println(message); } public static void fail(String message) { TestCase.fail(message); } public static String getEmailBody(String index) throws Exception { return EmailCommands.getEmailBody(GetterUtil.getInteger(index)); } public static String getEmailSubject(String index) throws Exception { return EmailCommands.getEmailSubject(GetterUtil.getInteger(index)); } public static ImageTarget getImageTarget( LiferaySelenium liferaySelenium, String image) throws Exception { String filePath = FileUtil.getSeparator() + liferaySelenium.getSikuliImagesDirName() + image; File file = new File(getSourceDirFilePath(filePath)); return new ImageTarget(file); } public static String getNumberDecrement(String value) { return StringUtil.valueOf(GetterUtil.getInteger(value) - 1); } public static String getNumberIncrement(String value) { return StringUtil.valueOf(GetterUtil.getInteger(value) + 1); } public static String getSourceDirFilePath(String fileName) throws Exception { List<String> filePaths = new ArrayList<>(); List<String> baseDirNames = new ArrayList<>(); baseDirNames.add(PropsValues.TEST_BASE_DIR_NAME); if (Validator.isNotNull(PropsValues.TEST_INCLUDE_DIR_NAMES)) { Collections.addAll( baseDirNames, PropsValues.TEST_INCLUDE_DIR_NAMES); } if (Validator.isNotNull(PropsValues.TEST_SUBREPO_DIRS)) { Collections.addAll(baseDirNames, PropsValues.TEST_SUBREPO_DIRS); } for (String baseDirName : baseDirNames) { String filePath = PoshiRunnerGetterUtil.getCanonicalPath( baseDirName + FileUtil.getSeparator() + fileName); if (FileUtil.exists(filePath)) { filePaths.add(filePath); } } if (filePaths.size() > 1) { StringBuilder sb = new StringBuilder(); sb.append("Duplicate file names found!\n"); for (String filePath : filePaths) { sb.append(filePath); sb.append("\n"); } throw new Exception(sb.toString()); } else if (filePaths.isEmpty()) { throw new Exception("File not found " + fileName); } return filePaths.get(0); } public static String getTestConsoleLogFileContent() throws Exception { Map<String, File> consoleLogFiles = new TreeMap<>(); DirectoryScanner directoryScanner = new DirectoryScanner(); directoryScanner.setIncludes( new String[] {PropsValues.TEST_CONSOLE_LOG_FILE_NAME}); directoryScanner.scan(); for (String filePath : directoryScanner.getIncludedFiles()) { if (OSDetector.isWindows()) { filePath = filePath.replace("/", "\\"); } File file = new File(filePath); consoleLogFiles.put(Long.toString(file.lastModified()), file); } StringBuilder sb = new StringBuilder(); SortedSet<String> keys = new TreeSet<>(consoleLogFiles.keySet()); for (String key : keys) { File file = consoleLogFiles.get(key); sb.append(FileUtil.read(file)); } return sb.toString(); } public static boolean isConsoleTextPresent(String text) throws Exception { String content = getTestConsoleLogFileContent(); if (content.equals("")) { return false; } SAXReader saxReader = new SAXReader(); content = "<log4j>" + content + "</log4j>"; content = content.replaceAll("log4j:", ""); InputStream inputStream = new ByteArrayInputStream( content.getBytes("UTF-8")); Document document = saxReader.read(inputStream); Element rootElement = document.getRootElement(); List<Element> eventElements = rootElement.elements("event"); for (Element eventElement : eventElements) { Element messageElement = eventElement.element("message"); String messageText = messageElement.getText(); Pattern pattern = Pattern.compile(text); Matcher matcher = pattern.matcher(messageText); if (matcher.find()) { return true; } } return false; } public static boolean isIgnorableErrorLine(String line) throws Exception { if (isInIgnoreErrorsFile(line, "log")) { return true; } if (Objects.equals(PropsValues.LIFERAY_PORTAL_BUNDLE, "6.2.10.1") || Objects.equals(PropsValues.LIFERAY_PORTAL_BUNDLE, "6.2.10.2") || Objects.equals(PropsValues.LIFERAY_PORTAL_BUNDLE, "6.2.10.3") || Objects.equals(PropsValues.LIFERAY_PORTAL_BUNDLE, "6.2.10.4") || Objects.equals(PropsValues.LIFERAY_PORTAL_BRANCH, "ee-6.2.10")) { if (line.contains( "com.liferay.portal.kernel.search.SearchException: " + "java.nio.channels.ClosedByInterruptException")) { return true; } if (line.contains( "org.apache.lucene.store.AlreadyClosedException")) { return true; } } if (Validator.isNotNull(PropsValues.IGNORE_ERRORS)) { if (Validator.isNotNull(PropsValues.IGNORE_ERRORS_DELIMITER)) { String ignoreErrorsDelimiter = PropsValues.IGNORE_ERRORS_DELIMITER; if (ignoreErrorsDelimiter.equals("|")) { ignoreErrorsDelimiter = "\\|"; } String[] ignoreErrors = PropsValues.IGNORE_ERRORS.split( ignoreErrorsDelimiter); for (String ignoreError : ignoreErrors) { if (line.contains(ignoreError)) { return true; } } } else if (line.contains(PropsValues.IGNORE_ERRORS)) { return true; } } return false; } public static boolean isInIgnoreErrorsFile(String line, String errorType) throws Exception { if (Validator.isNotNull(PropsValues.IGNORE_ERRORS_FILE_NAME)) { SAXReader saxReader = new SAXReader(); String content = FileUtil.read(PropsValues.IGNORE_ERRORS_FILE_NAME); InputStream inputStream = new ByteArrayInputStream( content.getBytes("UTF-8")); Document document = saxReader.read(inputStream); Element rootElement = document.getRootElement(); Element errorTypeElement = rootElement.element(errorType); if (errorTypeElement == null) { return false; } List<Element> ignoreErrorElements = errorTypeElement.elements( "ignore-error"); for (Element ignoreErrorElement : ignoreErrorElements) { Element containsElement = ignoreErrorElement.element( "contains"); Element matchesElement = ignoreErrorElement.element("matches"); String containsText = containsElement.getText(); String matchesText = matchesElement.getText(); if (Validator.isNotNull(containsText) && Validator.isNotNull(matchesText)) { if (line.contains(containsText) && line.matches(matchesText)) { return true; } } else if (Validator.isNotNull(containsText)) { if (line.contains(containsText)) { return true; } } else if (Validator.isNotNull(matchesText)) { if (line.matches(matchesText)) { return true; } } } } return false; } public static void pause(String waitTime) throws Exception { Thread.sleep(GetterUtil.getInteger(waitTime)); } public static void printJavaProcessStacktrace() throws Exception { if (Validator.isNull(PropsValues.PRINT_JAVA_PROCESS_ON_FAIL)) { return; } String line = null; String pid = null; BufferedReader bufferedReader = _execute("jps"); while ((line = bufferedReader.readLine()) != null) { System.out.println(line); if (line.contains(PropsValues.PRINT_JAVA_PROCESS_ON_FAIL)) { pid = line.substring(0, line.indexOf(" ")); System.out.println( PropsValues.PRINT_JAVA_PROCESS_ON_FAIL + " PID: " + pid); } } if (Validator.isNotNull(pid)) { bufferedReader = _execute("jstack -l " + pid); while ((line = bufferedReader.readLine()) != null) { System.out.println(line); } } } public static void selectFieldText() { Keyboard keyboard = new DesktopKeyboard(); keyboard.keyDown(KeyEvent.VK_CONTROL); keyboard.type("a"); keyboard.keyUp(KeyEvent.VK_CONTROL); } public static void typeScreen(String value) { Keyboard keyboard = new DesktopKeyboard(); keyboard.type(value); } public static void writePoshiWarnings() throws Exception { StringBuilder sb = new StringBuilder(); if (!_javaScriptExceptions.isEmpty()) { for (int i = 0; i < _javaScriptExceptions.size(); i++) { Exception exception = _javaScriptExceptions.get(i); sb.append("<value><![CDATA["); sb.append(exception.getMessage()); sb.append("]]></value>\n"); } } if (!_liferayExceptions.isEmpty()) { for (int i = 0; i < _liferayExceptions.size(); i++) { Exception exception = _liferayExceptions.get(i); sb.append("<value><![CDATA["); sb.append(exception.getMessage()); sb.append("]]></value>\n"); } } FileUtil.write( PropsValues.TEST_POSHI_WARNINGS_FILE_NAME, sb.toString()); } private static BufferedReader _execute(String command) throws Exception { String[] runCommand; if (!OSDetector.isWindows()) { runCommand = new String[] {"/bin/bash", "-c", command}; } else { runCommand = new String[] {"cmd", "/c", command}; } Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(runCommand); InputStreamReader inputStreamReader = new InputStreamReader( process.getInputStream()); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); return bufferedReader; } private static final List<String> _errorTimestamps = new ArrayList<>(); private static final List<Exception> _javaScriptExceptions = new ArrayList<>(); private static final List<Exception> _liferayExceptions = new ArrayList<>(); }