package org.develnext.jphp; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.junit.runners.MethodSorters; import php.runtime.env.Context; import php.runtime.env.Environment; import php.runtime.env.TraceInfo; import php.runtime.exceptions.ParseException; import org.develnext.jphp.core.tokenizer.Tokenizer; import org.develnext.jphp.core.tokenizer.token.CommentToken; import org.develnext.jphp.core.tokenizer.token.SemicolonToken; import org.develnext.jphp.core.tokenizer.token.Token; import org.develnext.jphp.core.tokenizer.token.expr.*; import org.develnext.jphp.core.tokenizer.token.expr.operator.*; import org.develnext.jphp.core.tokenizer.token.expr.value.*; import org.develnext.jphp.core.tokenizer.token.expr.value.macro.*; import org.develnext.jphp.core.tokenizer.token.stmt.*; import java.io.IOException; import java.math.BigInteger; import static org.junit.Assert.*; @RunWith(JUnit4.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TokenizerTest { private Environment environment = new Environment(); @Test public void testSimple() throws IOException { Tokenizer tokenizer = new Tokenizer(new Context( "")); assertNull(tokenizer.nextToken()); assertEquals("", tokenizer.getCode()); tokenizer = new Tokenizer(new Context( " ")); assertNull(tokenizer.nextToken()); tokenizer = new Tokenizer(new Context( " ")); assertNull(tokenizer.nextToken()); tokenizer = new Tokenizer(new Context( "\t")); assertNull(tokenizer.nextToken()); tokenizer = new Tokenizer(new Context( "\n")); assertNull(tokenizer.nextToken()); tokenizer = new Tokenizer(new Context( "\r")); assertNull(tokenizer.nextToken()); } @Test public void testScalarTokens() throws IOException { Token token; Tokenizer tokenizer = new Tokenizer(new Context( "10 3.3 'foo' '' \"xyz\" 0xCC 0b0011 true false")); token = tokenizer.nextToken(); assertTrue(token instanceof IntegerExprToken); assertEquals(10L, ((IntegerExprToken) token).getValue()); token = tokenizer.nextToken(); assertTrue(token instanceof DoubleExprToken); assertEquals(3.3, ((DoubleExprToken) token).getValue(), 0.01); token = tokenizer.nextToken(); assertTrue(token instanceof StringExprToken); assertEquals(StringExprToken.Quote.SINGLE, ((StringExprToken) token).getQuote()); assertEquals("foo", ((StringExprToken) token).getValue()); token = tokenizer.nextToken(); assertTrue(token instanceof StringExprToken); assertEquals(StringExprToken.Quote.SINGLE, ((StringExprToken) token).getQuote()); assertEquals("", ((StringExprToken) token).getValue()); token = tokenizer.nextToken(); assertTrue(token instanceof StringExprToken); assertEquals(StringExprToken.Quote.DOUBLE, ((StringExprToken) token).getQuote()); assertEquals("xyz", ((StringExprToken) token).getValue()); token = tokenizer.nextToken(); assertTrue(token instanceof IntegerExprToken); assertEquals(new BigInteger("CC", 16).longValue(), ((IntegerExprToken) token).getValue()); token = tokenizer.nextToken(); assertTrue(token instanceof IntegerExprToken); assertEquals(new BigInteger("0011", 2).longValue(), ((IntegerExprToken) token).getValue()); token = tokenizer.nextToken(); assertTrue(token instanceof BooleanExprToken); assertEquals(true, ((BooleanExprToken) token).getValue()); token = tokenizer.nextToken(); assertTrue(token instanceof BooleanExprToken); assertEquals(false, ((BooleanExprToken) token).getValue()); token = tokenizer.nextToken(); assertNull(token); } @Test public void testStringSlashes() throws IOException { Token token; Tokenizer tokenizer = new Tokenizer(new Context( " 'foo\\'bar' \"foo\\\"bar\"")); token = tokenizer.nextToken(); assertTrue(token instanceof StringExprToken); assertEquals("foo'bar", ((StringExprToken) token).getValue()); token = tokenizer.nextToken(); assertTrue(token instanceof StringExprToken); assertEquals("foo\"bar", ((StringExprToken) token).getValue()); } @Test public void testMagicString() throws IOException { Token token; Tokenizer tokenizer = new Tokenizer(new Context("\"\\.{$foo}\"")); token = tokenizer.nextToken(); assertTrue(token instanceof StringExprToken); assertEquals(".{$foo}", ((StringExprToken) token).getValue()); assertEquals(1, ((StringExprToken) token).getSegments().size()); StringExprToken.Segment segment =((StringExprToken) token).getSegments().get(0); assertEquals(1, segment.from); assertEquals(7, segment.to); } @Test public void testComplexOperators() throws IOException { Tokenizer tokenizer = new Tokenizer(new Context( "== >= <= === !== != && ||")); assertTrue(tokenizer.nextToken() instanceof EqualExprToken); assertTrue(tokenizer.nextToken() instanceof GreaterOrEqualExprToken); assertTrue(tokenizer.nextToken() instanceof SmallerOrEqualToken); assertTrue(tokenizer.nextToken() instanceof IdenticalExprToken); assertTrue(tokenizer.nextToken() instanceof NotIdenticalExprToken); assertTrue(tokenizer.nextToken() instanceof BooleanNotEqualExprToken); assertTrue(tokenizer.nextToken() instanceof BooleanAndExprToken); assertTrue(tokenizer.nextToken() instanceof BooleanOrExprToken); } @Test public void testSimpleOperators() throws IOException { Tokenizer tokenizer = new Tokenizer(new Context( "= + - / * % . and or new && || ! xor **")); assertTrue(tokenizer.nextToken() instanceof AssignExprToken); assertTrue(tokenizer.nextToken() instanceof PlusExprToken); assertTrue(tokenizer.nextToken() instanceof MinusExprToken); assertTrue(tokenizer.nextToken() instanceof DivExprToken); assertTrue(tokenizer.nextToken() instanceof MulExprToken); assertTrue(tokenizer.nextToken() instanceof ModExprToken); assertTrue(tokenizer.nextToken() instanceof ConcatExprToken); assertTrue(tokenizer.nextToken() instanceof BooleanAnd2ExprToken); assertTrue(tokenizer.nextToken() instanceof BooleanOr2ExprToken); assertTrue(tokenizer.nextToken() instanceof NewExprToken); assertTrue(tokenizer.nextToken() instanceof BooleanAndExprToken); assertTrue(tokenizer.nextToken() instanceof BooleanOrExprToken); assertTrue(tokenizer.nextToken() instanceof BooleanNotExprToken); assertTrue(tokenizer.nextToken() instanceof BooleanXorExprToken); assertTrue(tokenizer.nextToken() instanceof PowExprToken); } @Test public void testParseError() throws IOException { Throwable ex = null; Tokenizer tokenizer = new Tokenizer(new Context( " 'foobar \n ")); try { tokenizer.nextToken(); } catch (Throwable e){ ex = e; } assertTrue(ex instanceof ParseException); TraceInfo traceInfo = ((ParseException) ex).getTraceInfo(); assertNotNull(traceInfo); assertNull(traceInfo.getContext().getFileName()); assertEquals(1, traceInfo.getStartLine()); assertEquals(1, traceInfo.getEndLine()); assertEquals(1, traceInfo.getStartPosition()); assertEquals(1, traceInfo.getEndPosition()); } @Test public void testComplex() throws IOException { Tokenizer tokenizer = new Tokenizer(new Context( "0==10==='30';")); assertTrue(tokenizer.nextToken() instanceof IntegerExprToken); assertTrue(tokenizer.nextToken() instanceof EqualExprToken); assertTrue(tokenizer.nextToken() instanceof IntegerExprToken); assertTrue(tokenizer.nextToken() instanceof IdenticalExprToken); assertTrue(tokenizer.nextToken() instanceof StringExprToken); assertTrue(tokenizer.nextToken() instanceof SemicolonToken); tokenizer = new Tokenizer(new Context("F =; 20;")); Token token; assertTrue((token = tokenizer.nextToken()) instanceof NameToken); assertEquals("F", ((NameToken)token).getName()); assertTrue(tokenizer.nextToken() instanceof AssignExprToken); assertTrue(tokenizer.nextToken() instanceof SemicolonToken); assertTrue(tokenizer.nextToken() instanceof IntegerExprToken); assertTrue(tokenizer.nextToken() instanceof SemicolonToken); tokenizer = new Tokenizer(new Context("123foobar MAX_64Bit")); token = tokenizer.nextToken(); assertTrue(token instanceof IntegerExprToken); token = tokenizer.nextToken(); assertTrue(token instanceof NameToken); assertEquals("foobar", token.getWord()); assertTrue(tokenizer.nextToken() instanceof NameToken); assertNull(tokenizer.nextToken()); assertNull(tokenizer.nextToken()); } @Test public void testBraces() throws IOException { Tokenizer tokenizer = new Tokenizer(new Context(" :: ->foobar('a', 1, 3.0);")); assertTrue(tokenizer.nextToken() instanceof StaticAccessExprToken); assertTrue(tokenizer.nextToken() instanceof DynamicAccessExprToken); assertTrue(tokenizer.nextToken() instanceof NameToken); assertTrue(tokenizer.nextToken() instanceof BraceExprToken); assertTrue(tokenizer.nextToken() instanceof StringExprToken); assertTrue(tokenizer.nextToken() instanceof CommaToken); assertTrue(tokenizer.nextToken() instanceof IntegerExprToken); assertTrue(tokenizer.nextToken() instanceof CommaToken); assertTrue(tokenizer.nextToken() instanceof DoubleExprToken); assertTrue(tokenizer.nextToken() instanceof BraceExprToken); assertTrue(tokenizer.nextToken() instanceof SemicolonToken); } @Test public void testVarVar() throws IOException { Tokenizer tokenizer = new Tokenizer(new Context("$$foo $ $bar $$$foobar")); assertTrue(tokenizer.nextToken() instanceof DollarExprToken); assertTrue(tokenizer.nextToken() instanceof VariableExprToken); assertTrue(tokenizer.nextToken() instanceof DollarExprToken); assertTrue(tokenizer.nextToken() instanceof VariableExprToken); assertTrue(tokenizer.nextToken() instanceof DollarExprToken); assertTrue(tokenizer.nextToken() instanceof DollarExprToken); assertTrue(tokenizer.nextToken() instanceof VariableExprToken); tokenizer = new Tokenizer(new Context("${'foo;6bar'}")); assertTrue(tokenizer.nextToken() instanceof DollarExprToken); assertTrue(tokenizer.nextToken() instanceof BraceExprToken); assertTrue(tokenizer.nextToken() instanceof StringExprToken); assertTrue(tokenizer.nextToken() instanceof BraceExprToken); } @Test public void testMacro() throws IOException { Tokenizer tokenizer = new Tokenizer( new Context("__LINE__ __FILE__ __DIR__ __METHOD__ __FUNCTION__ __CLASS__ __NAMESPACE__ __TRAIT__") ); assertTrue(tokenizer.nextToken() instanceof LineMacroToken); assertTrue(tokenizer.nextToken() instanceof FileMacroToken); assertTrue(tokenizer.nextToken() instanceof DirMacroToken); assertTrue(tokenizer.nextToken() instanceof MethodMacroToken); assertTrue(tokenizer.nextToken() instanceof FunctionMacroToken); assertTrue(tokenizer.nextToken() instanceof ClassMacroToken); assertTrue(tokenizer.nextToken() instanceof NamespaceMacroToken); assertTrue(tokenizer.nextToken() instanceof TraitMacroToken); } @Test public void testStmt() throws IOException { Tokenizer tokenizer = new Tokenizer(new Context( "class function private public protected static final try catch for if foreach switch while " + "default return declare case do else elseif endif endfor endforeach endwhile endswitch " + "abstract use namespace finally extends implements global" )); assertTrue(tokenizer.nextToken() instanceof ClassStmtToken); assertTrue(tokenizer.nextToken() instanceof FunctionStmtToken); assertTrue(tokenizer.nextToken() instanceof PrivateStmtToken); assertTrue(tokenizer.nextToken() instanceof PublicStmtToken); assertTrue(tokenizer.nextToken() instanceof ProtectedStmtToken); assertTrue(tokenizer.nextToken() instanceof StaticExprToken); assertTrue(tokenizer.nextToken() instanceof FinalStmtToken); assertTrue(tokenizer.nextToken() instanceof TryStmtToken); assertTrue(tokenizer.nextToken() instanceof CatchStmtToken); assertTrue(tokenizer.nextToken() instanceof ForStmtToken); assertTrue(tokenizer.nextToken() instanceof IfStmtToken); assertTrue(tokenizer.nextToken() instanceof ForeachStmtToken); assertTrue(tokenizer.nextToken() instanceof SwitchStmtToken); assertTrue(tokenizer.nextToken() instanceof WhileStmtToken); assertTrue(tokenizer.nextToken() instanceof DefaultStmtToken); assertTrue(tokenizer.nextToken() instanceof ReturnStmtToken); assertTrue(tokenizer.nextToken() instanceof DeclareStmtToken); assertTrue(tokenizer.nextToken() instanceof CaseStmtToken); assertTrue(tokenizer.nextToken() instanceof DoStmtToken); assertTrue(tokenizer.nextToken() instanceof ElseStmtToken); assertTrue(tokenizer.nextToken() instanceof ElseIfStmtToken); assertTrue(tokenizer.nextToken() instanceof EndifStmtToken); assertTrue(tokenizer.nextToken() instanceof EndforStmtToken); assertTrue(tokenizer.nextToken() instanceof EndforeachStmtToken); assertTrue(tokenizer.nextToken() instanceof EndwhileStmtToken); assertTrue(tokenizer.nextToken() instanceof EndswitchStmtToken); assertTrue(tokenizer.nextToken() instanceof AbstractStmtToken); assertTrue(tokenizer.nextToken() instanceof NamespaceUseStmtToken); assertTrue(tokenizer.nextToken() instanceof NamespaceStmtToken); assertTrue(tokenizer.nextToken() instanceof FinallyStmtToken); assertTrue(tokenizer.nextToken() instanceof ExtendsStmtToken); assertTrue(tokenizer.nextToken() instanceof ImplementsStmtToken); assertTrue(tokenizer.nextToken() instanceof GlobalStmtToken); } @Test public void testSplitNot() throws IOException { Tokenizer tokenizer = new Tokenizer( new Context("!true") ); assertTrue(tokenizer.nextToken() instanceof BooleanNotExprToken); assertTrue(tokenizer.nextToken() instanceof BooleanExprToken); } @Test public void testComments() throws IOException { Tokenizer tokenizer = new Tokenizer( new Context("/** FOO BAR \n\r100500 */") ); Token token = tokenizer.nextToken(); assertTrue(token instanceof CommentToken); assertEquals(CommentToken.Kind.DOCTYPE, ((CommentToken) token).getKind()); assertEquals("FOO BAR\n\n100500", ((CommentToken) token).getComment()); // simple tokenizer = new Tokenizer( new Context("// foobar \n $x") ); token = tokenizer.nextToken(); assertTrue(token instanceof CommentToken); assertEquals(CommentToken.Kind.SIMPLE, ((CommentToken) token).getKind()); assertEquals(" foobar ", ((CommentToken) token).getComment()); assertTrue(tokenizer.nextToken() instanceof VariableExprToken); assertNull(tokenizer.nextToken()); tokenizer = new Tokenizer( new Context("# // foobar \n $x") ); token = tokenizer.nextToken(); assertTrue(token instanceof CommentToken); assertEquals(CommentToken.Kind.SIMPLE, ((CommentToken) token).getKind()); assertEquals(" // foobar ", ((CommentToken) token).getComment()); assertTrue(tokenizer.nextToken() instanceof VariableExprToken); assertNull(tokenizer.nextToken()); // block tokenizer = new Tokenizer( new Context("/* foobar \n */") ); token = tokenizer.nextToken(); assertTrue(token instanceof CommentToken); assertEquals(CommentToken.Kind.BLOCK, ((CommentToken) token).getKind()); } @Test public void testHeredoc() throws IOException { Tokenizer tokenizer = new Tokenizer( new Context("<<<DOC\n <foobar> \nDOC;\n") ); Token token = tokenizer.nextToken(); assertTrue(token instanceof StringExprToken); assertEquals(StringExprToken.Quote.DOC, ((StringExprToken) token).getQuote()); assertEquals(" <foobar> ", ((StringExprToken) token).getValue()); tokenizer = new Tokenizer( new Context("<<<\"DOC\"\n \\n<foobar> \nDOC;\n") ); token = tokenizer.nextToken(); assertTrue(token instanceof StringExprToken); assertEquals(StringExprToken.Quote.DOC, ((StringExprToken) token).getQuote()); assertEquals(" \n<foobar> ", ((StringExprToken) token).getValue()); tokenizer = new Tokenizer( new Context("<<<'DOC'\n \\n<foobar> \nDOC;\n") ); token = tokenizer.nextToken(); assertTrue(token instanceof StringExprToken); assertEquals(StringExprToken.Quote.DOC, ((StringExprToken) token).getQuote()); assertEquals(" \\n<foobar> ", ((StringExprToken) token).getValue()); tokenizer = new Tokenizer( new Context("a(<<<DOC\n<foobar>\nDOC\n)\n") ); token = tokenizer.nextToken(); assertTrue(token instanceof NameToken); token = tokenizer.nextToken(); assertTrue(token instanceof BraceExprToken); token = tokenizer.nextToken(); assertTrue(token instanceof StringExprToken); assertEquals(StringExprToken.Quote.DOC, ((StringExprToken) token).getQuote()); assertEquals("<foobar>", ((StringExprToken) token).getValue()); } @Test public void testBug122() throws IOException { Tokenizer tokenizer = new Tokenizer( new Context("<<<ESC\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "<?php\n" + "ESC;\n") ); Token token = tokenizer.nextToken(); assertTrue(token instanceof StringExprToken); assertEquals(StringExprToken.Quote.DOC, ((StringExprToken) token).getQuote()); assertEquals("\n\n\n\n\n<?php", ((StringExprToken) token).getValue()); } }