summaryrefslogtreecommitdiffstats
path: root/tests/Lexer
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Lexer')
-rw-r--r--tests/Lexer/ContextTest.php39
-rw-r--r--tests/Lexer/IsMethodsTest.php132
-rw-r--r--tests/Lexer/LexerTest.php73
-rw-r--r--tests/Lexer/TokenTest.php80
-rw-r--r--tests/Lexer/TokensList.php107
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]);
+
+ }
+}