/* * Copyright 2010 Pablo Arrighi, Alex Concha, Miguel Lezama for version 1. * Copyright 2013 Pablo Arrighi, Miguel Lezama, Kevin Mazet for version 2. * * This file is part of GOOL. * * GOOL is free software: you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation, version 3. * * GOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License version 3 for more details. * * You should have received a copy of the GNU General Public License along with GOOL, * in the file COPYING.txt. If not, see <http://www.gnu.org/licenses/>. */ package gool.test; import gool.generator.android.AndroidPlatform; import gool.generator.common.Platform; import gool.generator.cpp.CppPlatform; import gool.generator.csharp.CSharpPlatform; import gool.generator.java.JavaPlatform; import gool.generator.objc.ObjcPlatform; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class GoolTestCpp { /* * At this day, the GOOL system supports 6 output languages that are * symbolized by Platforms. You may comment/uncomment these platforms to * enable/disable tests for the corresponding output language. * * You may also add your own tests by creating a new method within this * class preceded by a @Test annotation. */ private List<Platform> platforms = Arrays.asList( (Platform) JavaPlatform.getInstance()//, //(Platform) CSharpPlatform.getInstance(), // (Platform) CppPlatform.getInstance()//, // (Platform) PythonPlatform.getInstance() , // (Platform) AndroidPlatform.getInstance() , // (Platform) ObjcPlatform.getInstance() ); private static class GoolTestExecutor { private static final String CLEAN_UP_REGEX = "Note:.*?[\r\n]|(\\w+>\\s)|[\\r\\n]+"; private String input; private String expected; private List<Platform> testedPlatforms; private List<Platform> excludedPlatforms; public GoolTestExecutor(String input, String expected, List<Platform> testedPlatforms, List<Platform> excludedPlatforms) { this.input = input; this.expected = expected; this.testedPlatforms = testedPlatforms; this.excludedPlatforms = excludedPlatforms; } public void compare(Platform platform) throws Exception { if (excludedPlatforms.contains(platform)) { String errorMsg = "The following target platform(s) have been excluded for this test: "; for (Platform p : excludedPlatforms) if (testedPlatforms.contains(p)) errorMsg += p + " "; Assert.fail(errorMsg + "\nThis test may contain some patterns that are not supported by GOOL at the moment for these target platforms. You may see the GOOL wiki for further documentation."); } // This inserts a package which is mandatory for android // TODO Not the ideal place to put it also com.test should be in the // properties file if (platform instanceof AndroidPlatform) { this.input = "package com.test; " + input; } String result = compileAndRun(platform); // The following instruction is used to remove some logging data // at the beginning of the result string if (platform == ObjcPlatform.getInstance() && result.indexOf("] ") != -1) result = result.substring(result.indexOf("] ") + 2); Assert.assertEquals(String.format("The platform %s", platform), expected, result); } protected String compileAndRun(Platform platform) throws Exception { String cleanOutput = cleanOutput(TestHelperCpp.generateCompileRun( platform, input, MAIN_CLASS_NAME)); return cleanOutput; } private static String cleanOutput(String result) { return result.replaceAll(CLEAN_UP_REGEX, "").trim(); } } private static final String MAIN_CLASS_NAME = "Test"; private List<Platform> testNotImplementedOnPlatforms = new ArrayList<Platform>(); private void excludePlatformForThisTest(Platform platform) { testNotImplementedOnPlatforms.add(platform); } @BeforeClass public static void init() { } //@Before @Test public void helloWorld() throws Exception { String input = TestHelperCpp.surroundWithIOSTREAMInclude(TestHelperCpp.surroundWithMain( "std::cout << \"Hello World\" << std::endl;")); String expected = "Hello World"; compareResultsDifferentPlatforms(input, expected); } @Test public void simpleAddition() throws Exception { String input = TestHelperCpp.surroundWithIOSTREAMInclude(TestHelperCpp.surroundWithMain( "int i = 2 + 2 ;" + "std::cout << i << std::endl;")); String expected = "4"; compareResultsDifferentPlatforms(input, expected); } @Test public void simpleIf1() throws Exception { String input = TestHelperCpp.surroundWithIOSTREAMInclude(TestHelperCpp.surroundWithMain( "int i = 0 ;" + "if(i==0) { std::cout << 4 << std::endl; } else { std::cout << 2 << std::endl; }")); String expected = "4"; compareResultsDifferentPlatforms(input, expected); } @Test public void simpleIf2() throws Exception { String input = TestHelperCpp.surroundWithIOSTREAMInclude(TestHelperCpp.surroundWithMain( "int i = 1 ;" + "if(i==0) { std::cout << 4 << std::endl; } else { std::cout << 2 << std::endl; }")); String expected = "2"; compareResultsDifferentPlatforms(input, expected); } @Test public void simpleFor() throws Exception { String input = TestHelperCpp.surroundWithIOSTREAMInclude(TestHelperCpp.surroundWithMain( "int total = 0 ;" + "for(int i = 0 ; i < 4 ; i++){ total++ ; } " + " std::cout << total << std::endl; ")); String expected = "4"; compareResultsDifferentPlatforms(input, expected); } @Test public void simpleWhile() throws Exception { String input = TestHelperCpp.surroundWithIOSTREAMInclude(TestHelperCpp.surroundWithMain( "int total = 0 ; int i = 0 ;" + "while( i < 4){ i++; total++ ; } " + " std::cout << total << std::endl; ")); String expected = "4"; compareResultsDifferentPlatforms(input, expected); } @Test public void simpleClass() throws Exception { String input = "#include <iostream>\n" + "class A{ public: int k = 5 * 2 + 3 }; " + TestHelperCpp.surroundWithMain(""); String expected = ""; compareResultsDifferentPlatforms(input, expected); } @Test public void simpleNew() throws Exception { String input = "#include <iostream>\n" + "class A{ public: " + " A(int newk){ k = newk; } ; " + " int k ; }; " + TestHelperCpp.surroundWithMain( " A a(5*2+3); " + "int toPrint = a.k ; " + " std::cout << toPrint << std::endl;" ); String expected = "13"; // TODO: Fix bugs. //excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void simpleMethod() throws Exception { String input = "#include <iostream>\n" + "class A{ public: " + " A(int newk){ k = newk; } ; " + " int k ; " + " int getK(){ return k ;} ; }; " + TestHelperCpp.surroundWithMain( " A a(5*2+3); " + "int toPrint = a.getK() ; " + " std::cout << toPrint << std::endl;" ); String expected = "13"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void simpleInheritance1() throws Exception { String input = "#include <iostream>\n" + "class A { public: " + " int k = 13; " + " int getK(){ return k ;} ; }; " + "class B : public A { public :" + " B(int newk2){ k2 = newk2 ;} ;" + " int k2 ; } ;" + TestHelperCpp.surroundWithMain( " B b(55); " + "int toPrint = b.getK() ; " + " std::cout << toPrint << std::endl;" ); String expected = "13"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void simpleInheritance2() throws Exception { String input = "#include <iostream>\n" + "class A { public: " + " int k = 13; " + " int getK(){ return k ;} ; }; " + "class B : public A { public :" + " B(int newk2){ k2 = newk2 ;} ;" + " int k2 ; } ;" + TestHelperCpp.surroundWithMain( " B b(55); " + "int toPrint = b.k2 ; " + " std::cout << toPrint << std::endl;" ); String expected = "55"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void simpleFileRefactoring1() throws Exception { String input = "#include <iostream>\n" + "int VARBLOBAL = 4 * 2 - 1; " + TestHelperCpp.surroundWithMain( " std::cout << VARBLOBAL << std::endl;" ); String expected = "7"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void simpleFileRefactoring2() throws Exception { String input = "#include <iostream>\n" + "int mult(int s1, int s2){ return s1 * s2 ; } " + TestHelperCpp.surroundWithMain( " int toPrint = mult(2, 4);" +" std::cout << toPrint << std::endl;" ); String expected = "8"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void unknownOperator() throws Exception { String input = TestHelperCpp.surroundWithMain( " int toPrint = 5 ^ 4 ; " +" std::cout << toPrint << std::endl;" ); String expected = ""; compareResultsDifferentPlatforms(input, expected); } @Test public void externalMethod() throws Exception { String input = "#include <iostream>\n" + "class A { public: " + " int k ; " + " A(int newk){ k = newk; } ; " + " int getK(); }; " + " int A::getK(){ return k; }" + TestHelperCpp.surroundWithMain( " A a(55);" + "int toPrint = a.getK(); ; " +" std::cout << toPrint << std::endl;" ); String expected = "55"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void externalField() throws Exception { String input = "#include <iostream>\n" + "class A { public: " + " int k ; " + " int k2 = 55 ; " + " A(int newk){ k = newk; } ; " + " int getK(){ return k; } ; } ;" + " A::k2 = 66 ; " + TestHelperCpp.surroundWithMain( " A a(55);" + "int toPrint = a.k2; ; " +" std::cout << toPrint << std::endl;" ); String expected = "66"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void simpleArray() throws Exception { String input = "#include <iostream>\n" + TestHelperCpp.surroundWithMain( " int array[12] ;" + " array[5] = 158 ; " +" std::cout << array[5] << std::endl;" ); String expected = "158"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void returnValue() throws Exception { String input = "#include <iostream>\n" + "int get(){ return 158; }" + TestHelperCpp.surroundWithMain( " std::cout << get() << std::endl;" ); String expected = "158"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void simpletryCatch() throws Exception { String input = "#include <iostream>\n" + TestHelperCpp.surroundWithMain( " int k = 55 ;" + " try { } catch (int e){ " +" std::cout << e << std::endl;}" + "std::cout << k << std::endl;" ); String expected = "55"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) JavaPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void simpleThrow() throws Exception { String input = "#include <iostream>\n" + TestHelperCpp.surroundWithMain( " try { throw 158; } catch (int e){ " +" std::cout << e << std::endl;}" ); String expected = "158"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) JavaPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void simpleThis() throws Exception { String input = "#include <iostream>\n" + "class Test { public :" + "Test(int k){ this.set(k); } ;" + "int get(){ return this->k ; };" + "void set(int k){ this->k = k; };" + "private :" + "int k ; } ;" + TestHelperCpp.surroundWithMain( " Test t(55*2); " + "int toPrint = t.get();" +" std::cout << toPrint << std::endl;}" ); String expected = "110"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void simpleRecursive() throws Exception { String input = "#include <iostream>\n" + " class A { public :" + " A(int k){ this.k = k ; } ; " + " A newA(int k){ A toReturn(k); return toReturn ; };" + " int getK(){ return this.k ; } ;" + " int k ;};" + "int k ; } ;" + TestHelperCpp.surroundWithMain( " A a(1); " + "int toPrint = a.newA(a.k+1).newA(a.k+2).newA(a.k+3).getK();" +" std::cout << toPrint << std::endl;}" ); String expected = "4"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void binaryAssign() throws Exception { String input = "#include <iostream>\n" + TestHelperCpp.surroundWithMain( " int i = 1; " + "i+=1; i*=2;" +" std::cout << i << std::endl;}" ); String expected = "4"; compareResultsDifferentPlatforms(input, expected); } @Test public void simpleEnum1() throws Exception { String input = "#include <iostream>\n" + "enum MyEnum { SMALL = 10, MEDIUM = 100, LARGE = 1000 };" + TestHelperCpp.surroundWithMain( " MyEnum state = MyEnum.SMALL ; " + "if(state == MyEnum.SMALL){" +" std::cout << \"1\" ;}" +" state = MyEnum.MEDIUM ; " + "if(state == MyEnum.MEDIUM){" +" std::cout << \"2\" ;}" +" state = MyEnum.LARGE ; " + "if(state == MyEnum.LARGE){" +" std::cout << \"3\" ;}" ); String expected = "123"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } @Test public void simpleEnum2() throws Exception { String input = "#include <iostream>\n" + "enum MyEnum { SMALL = 10, MEDIUM = 100, LARGE = 1000 };" + TestHelperCpp.surroundWithMain( " MyEnum state = MyEnum.SMALL ; " + "if(state == MyEnum.SMALL){" +" std::cout << \"1\" ;}" + "if(state == MyEnum.MEDIUM){" +" std::cout << \"2\" ;}" +" state = MyEnum.LARGE ; " + "if(state == MyEnum.LARGE){" +" std::cout << \"3\" ;}" ); String expected = "13"; // TODO: Fix bugs. excludePlatformForThisTest((Platform) CppPlatform.getInstance()); compareResultsDifferentPlatforms(input, expected); } private void compareResultsDifferentPlatforms(String input, String expected) throws Exception { compareResultsDifferentPlatforms(new GoolTestExecutor(input, expected, platforms, testNotImplementedOnPlatforms)); this.testNotImplementedOnPlatforms = new ArrayList<Platform>(); } private void compareResultsDifferentPlatforms(GoolTestExecutor executor) throws Exception { for (Platform platform : platforms) { executor.compare(platform); } } }