package org.testng; import org.testng.collections.Lists; import org.testng.collections.Maps; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Vector; /** * This class is used for test methods to log messages that will be * included in the HTML reports generated by TestNG. * <br> * <br> * <b>Implementation details.</b> * <br> * <br> * The reporter keeps a combined output of strings (in m_output) and also * a record of which method output which line. In order to do this, callers * specify what the current method is with setCurrentMethod() and the * Reporter maintaing a mapping of each method with a list of integers. * These integers are indices in the combined output (avoids duplicating * the output). * * Created on Nov 2, 2005 * @author cbeust */ public class Reporter { // when tests are run in parallel, each thread may be working with different // 'current test result'. Also, this value should be inherited if the test code // spawns its own thread. private static ThreadLocal<ITestResult> m_currentTestResult = new InheritableThreadLocal<ITestResult>(); /** * All output logged in a sequential order. */ private static List<String> m_output = new Vector<String>(); private static Map<ITestResult, List<Integer>> m_methodOutputMap = Maps.newHashMap(); public static void setCurrentTestResult(ITestResult m) { m_currentTestResult.set(m); } public static List<String> getOutput() { return m_output; } /** * Erase the content of all the output generated so far. */ public static void clear() { m_methodOutputMap.clear(); m_output.clear(); } private static synchronized void log(String s, ITestResult m) { // synchronization needed to ensure the line number and m_output are updated atomically int n = getOutput().size(); List<Integer> lines = m_methodOutputMap.get(m); if (lines == null) { lines = Lists.newArrayList(); m_methodOutputMap.put(m, lines); } lines.add(n); getOutput().add(s); } /** * Log the passed string to the HTML reports * @param s The message to log */ public static void log(String s) { log(s, getCurrentTestResult()); } /** * Log the passed string to the HTML reports if the current verbosity * is equal or greater than the one passed in parameter. If logToStandardOut * is true, the string will also be printed on standard out. * * @param s The message to log * @param level The verbosity of this message * @param logToStandardOut Whether to print this string on standard * out too */ public static void log(String s, int level, boolean logToStandardOut) { if (TestRunner.getVerbose() >= level) { log(s, getCurrentTestResult()); if (logToStandardOut) { System.out.println(s); } } } /** * Log the passed string to the HTML reports. If logToStandardOut * is true, the string will also be printed on standard out. * * @param s The message to log * @param logToStandardOut Whether to print this string on standard * out too */ public static void log(String s, boolean logToStandardOut) { log(s, getCurrentTestResult()); if (logToStandardOut) { System.out.println(s); } } /** * Log the passed string to the HTML reports if the current verbosity * is equal or greater than the one passed in parameter * * @param s The message to log * @param level The verbosity of this message */ public static void log(String s, int level) { if (TestRunner.getVerbose() >= level) { log(s, getCurrentTestResult()); } } public static ITestResult getCurrentTestResult() { return m_currentTestResult.get(); } private static void ppp(String s) { System.out.println("[Reporter] " + s); } public static synchronized List<String> getOutput(ITestResult tr) { List<String> result = Lists.newArrayList(); List<Integer> lines = m_methodOutputMap.get(tr); if (lines != null) { for (Integer n : lines) { result.add(getOutput().get(n)); } } return result; } // public static void setCurrentOutput(List<String> tmr) { // m_output = tmr; //// m_localResult.set(tmr); // } // public static List<String> getCurrentOutput() { // return m_output; //// List<String> result = (List<String>) m_localResult.get(); //// return result; // } }