/**
 * 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 CodeGenMapTest {
	
	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 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 testMapEqual3(){
		String input = "prog test1 " +
				"map[int, string] m; " +
				"m={[1,\"xyz\"], [2,\"cde\"], [3, \"fgh\"]};" +
				"map[int, string] m2; " +
				"m2={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};" +
				"print m == m2;" +
				"gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testMapNotEqual1(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};print m != m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testMapNotEqual2(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[4,\"abc\"], [5,\"cde\"], [6, \"fgh\"]};print m != m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testMapNotEqual3(){
		String input = "prog test1 map[int, string] m; m={[1,\"xyz\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};print m != m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testMapPlus1(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[4,\"abc\"], [5,\"cde\"], [6, \"fgh\"]};print m + m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{1=abc, 2=cde, 3=fgh, 4=abc, 5=cde, 6=fgh}", executeCode());
	}
	@Test
	public final void testMapPlus2String(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[4,\"abc\"], [5,\"cde\"], [1, \"fgh\"]};print m + m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{1=fgh, 2=cde, 3=fgh, 4=abc, 5=cde}", executeCode());
	}
	@Test
	public final void testMapMinus1(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[4,\"abc\"], [5,\"cde\"], [6, \"fgh\"]};print m - m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{1=abc, 2=cde, 3=fgh}", executeCode());
	}
	@Test
	public final void testMapMinus2(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[4,\"abc\"], [5,\"cde\"], [6, \"fgh\"]};print m2 - m;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{4=abc, 5=cde, 6=fgh}", executeCode());
	}
	@Test
	public final void testMapMinus3(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"], [6, \"fgh\"]};print m - m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{3=fgh}", executeCode());
	}
	@Test
	public final void testMapMinus4(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abcd\"], [2,\"cdef\"], [6, \"fgh\"]};print m - m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{1=abc, 2=cde, 3=fgh}", executeCode());
	}
	@Test
	public final void testMapTimes1(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"], [6, \"fgh\"]};print m * m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{1=abc, 2=cde}", executeCode());
	}
	@Test
	public final void testMapTimes2(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"], [6, \"fgh\"]};print m2 * m;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{1=abc, 2=cde}", executeCode());
	}
	@Test
	public final void testMapTimes3(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abcd\"], [2,\"cdef\"], [6, \"fgh\"]};print m2 * m;gorp	";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("{}", executeCode());
	}
	@Test
	public final void testMapLessThan1(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"], [6, \"fgh\"]};print m < m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testMapLessThan2(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"]};print m < m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testMapLessThan3(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"]};print m < m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testMapAtMost1(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"], [6, \"fgh\"]};print m <= m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testMapAtMost2(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"]};print m <= m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testMapAtMost3(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"]};print m <= m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testMapGreaterThan1(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"], [6, \"fgh\"]};print m2 > m;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testMapGreaterThan2(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"]};print m2 > m;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testMapGreaterThan3(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"]};print m2 > m;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testMapAtLeast1(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"], [6, \"fgh\"]};print m2 >= m;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testMapAtLeast2(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"]};print m2 >= m;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testMapAtLeast3(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"]};print m2 >= m;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}
	@Test
	public final void testSelectSort(){
		String input = "prog test1 map [int, int] m1;" +
				"m1 = {[1,8], [2,1], [3,7], [4,5], [5,2], [6,3], [7,4], [8,6]};int i; int j; i=1; j=1;" +
				"do (i<=7)j=i+1;" +
				"do (j<=8)if (m1[i] > m1[j])int tmp;tmp = m1[i];m1[i] = m1[j];m1[j] = tmp;fi;" +
				"j=j+1;od;i=i+1;od;int k; int v;" +
				"do m1:[k,v]print v; print \" \";" +
				"od;" +
				"gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("1 2 3 4 5 6 7 8 ", executeCode());
	}
	@Test
	public final void testBubbleSort(){
		String input = "prog test1 map [int, int] m1;" +
				"m1 = {[1,8], [2,1], [3,7], [4,5], [5,2], [6,3], [7,4], [8,6]};" +
				"int i; int j; i=2; j=1;boolean swapped; swapped = true;" +
				"do (j<=8 & swapped)swapped = false;i=2;" +
				"do (i<=8)if (m1[i-1] > m1[i])int tmp;tmp = m1[i];m1[i] = m1[i-1];m1[i-1] = tmp;swapped = true;fi;i=i+1;" +
				"od;" +
				"j=j+1;" +
				"od;" +
				"int k; int v;do m1:[k,v]print v; print \" \";" +
				"od;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("1 2 3 4 5 6 7 8 ", executeCode());
	}
	@Test
	public final void testInsertionSort(){
		String input = "prog test1 map [int, int] m1;" +
				"m1 = {[1,8], [2,1], [3,7], [4,5], [5,2], [6,3], [7,4], [8,6]};" +
				"int j; j=2;do (j<=8)int item; item = m1[j];" +
				"int hole; hole = j;" +
				"boolean condition; condition = false;" +
				"condition = hole > 1; " +
				"if (condition) condition = m1[hole-1] > item; " +
				"fi;" +
				"do (condition)m1[hole] = m1[hole-1];hole = hole-1;condition = hole > 1; " +
				"if (condition) condition = m1[hole-1] > item; " +
				"fi;" +
				"od;" +
				"m1[hole] = item;j=j+1;" +
				"od;int k; int v;do m1:[k,v]print v; print \" \";" +
				"od;" +
				"gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("1 2 3 4 5 6 7 8 ", executeCode());
	}
	@Test
	public final void testBinarySearch(){
		String input = "prog test1 map [int, int] m1;" +
				"m1 = {[1,1], [2,2], [3,3], [4,4], [5,5], [6,6], [7,7], [8,8]};" +
				"int key; key = 5;int imin; int imax;imin=1; imax=8; " +
				"do (imax > imin)int imid; imid = (imin + imax)/2;" +
				"if (m1[imid] < key) imin = imid+1; else imax = imid; " +
				"fi;" +
				"od;" +
				"if ((imax == imin) & (m1[imin] == key)) print \"found at \" + imin; " +
				"else print \"not found\";" +
				"fi;" +
				"gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("found at 5", 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
	public final void testMapSimpleAssign2(){
		String input = "prog test1 map[int, int] m; m[1]=5; print m[1]; gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("5", executeCode());
	}
	@Test
	public final void testMapDoCommand2(){
		String input = "prog test1 " +
				"map[int, map[int, string]] comp1;map[int, string] m; " +
				"m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};" +
				"map[int, string] m2; " +
				"m2={[4,\"abc\"], [5,\"cde\"], [6, \"fgh\"]};" +
				"comp1[1] = m;comp1[2] = m2;int k; " +
				"map[int, string] v;" +
				"do comp1 :[k,v] print k; print \" \"; " +
				"print v; print \" \"; " +
				"od;  " +
				"gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("1 {1=abc, 2=cde, 3=fgh} 2 {4=abc, 5=cde, 6=fgh} ", executeCode());
	}
	@Test
	public final void testMapEqual1(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};print m == m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("true", executeCode());
	}
	@Test
	public final void testMapEqual2(){
		String input = "prog test1 map[int, string] m; m={[1,\"abc\"], [2,\"cde\"], [3, \"fgh\"]};map[int, string] m2; m2={[4,\"abc\"], [5,\"cde\"], [6, \"fgh\"]};print m == m2;gorp";
		this.initParser(input);		
		compileCode();
		assertEquals(true, codeGenSuccess);
			
		assertEquals("false", executeCode());
	}


}
