import java.util.Arrays;

import junit.framework.TestCase;
/*
 * File JavaTokenCounterTest.java
 * Created on Dec 2, 2004
 */


/*
 * File JavaTokenCounterTest.java
 * Created on Dec 2, 2004
 */


/**
 * @author Dave Matuszek
 * @version Dec 2, 2004
 */
public class JavaTokenCounterTest extends TestCase {
    JavaTokenCounter counter = new JavaTokenCounter();
    StringDataSource ds;

    private static final int NAME                = 1;
    private static final int KEYWORD             = 2;
    private static final int INTEGER             = 3;
    private static final int REAL                = 4;
    private static final int CHARACTER           = 5;
    private static final int STRING              = 6;
    private static final int C_STYLE_COMMENT     = 7;
    private static final int END_OF_LINE_COMMENT = 8;
    private static final int JAVADOC_COMMENT     = 9;
    private static final int OPERATOR            = 10;
    private static final int PUNCTUATION         = 11;

    private int[] expected = new int[12];
    private static boolean debugging = false;

    protected void setUp() throws Exception {
        super.setUp();
        counter.clearAllCounts();
        for (int i = 0; i < expected.length; i++) {
            expected[i] = 0;
        }
        debug(false);
    }

    public void testPunctuation() {
        String s = "[]{}(),:; [ ] { } ( ) , : ; }";
        expected[PUNCTUATION] = 19;
        verify(s);
    }

    public void testOperators() {
        String s = "+ - * / % ++ -- < << > >> >>> <= >= == != " +
                   "& ^ ~ | && || ?: = += -= *= /= %= >>= <<= " +
                   ">>>= &= ^= |= . . / ";
        expected[OPERATOR] = 38;
        expected[PUNCTUATION] = 1;
        verify(s);
    }

    public void testNames() {
        String s = "foo abc123 MAX_VAL MyClass poor_name ";
        expected[NAME] = 5;
        verify(s);

        s = "int2 forget iff $while do_while IF THEN ELSE Do instanceOf ";
        expected[NAME] += 10;
        verify(s);

        s = "FOO_BAR _12$$3 ab5cd __x__ $5 x+y-z ";
        expected[NAME] += 8;
        expected[OPERATOR] += 2;
        verify(s);
        
        counter.clearAllCounts();
        s = "import java.util.*; ";
        expected[KEYWORD] = 1;
        expected[NAME] = 2;
        expected[OPERATOR] = 3;
        expected[PUNCTUATION] = 1;
        verify(s);
    }

    public void testKeywords() {
        String s = "if while case catch public import";
        expected[KEYWORD] = 6;
        verify(s);
        s = "abstract boolean break byte case catch char "
                + "class const continue default do double else "
                + "enum extends false final finally float for "
                + "goto if implements import instanceof int "
                + "interface long native new null package private "
                + "protected public return short static super "
                + "switch synchronized this throw throws transient "
                + "true try void volatile while ";
        expected[KEYWORD] += 51;
        verify(s);
    }

    public void testIntegers() {        
        String s = "123 +456 -789 ";
        expected[INTEGER] = 3;
        expected[OPERATOR] = 2;
        verify(s);
        
        s = "0 1 123 123L 123l 0xABCDEF 0X12345 0123 0+0-0 ";
        expected[INTEGER] += 11;
        expected[OPERATOR] += 2;
        verify(s);
    }
    
    public void testReals() {
        String s = "1.2 0.3 00.3 .4 5. 6e7 8E9 10f 11F 1.E2 .3E-4 .5F 6.F 8E+9-8e-8 ";
        expected[REAL] = 15;
        expected[OPERATOR] = 1;
        verify(s);
    }
    
    public void testCharacters() {
        // Note: Backslashes in character literals must be escaped
        String s = "'a' '\\n' '\\t' '\\007' '\\u3c00' 'b' '\\\'' 'c' '\\\\' ";
        expected[CHARACTER] = 9;
        verify(s);
    }
    
    public void testStrings() {
        // Note: Backslashes in String literals must be escaped
        String s = "\"string\" \"another string\" ";
        expected[STRING] = 2;
        expected[NAME] = 0;
        verify(s);
        
        s = "\"She said, \\\"Hello\\\"\" and I said " +
                "\"\\\"Well...\\tGoodbye\\\"\" ";
        expected[STRING] += 2;
        expected[NAME] += 3;
        verify(s);
    }
    
