/*
 * This file is covered by the terms of the Common Public License v1.0.
 *
 * Copyright (c) SZEDER Gábor
 *
 * Parts of this software were developed within the JEOPARD research
 * project, which received funding from the European Union's Seventh
 * Framework Programme under grant agreement No. 216682.
 */

package de.fzi.cjunit.runners.statements;

import java.util.ArrayList;
import java.util.List;

import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

import de.fzi.cjunit.runners.model.ConcurrentFrameworkMethod;

import static de.fzi.cjunit.jpf.inside.TestWrapperOptions.*;

import de.fzi.cjunit.jpf.inside.TestWrapper;
import de.fzi.cjunit.jpf.outside.JPFInvoker;
import de.fzi.cjunit.jpf.util.ArgumentCreator;
import de.fzi.cjunit.jpf.util.OnFailurePublisher;
import de.fzi.cjunit.jpf.util.TestReporter;

public class ConcurrentStatement extends Statement {

	protected ConcurrentFrameworkMethod testMethod;
	protected Object target;
	protected List<FrameworkMethod> befores;
	protected List<FrameworkMethod> afters;
	protected Class<? extends Throwable> expectedExceptionClass;

	// for testing
	ConcurrentStatement() {}

	public ConcurrentStatement(ConcurrentFrameworkMethod testMethod,
			Object target) {
		this.testMethod = testMethod;
		this.target = target;
		befores = new ArrayList<FrameworkMethod>();
		afters = new ArrayList<FrameworkMethod>();
	}

	@Override
	public void evaluate() throws Throwable {
		invokeJPF();
	}

	protected void invokeJPF() throws Throwable {
		new JPFInvoker().run(createJPFArgs());
	}

	public void expectException(Class<? extends Throwable> expected) {
		expectedExceptionClass = expected;
	}

	public void addBefores(List<FrameworkMethod> befores) {
		this.befores = befores;
	}

	public void addAfters(List<FrameworkMethod> afters) {
		this.afters = afters;
	}

	protected String[] createJPFArgs() {
		List<String> testArgs = new ArrayList<String>();
		testArgs.add(TestClassOpt + target.getClass().getName());
		testArgs.add(TestOpt + MethodSubOpt + testMethod.getName()
				+ "," + ExceptionSubOpt
				+ getExceptionClassName(expectedExceptionClass));
		for (FrameworkMethod beforeMethod : befores) {
			testArgs.add(BeforeMethodOpt +
					beforeMethod.getName());
		}
		for (FrameworkMethod afterMethod : afters) {
			testArgs.add(AfterMethodOpt +
					afterMethod.getName());
		}

		return new ArgumentCreator()
			.publisher(OnFailurePublisher.class)
			.reporter(TestReporter.class)
			.jpfArgs(new String[] {
					"+vm.por.field_boundaries.never=",
					"+search.multiple_errors=true",
					"+jpf.report.console.start=",
					"+jpf.report.console.finished=result",
					"+jpf.report.console.show_steps=true"
				})
			.app(TestWrapper.class)
			.appArgs(testArgs)
			.getArgs();
	}

	protected String getExceptionClassName(
			Class<? extends Throwable> exceptionClass) {
		if (exceptionClass == null) {
			return "";
		} else {
			return exceptionClass.getName();
		}
	}
}

@@ -907,53 +907,564 @@
 %0A%0A%09p
-rotected ConcurrentFrameworkMethod testMethod
+ublic class MethodInfo %7B%0A%09%09ConcurrentFrameworkMethod method;%0A%09%09Class%3C? extends Throwable%3E exception;%0A%0A%09%09MethodInfo(ConcurrentFrameworkMethod method) %7B%0A%09%09%09this.method = method;%0A%09%09%7D%0A%0A%09%09MethodInfo(ConcurrentFrameworkMethod method,%0A%09%09%09%09Class%3C? extends Throwable%3E exception) %7B%0A%09%09%09this.method = method;%0A%09%09%09this.exception = exception;%0A%09%09%7D%0A%0A%09%09public ConcurrentFrameworkMethod getMethod() %7B%0A%09%09%09return method;%0A%09%09%7D%0A%0A%09%09public Class%3C? extends Throwable%3E getException() %7B%0A%09%09%09return exception;%0A%09%09%7D%0A%09%7D%0A%0A%09protected List%3CMethodInfo%3E testMethods = new ArrayList%3CMethodInfo%3E()
 ;%0A%09p
@@ -1573,70 +1573,8 @@
 ers;
-%0A%09protected Class%3C? extends Throwable%3E expectedExceptionClass;
 %0A%0A%09/
@@ -1707,25 +1707,38 @@
 %0A%09%09t
-his.test
+estMethods.add(new 
 Method
- = 
+Info(
 test
@@ -1739,24 +1739,26 @@
 o(testMethod
+))
 ;%0A%09%09this.tar
@@ -2101,33 +2101,44 @@
 ed) %7B%0A%09%09
-expectedE
+testMethods.get(0).e
 xception
 Class = 
@@ -2129,21 +2129,16 @@
 xception
-Class
  = expec
@@ -2312,24 +2312,94 @@
 afters;%0A%09%7D%0A%0A
+%09public List%3CMethodInfo%3E getTestMethods() %7B%0A%09%09return testMethods;%0A%09%7D%0A%0A
 %09protected S
@@ -2572,17 +2572,21 @@
 odSubOpt
- 
+%0A%09%09%09%09
 + testMe
@@ -2585,24 +2585,39 @@
 + testMethod
+s.get(0).method
 .getName()%0A%09
@@ -2675,25 +2675,36 @@
 ame(
-expectedE
+testMethods.get(0).e
 xception
 Clas
@@ -2699,21 +2699,16 @@
 xception
-Class
 ));%0A%09%09fo

store multiple ConcurrentFrameworkMethods