package jp.gr.java_conf.daisy.ajax_mutator;

import org.junit.Test;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * TestExecutor for testclasses written in Junit4.
 *
 * @author Kazuki Nishiura
 */
public class JUnitExecutor implements TestExecutor {
    Class<?>[] targetClasses;
    String executionMessage;

    public JUnitExecutor(Class<?>... targetClasses) {
        this.targetClasses = targetClasses;
    }

    @Override
    public boolean execute() {
        JUnitCore core = new JUnitCore();
        Result result = core.run(targetClasses);
        List<String> testMethods = new ArrayList<String>();
        for (Class<?> clazz: targetClasses) {
            for (Method method: clazz.getMethods()) {
                if (method.isAnnotationPresent(Test.class))
                    testMethods.add(method.getName());
            }
        }
        Map<String, Boolean> testSucceed = new TreeMap<String, Boolean>();
        for (String methodName: testMethods)
            testSucceed.put(methodName, true);

        StringBuilder messageBuilder = new StringBuilder();
        if (result.wasSuccessful()) {
            messageBuilder.append("Test succeed (failed to kill mutants), ")
                .append(result.getRunCount()).append(" tests ran.\n");
            for (int i = 0; i < testSucceed.size(); i++)
                messageBuilder.append("x ");
            messageBuilder.append("x");
            executionMessage = messageBuilder.toString();
            return true;
        } else {
            messageBuilder.append(result.getFailureCount())
                .append(" tests failed within ").append(result.getRunCount())
                .append('\n');
            for (Failure failure: result.getFailures()) {
                if (failure.getDescription().getMethodName() == null) {
                    testSucceed.put("setup or teardown", false);
                    continue;
                }
                testSucceed.put(failure.getDescription().getMethodName(), false);
            }
            for (Map.Entry<String, Boolean> entry: testSucceed.entrySet())
                messageBuilder.append(entry.getValue() ? 'x' : 'o').append(' ');
            messageBuilder.append("o");
            executionMessage = messageBuilder.toString();
            return false;
        }
    }

    @Override
    public String getMessageOnLastExecution() {
        return executionMessage;
    }
}

@@ -1083,23 +1083,23 @@
 an%3E test
-Succeed
+Results
  = new T
@@ -1182,31 +1182,31 @@
         test
-Succeed
+Results
 .put(methodN
@@ -1485,92 +1485,155 @@
 or (
-int i = 0; i %3C testSucceed.size(); i++)%0A                messageBuilder.append(%22x %22);
+Map.Entry%3CString, Boolean%3E testResult: testResults.entrySet()) %7B%0A                messageBuilder.append(testResult.getKey() + %22:x, %22);%0A            %7D
 %0A   
@@ -1664,16 +1664,24 @@
 append(%22
+result: 
 x%22);%0A   
@@ -2096,31 +2096,31 @@
         test
-Succeed
+Results
 .put(%22setup 
@@ -2209,23 +2209,23 @@
     test
-Succeed
+Results
 .put(fai
@@ -2344,15 +2344,15 @@
 test
-Succeed
+Results
 .ent
@@ -2355,24 +2355,26 @@
 .entrySet())
+ %7B
 %0A           
@@ -2384,32 +2384,92 @@
   messageBuilder
+.append(entry.getKey()).append(':')%0A                        
 .append(entry.ge
@@ -2501,13 +2501,28 @@
 end(
-' ');
+%22, %22);%0A            %7D
 %0A   
@@ -2553,16 +2553,24 @@
 append(%22
+result: 
 o%22);%0A   

Put method name besides test results on JUnitExecutor