| package org.testng.internal; |
| |
| import java.io.BufferedReader; |
| import java.io.BufferedWriter; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Modifier; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.StringTokenizer; |
| import java.util.logging.FileHandler; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| import org.testng.ITestNGMethod; |
| import org.testng.TestNG; |
| import org.testng.TestNGException; |
| import org.testng.TestRunner; |
| import org.testng.annotations.IConfigurationAnnotation; |
| import org.testng.annotations.ITestAnnotation; |
| import org.testng.collections.Lists; |
| import org.testng.internal.annotations.AnnotationHelper; |
| import org.testng.internal.annotations.IAnnotationFinder; |
| import org.testng.log.TextFormatter; |
| import org.testng.reporters.XMLStringBuffer; |
| import org.testng.xml.XmlClass; |
| |
| /** |
| * Helper methods to parse annotations. |
| * |
| * @author Cedric Beust, Apr 26, 2004 |
| */ |
| public final class Utils { |
| private static final String LINE_SEP = System.getProperty("line.separator"); |
| |
| public static final char[] SPECIAL_CHARACTERS = |
| {'*','/','\\','?','%',':',';','<','>','&','~','|'}; |
| public static final char CHAR_REPLACEMENT = '_'; |
| public static final char UNICODE_REPLACEMENT = 0xFFFD; |
| |
| /** |
| * Hide constructor for utility class. |
| */ |
| private Utils() { |
| // Hide constructor |
| } |
| |
| /** |
| * Splits the given String s into tokens where the separator is |
| * either the space character or the comma character. For example, |
| * if s is "a,b, c" this method returns {"a", "b", "c"} |
| * |
| * @param s the string to split |
| * @return the split token |
| */ |
| public static String[] stringToArray(String s) { |
| // TODO CQ would s.split() be a better way of doing this? |
| StringTokenizer st = new StringTokenizer(s, " ,"); |
| String[] result = new String[st.countTokens()]; |
| for (int i = 0; i < result.length; i++) { |
| result[i] = st.nextToken(); |
| } |
| |
| return result; |
| } |
| |
| public static XmlClass[] classesToXmlClasses(Class<?>[] classes) { |
| List<XmlClass> result = Lists.newArrayList(); |
| |
| for (Class<?> cls : classes) { |
| result.add(new XmlClass(cls, true /* load classes */)); |
| } |
| |
| return result.toArray(new XmlClass[classes.length]); |
| } |
| |
| public static String[] parseMultiLine(String line) { |
| List<String> vResult = Lists.newArrayList(); |
| if (isStringNotBlank(line)) { |
| StringTokenizer st = new StringTokenizer(line, " "); |
| while (st.hasMoreTokens()) { |
| vResult.add(st.nextToken()); |
| } |
| // Bug in split when passed " " : returns one too many result |
| // result = line.split(" "); |
| } |
| |
| return vResult.toArray(new String[vResult.size()]); |
| } |
| |
| public static void writeUtf8File(@Nullable String outputDir, String fileName, XMLStringBuffer xsb, String prefix) { |
| try { |
| final File outDir = (outputDir != null) ? new File(outputDir) : new File("").getAbsoluteFile(); |
| if (!outDir.exists()) { |
| outDir.mkdirs(); |
| } |
| final File file = new File(outDir, fileName); |
| if (!file.exists()) { |
| file.createNewFile(); |
| } |
| final OutputStreamWriter w = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); |
| if (prefix != null) { |
| w.append(prefix); |
| } |
| xsb.toWriter(w); |
| w.close(); |
| } catch(IOException ex) { |
| ex.printStackTrace(); |
| } |
| } |
| |
| /** |
| * Writes the content of the sb string to the file named filename in outDir encoding the output as UTF-8. |
| * If outDir does not exist, it is created. |
| * |
| * @param outputDir the output directory (may not exist). If <tt>null</tt> then current directory is used. |
| * @param fileName the filename |
| * @param sb the file content |
| */ |
| public static void writeUtf8File(@Nullable String outputDir, String fileName, String sb) { |
| final String outDirPath= outputDir != null ? outputDir : ""; |
| final File outDir= new File(outDirPath); |
| writeFile(outDir, fileName, escapeUnicode(sb), "UTF-8", false /* don't append */); |
| } |
| |
| /** |
| * Writes the content of the sb string to the file named filename in outDir. If |
| * outDir does not exist, it is created. |
| * |
| * @param outputDir the output directory (may not exist). If <tt>null</tt> then current directory is used. |
| * @param fileName the filename |
| * @param sb the file content |
| */ |
| public static void writeFile(@Nullable String outputDir, String fileName, String sb) { |
| final String outDirPath= outputDir != null ? outputDir : ""; |
| final File outDir= new File(outDirPath); |
| writeFile(outDir, fileName, sb, null, false /* don't append */); |
| } |
| |
| /** |
| * Writes the content of the sb string to the file named filename in outDir. If |
| * outDir does not exist, it is created. |
| * |
| * @param outDir the output directory (may not exist). If <tt>null</tt> then current directory is used. |
| * @param fileName the filename |
| * @param sb the file content |
| */ |
| private static void writeFile(@Nullable File outDir, String fileName, String sb, @Nullable String encoding, boolean append) { |
| try { |
| if (outDir == null) { |
| outDir = new File("").getAbsoluteFile(); |
| } |
| if (!outDir.exists()) { |
| outDir.mkdirs(); |
| } |
| |
| fileName = replaceSpecialCharacters(fileName); |
| File outputFile = new File(outDir, fileName); |
| if (!append) { |
| outputFile.delete(); |
| outputFile.createNewFile(); |
| } |
| writeFile(outputFile, sb, encoding, append); |
| } |
| catch (IOException e) { |
| if (TestRunner.getVerbose() > 1) { |
| e.printStackTrace(); |
| } |
| else { |
| log("[Utils]", 1, e.getMessage()); |
| } |
| } |
| } |
| |
| private static void writeFile(File outputFile, String sb, @Nullable String encoding, boolean append) { |
| BufferedWriter fw = null; |
| try { |
| fw = openWriter(outputFile, encoding, append); |
| fw.write(sb); |
| |
| Utils.log("", 3, "Creating " + outputFile.getAbsolutePath()); |
| } |
| catch(IOException ex) { |
| if (TestRunner.getVerbose() > 1) { |
| System.err.println("ERROR WHILE WRITING TO " + outputFile); |
| ex.printStackTrace(); |
| } |
| else { |
| log("[Utils]", 1, "Error while writing to " + outputFile + ": " + ex.getMessage()); |
| } |
| } |
| finally { |
| try { |
| if (fw != null) { |
| fw.close(); |
| } |
| } |
| catch (IOException e) { |
| ; // ignore |
| } |
| } |
| } |
| |
| /** |
| * Open a BufferedWriter for the specified file. If output directory doesn't |
| * exist, it is created. If the output file exists, it is deleted. The output file is |
| * created in any case. |
| * @param outputDir output directory. If <tt>null</tt>, then current directory is used |
| * @param fileName file name |
| * @throws IOException if anything goes wrong while creating files. |
| */ |
| public static BufferedWriter openWriter(@Nullable String outputDir, String fileName) throws IOException { |
| String outDirPath= outputDir != null ? outputDir : ""; |
| File outDir= new File(outDirPath); |
| if (outDir.exists()) { |
| outDir.mkdirs(); |
| } |
| fileName = replaceSpecialCharacters(fileName); |
| File outputFile = new File(outDir, fileName); |
| outputFile.delete(); |
| return openWriter(outputFile, null, false); |
| } |
| |
| private static BufferedWriter openWriter(File outputFile, @Nullable String encoding, boolean append) throws IOException { |
| if (!outputFile.exists()) { |
| outputFile.createNewFile(); |
| } |
| OutputStreamWriter osw= null; |
| if (null != encoding) { |
| osw = new OutputStreamWriter(new FileOutputStream(outputFile, append), encoding); |
| } |
| else { |
| osw = new OutputStreamWriter(new FileOutputStream(outputFile, append)); |
| } |
| return new BufferedWriter(osw); |
| } |
| |
| private static void ppp(String s) { |
| Utils.log("Utils", 0, s); |
| } |
| |
| /** |
| * @param result |
| */ |
| public static void dumpMap(Map<?, ?> result) { |
| System.out.println("vvvvv"); |
| for (Map.Entry<?, ?> entry : result.entrySet()) { |
| System.out.println(entry.getKey() + " => " + entry.getValue()); |
| } |
| System.out.println("^^^^^"); |
| } |
| |
| /** |
| * @param allMethods |
| */ |
| public static void dumpMethods(List<ITestNGMethod> allMethods) { |
| ppp("======== METHODS:"); |
| for (ITestNGMethod tm : allMethods) { |
| ppp(" " + tm); |
| } |
| } |
| |
| /** |
| * @return The list of dependent groups for this method, including the |
| * class groups |
| */ |
| public static String[] dependentGroupsForThisMethodForTest(Method m, IAnnotationFinder finder) { |
| List<String> vResult = Lists.newArrayList(); |
| Class<?> cls = m.getDeclaringClass(); |
| |
| // Collect groups on the class |
| ITestAnnotation tc = AnnotationHelper.findTest(finder, cls); |
| if (null != tc) { |
| for (String group : tc.getDependsOnGroups()) { |
| vResult.add(group); |
| } |
| } |
| |
| // Collect groups on the method |
| ITestAnnotation tm = AnnotationHelper.findTest(finder, m); |
| if (null != tm) { |
| String[] groups = tm.getDependsOnGroups(); |
| |
| // ppp("Method:" + m + " #Groups:" + groups.length); |
| for (String group : groups) { |
| vResult.add(group); |
| } |
| } |
| |
| return vResult.toArray(new String[vResult.size()]); |
| } |
| |
| /** |
| * @return The list of groups this method belongs to, including the |
| * class groups |
| */ |
| public static String[] groupsForThisMethodForTest(Method m, IAnnotationFinder finder) { |
| List<String> vResult = Lists.newArrayList(); |
| Class<?> cls = m.getDeclaringClass(); |
| |
| // Collect groups on the class |
| ITestAnnotation tc = AnnotationHelper.findTest(finder, cls); |
| if (null != tc) { |
| for (String group : tc.getGroups()) { |
| vResult.add(group); |
| } |
| } |
| |
| // Collect groups on the method |
| ITestAnnotation tm = AnnotationHelper.findTest(finder, m); |
| if (null != tm) { |
| String[] groups = tm.getGroups(); |
| |
| // ppp("Method:" + m + " #Groups:" + groups.length); |
| for (String group : groups) { |
| vResult.add(group); |
| } |
| } |
| |
| return vResult.toArray(new String[vResult.size()]); |
| } |
| |
| /** |
| * @return The list of groups this method belongs to, including the |
| * class groups |
| */ |
| public static String[] groupsForThisMethodForConfiguration(Method m, IAnnotationFinder finder) { |
| String[] result = {}; |
| |
| // Collect groups on the method |
| ITestAnnotation tm = AnnotationHelper.findTest(finder, m); |
| if (null != tm) { |
| result = tm.getGroups(); |
| } |
| |
| return result; |
| } |
| |
| /** |
| * @return The list of groups this method depends on, including the |
| * class groups |
| */ |
| public static String[] dependentGroupsForThisMethodForConfiguration(Method m, |
| IAnnotationFinder finder) { |
| String[] result = {}; |
| |
| // Collect groups on the method |
| IConfigurationAnnotation tm = AnnotationHelper.findConfiguration(finder, m); |
| if (null != tm) { |
| result = tm.getDependsOnGroups(); |
| } |
| |
| return result; |
| } |
| |
| public static void log(String msg) { |
| log("Utils", 2, msg); |
| } |
| |
| /** |
| * Logs the the message to System.out if level is greater than |
| * or equal to TestRunner.getVerbose(). The message is logged as: |
| * <pre> |
| * "[cls] msg" |
| * </pre> |
| * |
| * @param cls the class name to prefix the log message. |
| * @param level the logging level of the message. |
| * @param msg the message to log to System.out. |
| */ |
| public static void log(String cls, int level, String msg) { |
| // Why this coupling on a static member of TestRunner.getVerbose()? |
| if (TestRunner.getVerbose() >= level) { |
| if (cls.length() > 0) { |
| System.out.println("[" + cls + "] " + msg); |
| } |
| else { |
| System.out.println(msg); |
| } |
| } |
| } |
| |
| public static void error(String errorMessage) { |
| System.err.println("[Error] " + errorMessage); |
| } |
| |
| /** |
| * @return The number of methods invoked, taking into account the number |
| * of instances. |
| */ |
| // public static int calculateInvokedMethodCount(IResultMap map) { |
| // return calculateInvokedMethodCount( |
| // (ITestNGMethod[]) map.getAllMethods().toArray(new ITestNGMethod[map.size()])); |
| // } |
| |
| public static int calculateInvokedMethodCount(ITestNGMethod[] methods) { |
| return methods.length; |
| // int result = 0; |
| // |
| // for (ITestNGMethod method : methods) { |
| // int instanceCount = method.getInvocationCount(); |
| // result += instanceCount; |
| // } |
| // |
| // return result; |
| } |
| |
| // public static int calculateInvokedMethodCount(Map<ITestNGMethod, ITestResult> methods) { |
| // return calculateInvokedMethodCount(methods.keySet().toArray(new ITestNGMethod[methods.values() |
| // .size()])); |
| // } |
| |
| /** |
| * Tokenize the string using the separator. |
| */ |
| public static String[] split(String string, String sep) { |
| if ((string == null) || (string.length() == 0)) { |
| return new String[0]; |
| } |
| |
| // TODO How different is this from: |
| // return string.split(sep); |
| |
| int start = 0; |
| int idx = string.indexOf(sep, start); |
| int len = sep.length(); |
| List<String> strings = Lists.newArrayList(); |
| |
| while (idx != -1) { |
| strings.add(string.substring(start, idx).trim()); |
| start = idx + len; |
| idx = string.indexOf(sep, start); |
| } |
| |
| strings.add(string.substring(start).trim()); |
| |
| return strings.toArray(new String[strings.size()]); |
| } |
| |
| public static void initLogger(Logger logger, String outputLogPath) { |
| try { |
| logger.setUseParentHandlers(false); |
| FileHandler fh = new FileHandler(outputLogPath); |
| fh.setFormatter(new TextFormatter()); |
| fh.setLevel(Level.INFO); |
| logger.addHandler(fh); |
| } |
| catch (SecurityException | IOException se) { |
| se.printStackTrace(); |
| } |
| } |
| |
| public static void logInvocation(String reason, Method thisMethod, Object[] parameters) { |
| String clsName = thisMethod.getDeclaringClass().getName(); |
| int n = clsName.lastIndexOf("."); |
| if (n >= 0) { |
| clsName = clsName.substring(n + 1); |
| } |
| String methodName = clsName + '.' + thisMethod.getName(); |
| if (TestRunner.getVerbose() >= 2) { |
| StringBuffer paramString = new StringBuffer(); |
| if (parameters != null) { |
| for (Object p : parameters) { |
| paramString.append(p.toString()).append(' '); |
| } |
| } |
| log("", 2, "Invoking " + reason + methodName + '(' + paramString + ')'); |
| } |
| } |
| |
| public static void writeResourceToFile(File file, String resourceName, Class<?> clasz) throws IOException { |
| InputStream inputStream = clasz.getResourceAsStream("/" + resourceName); |
| if (inputStream == null) { |
| System.err.println("Couldn't find resource on the class path: " + resourceName); |
| // throw new IllegalArgumentException("Resource does not exist: " + resourceName); |
| } |
| |
| else { |
| |
| try { |
| FileOutputStream outputStream = new FileOutputStream(file); |
| try { |
| int nread; |
| byte[] buffer = new byte[4096]; |
| while (0 < (nread = inputStream.read(buffer))) { |
| outputStream.write(buffer, 0, nread); |
| } |
| } finally { |
| outputStream.close(); |
| } |
| } finally { |
| inputStream.close(); |
| } |
| } |
| } |
| |
| public static String defaultIfStringEmpty(String s, String defaultValue) { |
| return isStringEmpty(s) ? defaultValue : s; |
| } |
| |
| public static boolean isStringBlank(String s) { |
| return s == null || "".equals(s.trim()); |
| } |
| |
| public static boolean isStringEmpty(String s) { |
| return s == null || "".equals(s); |
| } |
| |
| public static boolean isStringNotBlank(String s) { |
| return !isStringBlank(s); |
| } |
| |
| public static boolean isStringNotEmpty(String s) { |
| return !isStringEmpty(s); |
| } |
| |
| /** |
| * @return an array of two strings: the short stack trace and the long stack trace. |
| */ |
| public static String[] stackTrace(Throwable t, boolean toHtml) { |
| StringWriter sw = new StringWriter(); |
| PrintWriter pw = new PrintWriter(sw); |
| t.printStackTrace(pw); |
| pw.flush(); |
| |
| String fullStackTrace = sw.getBuffer().toString(); |
| String shortStackTrace; |
| |
| if (Boolean.getBoolean(TestNG.SHOW_TESTNG_STACK_FRAMES) || TestRunner.getVerbose() >= 2) { |
| shortStackTrace = fullStackTrace; |
| } else { |
| shortStackTrace = filterTrace(sw.getBuffer().toString()); |
| } |
| |
| if (toHtml) { |
| shortStackTrace = escapeHtml(shortStackTrace); |
| fullStackTrace = escapeHtml(fullStackTrace); |
| } |
| |
| return new String[] { |
| shortStackTrace, fullStackTrace |
| }; |
| } |
| |
| private static final Map<Character, String> ESCAPES = new HashMap<Character, String>() { |
| private static final long serialVersionUID = 1285607660247157523L; |
| |
| { |
| put('<', "<"); |
| put('>', ">"); |
| put('\'', "'"); |
| put('"', """); |
| put('&', "&"); |
| }}; |
| |
| public static String escapeHtml(String s) { |
| if (s == null) { |
| return null; |
| } |
| |
| StringBuilder result = new StringBuilder(); |
| |
| for (int i = 0; i < s.length(); i++) { |
| char c = s.charAt(i); |
| String nc = ESCAPES.get(c); |
| if (nc != null) { |
| result.append(nc); |
| } else { |
| result.append(c); |
| } |
| } |
| |
| return result.toString(); |
| } |
| |
| public static String escapeUnicode(String s) { |
| if (s == null) { |
| return null; |
| } |
| |
| StringBuilder result = new StringBuilder(); |
| |
| for (int i = 0; i < s.length(); i++) { |
| char c = s.charAt(i); |
| char ca = (Character.isDefined(c)) ? c: UNICODE_REPLACEMENT; |
| result.append(ca); |
| } |
| |
| return result.toString(); |
| } |
| |
| private static String filterTrace(String trace) { |
| StringReader stringReader = new StringReader(trace); |
| BufferedReader bufferedReader = new BufferedReader(stringReader); |
| StringBuffer buf = new StringBuffer(); |
| |
| try { |
| // first line contains the thrown exception |
| String line = bufferedReader.readLine(); |
| if(line == null) { |
| return ""; |
| } |
| buf.append(line).append(LINE_SEP); |
| |
| // |
| // the stack frames of the trace |
| // |
| String[] excludedStrings = new String[] { |
| "org.testng", |
| "reflect", |
| "org.apache.maven.surefire" |
| }; |
| |
| int excludedCount = 0; |
| while((line = bufferedReader.readLine()) != null) { |
| boolean isExcluded = false; |
| for (String excluded : excludedStrings) { |
| if(line.contains(excluded)) { |
| isExcluded = true; |
| excludedCount++; |
| break; |
| } |
| } |
| if (! isExcluded) { |
| buf.append(line).append(LINE_SEP); |
| } |
| } |
| if (excludedCount > 0) { |
| buf.append("... Removed " + excludedCount + " stack frames"); |
| } |
| } |
| catch(IOException ioex) { |
| ; // do nothing |
| } |
| |
| return buf.toString(); |
| } |
| |
| public static String toString(Object object, Class<?> objectClass) { |
| if(null == object) { |
| return "null"; |
| } |
| final String toString= object.toString(); |
| if(isStringEmpty(toString)) { |
| return "\"\""; |
| } |
| else if (String.class.equals(objectClass)) { |
| return "\"" + toString + '\"'; |
| } |
| else { |
| return toString; |
| } |
| } |
| |
| public static String detailedMethodName(ITestNGMethod method, boolean fqn) { |
| StringBuffer buf= new StringBuffer(); |
| if(method.isBeforeSuiteConfiguration()) { |
| buf.append("@BeforeSuite "); |
| } |
| else if(method.isBeforeTestConfiguration()) { |
| buf.append("@BeforeTest "); |
| } |
| else if(method.isBeforeClassConfiguration()) { |
| buf.append("@BeforeClass "); |
| } |
| else if(method.isBeforeGroupsConfiguration()) { |
| buf.append("@BeforeGroups "); |
| } |
| else if(method.isBeforeMethodConfiguration()) { |
| buf.append("@BeforeMethod "); |
| } |
| else if(method.isAfterMethodConfiguration()) { |
| buf.append("@AfterMethod "); |
| } |
| else if(method.isAfterGroupsConfiguration()) { |
| buf.append("@AfterGroups "); |
| } |
| else if(method.isAfterClassConfiguration()) { |
| buf.append("@AfterClass "); |
| } |
| else if(method.isAfterTestConfiguration()) { |
| buf.append("@AfterTest "); |
| } |
| else if(method.isAfterSuiteConfiguration()) { |
| buf.append("@AfterSuite "); |
| } |
| |
| return buf.append(fqn ? method.toString() : method.getMethodName()).toString(); |
| } |
| |
| public static String arrayToString(String[] strings) { |
| StringBuffer result = new StringBuffer(""); |
| if ((strings != null) && (strings.length > 0)) { |
| for (int i = 0; i < strings.length; i++) { |
| result.append(strings[i]); |
| if (i < strings.length - 1) { |
| result.append(", "); |
| } |
| } |
| } |
| return result.toString(); |
| } |
| |
| /** |
| * If the file name contains special characters like *,/,\ and so on, |
| * exception will be thrown and report file will not be created.<br> |
| * Special characters are platform specific and they are not same for |
| * example on Windows and Macintosh. * is not allowed on Windows, but it is on Macintosh.<br> |
| * In order to have the same behavior of testng on the all platforms, characters like * will |
| * be replaced on all platforms whether they are causing the problem or not. |
| * |
| * @param fileName file name that could contain special characters. |
| * @return fileName with special characters replaced |
| * @author Borojevic |
| */ |
| public static String replaceSpecialCharacters(String fileName) { |
| if (fileName == null || fileName.length() == 0) { |
| return fileName; |
| } |
| for (char element : SPECIAL_CHARACTERS) { |
| fileName = fileName.replace(element, CHAR_REPLACEMENT); |
| } |
| |
| return fileName; |
| } |
| |
| public static <T> String join(List<T> objects, String separator) { |
| StringBuilder result = new StringBuilder(); |
| for (int i = 0; i < objects.size(); i++) { |
| if (i > 0) { |
| result.append(separator); |
| } |
| result.append(objects.get(i).toString()); |
| } |
| return result.toString(); |
| } |
| |
| public static void copyFile(File from, File to) { |
| try (InputStream in = new FileInputStream(from)) { |
| |
| //For Append the file. |
| // OutputStream out = new FileOutputStream(f2,true); |
| |
| //For Overwrite the file. |
| to.getParentFile().mkdirs(); |
| try (OutputStream out = new FileOutputStream(to)) { |
| byte[] buf = new byte[1024]; |
| int len; |
| while ((len = in.read(buf)) > 0) { |
| out.write(buf, 0, len); |
| } |
| } |
| } catch(IOException e){ |
| e.printStackTrace(); |
| } |
| } |
| |
| /** |
| * @return a temporary file with the given content. |
| */ |
| public static File createTempFile(String content) { |
| try { |
| // Create temp file. |
| File result = File.createTempFile("testng-tmp", ""); |
| |
| // Delete temp file when program exits. |
| result.deleteOnExit(); |
| |
| // Write to temp file |
| BufferedWriter out = new BufferedWriter(new FileWriter(result)); |
| out.write(content); |
| out.close(); |
| |
| return result; |
| } catch (IOException e) { |
| throw new TestNGException(e); |
| } |
| } |
| |
| /** |
| * Make sure that either we have an instance or if not, that the method is static |
| */ |
| public static void checkInstanceOrStatic(Object instance, Method method) { |
| if (instance == null && method != null && ! Modifier.isStatic(method.getModifiers())) { |
| throw new TestNGException("Can't invoke " + method + ": either make it static or add " |
| + "a no-args constructor to your class"); |
| } |
| } |
| |
| public static void checkReturnType(Method method, Class<?>... returnTypes) { |
| if (method == null) { |
| return; |
| } |
| for (Class<?> returnType : returnTypes) { |
| if (method.getReturnType() == returnType) { |
| return; |
| } |
| } |
| throw new TestNGException(method.getDeclaringClass().getName() + "." |
| + method.getName() + " MUST return " + toString(returnTypes) + " but returns " + method.getReturnType().getName()); |
| } |
| |
| private static String toString(Class<?>[] classes) { |
| StringBuilder sb = new StringBuilder("[ "); |
| for (int i=0; i<classes.length;) { |
| Class<?> clazz = classes[i]; |
| if (clazz.isArray()) { |
| sb.append(clazz.getComponentType().getName()).append("[]"); |
| } else { |
| sb.append(clazz.getName()); |
| } |
| if (++i < classes.length) { // increment and compare |
| sb.append(" or "); |
| } |
| } |
| sb.append(" ]"); |
| return sb.toString(); |
| } |
| |
| /** |
| * Returns the string representation of the specified object, transparently |
| * handling null references and arrays. |
| * |
| * @param obj |
| * the object |
| * @return the string representation |
| */ |
| public static String toString(Object obj) { |
| String result; |
| if (obj != null) { |
| if (obj instanceof boolean[]) { |
| result = Arrays.toString((boolean[]) obj); |
| } else if (obj instanceof byte[]) { |
| result = Arrays.toString((byte[]) obj); |
| } else if (obj instanceof char[]) { |
| result = Arrays.toString((char[]) obj); |
| } else if (obj instanceof double[]) { |
| result = Arrays.toString((double[]) obj); |
| } else if (obj instanceof float[]) { |
| result = Arrays.toString((float[]) obj); |
| } else if (obj instanceof int[]) { |
| result = Arrays.toString((int[]) obj); |
| } else if (obj instanceof long[]) { |
| result = Arrays.toString((long[]) obj); |
| } else if (obj instanceof Object[]) { |
| result = Arrays.deepToString((Object[]) obj); |
| } else if (obj instanceof short[]) { |
| result = Arrays.toString((short[]) obj); |
| } else { |
| result = obj.toString(); |
| } |
| } else { |
| result = "null"; |
| } |
| return result; |
| } |
| } |