package net.morilib.sh;

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

import junit.framework.TestCase;

public class ShLexerTest extends TestCase {

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

	public void eqk(ShLexer r, String s) {
		try {
			r.skipws();
			assertEquals(r.nextToken(), new ShKeyword(s));
		} catch (IOException e) {
			throw new RuntimeException(e);
		} catch (ShSyntaxException e) {
			throw new RuntimeException(e);
		}
	}

	public void eqs(ShLexer r, String s) {
		try {
			r.skipws();
			assertEquals(r.nextToken(), new ShString(s));
		} catch (IOException e) {
			throw new RuntimeException(e);
		} catch (ShSyntaxException e) {
			throw new RuntimeException(e);
		}
	}

	public void eqh(ShLexer r, String s) {
		try {
			r.skipws();
			assertEquals(r.nextToken(), new ShRedirector(s));
		} catch (IOException e) {
			throw new RuntimeException(e);
		} catch (ShSyntaxException e) {
			throw new RuntimeException(e);
		}
	}

	public void eq0(ShLexer r, ShToken t) {
		try {
			r.skipws();
			assertEquals(r.nextToken(), t);
		} catch (IOException e) {
			throw new RuntimeException(e);
		} catch (ShSyntaxException e) {
			throw new RuntimeException(e);
		}
	}

	public void testS001() {
		ShLexer r = grd("echo aaa");

		eqk(r, "echo");
		eqk(r, "aaa");
		eq0(r, ShToken.EOF);
	}

	public void testS002() {
		ShLexer r = grd("echo aaa | cat -n &");

		eqk(r, "echo");
		eqk(r, "aaa");
		eq0(r, ShToken.PIPE);
		eqk(r, "cat");
		eqk(r, "-n");
		eq0(r, ShToken.BG);
		eq0(r, ShToken.EOF);
	}

	public void testS003() {
		ShLexer r = grd(
				"echo \"\n" +
				"aaa\'\n" +
				"bbb\"");

		eqk(r, "echo");
		eqs(r, "\"\naaa\'\nbbb\"");
		eq0(r, ShToken.EOF);
	}

	public void testS004() {
		ShLexer r = grd(
				"echo \'\n" +
				"aaa\"\n" +
				"bbb\'");

		eqk(r, "echo");
		eqs(r, "'\naaa\"\nbbb'");
		eq0(r, ShToken.EOF);
	}

	public void testS005() {
		ShLexer r = grd("echo $A_b${AAAA}");

		eqk(r, "echo");
		eqs(r, "${A_b}${AAAA}");
		eq0(r, ShToken.EOF);
	}

	public void testS006() {
		ShLexer r = grd("echo $A_b ${AAAA}");

		eqk(r, "echo");
		eqs(r, "${A_b}");
		eqs(r, "${AAAA}");
		eq0(r, ShToken.EOF);
	}

	public void testS007() {
		ShLexer r = grd("echo aaa > 1 >> 2");

		eqk(r, "echo");
		eqk(r, "aaa");
		eq0(r, ShRedirector.OUT);
		eqk(r, "1");
		eq0(r, ShRedirector.APPEND);
		eqk(r, "2");
		eq0(r, ShToken.EOF);
	}

	public void testS008() {
		ShLexer r = grd("echo aaa < 1");

		eqk(r, "echo");
		eqk(r, "aaa");
		eq0(r, ShRedirector.IN);
		eqk(r, "1");
		eq0(r, ShToken.EOF);
	}

	public void testS009() {
		ShLexer r = grd(
				"echo aaa << END\n" +
				"aaaaa\n" +
				"bbbbb\n" +
				"END");

		eqk(r, "echo");
		eqk(r, "aaa");
		eqh(r, "aaaaa\nbbbbb\n");
		eq0(r, ShToken.EOF);
	}

	public void testS010() {
		ShLexer r = grd("echo \"$A_b  ${AAAA}\"");

		eqk(r, "echo");
		eqs(r, "\"${A_b}  ${AAAA}\"");
		eq0(r, ShToken.EOF);
	}

	public void testS011() {
		ShLexer r = grd("echo \"${AAAA} $A_b\"");

		eqk(r, "echo");
		eqs(r, "\"${AAAA} ${A_b}\"");
		eq0(r, ShToken.EOF);
	}

	public void testS012() {
		ShLexer r = grd("echo \"${AAAA}$A_b\"");

		eqk(r, "echo");
		eqs(r, "\"${AAAA}${A_b}\"");
		eq0(r, ShToken.EOF);
	}

	public void testS013() {
		ShLexer r = grd("echo \"${AAAA} $A_b;a\"");

		eqk(r, "echo");
		eqs(r, "\"${AAAA} ${A_b};a\"");
		eq0(r, ShToken.EOF);
	}

