/**
 * INITIAL VERIFICATION DONE April 16th 2012
 * Need futher correction at executeCode function to capture the Sysout.
 */
package edu.ufl.cise.cop5555.sp12.codegen;

import static java.lang.System.err;
import static org.junit.Assert.*;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import edu.ufl.cise.cop5555.sp12.Parser;
import edu.ufl.cise.cop5555.sp12.SyntaxException;
import edu.ufl.cise.cop5555.sp12.TestParser;
import edu.ufl.cise.cop5555.sp12.TokenStream;
import edu.ufl.cise.cop5555.sp12.ast.AST;
import edu.ufl.cise.cop5555.sp12.ast.Program;
import edu.ufl.cise.cop5555.sp12.ast.ToStringVisitor;
import edu.ufl.cise.cop5555.sp12.context.ContextCheckVisitor;
import edu.ufl.cise.cop5555.sp12.context.ContextException;

/**
 * @author Devesh Bisht
 *	Testsuite: edu.ufl.cise.cop5555.sp12.codegen.TestCodeGen
 *	Tests run: 65, Failures: 0, Errors: 58, Time elapsed: 0.63 sec
 */
public class CodeGenVisitorTest {
	
	static boolean WRITE_TO_FILE = true; // write generated classfile?
	static boolean EXECUTE = true; // dynamically execute generated classfile?
	static class COP5555ClassLoader extends ClassLoader {
		@SuppressWarnings("rawtypes")
		public Class defineClass(String name, byte[] b) {
			return defineClass(name, b, 0, b.length);
		}
	}
	
	
	private Parser parser = null;
    private ContextCheckVisitor contextCVisitor = new ContextCheckVisitor();
	//private CodeGenVisitor codeGenVisitor = new CodeGenVisitor();
	private boolean codeGenSuccess = false;
	private AST tree = null;
	private String progName = null; // this stores program name for giving class file name.
	private byte[] bytes = null; // this stores the class file bytecode
	
	private void initParser(String input)
    {
        TokenStream stream = TestParser.getInitializedTokenStream(input);
        parser = new Parser(stream);
    }
	
