package net.morilib.sh;

import java.io.IOException;
import java.io.PushbackReader;
import java.io.StringReader;

import junit.framework.TestCase;

public class ShParserStatementTest extends TestCase {

	public static PushbackReader grd(String s) {
		return new PushbackReader(new StringReader(s));
	}

	public void eqs(String t, String s) {
		try {
			ShLexer r = new ShLexer(grd(t));

			assertEquals(s, ShParser.parseCommand(r, r.nextToken()).toString());
		} catch (IOException e) {
			throw new RuntimeException(e);
		} catch (ShSyntaxException e) {
			throw new RuntimeException(e);
		}
	}

	public void err(String t) {
		try {
			ShLexer r = new ShLexer(grd(t));

			ShParser.parseCommand(r, r.nextToken());
			fail();
		} catch (IOException e) {
			throw new RuntimeException(e);
		} catch (ShSyntaxException e) {
			// OK
		}
	}

	public void testSimple001() {
//		eqs("echo   aaa", "echo aaa");
		eqs("echo   aaa | cat", "echo aaa | cat");
	}

	public void testSimple002() {
		eqs("{\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				"}",
				"{\necho aaa ; echo bbb\n}");
		eqs("{ echo aaa; echo bbb; }",
				"{\necho aaa ; echo bbb\n}");
		eqs("{ echo aaa; echo bbb; } > 1.txt",
				"{\necho aaa ; echo bbb\n} 1> 1.txt");
	}

	public void testSimple003() {
		eqs("(\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				")",
				"({\necho aaa ; echo bbb\n})");
		eqs("( echo aaa; echo bbb; )",
				"({\necho aaa ; echo bbb\n})");
		eqs("( echo aaa; echo bbb; ) > 1.txt",
				"({\necho aaa ; echo bbb\n}) 1> 1.txt");
	}

	public void testIf001() {
		eqs("if test\n" +
				"then\n" +
				"  aaa\n" +
				"fi",
				"if test\nthen\n{\naaa\n}\nfi");
		eqs("if test; then; aaa; fi", "if test\nthen\n{\naaa\n}\nfi");
		eqs("if test\n" +
				"then\n" +
				"  aaa\n" +
				"  bbb\n" +
				"fi",
				"if test\nthen\n{\naaa ; bbb\n}\nfi");
		eqs("if test; then; aaa; bbb; fi", "if test\nthen\n{\naaa ; bbb\n}\nfi");
		eqs("if test\n" +
				"then\n" +
				"fi",
				"if test\nthen\n{\n\n}\nfi");
		eqs("if test; then; fi", "if test\nthen\n{\n\n}\nfi");
	}

	public void testIf002() {
		eqs("if test\n" +
				"then\n" +
				"  aaa\n" +
				"else\n" +
				"  bbb\n" +
				"fi",
				"if test\nthen\n{\naaa\n}\nelse\n{\nbbb\n}\nfi");
		eqs("if test; then; aaa; else; bbb; fi", "if test\nthen\n{\naaa\n}\nelse\n{\nbbb\n}\nfi");
	}

	public void testIf003() {
		eqs("if test\n" +
				"then\n" +
				"  aaa\n" +
				"elif test\n" +
				"then\n" +
				"  bbb\n" +
				"fi",
				"if test\nthen\n{\naaa\n}\nelif test\nthen\n{\nbbb\n}\nfi");
		eqs("if test; then; aaa; elif test; then; bbb; fi",
				"if test\nthen\n{\naaa\n}\nelif test\nthen\n{\nbbb\n}\nfi");
	}

	public void testIf004() {
		eqs("if test\n" +
				"then\n" +
				"  aaa\n" +
				"elif test\n" +
				"then\n" +
				"  bbb\n" +
				"else\n" +
				"  ccc\n" +
				"fi",
				"if test\nthen\n{\naaa\n}\n" +
				"elif test\nthen\n{\nbbb\n}\n" +
				"else\n{\nccc\n}\nfi");
		eqs("if test; then; aaa; elif test; then; bbb; else; ccc; fi",
				"if test\nthen\n{\naaa\n}\n" +
				"elif test\nthen\n{\nbbb\n}\n" +
				"else\n{\nccc\n}\nfi");
	}

	public void testIf005() {
		eqs("if test\n" +
				"then\n" +
				"  aaa\n" +
				"elif test\n" +
				"then\n" +
				"  bbb\n" +
				"elif test\n" +
				"then\n" +
				"  ccc\n" +
				"fi",
				"if test\nthen\n{\naaa\n}\n" +
				"elif test\nthen\n{\nbbb\n}\n" +
				"elif test\nthen\n{\nccc\n}\n" +
				"fi");
		eqs("if test; then; aaa; elif test; then; bbb; elif test; then; ccc; fi",
				"if test\nthen\n{\naaa\n}\n" +
				"elif test\nthen\n{\nbbb\n}\n" +
				"elif test\nthen\n{\nccc\n}\n" +
				"fi");
	}

	public void testIf006() {
		eqs("if test\n" +
				"then\n" +
				"  aaa\n" +
				"elif test\n" +
				"then\n" +
				"  bbb\n" +
				"elif test\n" +
				"then\n" +
				"  ccc\n" +
				"else\n" +
				"  ddd\n" +
				"fi",
				"if test\nthen\n{\naaa\n}\n" +
				"elif test\nthen\n{\nbbb\n}\n" +
				"elif test\nthen\n{\nccc\n}\n" +
				"else\n{\nddd\n}\nfi");
		eqs("if test; then; aaa; elif test; then; bbb; elif test; then; ccc; else; ddd; fi",
				"if test\nthen\n{\naaa\n}\n" +
				"elif test\nthen\n{\nbbb\n}\n" +
				"elif test\nthen\n{\nccc\n}\n" +
				"else\n{\nddd\n}\nfi");
	}

	public void testIf901() {
		err("if test; else; bbb; elif test; then; aaa; fi");
		err("if test; else; bbb; else; aaa; fi");
	}

	public void testCase001() {
		eqs("case i in\n" +
				"esac",
				"case i in\nesac");
		eqs("case i in; esac", "case i in\nesac");
	}

	public void testCase002() {
		eqs("case i in\n" +
				" aaa) echo aaa;;\n" +
				"esac",
				"case i in\naaa)\n{\necho aaa\n};;\nesac");
		eqs("case i in; aaa) echo aaa;; ; esac",
				"case i in\naaa)\n{\necho aaa\n};;\nesac");
	}

	public void testCase003() {
		eqs("case i in\n" +
				" aaa|bbb) echo aaa;;\n" +
				"esac",
				"case i in\naaa|bbb)\n{\necho aaa\n};;\nesac");
		eqs("case i in; aaa|bbb) echo aaa;; ; esac",
				"case i in\naaa|bbb)\n{\necho aaa\n};;\nesac");
	}

	public void testCase004() {
		eqs("case i in\n" +
				" aaa|bbb) echo aaa;;\n" +
				" *) echo bbb;;\n" +
				"esac",
				"case i in\n" +
				"aaa|bbb)\n{\necho aaa\n};;\n" +
				"*)\n{\necho bbb\n};;\n" +
				"esac");
		eqs("case i in; aaa|bbb) echo aaa;;; *) echo bbb;;; esac",
				"case i in\n" +
				"aaa|bbb)\n{\necho aaa\n};;\n" +
				"*)\n{\necho bbb\n};;\n" +
				"esac");
	}

	public void testCase005() {
		eqs("case i in\n" +
				" aaa|bbb)\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				"  ;;\n" +
				"esac",
				"case i in\naaa|bbb)\n{\necho aaa ; echo bbb\n};;\nesac");
	}

	public void testCase006() {
		eqs("case i in\n" +
				" aaa|bbb) ;;\n" +
				"esac",
				"case i in\naaa|bbb)\n{\n\n};;\nesac");
	}

	public void testFor001() {
		eqs("for i in *\n" +
				"do\n" +
				"  echo aaa\n" +
				"done",
				"for i in *\n" +
				"do\n" +
				"{\necho aaa\n}\n" +
				"done");
		eqs("for i in *; do; echo aaa; done",
				"for i in *\n" +
				"do\n" +
				"{\necho aaa\n}\n" +
				"done");
	}

	public void testFor002() {
		eqs("for i in *\n" +
				"do\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				"done",
				"for i in *\n" +
				"do\n" +
				"{\necho aaa ; echo bbb\n}\n" +
				"done");
		eqs("for i in *; do; echo aaa; echo bbb; done",
				"for i in *\n" +
				"do\n" +
				"{\necho aaa ; echo bbb\n}\n" +
				"done");
	}

	public void testFor003() {
		eqs("for i in *\n" +
				"do\n" +
				"done",
				"for i in *\n" +
				"do\n" +
				"{\n\n}\n" +
				"done");
		eqs("for i in *; do; done",
				"for i in *\n" +
				"do\n" +
				"{\n\n}\n" +
				"done");
	}

	public void testFor004() {
		eqs("for i in\n" +
				"do\n" +
				"  echo aaa\n" +
				"done",
				"for i in\n" +
				"do\n" +
				"{\necho aaa\n}\n" +
				"done");
		eqs("for i in; do; echo aaa; done",
				"for i in\n" +
				"do\n" +
				"{\necho aaa\n}\n" +
				"done");
	}

	public void testFor005() {
		eqs("for i in 1 2\n" +
				"do\n" +
				"done",
				"for i in 1 2\n" +
				"do\n" +
				"{\n\n}\n" +
				"done");
		eqs("for i in 1 2; do; done",
				"for i in 1 2\n" +
				"do\n" +
				"{\n\n}\n" +
				"done");
	}

	public void testWhile001() {
		eqs("while test\n" +
				"do\n" +
				"  echo aaa\n" +
				"done",
				"while test\n" +
				"do\n" +
				"{\necho aaa\n}\n" +
				"done");
		eqs("while test; do; echo aaa; done",
				"while test\n" +
				"do\n" +
				"{\necho aaa\n}\n" +
				"done");
	}

	public void testWhile002() {
		eqs("while test\n" +
				"do\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				"done",
				"while test\n" +
				"do\n" +
				"{\necho aaa ; echo bbb\n}\n" +
				"done");
		eqs("while test; do; echo aaa; echo bbb; done",
				"while test\n" +
				"do\n" +
				"{\necho aaa ; echo bbb\n}\n" +
				"done");
	}

	public void testWhile003() {
		eqs("while test\n" +
				"do\n" +
				"done",
				"while test\n" +
				"do\n" +
				"{\n\n}\n" +
				"done");
		eqs("while test; do; done",
				"while test\n" +
				"do\n" +
				"{\n\n}\n" +
				"done");
	}

	public void testUntil001() {
		eqs("until test\n" +
				"do\n" +
				"  echo aaa\n" +
				"done",
				"until test\n" +
				"do\n" +
				"{\necho aaa\n}\n" +
				"done");
		eqs("until test; do; echo aaa; done",
				"until test\n" +
				"do\n" +
				"{\necho aaa\n}\n" +
				"done");
	}

	public void testUntil002() {
		eqs("until test\n" +
				"do\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				"done",
				"until test\n" +
				"do\n" +
				"{\necho aaa ; echo bbb\n}\n" +
				"done");
		eqs("until test; do; echo aaa; echo bbb; done",
				"until test\n" +
				"do\n" +
				"{\necho aaa ; echo bbb\n}\n" +
				"done");
	}

	public void testUntil003() {
		eqs("until test\n" +
				"do\n" +
				"done",
				"until test\n" +
				"do\n" +
				"{\n\n}\n" +
				"done");
		eqs("until test; do; done",
				"until test\n" +
				"do\n" +
				"{\n\n}\n" +
				"done");
	}

	public void testCompound001() {
		eqs("case i in\n" +
				" aaa|bbb)\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				"  ;;\n" +
				"esac | cat",
				"case i in\naaa|bbb)\n{\necho aaa ; echo bbb\n};;\nesac | cat");
	}

	public void testCompound002() {
		eqs("case i in\n" +
				" aaa|bbb)\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				"  ;;\n" +
				"esac && cat",
				"case i in\naaa|bbb)\n{\necho aaa ; echo bbb\n};;\nesac && cat");
	}

	public void testCompound003() {
		eqs("case i in\n" +
				" aaa|bbb)\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				"  ;;\n" +
				"esac || cat",
				"case i in\naaa|bbb)\n{\necho aaa ; echo bbb\n};;\nesac || cat");
	}

	public void testCompound004() {
		eqs("case i in\n" +
				" aaa|bbb)\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				"  ;;\n" +
				"esac > 1",
				"case i in\naaa|bbb)\n{\necho aaa ; echo bbb\n};;\nesac 1> 1");
	}

	public void testCompound005() {
		eqs("case i in\n" +
				" aaa|bbb)\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				"  ;;\n" +
				"esac 2>&1 > 1",
				"case i in\naaa|bbb)\n{\necho aaa ; echo bbb\n};;\nesac 2>&1 1> 1");
	}

	public void testCompound006() {
		eqs("case i in\n" +
				" aaa|bbb)\n" +
				"  echo aaa\n" +
				"  echo bbb\n" +
				"  ;;\n" +
				"esac &> 1",
				"case i in\naaa|bbb)\n{\necho aaa ; echo bbb\n};;\nesac &> 1");
	}

}
