package ch.unibe.scg.cc.javaFrontend; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.util.Iterator; import org.junit.Test; import ch.unibe.scg.cc.Protos.Function; import dk.brics.automaton.Automaton; import dk.brics.automaton.AutomatonMatcher; import dk.brics.automaton.RegExp; import dk.brics.automaton.RunAutomaton; @SuppressWarnings("javadoc") public class JavaTokenizerTest { @Test public void theRegexWorks() { String regex = JavaTokenizer.splitterRegex; Automaton a = new RegExp(regex).toAutomaton(); RunAutomaton r = new RunAutomaton(a); assertFalse(r.newMatcher("String myString = new String(new int[] { 1, 2, 3});").find()); assertFalse(r.newMatcher("return Integer.class").find()); assertTrue(r.newMatcher("\nclass MyClass<String> {\n").find()); assertTrue(r.newMatcher("\n class MyClass<String> {").find()); } @Test public void scumBagRegex() { String regex = "[\n]+"; Automaton a = new RegExp(regex).toAutomaton(); RunAutomaton r = new RunAutomaton(a); AutomatonMatcher m = r.newMatcher("\n\n\n"); assertTrue(m.find()); assertFalse(r.newMatcher("\\n").find()); } @Test public void testSampleClass() { Iterator<Function> iter = new JavaTokenizer().tokenize(sampleClass()).iterator(); assertThat(iter.next(), is(Function.newBuilder().setBaseLine(4).setContents("public class Rod {\n").build())); assertThat(iter.next(), is(Function.newBuilder().setBaseLine(5).setContents( "\tpublic static void main(String[] args) {\n\t\tout.println(\"Hiya, wassup?\");\n\t\tfish.stink.Rod.doIt(new int[] { 1, 2 ,3 });\n\t}\n").build())); assertThat(iter.next(), is(Function.newBuilder().setBaseLine(9).setContents( "\t\t\tprotected static void doIt() {\n\t\tif(System.timeInMillis() > 10000)\n\t\t\tout.println(1337);\n\t\tmain(null);\n\t}\n}\n").build())); assertThat(iter.hasNext(), is(Boolean.FALSE)); } String sampleClass() { return "package fish.stink;\n" + "import java.util.*;\n" + "import static System.out;\n\n" + "public class Rod {\n" + "\tpublic static void main(String[] args) {\n" + "\t\tout.println(\"Hiya, wassup?\");\n" + "\t\tfish.stink.Rod.doIt(new int[] { 1, 2 ,3 });\n" + " }\n" + "\t\t\tprotected static void doIt() {\n" + "\t\tif(System.timeInMillis() > 10000)\n" + "\t\t\tout.println(1337);\n" + "\t\tmain(null);\n" + "\t}\n" + "}\n"; } @Test public void testBiggerSampleClass() { Iterator<Function> iter = new JavaTokenizer().tokenize(biggerSampleClass()).iterator(); assertThat(iter.next(), is(Function.newBuilder().setBaseLine(4).setContents( "public class Math {\n" + "\tstatic final int[] POWERS_OF_10 = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };\n" + "\tstatic final int[] HALF_POWERS_OF_10 = { 3, 31, 316, 3162, 31622, 316227, 3162277, 31622776, 316227766,\n" + "\t\t\tInteger.MAX_VALUE };\n" + "\tstatic final byte[] MAX_LOG_10_FOR_LEADING_ZEROS = { 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0 };\n" + "\n").build())); assertThat(iter.next(), is(Function.newBuilder().setBaseLine(10).setContents( "\tpublic static int log10(int x, RoundingMode mode) {\n" + "\t\tcheckPositive(\"x\", x);\n" + "\t\tint logFloor = log10Floor(x);\n" + "\t\tint floorPow = POWERS_OF_10[logFloor];\n" + "\t\tint result = -1;\n" + "\t\tswitch (mode) {\n" + "\t\tcase UNNECESSARY:\n" + "\t\t\tcheckRoundingUnnecessary(x == floorPow);\n" + "\t\t\t// fall through\n" + "\t\tcase DOWN:\n" + "\t\t\tresult = logFloor;\n" + "\t\tcase CEILING:\n" + "\t\tcase UP:\n" + "\t\t\tresult = (x == floorPow) ? logFloor : logFloor - 1;\n" + "\t\tcase HALF_DOWN:\n" + "\t\tcase HALF_UP:\n" + "\t\tcase HALF_EVEN:\n" + "\t\t\t// sqrt(10) is irrational, so log10(x) - logFloor is never exactly\n" + "\t\t\t// 0.5\n" + "\t\t\tresult = (x <= HALF_POWERS_OF_10[logFloor]) ? logFloor : logFloor - 1;\n" + "\t\t}\n" + "\t\treturn result;\n" + "\t}\n" + "\n").build())); assertThat(iter.next(), is(Function.newBuilder().setBaseLine(34).setContents( "\tprivate static int log10Floor(int x) {\n" + "\t\tint y = MAX_LOG_10_FOR_LEADING_ZEROS[Integer.numberOfLeadingZeros(x)];\n" + "\t\tint sgn = (x - POWERS_OF_10[y]) >>> (Integer.SIZE - 1);\n" + "\t\treturn y - sgn;\n" + "\t}\n" + "\n").build())); assertThat(iter.next(), is(Function.newBuilder().setBaseLine(40).setContents( "\tstatic void checkRoundingUnnecessary(boolean condition) {\n" + "\t\tif (!condition) {\n" + "\t\t\tthrow new ArithmeticException(\"mode was UNNECESSARY, but rounding was necessary\");\n" + "\t\t}\n" + "\t}\n" + "\n").build())); assertThat(iter.next(), is(Function.newBuilder().setBaseLine(46).setContents( "\tstatic int checkPositive(String role, int x) {\n" + "\t\tif (x <= 0) {\n" + "\t\t\tthrow new IllegalArgumentException(role + \" (\" + x + \") must be > 0\");\n" + "\t\t}\n" + "\t\treturn x;\n" + "\t}\n" + "}\n").build())); assertThat(iter.hasNext(), is(Boolean.FALSE)); } String biggerSampleClass() { return "package com.stradivari.util;\n" + "\n" + "import java.math.RoundingMode;\n" + "\n" + "public class Math {\n" + "\tstatic final int[] POWERS_OF_10 = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };\n" + "\tstatic final int[] HALF_POWERS_OF_10 = { 3, 31, 316, 3162, 31622, 316227, 3162277, 31622776, 316227766,\n" + "\t\t\tInteger.MAX_VALUE };\n" + "\tstatic final byte[] MAX_LOG_10_FOR_LEADING_ZEROS = { 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0 };\n" + "\n" + "\tpublic static int log10(int x, RoundingMode mode) {\n" + "\t\tcheckPositive(\"x\", x);\n" + "\t\tint logFloor = log10Floor(x);\n" + "\t\tint floorPow = POWERS_OF_10[logFloor];\n" + "\t\tint result = -1;\n" + "\t\tswitch (mode) {\n" + "\t\tcase UNNECESSARY:\n" + "\t\t\tcheckRoundingUnnecessary(x == floorPow);\n" + "\t\t\t// fall through\n" + "\t\tcase DOWN:\n" + "\t\t\tresult = logFloor;\n" + "\t\tcase CEILING:\n" + "\t\tcase UP:\n" + "\t\t\tresult = (x == floorPow) ? logFloor : logFloor - 1;\n" + "\t\tcase HALF_DOWN:\n" + "\t\tcase HALF_UP:\n" + "\t\tcase HALF_EVEN:\n" + "\t\t\t// sqrt(10) is irrational, so log10(x) - logFloor is never exactly\n" + "\t\t\t// 0.5\n" + "\t\t\tresult = (x <= HALF_POWERS_OF_10[logFloor]) ? logFloor : logFloor - 1;\n" + "\t\t}\n" + "\t\treturn result;\n" + "\t}\n" + "\n" + "\tprivate static int log10Floor(int x) {\n" + "\t\tint y = MAX_LOG_10_FOR_LEADING_ZEROS[Integer.numberOfLeadingZeros(x)];\n" + "\t\tint sgn = (x - POWERS_OF_10[y]) >>> (Integer.SIZE - 1);\n" + "\t\treturn y - sgn;\n" + "\t}\n" + "\n" + "\tstatic void checkRoundingUnnecessary(boolean condition) {\n" + "\t\tif (!condition) {\n" + "\t\t\tthrow new ArithmeticException(\"mode was UNNECESSARY, but rounding was necessary\");\n" + "\t\t}\n" + "\t}\n" + "\n" + "\tstatic int checkPositive(String role, int x) {\n" + "\t\tif (x <= 0) {\n" + "\t\t\tthrow new IllegalArgumentException(role + \" (\" + x + \") must be > 0\");\n" + "\t\t}\n" + "\t\treturn x;\n" + "\t}\n" + "}\n"; } }