	private boolean compileCode() {		
		
		try {
			tree = parser.parse(); // parsing happens here	AST is constructed.
													System.err.println("------------PRINTING Parse Tree------------------");
													ToStringVisitor.printAST(tree);
													//System.err.println(tree.toString());
													System.err.println("------------Starting Type Checking---------------");
													
			tree.visit(contextCVisitor, null); // context checking happens , Otherwise will pop out error
													 //To Check Symbol Table
														//tcv.SymbolTabPrint();
			                                         //TO check the AST ----
														System.out.println("TYPE CHECKING COMPLETE -------=============------- ALL IZ WELL ");
			                                            //System.out.println("the Parse tree is \n" + tree.toString());
			progName = ((Program) tree).ident.getText(); // program name retrieved and stored
			CodeGenVisitor genVisitor = new CodeGenVisitor();
			bytes = (byte[]) tree.visit(genVisitor, progName);  // code generation happens.
			codeGenSuccess = true;
						if (codeGenSuccess) {
							if (WRITE_TO_FILE) {  //  write classfile
								FileOutputStream f;
								System.out.println("writing class " + progName + ".class");
								f = new FileOutputStream(progName + ".class");
								f.write(bytes);
								f.close();
							}
						}
			
		} catch (SyntaxException e) {
			err.println(e.t.getLineNumber() + ": Syntax error: "  + e.getMessage());
		} catch (ContextException e) {
			err.println("Type error: " + e.getMessage());
		} catch (Exception e) {
			err.println("Error " + e.getMessage());
			e.printStackTrace();
		}
		return codeGenSuccess;
	}
	private String executeCode(){
		String result= null;
		if (codeGenSuccess) {
			System.err.println("\nEXECUTING CODE NOW");
			if (EXECUTE) {  //dynamically execute generated code
				COP5555ClassLoader cl = new COP5555ClassLoader();
				@SuppressWarnings("rawtypes")
				Class c = cl.defineClass(progName, bytes);
				try {					
					@SuppressWarnings("unchecked")
					Method mainMethod = c.getMethod("main", String[].class);
					
					Object[] objectParams = new Object[1];
							final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
							//final PrintStream restore = new PrintStream(System.out);
							final PrintStream restore = System.out;  //either of these may work
							
								System.setOut(new PrintStream(outContent,true));					   
							
					mainMethod.invoke(null, objectParams); 
					 
							result = outContent.toString();
						
								System.setOut(restore);
								System.out.println("The console output of program is like\n"+ result);
					
				} catch (SecurityException e) {
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		} // else (!codeGenSuccess) terminate
		return result;
	
	}
	

	/**
	 * @throws java.lang.Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
	}


	@Test
	public final void testCompiler() {				
		String str[] = {"resources\\print43.plp"};
		try {
			Compiler.main(str);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//fail("Not yet implemented"); // TODO
	}
	
	@Test
	public final void testConflictingDeclaration1() {
		String input = "prog Test1 int x; if (true) boolean x; x = true; print x; fi; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());	
		
	}
	@Test
	public final void testConflictingDeclaration2() {
		String input = "prog Test1 int x; if (true) string x; x = \"true\"; print x; fi; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());	
		
	}
	@Test
	public final void testConflictingDeclaration3() {
		String input = "prog Test1 int x; if (true) boolean x; x = true; print x; fi; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());	
		
	}
	@Test
	public final void testConflictingDeclaration4() {
		String input = "prog Test1 int x; if (true) boolean x; x = true; print x; fi; x = 4; print x; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true4", executeCode());
	}
	@Test
	public final void testConflictingDeclaration5() {
		String input = "prog Test1 string x; if (true) boolean x; x = true; if (true) print x; fi; fi; x = \"a\"; print x; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("truea", executeCode());
	}
	
	@Test
	public final void testSimplePrint1(){
		
		String input = "prog Test1 print true; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testSimplePrint2(){
		
		String input = "prog Test1 print 56; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("56", executeCode());
	}
	@Test
	public final void testSimplePrint3(){
		
		String input = "prog Test1 print \"abc\"; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("abc", executeCode());
	}
	@Test
	public final void testSimplePrint4(){
		
		String input = "prog Test1 print true; print true; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("truetrue", executeCode());
	}
	@Test
	public final void testSimplePrint5(){
		
		String input = "prog Test1 println 56; println 56; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
		//String comp= executeCode() ;
		//System.out.println(" i expect -\n56\n"+"56\n");
		//System.out.println("i get -\n"+comp);
		assertEquals("56\r\n56\r\n",executeCode() );  //TRICKY since windows execution converts \n into \r\n
		
		//assertTrue(comp.equals("\n56\n56\n"));
		
	}
	@Test
	public final void testSimplePrint6(){
		
		String input = "prog Test1 println \"abc\"; print 56; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
		//assertTrue(executeCode().equals("abc\n56"))	;
		assertEquals("abc\r\n56",executeCode());
	}
	/*
	public final void testSimplePrint7(){
		
		String input = "prog Test1 int x; int y; int z; x=4; y=2; print x > y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	public final void testSimplePrint8(){
		
		String input = "prog Test1 int x; int y; int z; x=4; y=2; print x < y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	*/
	
	@Test
	public final void testDoCommand1() {
		String input = "prog Test1 int end; int i; int count; i=1; end=10; count=0; do(i<=end) i=i+1; count=count+1; od; print count; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("10", executeCode());
	}
	@Test
	public final void testDoCommand2() {
		String input = "prog Test1 int i; int j; int k; i=1; j=1; k=100; do(i+j<k) i=i+1; j=j+1; od; print i; print j; print k; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("5050100", executeCode());
	}
	@Test
	public final void testDoCommand4() {
		String input = "prog Test1 int i; i=1; int count; count=0; do(i<=50) i=i+1; int j; j=1; do (j<=50) j=j+1; count=count+1; od; od; print count; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("2500", executeCode());
	}
	@Test
	public final void testDoCommand5() {
		String input = "prog Test1 int i; i=1; int count; count=0; do(i<=50) i=i+1; int j; j=1; do (j<=50) j=j+1; if (i<j) count=count+1; fi; od; od; print count; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("1225", executeCode());
	}
	
	
	@Test
	public final void testIfCommand1() {
		String input = "prog Test1 int x; x=4; if (x == 4) print x; fi; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("4", executeCode());
	}
	@Test
	public final void testIfCommand2() {
		String input = "prog Test1 int x; x=4; if (x < 4) print x; fi; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("", executeCode());
	}
	@Test
	public final void testIfCommand3() {
		String input = "prog Test1 int x; int y; y=4; x=4; if (x == y) print x; fi; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("4", executeCode());
	}
	@Test
	public final void testIfCommand4() {
		String input = "prog Test1 int x; int y; y=4; x=4; if (x == y != false) print x; fi; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("4", executeCode());
	}
	@Test
	public final void testIfCommand5() {
		String input = "prog Test1 boolean x; int y; y=4; x=true; if (x == (y == 4)) print 4; fi; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("4", executeCode());
	}
	
	
	@Test
	public final void testIfElseCommand1() {
		String input = "prog Test1 int x; x=4; if (x == 4) print x; else print 2; fi; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("4", executeCode());
	}
	@Test
	public final void testIfElseCommand2() {
		String input = "prog Test1 int x; x=4; if (x != 4) print x; else print 2; fi; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("2", executeCode());
	}
	@Test
	public final void testIfElseCommand3() {
		String input = "prog Test1 int x; x=4; if (false) print x; else print 2; fi; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("2", executeCode());
	}
	
	
	@Test
	public final void testAssignment1() {
		String input = "prog Test1 int x; int y; x=3; y=x; print y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("3", executeCode());
	}
	@Test
	public final void testAssignment2() {
		String input = "prog Test1 int x; int y; x=3; y=x; y=4; print y; print x; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("43", executeCode());
	}
	@Test
	public final void testAssignment3() {
		String input = "prog Test1 int x; int y; x=3; y=x; y=4; print y; print x; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("43", executeCode());
	}
	
	
	//To be corrected
	@Test
	public final void testUnaryOpExpression1() {
		String input = "prog Test1 int x; int y; x=1; y=-x; print y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("-1", executeCode());
	}
	@Test
	public final void testUnaryOpExpression2() {
		String input = "prog Test1 boolean x; x=true; boolean y; print !x; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testUnaryOpExpression3() {
		String input = "prog Test1 boolean x; x=true; boolean y; print !!!!x; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	
	
	
	@Test
	public final void testBinaryExpression1() {
		String input = "prog Test1 int x; int y; int z; x=4; y=3; z = x + y; print z; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("7", executeCode());
	}
	@Test
	public final void testBinaryExpression2() {
		String input = "prog Test1 int x; int y; int z; x=4; y=3; z = x - y; print z; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("1", executeCode());
	}
	@Test
	public final void testBinaryExpression3() {
		String input = "prog Test1 int x; int y; int z; x=4; y=3; z = y - x; print z; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("-1", executeCode());
	}
	@Test
	public final void testBinaryExpression4() {
		String input = "prog Test1 int x; int y; int z; x=4; y=3; z = x * y; print z; gorp ";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("12", executeCode());
	}
	@Test
	public final void testBinaryExpression5() {
		String input = "prog Test1 int x; int y; int z; x=4; y=3; z = x / y; print z; gorp ";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("1", executeCode());
	}
	@Test
	public final void testBinaryExpression6() {
		String input = "prog Test1 int x; int y; int z; x=4; y=2; z = x / y; print z; gorp ";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("2", executeCode());
	}
	@Test
	public final void testBinaryExpression7() {
		String input = "prog Test1 int x; int y; int z; x=4; y=2; print x < y; gorp ";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testBinaryExpression8() {
		String input = "prog Test1 int x; int y; int z; x=4; y=2; print x > y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testBinaryExpression9() {
		String input = "prog Test1 int x; int y; int z; x=4; y=2; print x >= y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testBinaryExpression10() {
		String input = "prog Test1 int x; int y; int z; x=4; y=4; print x >= y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testBinaryExpression11() {
		String input = "prog Test1 int x; int y; int z; x=4; y=2; print x <= y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testBinaryExpression12() {
		String input = "prog Test1 int x; int y; int z; x=2; y=2; print x <= y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testBinaryExpression13() {
		String input = "prog Test1 int x; int y; int z; x=2; y=2; print x == y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testBinaryExpression14() {
		String input = "prog Test1 int x; int y; int z; x=2; y=2; print x != y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testBinaryExpression15() {
		String input = "prog Test1 int x; int y; int z; x=2; y=2; print x != y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testBinaryExpression16() {
		String input = "prog Test1 int x; string y; string z; x=2; y=\"a\"; z = x + y; print z; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("2a", executeCode());
	}
	@Test
	public final void testBinaryExpression17() {
		String input = "prog Test1 string x; string y; string z; x=\"b\"; y=\"a\"; z = x + y; print z; gorp ";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("ba", executeCode());
	}
	@Test
	public final void testBinaryExpression18() {
		String input = "prog Test1 string x; boolean y; string z; x=\"b\"; y=false; z = x + y; print z; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("bfalse", executeCode());
	}
	@Test
	public final void testBinaryExpression19() {
		String input = "prog Test1 string x; string y; x=\"abc\"; y= \"abcdef\"; print x <= y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testBinaryExpression20() {
		String input = "prog Test1 string x; string y; x=\"abcefg\"; y= \"abcdef\"; print x <= y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testBinaryExpression21() {
		String input = "prog Test1 boolean x; boolean y; x=true; y=false; print x&y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testBinaryExpression22() {
		String input = "prog Test1 boolean x; boolean y; x=false; y=true; print x|y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testBinaryExpression23() {
		String input = "prog Test1 boolean x; boolean y; x=false; y=true; print x == y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testBinaryExpression24() {
		String input = "prog Test1 boolean x; boolean y; x=false; y=true; print x != y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testBinaryExpression25() {
		String input = "prog Test1 boolean x; boolean y; x=false; y=true; print x <= y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testBinaryExpression26() {
		String input = "prog Test1 boolean x; boolean y; x=false; y=true; print x < y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testBinaryExpression27() {
		String input = "prog Test1 boolean x; boolean y; x=false; y=true; print x > y; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testBinaryExpression28() {
		String input = "prog Test1 boolean x; boolean y; x=false; y=true; print x >= y; gorp ";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testBinaryExpression29() {
		String input = "prog Test1 int x; x=3; int y; y=2; int z; z = x + y - 5 * y / 4; print z; gorp ";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("3", executeCode());
	}
	@Test
	public final void testBinaryExpression30() {
		String input = "prog Test1 int x; x=3; int y; y=2; int z; z = x * y - 8 * y / 4 / 5; print z; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("6", executeCode());
	}
	@Test
	public final void testBinaryExpression31() {
		String input = "prog Test1 int x; x=3; int y; y=2; boolean z; z = x * y - 8 * y / 4 / 5 < 6; print z; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testBinaryExpression32() {
		String input = "prog Test1 int x; x=3; int y; y=2; int z; z = x * (y - 8) * y / 4 ; print z; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("-9", executeCode());
	}
	
	
	
	@Test
	public final void testEmptyProg() {
		String input = "prog Test1 gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		//assertEquals("2a", executeCode());
	}
	
	@Test
	public final void testDeclared1(){
		String input = "prog Test1 int x; x=4; print x; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("4", executeCode());
	}
	@Test
	public final void testDeclared2(){
		String input = "prog Test1 boolean x; x=true; print x; gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testDeclared3(){
		String input = "prog Test1 string x; x=\"aabbcc\"; print x; gorp ";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("aabbcc", executeCode());
	}
	@Test
    public void testNestedDeclaration1() throws Exception{
        String input = "prog progname int myname; int x; x=2; do (x<5) int myname; x=x+1; od; gorp";
        this.initParser(input);
        compileCode();
		assertEquals(true, codeGenSuccess);
		executeCode();
    }
    @Test
    public void testNestedDeclaration2() throws Exception{
        String input = "prog progname int myname; if(2>4) int myname; fi; gorp";
        this.initParser(input);
        compileCode();
		assertEquals(true, codeGenSuccess);
		executeCode();
    }
    @Test
    public void testDoEachCommand1() throws Exception
    {
        String input = "prog Test1 map[int, string] x; int y; string z; do x : [y,z] od; gorp";
        this.initParser(input);
        compileCode();
		assertEquals(true, codeGenSuccess);
		executeCode();
    }
    @Test
    public void testDoEachCommand2() throws Exception
    {
        String input = "prog Test1 map[int, map[string, string]] x; map[string, string] y; int z; do x : [z,y] od; gorp";
        this.initParser(input);
        compileCode();
		assertEquals(true, codeGenSuccess);
		executeCode();
    }
    @Test
	public final void testForEach2(){
		String input = "prog TestForEach2 " +
				"int k; " +
				"map[boolean, int] v; " +
				"map[int, map[boolean, int]] m; " +
				"map [boolean, int] m1; " +
				"m1 = {[true,43],[false,95]}; " +
				" m[100] = m1; " +
				"do m : [k,v] " +
				"print k; " +
				"boolean kb; " +
				"int vi; " +
				"do v : [kb,vi] " +
				"print kb; " +
				"print vi; " +
				"od; " +
				"od ; " +
				"gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("100false95true43", executeCode());
	}
	@Test
	public void testMapDec() throws Exception{
		String input = "prog Test1 map[int,string] y; y[3] = \"hello\"; gorp";
	    this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
		executeCode();
	}
	@Test
	public void testMapDec2() throws Exception{
		String input = "prog Test1 map[int,string] y; y = {[3,\"hello\"], [4,\"asd\"]}; gorp";
	    this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
		executeCode();
	}
	@Test
	public void testMapDec3() throws Exception{
		String input = "prog Test1 map[int,string] y; y = {}; gorp";
	    this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
		executeCode();
	}
	@Test
	public void testMapDec4() throws Exception{
		String input = "prog Test1 map[int,map[int, string]] y; map[int, string] x; x = {[3,\"hello\"], [4,\"asd\"]}; y = {[2, x]}; gorp";
	    this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
		executeCode();
	}
	@Test
    public void testPairExpression1() throws Exception{
		String input = "prog Test1 map [int, string] m; m ={[3+4, \"abc\"]};  gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
		executeCode();
    }
	@Test
    public void testPairExpression2() throws Exception{
		String input = "prog Test1 map [int, string] m; int a; string s1; m ={[a + 3, s1 + \"abc\"]};  gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
		executeCode();
    }
	@Test
    public void testPairExpression3() throws Exception{
		String input = "prog Test1 map [int, map[string, boolean]] m; map[string, boolean] m1; m1 = {[\"as\" + \"qr\", true != false]}; int a; string s1; m ={[a - a * a / a, m1 + m1]};  gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
		executeCode();
    }
	@Test
	public final void testMap2(){
		String input = "prog TestMap2 " +
				"int k; " +
				"map[int,int] m0; "+
				"map[int,int] m1; " +
				"m0 = {[0,100],[2,102], [3,103]}; " +
				"m1 = {[0,100],[2,102], [3,103]}; " +
				"print m0; "+
				"print m1; " +
				"gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{0=100, 2=102, 3=103}{0=100, 2=102, 3=103}", executeCode());
	}
	@Test
	public final void testMap3(){
		String input = "prog TestMap3 " +
				"int k; " +
				"map[boolean, int] v; " +
				"map[int, map[boolean, int]] m; " +
				"map [boolean, int] m1; " +
				"m1 = {[true,43],[false,95]}; " +
				"print m;" +
				"gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{}", executeCode());
	}
	@Test
	public final void testMap4(){
		String input = "prog TestMap4 " +
				"int k; " +
				"map[boolean, int] v; " +
				"map[int, map[boolean, int]] m; " +
				"map [boolean, int] m1; " +
				"m1 = {[true,43],[false,95]}; " +
				" m[100] = m1; " +
				"print m;" +
				"gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{100={false=95, true=43}}", executeCode());
	}	
	@Test
	public final void testMapPlus(){
		String input = "prog TestMapPlus " +
				"int k; " +
				"map[int,int] m0; "+
				"map[int,int] m1; " +
				"m0 = {[0,100],[2,102], [3,103]}; " +
				"m1 = {[0,100],[2,102], [3,103]}; " +
				"m0 = m0 + m1; " +
				"print m0; "+
				"print m1; " +
				"gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{0=100, 2=102, 3=103}{0=100, 2=102, 3=103}", executeCode());
	}
	@Test
	public final void testMapPlus2(){
		String input = "prog TestMapPlus2 " +
				"int k; " +
				"map[int,int] m0; "+
				"map[int,int] m1; " +
				"m0 = {[0,100],[2,102], [3,103]}; " +
				"m1 = {[0,100],[2,102], [3,104]}; " +
				"m0 = m0 + m1; " +
				"print m0; "+
				"print m1; " +
				"gorp";		
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{0=100, 2=102, 3=104}{0=100, 2=102, 3=104}", executeCode());
	}
	@Test
	public final void testMapPlus3(){
		String input = "prog TestMapPlus3 " +
				"int k; " +
				"map[int,int] m0; "+
				"map[int,int] m1; " +
				"m0 = {[0,100],[2,102], [3,103]}; " +
				"m1 = {[5,100],[6,102], [7,104]}; " +
				"m0 = m0 + m1; " +
				"print m0; "+
				"print m1; " +
				"gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{0=100, 2=102, 3=103, 5=100, 6=102, 7=104}{5=100, 6=102, 7=104}", executeCode());
	}
	@Test
	public final void testMapEq(){
		String input = "prog TestMapEq " +
				"int k; " +
				"boolean b;" +
				"map[int,int] m0; "+
				"map[int,int] m1; " +
				"m0 = {[0,100],[2,102], [3,103]}; " +
				"m1 = {[0,100],[2,102], [3,104]}; " +
				"b = m0 == m1; " +
				"print m0; "+
				"print m1; " +
				"print b; " +
				"gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{0=100, 2=102, 3=103}{0=100, 2=102, 3=104}false", executeCode());
	}
	@Test
	public final void testMapEq1(){
		String input = "prog TestMapEq1 " +
				"int k; " +
				"boolean b;" +
				"map[int,int] m0; "+
				"map[int,int] m1; " +
				"m0 = {[0,100],[2,102], [3,103]}; " +
				"m1 = {[0,100],[2,102], [3,103]}; " +
				"b = m0 == m1; " +
				"print m0; "+
				"print m1; " +
				"print b; " +
				"gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{0=100, 2=102, 3=103}{0=100, 2=102, 3=103}true", executeCode());
	}
	@Test
	public final void testMapNeq(){
		String input = "prog TestMapNeq " +
				"int k; " +
				"boolean b;" +
				"map[int,int] m0; "+
				"map[int,int] m1; " +
				"m0 = {[0,100],[2,102], [3,103]}; " +
				"m1 = {[0,100],[2,102], [3,104]}; " +
				"b = m0 != m1; " +
				"print m0; "+
				"print m1; " +
				"print b; " +
				"gorp";				
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{0=100, 2=102, 3=103}{0=100, 2=102, 3=104}true", executeCode());
	}
	@Test
	public final void testMapNeq1(){
		String input = "prog TestMapNeq1 " +
				"int k; " +
				"boolean b;" +
				"map[int,int] m0; "+
				"map[int,int] m1; " +
				"m0 = {[0,100],[2,102], [3,103]}; " +
				"m1 = {[0,100],[2,102], [3,103]}; " +
				"b = m0 != m1; " +
				"print m0; "+
				"print m1; " +
				"print b; " +
				"gorp";			
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{0=100, 2=102, 3=103}{0=100, 2=102, 3=103}false", executeCode());
	}
	
