From e7924f3739218575b6d06795787b0dd85e8c5b6a Mon Sep 17 00:00:00 2001 From: Martin Kleusberg Date: Fri, 11 Jul 2014 21:31:34 +0200 Subject: [PATCH] Tests: Add unit tests for CSV import Add a new test class for testing the import functionality. Currently it's only covers some test cases for the CSV import. Since the function to test here (DBBrowserDB::decodeCSV) is part of the DBBrowserDB class, that class has a reference to the main window and the main window basically depends on the entire rest of the project the makefile grew quite a bit unfortunately. --- src/src.pro | 4 +- src/tests/TestImport.cpp | 98 +++++++++++++++++++++ src/tests/TestImport.h | 15 ++++ src/tests/TestMain.cpp | 17 ++++ src/tests/testsqlobjects.cpp | 3 - tests/CMakeLists.txt | 165 +++++++++++++++++++++++++++++++---- 6 files changed, 278 insertions(+), 24 deletions(-) create mode 100644 src/tests/TestImport.cpp create mode 100644 src/tests/TestImport.h create mode 100644 src/tests/TestMain.cpp diff --git a/src/src.pro b/src/src.pro index ca72f0ae..478db44f 100644 --- a/src/src.pro +++ b/src/src.pro @@ -12,8 +12,8 @@ CONFIG += warn_on # create a unittest option CONFIG(unittest) { CONFIG += qtestlib - HEADERS += tests/testsqlobjects.h - SOURCES += tests/testsqlobjects.cpp + HEADERS += tests/testsqlobjects.h tests/TestImport.h + SOURCES += tests/testsqlobjects.cpp tests/TestImport.cpp tests/TestMain.cpp } else { SOURCES += main.cpp } diff --git a/src/tests/TestImport.cpp b/src/tests/TestImport.cpp new file mode 100644 index 00000000..981f8911 --- /dev/null +++ b/src/tests/TestImport.cpp @@ -0,0 +1,98 @@ +#include +#include + +#include "Application.h" +#include "TestImport.h" +#include "../sqlitedb.h" + +void TestImport::csvImport() +{ + // Fetch data + QFETCH(QString, csv); + QFETCH(char, separator); + QFETCH(char, quote); + QFETCH(int, numfields); + QFETCH(QStringList, result); + + // Init basic application + int argcount = 1; + const char* appname = "sqlb-unittests"; + Application app(argcount, const_cast(&appname)); + + // Create temporary CSV file + QTemporaryFile file; + QVERIFY(file.open()); + file.write(csv.toUtf8()); + file.flush(); + + // Call decodeCSV function + DBBrowserDB db; + int numfields_read; + QStringList retval = db.decodeCSV(file.fileName(), separator, quote, -1, &numfields_read); + + // Check return values + QCOMPARE(retval, result); + QCOMPARE(numfields_read, numfields); +} + +void TestImport::csvImport_data() +{ + QTest::addColumn("csv"); + QTest::addColumn("separator"); + QTest::addColumn("quote"); + QTest::addColumn("numfields"); + QTest::addColumn("result"); + + QStringList result; + result << "a" << "b" << "c" << "d" << "e" << "f" << "g" << "h" << "i"; + QTest::newRow("commas_noquotes") << "a,b,c\nd,e,f\ng,h,i\n" + << ',' + << (char)0 + << 3 + << result; + QTest::newRow("semicolons_noquotes") << "a;b;c\nd;e;f\ng;h;i\n" + << ';' + << (char)0 + << 3 + << result; + QTest::newRow("commas_doublequotes") << "\"a\",\"b\",\"c\"\n\"d\",\"e\",\"f\"\n\"g\",\"h\",\"i\"\n" + << ',' + << '"' + << 3 + << result; + QTest::newRow("noquotes_butquotesset") << "a,b,c\nd,e,f\ng,h,i\n" + << ',' + << '"' + << 3 + << result; + QTest::newRow("windowslinebreaks") << "a,b,c\r\nd,e,f\r\ng,h,i\r\n" + << ',' + << (char)0 + << 3 + << result; + + result.clear(); + result << "a" << "b" << "c"; + QTest::newRow("oneline") << "a,b,c" + << ',' + << (char)0 + << 3 + << result; + + result.clear(); + result << "a,a\"" << "b" << "c" << "d" << "e" << "\"\"f,f"; + QTest::newRow("manyquotes") << "\"a,a\"\"\",\"b\",\"c\"\n\"d\",\"e\",\"\"\"\"\"f,f\"\n" + << ',' + << '"' + << 3 + << result; + + result.clear(); + result << QString::fromUtf8("\u4E18") << QString::fromUtf8("\u4E26") << QString::fromUtf8("\u4E4B"); + QString csv = QString::fromUtf8("\u4E18") + "," + QString::fromUtf8("\u4E26") + "," + QString::fromUtf8("\u4E4B") + "\n"; + QTest::newRow("utf8chars") << csv + << ',' + << (char)0 + << 3 + << result; +} diff --git a/src/tests/TestImport.h b/src/tests/TestImport.h new file mode 100644 index 00000000..ed78527b --- /dev/null +++ b/src/tests/TestImport.h @@ -0,0 +1,15 @@ +#ifndef __TESTIMPORT_H__ +#define __TESTIMPORT_H__ + +#include + +class TestImport : public QObject +{ + Q_OBJECT + +private slots: + void csvImport(); + void csvImport_data(); +}; + +#endif diff --git a/src/tests/TestMain.cpp b/src/tests/TestMain.cpp new file mode 100644 index 00000000..f26741b6 --- /dev/null +++ b/src/tests/TestMain.cpp @@ -0,0 +1,17 @@ +#include +#include "tests/testsqlobjects.h" +#include "tests/TestImport.h" + +int main(int argc, char** argv) +{ + int status = 0; + { + TestTable tc; + status |= QTest::qExec(&tc, argc, argv); + } + { + TestImport tc; + status |= QTest::qExec(&tc, argc, argv); + } + return status; +} diff --git a/src/tests/testsqlobjects.cpp b/src/tests/testsqlobjects.cpp index 40a1eee2..20f2adff 100644 --- a/src/tests/testsqlobjects.cpp +++ b/src/tests/testsqlobjects.cpp @@ -249,6 +249,3 @@ void TestTable::createTableWithNotLikeConstraint() QVERIFY(tab.fields().at(5)->check() == "value6 NOT BETWEEN 1 AND 100"); QVERIFY(tab.fields().at(6)->check() == "NOT EXISTS ( 1 )"); } - -QTEST_MAIN(TestTable) -//#include "testsqlobjects.moc" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f2742be9..917b813b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -8,47 +8,174 @@ if(NOT CMAKE_BUILD_TYPE) endif() set(ANTLR_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../libs/antlr-2.7.7) +set(QHEXEDIT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../libs/qhexedit) +set(QCUSTOMPLOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../libs/qcustomplot-source) + add_subdirectory(${ANTLR_DIR} ${CMAKE_CURRENT_BINARY_DIR}/antlr) +add_subdirectory(${QHEXEDIT_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qcustomplot-source) +add_subdirectory(${QCUSTOMPLOT_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qhexedit) if(USE_QT5) find_package(Qt5Widgets REQUIRED) set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) else() - find_package(Qt4 COMPONENTS QtCore QtTest REQUIRED) + find_package(Qt4 COMPONENTS QtTest QtCore QtGui QtNetwork REQUIRED) include(${QT_USE_FILE}) add_definitions(${QT_DEFINITIONS}) endif() -set(SQLB_SRC - ../src/sqlitetypes.cpp - ../src/grammar/Sqlite3Lexer.cpp - ../src/grammar/Sqlite3Parser.cpp - ../src/tests/testsqlobjects.cpp) - set(SQLB_HDR + ../src/gen_version.h + ../src/sqlitedb.h + ../src/sqlitetypes.h ../src/grammar/sqlite3TokenTypes.hpp ../src/grammar/Sqlite3Lexer.hpp ../src/grammar/Sqlite3Parser.hpp - ../src/sqlitetypes.h) +) set(SQLB_MOC_HDR - ../src/tests/testsqlobjects.h) + ../src/AboutDialog.h + ../src/CreateIndexDialog.h + ../src/EditDialog.h + ../src/EditTableDialog.h + ../src/ExportCsvDialog.h + ../src/ExtendedTableWidget.h + ../src/FilterTableHeader.h + ../src/ImportCsvDialog.h + ../src/MainWindow.h + ../src/PreferencesDialog.h + ../src/SQLiteSyntaxHighlighter.h + ../src/SqlExecutionArea.h + ../src/VacuumDialog.h + ../src/sqlitetablemodel.h + ../src/sqltextedit.h + ../src/DbStructureModel.h + ../src/Application.h + ../src/tests/TestImport.h + ../src/tests/testsqlobjects.h +) -if(NOT USE_QT5) - QT4_WRAP_CPP(SQLB_MOC ${SQLB_MOC_HDR}) -endif() +set(SQLB_SRC + ../src/AboutDialog.cpp + ../src/CreateIndexDialog.cpp + ../src/EditDialog.cpp + ../src/EditTableDialog.cpp + ../src/ExportCsvDialog.cpp + ../src/ExtendedTableWidget.cpp + ../src/FilterTableHeader.cpp + ../src/ImportCsvDialog.cpp + ../src/MainWindow.cpp + ../src/PreferencesDialog.cpp + ../src/SQLiteSyntaxHighlighter.cpp + ../src/SqlExecutionArea.cpp + ../src/VacuumDialog.cpp + ../src/sqlitedb.cpp + ../src/sqlitetablemodel.cpp + ../src/sqlitetypes.cpp + ../src/sqltextedit.cpp + ../src/DbStructureModel.cpp + ../src/Application.cpp + ../src/grammar/Sqlite3Lexer.cpp + ../src/grammar/Sqlite3Parser.cpp + ../src/tests/TestImport.cpp + ../src/tests/testsqlobjects.cpp + ../src/tests/TestMain.cpp +) -include_directories(${ANTLR_DIR}) +set(SQLB_FORMS + ../src/AboutDialog.ui + ../src/CreateIndexDialog.ui + ../src/EditDialog.ui + ../src/EditTableDialog.ui + ../src/ExportCsvDialog.ui + ../src/ImportCsvDialog.ui + ../src/MainWindow.ui + ../src/PreferencesDialog.ui + ../src/SqlExecutionArea.ui + ../src/VacuumDialog.ui +) -add_executable(${PROJECT_NAME} ${SQLB_MOC} ${SQLB_HDR} ${SQLB_SRC}) +set(SQLB_RESOURCES + ../src/icons/icons.qrc +) if(USE_QT5) - qt5_use_modules(${PROJECT_NAME} Test) - set(QT_LIBRARIES "") + qt5_wrap_ui(SQLB_FORM_HDR ${SQLB_FORMS}) + qt5_add_resources(SQLB_RESOURCES_RCC ${SQLB_RESOURCES}) +else() + QT4_WRAP_CPP(SQLB_MOC ${SQLB_MOC_HDR}) + QT4_WRAP_UI(SQLB_FORM_HDR ${SQLB_FORMS}) + QT4_ADD_RESOURCES(SQLB_RESOURCES_RCC ${SQLB_RESOURCES}) endif() -add_dependencies(${PROJECT_NAME} antlr) -target_link_libraries(${PROJECT_NAME} antlr ${QT_LIBRARIES}) +# get git version hash +file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/../src/gen_version.h + "#ifndef __GEN_VERSIONS_H__\n" + "#define __GEN_VERSIONS_H__\n" + "#define APP_VERSION \"master_git\"\n" + "#define MAJOR_VERSION 999\n" + "#define MINOR_VERSION 0\n" + "#define PATCH_VERSION 0\n" + "#endif\n") -MESSAGE(STATUS "Build type is ${CMAKE_BUILD_TYPE}") +#icon and correct libs/subsystem for windows +if(WIN32) + #enable version check for windows + add_definitions(-DCHECKNEWVERSION) + + IF( MINGW ) + # resource compilation for MinGW + ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sqlbicon.o + COMMAND windres -I${CMAKE_CURRENT_SOURCE_DIR} -i${CMAKE_CURRENT_SOURCE_DIR}/src/winapp.rc -o ${CMAKE_CURRENT_BINARY_DIR}/sqlbicon.o ) + set(SQLB_SRC ${SQLB_SRC} ${CMAKE_CURRENT_BINARY_DIR}/sqlbicon.o) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-subsystem,windows") + set(WIN32_STATIC_LINK -Wl,-Bstatic -lssl -lcrypto -lws2_32) + set(ADDITIONAL_LIBS lcms lzma) + ELSE( MINGW ) + set(SQLB_SRC ${SQLB_SRC} ${CMAKE_CURRENT_SOURCE_DIR}src/winapp.rc) + ENDIF( MINGW ) +endif(WIN32) + +# add extra library path for MacOS +if(APPLE) + find_library(LIBSQLITE sqlite3 HINTS /usr/local/lib /usr/local/opt/sqlite/lib) + set(ADDITIONAL_INCLUDE_PATHS /usr/local/include /usr/local/opt/sqlite/include) +else(APPLE) + find_library(LIBSQLITE sqlite3) +endif(APPLE) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${ANTLR_DIR} + ${QHEXEDIT_DIR} + ${QCUSTOMPLOT_DIR} + ${ADDITIONAL_INCLUDE_PATHS} + ../src) + +add_executable(${PROJECT_NAME} + ${SQLB_HDR} + ${SQLB_SRC} + ${SQLB_FORM_HDR} + ${SQLB_MOC} + ${SQLB_RESOURCES_RCC}) + +if(USE_QT5) + qt5_use_modules(${PROJECT_NAME} Gui Widgets Network Test PrintSupport) + set(QT_LIBRARIES "") +endif() +add_dependencies(${PROJECT_NAME} antlr qhexedit qcustomplot) + +link_directories( + ${CMAKE_CURRENT_BINARY_DIR}/${ANTLR_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/${QHEXEDIT_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/${QCUSTOMPLOT_DIR}) + +target_link_libraries(${PROJECT_NAME} + antlr + qhexedit + qcustomplot + ${QT_LIBRARIES} + ${WIN32_STATIC_LINK} + ${LIBSQLITE} + ${ADDITIONAL_LIBS})