	public void testS014() {
		ShLexer r = grd("echo $(ls -l)");

		eqk(r, "echo");
		eqs(r, "$(ls -l)");
		eq0(r, ShToken.EOF);
	}

	public void testS015() {
		ShLexer r = grd("echo `ls -l`");

		eqk(r, "echo");
		eqs(r, "$(ls -l)");
		eq0(r, ShToken.EOF);
	}

	public void testS016() {
		ShLexer r = grd("echo $(ls -l)1");

		eqk(r, "echo");
		eqs(r, "$(ls -l)1");
		eq0(r, ShToken.EOF);
	}

	public void testS017() {
		ShLexer r = grd("echo `ls -l`1");

		eqk(r, "echo");
		eqs(r, "$(ls -l)1");
		eq0(r, ShToken.EOF);
	}

	public void testS018() {
		ShLexer r = grd("echo 1$(ls -l)");

		eqk(r, "echo");
		eqs(r, "1$(ls -l)");
		eq0(r, ShToken.EOF);
	}

	public void testS019() {
		ShLexer r = grd("echo 1`ls -l`");

		eqk(r, "echo");
		eqs(r, "1$(ls -l)");
		eq0(r, ShToken.EOF);
	}

	public void testS020() {
		ShLexer r = grd("echo 1$(ls -l)2$(ls)");

		eqk(r, "echo");
		eqs(r, "1$(ls -l)2$(ls)");
		eq0(r, ShToken.EOF);
	}

	public void testS021() {
		ShLexer r = grd("echo 1`ls -l`2`ls`");

		eqk(r, "echo");
		eqs(r, "1$(ls -l)2$(ls)");
		eq0(r, ShToken.EOF);
	}

	public void testS022() {
		ShLexer r = grd("echo a$(ls -l)");

		eqk(r, "echo");
		eqs(r, "a$(ls -l)");
		eq0(r, ShToken.EOF);
	}

	public void testS023() {
		ShLexer r = grd("echo a`ls -l`");

		eqk(r, "echo");
		eqs(r, "a$(ls -l)");
		eq0(r, ShToken.EOF);
	}

	public void testS024() {
		ShLexer r = grd("echo a$(ls -l)2$(ls)");

		eqk(r, "echo");
		eqs(r, "a$(ls -l)2$(ls)");
		eq0(r, ShToken.EOF);
	}

	public void testS025() {
		ShLexer r = grd("echo a`ls -l`b`ls`");

		eqk(r, "echo");
		eqs(r, "a$(ls -l)b$(ls)");
		eq0(r, ShToken.EOF);
	}

	public void testS026() {
		ShLexer r = grd("echo aaa 2> 2");

		eqk(r, "echo");
		eqk(r, "aaa");
		eq0(r, new ShRedirector(ShRedirectType.OUT, 2, -1));
		eqk(r, "2");
		eq0(r, ShToken.EOF);
	}

	public void testS027() {
		ShLexer r = grd("echo aaa 2>&1 2> 2");

		eqk(r, "echo");
		eqk(r, "aaa");
		eq0(r, new ShRedirector(ShRedirectType.OUT, 2, 1));
		eq0(r, new ShRedirector(ShRedirectType.OUT, 2, -1));
		eqk(r, "2");
		eq0(r, ShToken.EOF);
	}

	public void testS028() {
		ShLexer r = grd("echo aaa 0<&0 0< 2");

		eqk(r, "echo");
		eqk(r, "aaa");
		eq0(r, new ShRedirector(ShRedirectType.IN, 0, 0));
		eq0(r, new ShRedirector(ShRedirectType.IN, 0, -1));
		eqk(r, "2");
		eq0(r, ShToken.EOF);
	}

	public void testS029() {
		ShLexer r = grd("echo aaa 2>&1 2>> 2");

		eqk(r, "echo");
		eqk(r, "aaa");
		eq0(r, new ShRedirector(ShRedirectType.OUT, 2, 1));
		eq0(r, new ShRedirector(ShRedirectType.APPEND, 2, -1));
		eqk(r, "2");
		eq0(r, ShToken.EOF);
	}

	public void testS030() {
		ShLexer r = grd("echo aaa 841>&765 765> 2");

		eqk(r, "echo");
		eqk(r, "aaa");
		eq0(r, new ShRedirector(ShRedirectType.OUT, 841, 765));
		eq0(r, new ShRedirector(ShRedirectType.OUT, 765, -1));
		eqk(r, "2");
		eq0(r, ShToken.EOF);
	}

	public void testS031() {
		ShLexer r = grd("echo aaa 841<&765 765< 2");

		eqk(r, "echo");
		eqk(r, "aaa");
		eq0(r, new ShRedirector(ShRedirectType.IN, 841, 765));
		eq0(r, new ShRedirector(ShRedirectType.IN, 765, -1));
		eqk(r, "2");
		eq0(r, ShToken.EOF);
	}

}
