From 7167ce41b61d2ba2cdb526777a4233eb84a3b66a Mon Sep 17 00:00:00 2001 From: Unit 193 Date: Sat, 6 Dec 2014 17:33:25 -0500 Subject: Imported Upstream version 2.99.6 --- SQLiteStudio3/Tests/ParserTest/tst_parsertest.cpp | 357 ++++++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 SQLiteStudio3/Tests/ParserTest/tst_parsertest.cpp (limited to 'SQLiteStudio3/Tests/ParserTest/tst_parsertest.cpp') diff --git a/SQLiteStudio3/Tests/ParserTest/tst_parsertest.cpp b/SQLiteStudio3/Tests/ParserTest/tst_parsertest.cpp new file mode 100644 index 0000000..5eb96a8 --- /dev/null +++ b/SQLiteStudio3/Tests/ParserTest/tst_parsertest.cpp @@ -0,0 +1,357 @@ +#include "parser/parser.h" +#include "parser/ast/sqliteselect.h" +#include "parser/ast/sqlitecreatetable.h" +#include "parser/keywords.h" +#include "parser/lexer.h" +#include "parser/parsererror.h" +#include +#include +#include + +class ParserTest : public QObject +{ + Q_OBJECT + + public: + ParserTest(); + + private: + Parser* parser2 = nullptr; + Parser* parser3 = nullptr; + + private Q_SLOTS: + void testGetTableTokens(); + void testGetTableTokens2(); + void testGetDatabaseTokens(); + void testGetFullObjects(); + void testGetFullObjects2(); + void testUnfinishedSingleSourceWithTolerance(); + void testCommentEnding1(); + void testCommentEnding2(); + void testOper1(); + void testBig1(); + void testTableFk(); + void testDoubleQuotes(); + void testInsertError(); + void testExpr(); + void testCommentBeginMultiline(); + void initTestCase(); + void cleanupTestCase(); +}; + +ParserTest::ParserTest() +{ +} + +void ParserTest::testGetTableTokens() +{ + QString sql = "select someTable.* FROM someTable;"; + + parser3->parse(sql); + QVERIFY(parser3->getErrors().size() == 0); + + SqliteQueryPtr query = parser3->getQueries()[0]; + TokenList tokens = query->getContextTableTokens(); + QVERIFY(tokens.size() == 2); + QVERIFY(tokens[0]->type == Token::OTHER); + QVERIFY(tokens[1]->type == Token::OTHER); +} + +void ParserTest::testGetTableTokens2() +{ + QString sql = "select db.tab.col FROM someTable;"; + + parser3->parse(sql); + QVERIFY(parser3->getErrors().size() == 0); + + SqliteQueryPtr query = parser3->getQueries()[0]; + TokenList tokens = query->getContextTableTokens(); + QVERIFY(tokens.size() == 2); + QVERIFY(tokens[0]->type == Token::OTHER); + QVERIFY(tokens[1]->type == Token::OTHER); +} + +void ParserTest::testGetDatabaseTokens() +{ + QString sql = "select * FROM someDb.[table];"; + + parser3->parse(sql); + QVERIFY(parser3->getErrors().size() == 0); + + SqliteQueryPtr query = parser3->getQueries()[0]; + TokenList tokens = query->getContextTableTokens(); + QVERIFY(tokens.size() == 1); + QVERIFY(tokens[0]->type == Token::OTHER); +} + +void ParserTest::testGetFullObjects() +{ + QString sql = "select col FROM someDb.[table];"; + + parser3->parse(sql); + QVERIFY(parser3->getErrors().size() == 0); + + SqliteQueryPtr query = parser3->getQueries()[0]; + QList fullObjects = query->getContextFullObjects(); + QVERIFY(fullObjects.size() == 2); + + foreach (const SqliteStatement::FullObject& fullObj, fullObjects) + { + switch (fullObj.type) + { + case SqliteStatement::FullObject::TABLE: + QVERIFY(fullObj.database && fullObj.database->value == "someDb"); + QVERIFY(fullObj.object && fullObj.object->value == "[table]"); + break; + case SqliteStatement::FullObject::DATABASE: + QVERIFY(fullObj.database && fullObj.database->value == "someDb"); + break; + default: + QFAIL("Unexpected FullObject type."); + } + } +} + +void ParserTest::testGetFullObjects2() +{ + QString sql = "select col, tab2.*, abcDb.abcTab.abcCol FROM someDb.[table];"; + + parser3->parse(sql); + QVERIFY(parser3->getErrors().size() == 0); + + SqliteQueryPtr query = parser3->getQueries()[0]; + QList fullObjects = query->getContextFullObjects(); + QVERIFY(fullObjects.size() == 5); + + foreach (const SqliteStatement::FullObject& fullObj, fullObjects) + { + switch (fullObj.type) + { + case SqliteStatement::FullObject::TABLE: + { + QVERIFY(fullObj.object); + if (fullObj.database && fullObj.database->value == "someDb") + QVERIFY(fullObj.object->value == "[table]"); + else if (fullObj.database && fullObj.database->value == "abcDb") + QVERIFY(fullObj.object->value == "abcTab"); + else if (!fullObj.database) + QVERIFY(fullObj.object->value == "tab2"); + else + QFAIL("Invalid TABLE full object."); + + break; + } + case SqliteStatement::FullObject::DATABASE: + { + if (fullObj.database) + QVERIFY(fullObj.database->value == "someDb" || fullObj.database->value == "abcDb"); + else + QFAIL("Invalid DATABASE full object."); + + break; + } + default: + QFAIL("Unexpected FullObject type."); + } + } +} + +void ParserTest::testUnfinishedSingleSourceWithTolerance() +{ + QString sql = "SELECT * FROM test.;"; + bool res = parser3->parse(sql, true); + QVERIFY(res); +} + +void ParserTest::testCommentEnding1() +{ + QString sql = "select 1 --aaa"; + bool res = parser3->parse(sql); + QVERIFY(res); +} + +void ParserTest::testCommentEnding2() +{ + QString sql = "select 1 /*aaa"; + bool res = parser3->parse(sql); + QVERIFY(res); +} + +void ParserTest::testOper1() +{ + QString sql = "SELECT dfgd<=2"; + TokenList tokens = Lexer::tokenize(sql, Dialect::Sqlite3); + QVERIFY(tokens[2]->value == "dfgd"); + QVERIFY(tokens[3]->value == "<="); + QVERIFY(tokens[4]->value == "2"); +} + +void ParserTest::testBig1() +{ + QString sql = "select " + "''|| " + "''|| " + "''|| " + "''|| " + "''|| " + "''|| " + "''|| " + "'Ð�TH;°Ñ禅TH;°Ð»Ñ즅TH;½Ð¸Ðº Ñ㦅TH;¿ÑঅTH;°Ð²Ð»ÐµÐ½Ð¸Ñ怜t;/P1>'|| " + "''|| " + "''||strftime('%d.%m.%Y',d.demdate)||''|| " + "'4642'||substr('000000'||d.id, -6, 6)||''|| " + "''|| " + "''||ins.fullname||''|| " + "''||ins.shortname||''|| " + "'0'||ins.regnum||''|| " + "''|| " + "''||ins.inn||''|| " + "''||ins.kpp||''|| " + "''||ins.addr||''|| " + "''||ins.postaddr||''|| " + "''||round(dem_s+dem_n+dem_f+dem_t,2)||''|| " + "''||strftime('%d.%m.%Y',d.demdate,'+15 day')||''|| " + "'0,00'|| " + "'0,00'|| " + "''|| " + "'0,00'|| " + "''|| " + "'0,00'|| " + "'0,00'|| " + "''|| " + "'0,00'|| " + "''|| " + "'0,00'|| " + "'0,00'|| " + "''||round(dem_s+dem_n+dem_f+dem_t,2)||''|| " + "''||round(dem_s+dem_n,2)||''|| " + "'0,00'|| " + "''||round(dem_s,2)||''|| " + "''||case when d.dem_s>0 then '(ÐꦅTH;ᦅTH;ꠧ'||kbk.kbk_s||')' else '' end || ''|| " + "''||round(dem_n,2)||''|| " + "''||case when d.dem_n>0 then '(ÐꦅTH;ᦅTH;ꠧ'||kbk.kbk_n||')' else '' end||''|| " + "''||round(dem_f,2)||''|| " + "''||case when d.dem_f>0 then '(ÐꦅTH;ᦅTH;ꠧ'||kbk.kbk_f||')' else '' end||''|| " + "''||round(dem_t,2)||''|| " + "''||case when d.dem_t>0 then '(ÐꦅTH;ᦅTH;ꠧ'||kbk.kbk_t||')' else '' end||''|| " + "'0,00'|| " + "'0,00 0,00 0,00 0,00'|| " + "'Ñ঎tilde;㦅TH;±.;'|| " + "'0,00'|| " + "''|| " + "'0,00'|| " + "''|| " + "'0,00'|| " + "''|| " + "'0,00'|| " + "''|| " + "'0,00'|| " + "''|| " + "''|| " + "''|| " + "''||strftime('%d.%m.%Y',d.demdate)||''|| " + "'0'|| " + "''|| " + "'0'|| " + "''|| " + "''||ins.Specname||''|| " + "''|| " + "'' " + "from demands d " + "left join ins on ins.regnum=d.regnum " + "left join kbk on kbk.cat=ins.Cat " + "limit 1"; + + bool res = parser3->parse(sql); + if (!res) + { + qWarning() << parser3->getErrorString(); + ParserError* error = parser3->getErrors().first(); + qDebug() << "Error starts at:" << sql.mid(error->getFrom()); + } + + QVERIFY(res); +} + +void ParserTest::testTableFk() +{ + QString sql = "CREATE TABLE test (id INTEGER, FOREIGN KEY (id) REFERENCES test2 (id2));"; + + parser3->parse(sql); + QVERIFY(parser3->getErrors().size() == 0); + + SqliteQueryPtr query = parser3->getQueries()[0]; + SqliteCreateTablePtr creatrTable = query.dynamicCast(); + QVERIFY(creatrTable->constraints.size() == 1); + QVERIFY(creatrTable->constraints.first()->indexedColumns.size() == 1); + QVERIFY(creatrTable->constraints.first()->indexedColumns.first()->name == "id"); + QVERIFY(creatrTable->constraints.first()->type == SqliteCreateTable::Constraint::FOREIGN_KEY); + QVERIFY(creatrTable->constraints.first()->foreignKey != nullptr); + QVERIFY(creatrTable->constraints.first()->foreignKey->foreignTable == "test2"); + QVERIFY(creatrTable->constraints.first()->foreignKey->indexedColumns.size() == 1); + QVERIFY(creatrTable->constraints.first()->foreignKey->indexedColumns.first()->name == "id2"); +} + +void ParserTest::testDoubleQuotes() +{ + QString sql = "select \"1\""; + bool res = parser3->parse(sql); + QVERIFY(res); + QVERIFY(parser3->getQueries().size() > 0); + + SqliteQueryPtr query = parser3->getQueries().first(); + QVERIFY(query); + + SqliteSelectPtr select = query.dynamicCast(); + QVERIFY(select); + QVERIFY(select->coreSelects.size() > 0); + QVERIFY(select->coreSelects.first()->resultColumns.size() > 0); + + SqliteSelect::Core::ResultColumn* rc = select->coreSelects.first()->resultColumns.first(); + SqliteExpr* e = rc->expr; + QVERIFY(e); + + QVERIFY(e->mode == SqliteExpr::Mode::ID); + QVERIFY(e->possibleDoubleQuotedString); +} + +void ParserTest::testInsertError() +{ + QString sql = "INSERT INTO test "; + bool res = parser3->parse(sql); + QVERIFY(!res); + QVERIFY(parser3->getErrors().size() == 1); +} + +void ParserTest::testExpr() +{ + QString sql = "CAST (CASE WHEN port REGEXP '^[A-Z]' THEN substr(port, 2) ELSE port END AS INT) AS port"; + SqliteExpr* expr = parser3->parseExpr(sql); + QVERIFY(expr); +} + +void ParserTest::testCommentBeginMultiline() +{ + QString sql = "/*"; + TokenList tokens = Lexer::tokenize(sql, Dialect::Sqlite3); + QVERIFY(tokens.size() == 1); + QVERIFY(tokens[0]->type == Token::COMMENT); +} + +void ParserTest::initTestCase() +{ + initKeywords(); + Lexer::staticInit(); + parser2 = new Parser(Dialect::Sqlite2); + parser3 = new Parser(Dialect::Sqlite3); +} + +void ParserTest::cleanupTestCase() +{ + delete parser2; + delete parser3; +} + +QTEST_APPLESS_MAIN(ParserTest) + +#include "tst_parsertest.moc" -- cgit v1.2.3