package com.sandwich.koan.runner; import static com.sandwich.koan.constant.KoanConstants.EOLS; import static com.sandwich.koan.constant.KoanConstants.EXPECTATION_LEFT_ARG; import static com.sandwich.koan.constant.KoanConstants.EXPECTED_LEFT; import static com.sandwich.koan.constant.KoanConstants.EXPECTED_RIGHT; import static com.sandwich.koan.constant.KoanConstants.__; import java.lang.reflect.Method; import java.util.logging.Logger; import com.sandwich.koan.KoanIncompleteException; import com.sandwich.koan.KoanMethod; import com.sandwich.koan.cmdline.CommandLineArgumentRunner; import com.sandwich.koan.constant.KoanConstants; import com.sandwich.koan.result.KoanMethodResult; import com.sandwich.util.ExceptionUtils; import com.sandwich.util.Strings; import com.sandwich.util.io.directories.DirectoryManager; import com.sandwich.util.io.filecompiler.CompilerConfig; import com.sandwich.util.io.filecompiler.FileCompiler; public class KoanMethodRunner { private static final String EXPECTED_PROPERTY_KEY = "expected"; public static KoanMethodResult run(Object suite, KoanMethod koan){ try { Method method = koan.getMethod(); method.setAccessible(true); method.invoke(suite); } catch (Throwable t) { Throwable tempException = t; String message = ExceptionUtils.convertToPopulatedStackTraceString(t); while(tempException != null){ if(tempException instanceof KoanIncompleteException){ t = (KoanIncompleteException)tempException; message = t.getMessage(); if(message.contains(Strings.getMessage(EXPECTED_PROPERTY_KEY) + EXPECTED_LEFT + __ + EXPECTED_RIGHT)) { logExpectationOnWrongSideWarning(suite.getClass(), koan.getMethod()); } break; } tempException = tempException.getCause(); } return new KoanMethodResult(koan, message, getOriginalLineNumber(t, suite.getClass())); } return KoanMethodResult.PASSED; } private static void logExpectationOnWrongSideWarning(Class<?> firstFailingSuite, Method firstFailingMethod) { Logger.getLogger(CommandLineArgumentRunner.class.getSimpleName()).severe( new StringBuilder( firstFailingSuite.getSimpleName()).append( ".").append( firstFailingMethod.getName()).append( " ").append( EXPECTATION_LEFT_ARG).toString()); } /** * Return the line number found closest to the point of failure, with a reference to the * failing suite's classname. * * @param t * @param failingSuite * @return */ static String getOriginalLineNumber(Throwable t, Class<?> failingSuite){ if(failingSuite != null && CompilerConfig.getSuffix(FileCompiler.getSourceFileFromClass(DirectoryManager.getSourceDir(), failingSuite.getName()).getAbsolutePath()) .equals(".java")){ String[] lines = ExceptionUtils.convertToPopulatedStackTraceString(t).split(EOLS); for(int i = lines.length - 1; i >= 0; --i){ String line = lines[i]; if(line.contains(failingSuite.getName())){ int start = line.indexOf(KoanConstants.LINE_NO_START)+KoanConstants.LINE_NO_START.length(); int end = line.lastIndexOf(KoanConstants.LINE_NO_END); end = end > line.length() ? line.length() : end; return line.substring(start, end); } } } return null; } }