/*	*//**
	 * Test method for {@link edu.ufl.cise.cop5555.sp12.codegen.CodeGenVisitor#visitAssignExprCommand(edu.ufl.cise.cop5555.sp12.ast.AssignExprCommand, java.lang.Object)}.
	 *//*
	@Test
	public final void testVisitAssignExprCommand() {
		fail("Not yet implemented"); // TODO
	}

	*//**
	 * Test method for {@link edu.ufl.cise.cop5555.sp12.codegen.CodeGenVisitor#visitPrintCommand(edu.ufl.cise.cop5555.sp12.ast.PrintCommand, java.lang.Object)}.
	 *//*
	@Test
	public final void testVisitPrintCommand() {
		fail("Not yet implemented"); // TODO
	}

	*//**
	 * Test method for {@link edu.ufl.cise.cop5555.sp12.codegen.CodeGenVisitor#visitPrintlnCommand(edu.ufl.cise.cop5555.sp12.ast.PrintlnCommand, java.lang.Object)}.
	 *//*
	@Test
	public final void testVisitPrintlnCommand() {
		fail("Not yet implemented"); // TODO
	}

	*//**
	 * Test method for {@link edu.ufl.cise.cop5555.sp12.codegen.CodeGenVisitor#visitDoCommand(edu.ufl.cise.cop5555.sp12.ast.DoCommand, java.lang.Object)}.
	 *//*
	@Test
	public final void testVisitDoCommand() {
		fail("Not yet implemented"); // TODO
	}

	*//**
	 * Test method for {@link edu.ufl.cise.cop5555.sp12.codegen.CodeGenVisitor#visitDoEachCommand(edu.ufl.cise.cop5555.sp12.ast.DoEachCommand, java.lang.Object)}.
	 *//*
	@Test
	public final void testVisitDoEachCommand() {
		fail("Not yet implemented"); // TODO
	}

	*//**
	 * Test method for {@link edu.ufl.cise.cop5555.sp12.codegen.CodeGenVisitor#visitBinaryOpExpression(edu.ufl.cise.cop5555.sp12.ast.BinaryOpExpression, java.lang.Object)}.
	 *//*
	@Test
	public final void testVisitBinaryOpExpression() {
		fail("Not yet implemented"); // TODO
	}*/

}
