package org.jmlspecs.openjmltest.testcases;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.jmlspecs.openjml.JmlPretty;
import org.jmlspecs.openjmltest.ParseBase;
import org.jmlspecs.openjmltest.TestJavaFileObject;
import org.junit.Test;
import com.sun.tools.javac.parser.Parser;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Log;
/** This set of tests test that the pretty printer outputs properly. The test
* checks this by comparing the input code to the output code; before comparison,
* each sequence of white space is replaced by a single space, so that the
* output formatting does not have to precisely match the input (unless
* precise is set true, which it currently is).
*/
public class prettyprinting extends ParseBase {
boolean precise = true;
@Override
public void setUp() throws Exception {
super.setUp();
print = false;
}
public void helpPP(String code) {
try {
//print = true;
Log.instance(context).useSource(new TestJavaFileObject(code));
Parser p = fac.newParser(code,false,true,true);
//sc = ((JmlParser)p).getScanner();
JCTree tree = p.parseCompilationUnit();
String out = JmlPretty.write(tree);
if (collector.getDiagnostics().size() != 0) printDiagnostics();
assertEquals("Found parsing errors",0,collector.getDiagnostics().size());
if (!precise) {
code = code.replaceAll("[ \t\r\n]+"," ");
out = out.replaceAll("[ \t\r\n]+"," ");
} else {
code = code.replaceAll("[\r]","");
out = out.replaceAll("[\r]","");
}
if (print || !code.equals(out)) {
System.out.println("IN:");
System.out.print(code);
System.out.println("OUT:");
System.out.print(out);
//printTree(ParseTreeScanner.walk(tree));
}
assertEquals("Output differs",code,out);
} catch (Exception e) {
e.printStackTrace(System.out);
fail("Exception thrown while processing test: " + e);
}
}
String eol = System.getProperty("line.separator");
@Test
public void testSimpleClass() {
helpPP(
eol +
"class A {" + eol +
"}"
);
}
@Test
public void testPackage() {
helpPP(
"package t;" + eol +
eol +
"class A {" + eol +
"}"
);
}
@Test
public void testImport() {
helpPP(
"package t;" + eol +
eol +
"import java.io.File;" + eol +
eol +
"class A {" + eol +
"}"
);
}
@Test
public void testImportStar() {
helpPP(
"package t;" + eol + eol +
"import java.io.File;" + eol +
"import java.io.*;" + eol + eol +
"class A {" + eol +
"}"
);
}
@Test
public void testModelImport() {
helpPP(
"package t;" + eol + eol +
"//@ model import java.io.File;" + eol +
"//@ model import java.io.*;" + eol + eol +
"class A {" + eol +
"}"
);
}
@Test
public void testClassModifiers() {
helpPP(
eol +
"public static final class A {" + eol +
"}"
);
}
@Test
public void testMethodDecl() {
helpPP(
eol +
"public static final class A {" + eol +
" " + eol +
" void m() {" + eol +
" }" + eol +
"}"
);
}
@Test
public void testMethodModifiers() {
helpPP(
eol +
"class A {" + eol +
" " + eol +
" public static void m() {" + eol +
" }" + eol +
"}"
);
}
@Test
public void testMethodStatements() {
precise = true;
helpPP(
eol +
"public static final class A {" + eol +
" " + eol +
" int p(int a, Object o) {" + eol +
" }" + eol +
" " + eol +
" void m() {" + eol +
" int a;" + eol +
" a = 5;" + eol +
" ;" + eol +
" a += 5;" + eol +
" /*@ assume a == 6;*/" + eol +
" /*@ assert a == 6;*/" + eol +
" /*@ debug a = 6;*/" + eol +
" /*@ set a = 6;*/" + eol +
" a += 5;" + eol +
" a -= 5;" + eol +
" a *= 5;" + eol +
" a /= 5;" + eol +
" a %= 5;" + eol +
" a |= 5;" + eol +
" a &= 5;" + eol +
" a ^= 5;" + eol +
" a <<= 5;" + eol +
" a >>= 5;" + eol +
" a >>>= 5;" + eol +
" m();" + eol +
" for (int i = 0; i < 5; i++) {" + eol +
" }" + eol +
" for (int i : new int[6]) {" + eol +
" }" + eol +
" while (true) {" + eol +
" do {" + eol +
" } while (true);" + eol + // FIXME - excess space
" }" + eol +
" }" + eol +
"}"
);
}
// FIXME - need to test every construct (lots more) for pretty printing; also for with and without jml comments
}