    public void testCStyleComments() {
        String s = "/*comment*/ /* second * comment */" +
                   "/* third /comment *//*fourth /* comment*/" +
                   " /* fifth comment\nover multiple\nlines */" +
                   "/* sixth ** comment **/ /* *not Javadoc! * */";
        expected[C_STYLE_COMMENT] = 7;
        verify(s);
    }
    
    public void testEndOfLineComments() {
        String s = "// comment to end of line\n";
        expected[END_OF_LINE_COMMENT] = 1;
        verify(s);
        
        s = "\"String\"//comment 2 \n// comment 3 \n\n";
        expected[STRING] += 1;
        expected[END_OF_LINE_COMMENT] += 2;
        verify(s);
        
        s = " // just */ one // comment // here\n";

        expected[END_OF_LINE_COMMENT] += 1;
        verify(s);
    }
    
    public void testJavadocComments() {
        String s = "/**comment*/ /** second /* *comment */" +
                   "/** third /comment *//**fourth /* comment*/" +
                   " /** fifth comment\n* over multiple\nlines */" +
                   "/** sixth ** comment **/";
        expected[JAVADOC_COMMENT] = 6;
        verify(s);
    }
    
    public void testStatements() {
        String s = "for(int i=0;i<100;i++)System.out.println(i+\" \"+(i*i)); ";
        expected[KEYWORD] = 2;
        expected[PUNCTUATION] = 9;
        expected[NAME] = 9;
        expected[OPERATOR] = 8;
        expected[INTEGER] = 2;
        expected[STRING] = 1;
        verify(s);
        
        s = "while ((ch = nextChar()) != '\\n') {\n    getChar();\n}";
        expected[KEYWORD] += 1;
        expected[PUNCTUATION] += 11;
        expected[NAME] += 3;
        expected[OPERATOR] += 2;
        expected[CHARACTER] += 1;
        verify(s);
        
        s = "assert x >= 0.0: \"Negative value of x\"; ";
        expected[KEYWORD] += 1;
        expected[PUNCTUATION] += 2;
        expected[NAME] += 1;
        expected[OPERATOR] += 1;
        expected[REAL] += 1;
        expected[STRING] += 1;
        verify(s);
    }
    
    public void testMoreStuff() {
        String s = "b=!b; i=~i; k=-k; x=.5; ";
        expected[NAME] = 7;
        expected[OPERATOR] = 7;
        expected[PUNCTUATION] = 4;
        expected[REAL] = 1;
        verify(s);
        
        // Unused variables, just to show that syntax is legal
        double d1 = 1.23D;
        float f = 1.23E12F;
        long hex = 0xCAFEBABEL;
        long oct = 0777L;
        
        s = "123d 1.23D 1.23E12F 1.23E12d 0xCAFEBABEL 0777L ";
        expected[REAL] += 4;
        expected[INTEGER] += 2;
        verify(s);
        
        s = " /**/ 0L 00L 009.5 ";
        expected[C_STYLE_COMMENT] += 1;
        expected[INTEGER] += 2;
        expected[REAL] += 1;
        verify(s);
    }
    
    private void debug(boolean printStuff) {
        debugging = printStuff;
        // You can uncomment the next line if you provide this method
//        counter.debug(printStuff);
    }

    private void verify(String s) {
        ds = new StringDataSource(s);
        if (debugging) System.out.println(s);
        counter.countTokens(ds);
        assertEquals(expected[NAME],                counter.getNameCount());
        assertEquals(expected[KEYWORD],             counter.getKeywordCount());
        assertEquals(expected[INTEGER],             counter.getIntegerLiteralCount());
        assertEquals(expected[REAL],                counter.getRealLiteralCount());
        assertEquals(expected[CHARACTER],           counter.getCharacterLiteralCount());
        assertEquals(expected[PUNCTUATION],         counter.getPunctuationCount());
        assertEquals(expected[STRING],              counter.getStringLiteralCount());
        assertEquals(expected[C_STYLE_COMMENT],     counter.getCStyleCommentCount());
        assertEquals(expected[END_OF_LINE_COMMENT], counter.getEndOfLineCommentCount());
        assertEquals(expected[JAVADOC_COMMENT],     counter.getJavadocCommentCount());
        assertEquals(expected[OPERATOR],            counter.getOperatorCount());
    }
}