diff options
Diffstat (limited to 'tests/Lexer')
-rw-r--r-- | tests/Lexer/ContextTest.php | 39 | ||||
-rw-r--r-- | tests/Lexer/IsMethodsTest.php | 132 | ||||
-rw-r--r-- | tests/Lexer/LexerTest.php | 73 | ||||
-rw-r--r-- | tests/Lexer/TokenTest.php | 80 | ||||
-rw-r--r-- | tests/Lexer/TokensList.php | 107 |
5 files changed, 431 insertions, 0 deletions
diff --git a/tests/Lexer/ContextTest.php b/tests/Lexer/ContextTest.php new file mode 100644 index 0000000..b630d03 --- /dev/null +++ b/tests/Lexer/ContextTest.php @@ -0,0 +1,39 @@ +<?php + +namespace SqlParser\Tests\Lexer; + +use SqlParser\Context; + +use SqlParser\Tests\TestCase; + +class ContextTest extends TestCase +{ + + public function testLoad() + { + // Default context is 5.7.0. + $this->assertEquals('\\SqlParser\\Contexts\\ContextMySql50700', Context::$loadedContext); + $this->assertTrue(isset(Context::$KEYWORDS['STORED'])); + $this->assertFalse(isset(Context::$KEYWORDS['AUTHORS'])); + + Context::load('MySql50600'); + $this->assertEquals('\\SqlParser\\Contexts\\ContextMySql50600', Context::$loadedContext); + $this->assertFalse(isset(Context::$KEYWORDS['STORED'])); + $this->assertTrue(isset(Context::$KEYWORDS['AUTHORS'])); + + // Restoring context. + Context::load(''); + $this->assertEquals('\\SqlParser\\Contexts\\ContextMySql50700', Context::$defaultContext); + $this->assertTrue(isset(Context::$KEYWORDS['STORED'])); + $this->assertFalse(isset(Context::$KEYWORDS['AUTHORS'])); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Specified context ("\SqlParser\Contexts\ContextFoo") doesn't exist. + */ + public function testLoadError() + { + Context::load('Foo'); + } +} diff --git a/tests/Lexer/IsMethodsTest.php b/tests/Lexer/IsMethodsTest.php new file mode 100644 index 0000000..dfd065d --- /dev/null +++ b/tests/Lexer/IsMethodsTest.php @@ -0,0 +1,132 @@ +<?php + +namespace SqlParser\Tests\Lexer; + +use SqlParser\Context; +use SqlParser\Token; + +use SqlParser\Tests\TestCase; + +class IsMethodsTest extends TestCase +{ + + public function testIsKeyword() + { + $this->assertEquals(1 | Token::FLAG_KEYWORD_RESERVED, Context::isKeyword('SELECT')); + $this->assertEquals(1 | Token::FLAG_KEYWORD_RESERVED, Context::isKeyword('ALL')); + $this->assertEquals(1 | Token::FLAG_KEYWORD_RESERVED, Context::isKeyword('DISTINCT')); + + $this->assertEquals( + 1 | Token::FLAG_KEYWORD_COMPOSED | Token::FLAG_KEYWORD_KEY, + Context::isKeyword('PRIMARY KEY') + ); + $this->assertEquals(1 | Token::FLAG_KEYWORD_COMPOSED, Context::isKeyword('CHARACTER SET')); + + $this->assertEquals(1 | Token::FLAG_KEYWORD_RESERVED, Context::isKeyword('FROM', true)); + $this->assertEquals(null, Context::isKeyword('PRIMARY KEY', true)); + + $this->assertEquals(null, Context::isKeyword('foo')); + $this->assertEquals(null, Context::isKeyword('bar baz')); + } + + public function testIsOperator() + { + $this->assertEquals(Token::FLAG_OPERATOR_ARITHMETIC, Context::isOperator('%')); + $this->assertEquals(Token::FLAG_OPERATOR_LOGICAL, Context::isOperator('!')); + $this->assertEquals(Token::FLAG_OPERATOR_LOGICAL, Context::isOperator('&&')); + $this->assertEquals(Token::FLAG_OPERATOR_LOGICAL, Context::isOperator('<=>')); + $this->assertEquals(Token::FLAG_OPERATOR_BITWISE, Context::isOperator('&')); + $this->assertEquals(Token::FLAG_OPERATOR_ASSIGNMENT, Context::isOperator(':=')); + $this->assertEquals(Token::FLAG_OPERATOR_SQL, Context::isOperator(',')); + + $this->assertEquals(Context::isOperator('a'), null); + } + + public function testIsWhitespace() + { + $this->assertTrue(Context::isWhitespace(" ")); + $this->assertTrue(Context::isWhitespace("\r")); + $this->assertTrue(Context::isWhitespace("\n")); + $this->assertTrue(Context::isWhitespace("\t")); + + $this->assertFalse(Context::isWhitespace("a")); + $this->assertFalse(Context::isWhitespace("\b")); + $this->assertFalse(Context::isWhitespace("\u1000")); + } + + public function testIsComment() + { + $this->assertEquals(Token::FLAG_COMMENT_BASH, Context::isComment('#')); + $this->assertEquals(Token::FLAG_COMMENT_C, Context::isComment('/*')); + $this->assertEquals(Token::FLAG_COMMENT_C, Context::isComment('*/')); + $this->assertEquals(Token::FLAG_COMMENT_SQL, Context::isComment('-- ')); + $this->assertEquals(Token::FLAG_COMMENT_SQL, Context::isComment("--\t")); + + $this->assertEquals(Token::FLAG_COMMENT_BASH, Context::isComment('# a comment')); + $this->assertEquals(Token::FLAG_COMMENT_C, Context::isComment('/*comment */')); + $this->assertEquals(Token::FLAG_COMMENT_SQL, Context::isComment('-- my comment')); + + $this->assertEquals(Context::isComment("--\n"), null); + $this->assertEquals(Context::isComment('--not a comment'), null); + } + + public function testIsBool() + { + $this->assertTrue(Context::isBool('true')); + $this->assertTrue(Context::isBool('false')); + + $this->assertFalse(Context::isBool('tru')); + $this->assertFalse(Context::isBool('falsee')); + } + + public function testIsNumber() + { + $this->assertTrue(Context::isNumber('+')); + $this->assertTrue(Context::isNumber('-')); + $this->assertTrue(Context::isNumber('.')); + $this->assertTrue(Context::isNumber('0')); + $this->assertTrue(Context::isNumber('1')); + $this->assertTrue(Context::isNumber('2')); + $this->assertTrue(Context::isNumber('3')); + $this->assertTrue(Context::isNumber('4')); + $this->assertTrue(Context::isNumber('5')); + $this->assertTrue(Context::isNumber('6')); + $this->assertTrue(Context::isNumber('7')); + $this->assertTrue(Context::isNumber('8')); + $this->assertTrue(Context::isNumber('9')); + $this->assertTrue(Context::isNumber('e')); + $this->assertTrue(Context::isNumber('E')); + } + + public function testIsString() + { + $this->assertEquals(Token::FLAG_STRING_SINGLE_QUOTES, Context::isString("'")); + $this->assertEquals(Token::FLAG_STRING_DOUBLE_QUOTES, Context::isString('"')); + + $this->assertEquals(Token::FLAG_STRING_SINGLE_QUOTES, Context::isString("'foo bar'")); + $this->assertEquals(Token::FLAG_STRING_DOUBLE_QUOTES, Context::isString('"foo bar"')); + + $this->assertEquals(Context::isString('foo bar'), null); + } + + public function testIsSymbol() + { + $this->assertEquals(Token::FLAG_SYMBOL_VARIABLE, Context::isSymbol('@')); + $this->assertEquals(Token::FLAG_SYMBOL_BACKTICK, Context::isSymbol('`')); + + $this->assertEquals(Token::FLAG_SYMBOL_VARIABLE, Context::isSymbol('@id')); + $this->assertEquals(Token::FLAG_SYMBOL_BACKTICK, Context::isSymbol('`id`')); + + $this->assertEquals(Context::isSymbol('id'), null); + } + + public function testisSeparator() + { + $this->assertTrue(Context::isSeparator('+')); + $this->assertTrue(Context::isSeparator('.')); + + $this->assertFalse(Context::isSeparator('1')); + $this->assertFalse(Context::isSeparator('E')); + $this->assertFalse(Context::isSeparator('_')); + } +} diff --git a/tests/Lexer/LexerTest.php b/tests/Lexer/LexerTest.php new file mode 100644 index 0000000..dabe64d --- /dev/null +++ b/tests/Lexer/LexerTest.php @@ -0,0 +1,73 @@ +<?php + +namespace SqlParser\Tests\Lexer; + +use SqlParser\Exceptions\LexerException; +use SqlParser\Lexer; + +use SqlParser\Tests\TestCase; + +class LexerTest extends TestCase +{ + + public function testError() + { + $lexer = new Lexer(''); + + $lexer->error('error #1', 'foo', 1, 2); + $lexer->error('error #2', 'bar', 3, 4); + + $this->assertEquals( + $lexer->errors, + array( + new LexerException('error #1', 'foo', 1, 2), + new LexerException('error #2', 'bar', 3, 4), + ) + ); + } + + /** + * @expectedException SqlParser\Exceptions\LexerException + * @expectedExceptionMessage strict error + * @expectedExceptionCode 4 + */ + public function testErrorStrict() + { + $lexer = new Lexer(''); + $lexer->strict = true; + + $lexer->error('strict error', 'foo', 1, 4); + } + + /** + * @dataProvider testLexProvider + */ + public function testLex($test) + { + $this->runLexerTest($test); + } + + public function testLexProvider() + { + return array( + array('lex'), + array('lexBool'), + array('lexComment'), + array('lexDelimiter'), + array('lexDelimiter2'), + array('lexDelimiterErr1'), + array('lexDelimiterErr2'), + array('lexKeyword'), + array('lexNumber'), + array('lexOperator'), + array('lexString'), + array('lexStringErr1'), + array('lexSymbol'), + array('lexSymbolErr1'), + array('lexSymbolErr2'), + array('lexSymbolErr3'), + array('lexSymbolUser'), + array('lexWhitespace'), + ); + } +} diff --git a/tests/Lexer/TokenTest.php b/tests/Lexer/TokenTest.php new file mode 100644 index 0000000..24e2a4d --- /dev/null +++ b/tests/Lexer/TokenTest.php @@ -0,0 +1,80 @@ +<?php + +namespace SqlParser\Tests\Lexer; + +use SqlParser\Token; + +use SqlParser\Tests\TestCase; + +class TokenTest extends TestCase +{ + + public function testExtractKeyword() + { + $tok = new Token('SelecT', Token::TYPE_KEYWORD, Token::FLAG_KEYWORD_RESERVED); + $this->assertEquals($tok->value, 'SELECT'); + + $tok = new Token('aS', Token::TYPE_KEYWORD, Token::FLAG_KEYWORD_RESERVED); + $this->assertEquals($tok->value, 'AS'); + } + + public function testExtractWhitespace() + { + $tok = new Token(" \t \r \n ", Token::TYPE_WHITESPACE); + $this->assertEquals($tok->value, ' '); + } + + public function testExtractBool() + { + $tok = new Token('false', Token::TYPE_BOOL); + $this->assertFalse($tok->value); + + $tok = new Token('True', Token::TYPE_BOOL); + $this->assertTrue($tok->value); + } + + public function testExtractNumber() + { + $tok = new Token('--42', Token::TYPE_NUMBER, Token::FLAG_NUMBER_NEGATIVE); + $this->assertEquals($tok->value, 42); + + $tok = new Token('---42', Token::TYPE_NUMBER, Token::FLAG_NUMBER_NEGATIVE); + $this->assertEquals($tok->value, -42); + + $tok = new Token('0xFE', Token::TYPE_NUMBER, Token::FLAG_NUMBER_HEX); + $this->assertEquals($tok->value, 0xFE); + + $tok = new Token('-0xEF', Token::TYPE_NUMBER, Token::FLAG_NUMBER_NEGATIVE | Token::FLAG_NUMBER_HEX); + $this->assertEquals($tok->value, -0xEF); + + $tok = new Token('3.14', Token::TYPE_NUMBER, Token::FLAG_NUMBER_FLOAT); + $this->assertEquals($tok->value, 3.14); + } + + public function testExtractString() + { + $tok = new Token('"foo bar "', Token::TYPE_STRING); + $this->assertEquals($tok->value, 'foo bar '); + + $tok = new Token("' bar foo '", Token::TYPE_STRING); + $this->assertEquals($tok->value, ' bar foo '); + } + + public function testExtractSymbol() + { + $tok = new Token('@foo', Token::TYPE_SYMBOL, Token::FLAG_SYMBOL_VARIABLE); + $this->assertEquals($tok->value, 'foo'); + + $tok = new Token('`foo`', Token::TYPE_SYMBOL, Token::FLAG_SYMBOL_BACKTICK); + $this->assertEquals($tok->value, 'foo'); + + $tok = new Token('@`foo`', Token::TYPE_SYMBOL, Token::FLAG_SYMBOL_VARIABLE); + $this->assertEquals($tok->value, 'foo'); + } + + public function testInlineToken() + { + $token = new Token(" \r \n \t "); + $this->assertEquals($token->getInlineToken(), ' \r \n \t '); + } +} diff --git a/tests/Lexer/TokensList.php b/tests/Lexer/TokensList.php new file mode 100644 index 0000000..8887241 --- /dev/null +++ b/tests/Lexer/TokensList.php @@ -0,0 +1,107 @@ +<?php + +namespace SqlParser\Tests\Lexer; + +use SqlParser\Token; +use SqlParser\TokensList; + +use SqlParser\Tests\TestCase; + +class TokensListCase extends TestCase +{ + + /** + * Array of tokens that are used for testing. + * + * @var Token[] + */ + public $tokens; + + /** + * Constructor. + */ + public function __construct() + { + $this->tokens = array( + new Token('SELECT', Token::TYPE_KEYWORD), + new Token('*', Token::TYPE_OPERATOR), + new Token('FROM', Token::TYPE_KEYWORD), + new Token('`test`', Token::TYPE_SYMBOL) + ); + } + + /** + * Gets a list used for testing. + * + * @return TokensList + */ + public function getList() + { + $list = new TokensList(); + foreach ($this->tokens as $token) { + $list[] = $token; + } + return $list; + } + + public function testAdd() + { + $list = new TokensList(); + foreach ($this->tokens as $token) { + $list->add($token); + } + $this->assertEquals($this->getList(), $list); + } + + public function testGetNext() + { + $list = $this->getList(); + $this->assertEquals($this->tokens[0], $list->getNext()); + $this->assertEquals($this->tokens[1], $list->getNext()); + $this->assertEquals($this->tokens[2], $list->getNext()); + $this->assertEquals($this->tokens[3], $list->getNext()); + $this->assertEquals(null, $list->getNext()); + } + + public function testGetNextOfType() + { + $list = $this->getList(); + $this->assertEquals($this->tokens[0], $list->getNextOfType(Token::TYPE_KEYWORD)); + $this->assertEquals($this->tokens[2], $list->getNextOfType(Token::TYPE_KEYWORD)); + $this->assertEquals(null, $list->getNextOfType(Token::TYPE_KEYWORD)); + } + + public function testGetNextOfTypeAndValue() + { + $list = $this->getList(); + $this->assertEquals($this->tokens[0], $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'SELECT')); + $this->assertEquals(null, $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'SELECT')); + } + + public function testArrayAccess() + { + $list = new TokensList(); + + // offsetSet(NULL, $value) + foreach ($this->tokens as $token) { + $list[] = $token; + } + + // offsetSet($offset, $value) + $list[2] = $this->tokens[2]; + + // offsetGet($offset) + for ($i = 0, $count = count($this->tokens); $i < $count; ++$i) { + $this->assertEquals($this->tokens[$i], $list[$i]); + } + + // offsetExists($offset) + $this->assertTrue(isset($list[2])); + $this->assertFalse(isset($list[5])); + + // offsetUnset($offset) + unset($list[2]); + $this->assertEquals($this->tokens[3], $list[2]); + + } +} |