// don't put in jp.skypencil.brainjack to test call from other package
package jp.skypencil.brainjack.compiler;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import jp.skypencil.brainjack.AbstractTest;
import jp.skypencil.brainjack.Main;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestName;

import com.google.common.io.CountingOutputStream;
import com.google.common.io.Files;

public class CompilerWithCLITest extends AbstractTest {
	private static final String ROOT_DIR_PATH = "target/compilerWithCLI";
	private ByteArrayOutputStream byteArray;
	private PrintStream defaultOutput;
	@Rule
	public TestName testName = new TestName();
	private CountingOutputStream countingStream;

	@Before
	public void switchOutput() {
		byteArray = new ByteArrayOutputStream();
		defaultOutput = System.out;
		countingStream = new CountingOutputStream(byteArray);
		PrintStream stream = new PrintStream(countingStream);
		System.setOut(stream);
	}

	@After
	public void resetOutput() {
		System.setOut(defaultOutput);
	}

	@Override
	protected String execute(String commands, InputStream input)
			throws Throwable {
		String className = "pkg.withcli." + testName.getMethodName();
		File classFile = new File(ROOT_DIR_PATH, className.replaceAll("\\.", "/") + ".class");
		Files.createParentDirs(classFile);
		classFile.delete();

		assertThat(classFile.exists(), is(false));
		new Main().run(new String[] { "compile", "-c", commands, "-d", ROOT_DIR_PATH, "-n", className });
		assertThat(classFile.isFile(), is(true));
		Class<?> clazz = new OriginalClassLoader().defineClass(className, Files.toByteArray(classFile));
		Method method = clazz.getMethod("main", String[].class);
		assertThat(Modifier.isStatic(method.getModifiers()), is(true));
		assertThat(Modifier.isPublic(method.getModifiers()), is(true));

		InputStream defaultInput = System.in;
		System.setIn(input);
		try {
			method.invoke(null, new Object[] { new String[]{ } });
			System.out.flush();
		} catch (InvocationTargetException e) {
			throw e.getCause();
		} finally {
			System.setIn(defaultInput);
		}
		return new String(byteArray.toByteArray(), 0, (int) countingStream.getCount(), "UTF-8");
	}
}

@@ -244,24 +244,52 @@
 va.io.File;%0A
+import java.io.IOException;%0A
 import java.
@@ -627,22 +627,89 @@
 nit.
-rules.TestName
+Test;%0Aimport org.junit.rules.TestName;%0Aimport org.kohsuke.args4j.CmdLineException
 ;%0A%0Ai
@@ -2569,11 +2569,826 @@
 -8%22);%0A%09%7D
+%0A%0A%09@Test(expected=IllegalArgumentException.class)%0A%09public void testWithoutClassName() throws CmdLineException, IOException %7B%0A%09%09new Main().run(new String%5B%5D%7B%22compile%22, %22-c%22, %22%22, %22-d%22, ROOT_DIR_PATH%7D);%0A%09%7D%0A%0A%09@Test(expected=IllegalArgumentException.class)%0A%09public void testWithWrongDirectory() throws CmdLineException, IOException %7B%0A%09%09File file = new File(ROOT_DIR_PATH, %22file%22);%0A%09%09file.createNewFile();%0A%09%09new Main().run(new String%5B%5D%7B%22compile%22, %22-c%22, %22%22, %22-d%22, file.getAbsolutePath(), %22-n%22, %22pkg.ClassName%22 %7D);%0A%09%7D%0A%0A%09@Test%0A%09public void testWithoutPackage() throws CmdLineException, IOException %7B%0A%09%09File classFile = new File(ROOT_DIR_PATH, %22ClassName.class%22);%0A%09%09classFile.delete();%0A%09%09new Main().run(new String%5B%5D%7B%22compile%22, %22-c%22, %22%22, %22-d%22, ROOT_DIR_PATH, %22-n%22, %22ClassName%22 %7D);%0A%09%09assertThat(classFile.exists(), is(true));%0A%09%7D
 %0A%7D%0A

add test cases to increase coverage