/*
* 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.Settings;
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.python.PythonPlatform;
import gool.generator.objc.ObjcPlatform;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class GoolTestJava {
/*
* 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(TestHelperJava.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 = TestHelperJava.surroundWithClassMain(
"System.out.println(\"Hello World\");", MAIN_CLASS_NAME);
String expected = "Hello World";
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void goolLibraryTest1() throws Exception {
String input = "import java.io.File;"
+ TestHelperJava
.surroundWithClassMain(
"/* création puis suppression d'un fichier qui n'existait pas */"
+ "try{"
+ "File f = new File(\"../testGool.txt\");"
+
"if(f.exists()){ System.out.println(\"true\"); }"
+ "else{ System.out.println(\"false\");}"
+
"if(f.createNewFile()){ System.out.println(\"true\"); }"
+ "else{ System.out.println(\"false\"); }"
+
"if(f.exists()){ System.out.println(\"true\"); }"
+ "else{ System.out.println(\"false\");}"
+
"if(f.delete()){ System.out.println(\"true\"); }"
+ "else{ System.out.println(\"false\"); }"
+
"if(f.exists()){ System.out.println(\"true\"); }"
+ "else{ System.out.println(\"false\");}"
+ "}catch(Exception e){" + "}",
MAIN_CLASS_NAME);
String expected = "false" + "true" + "true" + "true" + "false";
// Matching of the GoolFile library class and of its method
// work only for the Java target language at the moment,
// so we exclude the other platforms for this test.
excludePlatformForThisTest((Platform) CSharpPlatform.getInstance());
excludePlatformForThisTest((Platform) CppPlatform.getInstance());
excludePlatformForThisTest((Platform) PythonPlatform.getInstance());
excludePlatformForThisTest((Platform) AndroidPlatform.getInstance());
excludePlatformForThisTest((Platform) ObjcPlatform.getInstance());
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void goolLibraryTest2() throws Exception {
String input = "import java.io.File;"
+ "import java.io.BufferedReader;"
+ "import java.io.FileReader;"
+ "import java.io.BufferedWriter;"
+ "import java.io.FileWriter;"
+
TestHelperJava
.surroundWithClassMain(
"/* Creation d'un fichier, écriture, lecture, puis suppression du fichier. */"
+ "try{"
+ "File f = new File(\"../testGool.txt\");"
+ "f.createNewFile();"
+
"FileWriter fw=new FileWriter(f);"
+ "BufferedWriter bw=new BufferedWriter(fw);"
+ "bw.write('a'); bw.write('b'); bw.close();"
+
"FileReader fr=new FileReader(f);"
+ "BufferedReader br=new BufferedReader(fr);"
+ "char c1=(char)br.read(), c2=(char)br.read(); br.close();"
+ "System.out.println(c1+\"\"+c2);" +
"f.delete();" + "}catch(Exception e){"
+ "}", MAIN_CLASS_NAME);
String expected = "ab";
// Matching of the io GOOL library with classes and methods
// of the output language work only for the Java target at the moment,
// so we exclude the other platforms for this test.
excludePlatformForThisTest((Platform) CSharpPlatform.getInstance());
excludePlatformForThisTest((Platform) CppPlatform.getInstance());
excludePlatformForThisTest((Platform) PythonPlatform.getInstance());
excludePlatformForThisTest((Platform) AndroidPlatform.getInstance());
excludePlatformForThisTest((Platform) ObjcPlatform.getInstance());
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void goolLibraryTest3() throws Exception {
String input = "import java.io.File;"
+ "import java.io.BufferedReader;"
+ "import java.io.FileReader;"
+ "import java.io.BufferedWriter;"
+ "import java.io.FileWriter;"
+
TestHelperJava.surroundWithClassMain(
"/* Creation d'un fichier, écriture, lecture, puis suppression du fichier. */"
+ "try{"
+ "File f = new File(\"../testGool.txt\");"
+ "f.createNewFile();" +
"FileWriter fw=new FileWriter(f);"
+ "BufferedWriter bw=new BufferedWriter(fw);"
+ "String s=\"hello world\\n42\\n\";"
+ "bw.write(s,0,s.length()); bw.close();" +
"FileReader fr=new FileReader(f);"
+ "BufferedReader br=new BufferedReader(fr);"
+ "String line=br.readLine();"
+ "while(line!=null){"
+ "System.out.println(line);"
+ "line=br.readLine();" + "}" + "br.close();"
+ "f.delete();" + "}catch(Exception e){" + "}",
MAIN_CLASS_NAME);
String expected = "hello world42";
// Matching of the io GOOL library with classes and methods
// of the output language work only for the Java target at the moment,
// so we exclude the other platforms for this test.
excludePlatformForThisTest((Platform) CSharpPlatform.getInstance());
excludePlatformForThisTest((Platform) CppPlatform.getInstance());
excludePlatformForThisTest((Platform) PythonPlatform.getInstance());
excludePlatformForThisTest((Platform) AndroidPlatform.getInstance());
excludePlatformForThisTest((Platform) ObjcPlatform.getInstance());
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void simpleTryCatch() throws Exception {
String input = TestHelperJava.surroundWithClassMain("try {\n "
+ "System.out.println(\"hello\");"
+
// "String s=null;" +
// "s.isEmpty();" +
"}" + "catch(Exception e){" + "System.out.println(\"world\");"
+ "}", MAIN_CLASS_NAME);
String expected = "hello";
// Generation of exceptions do not work in some of the target language
// at the
// moment, so we exclude their respective platform for this test.
excludePlatformForThisTest((Platform) CppPlatform.getInstance());
excludePlatformForThisTest((Platform) AndroidPlatform.getInstance());
excludePlatformForThisTest((Platform) ObjcPlatform.getInstance());
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void simpleChar() throws Exception {
String input = TestHelperJava.surroundWithClassMain(
"char testChar = 'A'; System.out.println(testChar);",
MAIN_CLASS_NAME);
String expected = "A";
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void simpleAddition() throws Exception {
String input = TestHelperJava.surroundWithClassMain(
"System.out.println(2 + 2);", MAIN_CLASS_NAME);
String expected = "4";
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void simpleIf() throws Exception {
String input = TestHelperJava
.surroundWithClassMain(
"boolean b = true; if (b) { System.out.println(2 + 2);} else { System.out.println(2 + 5); }",
MAIN_CLASS_NAME);
String expected = "4";
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void simpleFor() throws Exception {
String input = TestHelperJava
.surroundWithClassMain(
"int total = 0; for(int i = 0; i < 4; i++){ total ++;} System.out.println(total);",
MAIN_CLASS_NAME);
String expected = "4";
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void listAddGet() throws Exception {
String input = "import java.util.ArrayList;\n"
+ TestHelperJava
.surroundWithClassMain(
"ArrayList<Integer> l = new ArrayList<Integer>(); l.add(4); System.out.println(l.get(0));",
MAIN_CLASS_NAME);
String expected = "4";
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void mapAddGet() throws Exception {
// String input =
// TestHelper.surroundWithClassMain("HashMap<String, Integer > m = new HashMap<String, Integer>();",
// "Test");
String input = "import java.util.HashMap;\n"
+
TestHelperJava
.surroundWithClassMain(
"String four = \"four\"; HashMap<String, Integer > m = new HashMap<String, Integer>(); m.put(four,4); System.out.println(m.get(four));",
MAIN_CLASS_NAME);
String expected = "4";
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void simpleNew() throws Exception {
String input = TestHelperJava
.surroundWithClass(
"public void printr(){System.out.println(2 + 2);} public static void main(String[] args){ Test t = new Test(); t.printr();}",
MAIN_CLASS_NAME, "");
String expected = "4";
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void simpleTwoClasses() throws Exception {
String input = TestHelperJava.surroundWithClassMain(
"Printer p = new Printer(); p.printr();", MAIN_CLASS_NAME);
input += "\n"
+ TestHelperJava.surroundWithClass(
"public void printr() {System.out.println(2 + 2);}",
"Printer", "");
String expected = "4";
System.out.println(input);
excludePlatformForThisTest((Platform) CppPlatform.getInstance());
excludePlatformForThisTest((Platform) PythonPlatform.getInstance());
excludePlatformForThisTest((Platform) ObjcPlatform.getInstance());
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void simpleForEach() throws Exception {
String input = "import java.util.ArrayList;\n"
+ TestHelperJava
.surroundWithClassMain(
"Integer total = 0;"
+ " ArrayList<Integer> l = new ArrayList<Integer>();"
+ " l.add(-2); l.add(-1);l.add(0); l.add(1); l.add(2);l.add(4);"
+ " for(Integer i : l){"
+ "total = total + i;" + "}"
+ "System.out.println(total);",
MAIN_CLASS_NAME);
String expected = "4";
// There is a code generation problem to be fixed for this test in
// Objective C, so we exclude the ObjC platform for this test.
// (see GOOL wiki for further documentation)
excludePlatformForThisTest((Platform) ObjcPlatform.getInstance());
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void listWithDifferentTypeElement() throws Exception {
String input = "import java.util.ArrayList;\n"
+ TestHelperJava
.surroundWithClassMain(
"ArrayList l = new ArrayList();l.add(1);l.add(\"hola\");System.out.println(l.size());",
MAIN_CLASS_NAME);
compareResultsDifferentPlatforms(input, "2");
}
@Test
public void mapWithoutTypes() throws Exception {
try {
String input = "import java.util.HashMap;\n"
+ TestHelperJava
.surroundWithClassMain(
"HashMap m = new HashMap();m.put(0, 1);m.put(\"hola\", 2);System.out.println(m.size());",
MAIN_CLASS_NAME);
compareResultsDifferentPlatforms(input, "2");
} catch (Exception e) {
if (e.getCause() != null
&& e.getCause().getClass()
.equals(IllegalStateException.class)) {
return;
}
}
Assert.fail("Maps with object keys are not allowed in C++.");
}
@Test
public void removeElementsFromUntypedList() throws Exception {
String input = "import java.util.ArrayList;\n"
+ TestHelperJava
.surroundWithClassMain(
"ArrayList l = new ArrayList();l.add(\"\");l.add(\"hola\");l.remove(\"hola\");System.out.println(l.size());",
MAIN_CLASS_NAME);
compareResultsDifferentPlatforms(input, "1");
}
@Test
public void removeElementsFromIntegerList() throws Exception {
String input = "import java.util.ArrayList;\n"
+ TestHelperJava
.surroundWithClassMain(
"ArrayList<Integer> l = new ArrayList<Integer>();l.add(1);l.add(4);l.remove(1);System.out.println(l.size());",
MAIN_CLASS_NAME);
compareResultsDifferentPlatforms(input, "1");
}
@Test
public void removeElementsFromMap() throws Exception {
String input = "import java.util.HashMap;\n"
+ TestHelperJava
.surroundWithClassMain(
"HashMap<Integer, Integer> m = new HashMap<Integer, Integer>();m.put(1, 2);m.put(2, 3);m.remove(2);System.out.println(m.size());",
MAIN_CLASS_NAME);
compareResultsDifferentPlatforms(input, "1");
}
@Test
public void isEmptyList() throws Exception {
String input = "import java.util.ArrayList;\n"
+ TestHelperJava
.surroundWithClassMain(
"ArrayList l = new ArrayList();l.add(\"hola\");l.remove(\"hola\");System.out.println(l.isEmpty());",
MAIN_CLASS_NAME);
compareResultsDifferentPlatforms(new GoolTestExecutor(input, "true",
platforms, testNotImplementedOnPlatforms) {
@Override
protected String compileAndRun(Platform platform) throws Exception {
String output = super.compileAndRun(platform).toLowerCase();
// C++ does not have booleans
if ("1".equals(output)) {
output = "true";
} else if ("0".equals(output)) {
output = "false";
}
return output;
}
});
}
@Test
public void listContainsElement() throws Exception {
String input = "import java.util.ArrayList;\n"
+ TestHelperJava
.surroundWithClassMain(
"ArrayList l = new ArrayList();l.add(\"hola\");l.remove(\"hola\");l.add(\"hola\");System.out.println(l.contains(\"hola\"));",
MAIN_CLASS_NAME);
Assert.fail("Not implemented");
}
@Test
public void classWithAttributes() throws Exception {
String input = "class Test {"
+ "public int z; public Test(int i){this.z=i+2;}"
+ "public static void main(String[] args){"
+ "System.out.println(new Test(5).z);" + "}}";
compareResultsDifferentPlatforms(input, "7");
}
@Test
public void unknownOperator() throws Exception {
String input = TestHelperJava.surroundWithClassMain(
"int total = 1 ^ 0; System.out.println(total);",
MAIN_CLASS_NAME);
String expected = "";
compareResultsDifferentPlatforms(input, expected);
}
@Test
public void exceptionThrowTest() throws Exception {
String input = TestHelperJava
.surroundWithClassMain(
"try {\n Test t=new Test(); t.printr();\n}\n"
+ "catch(Exception e) {\n System.out.println(\"e\");\n}\n}"
+ "\n public void printr() throws Exception, Exception {System.out.println(2 + 2);",
MAIN_CLASS_NAME);
String expected = "4";
// Generation of exceptions do not work in some of the target language
// at the
// moment, so we exclude their respective platform for this test.
excludePlatformForThisTest((Platform) CppPlatform.getInstance());
excludePlatformForThisTest((Platform) AndroidPlatform.getInstance());
excludePlatformForThisTest((Platform) ObjcPlatform.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);
}
}
}