package deleteme;

import org.junit.Assert;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.Runner;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;

public class PrintlnTestRunner extends Runner {
	private Class<?> clazz;
	
	public PrintlnTestRunner(Class<?> clazz) {
		this.clazz = clazz;
	}

	@Override
	public Description getDescription() {
		Description parent = Description.createSuiteDescription(clazz);
		PrintlnStrings printLnStrings = clazz.getAnnotation(PrintlnStrings.class);
		for (String printMe : printLnStrings.value()) {
			String name = "Testing println for value " + printMe;
			Description child = Description.createTestDescription(clazz, name);
			parent.addChild(child);
		}
		return parent;
	}
	
	@Override
	public void run(RunNotifier notifier) {
		Description parent = getDescription();
		PrintlnStrings printLnStrings = clazz.getAnnotation(PrintlnStrings.class);
		
		Result result = new Result();
		notifier.fireTestRunStarted(parent);
		for (int i = 0; i < printLnStrings.value().length; ++ i) {
			String printMe = printLnStrings.value()[i];
			Description child = parent.getChildren().get(i);
			
			internalRun(child, notifier, result, printMe);
		}
		notifier.fireTestRunFinished(result);
	}
	
	
	protected void internalRun(Description description, RunNotifier notifier, Result result, String printMe) {
		try {
			notifier.fireTestStarted(description);
			if ("exception".equals(printMe)) {
				throw new Exception("Test exception");
			} else if ("fail".equals(printMe)) {
				Assert.fail();
			}
			System.out.println(printMe);
		} catch (Throwable e) {
			Failure failure = new Failure(description, e);
			notifier.fireTestFailure(failure);
			result.getFailures().add(failure);
		} finally {
			notifier.fireTestFinished(description);
		}
	}
}
