# HG changeset patch # User Andre Heinecke # Date 1392223947 0 # Node ID 992c0ec5766029365099ee7b65778922a7497c32 # Parent 1f6455d46b308cd4c0a09442df7dcd2c846afb12 Add unit tests make CertificateList work. diff -r 1f6455d46b30 -r 992c0ec57660 CMakeLists.txt --- a/CMakeLists.txt Tue Feb 11 17:57:55 2014 +0000 +++ b/CMakeLists.txt Wed Feb 12 16:52:27 2014 +0000 @@ -7,17 +7,25 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) +# Default to debug build +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Debug) +endif (NOT CMAKE_BUILD_TYPE) + find_package(Qt5Widgets REQUIRED) include_directories(${Qt5Widgets_INCLUDE_DIRS}) add_definitions(${Qt5Widgets_DEFINITIONS}) set(M13UI_SOURCES - ui/main.cpp - ui/mainwindow.cpp - ui/listutil.c + ${CMAKE_SOURCE_DIR}/ui/mainwindow.cpp + ${CMAKE_SOURCE_DIR}/ui/certificatelist.cpp + ${CMAKE_SOURCE_DIR}/ui/listutil.c ) +# Seperated to make it easier to include the sources in tests +set(M13UI_MAIN ui/main.cpp) + set(M13UI_RESOURCES ui/icons.qrc ) @@ -68,9 +76,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${HARDENING_FLAGS}") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_WARN_FLAGS} ${HARDENING_FLAGS}") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARN_HARDENING_FLAGS} ${HARDENING_FLAGS}") -add_executable(m13ui ${M13UI_SOURCES}) +add_executable(m13ui ${M13UI_SOURCES} ${M13UI_MAIN}) target_link_libraries(m13ui Qt5::Widgets ${EXTRA_STATIC_LIBS}) @@ -90,3 +98,5 @@ add_dependencies(static_check flawfinder) endif (FLAWFINDER_PATH) +# Tests +add_subdirectory(tests) diff -r 1f6455d46b30 -r 992c0ec57660 tests/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/CMakeLists.txt Wed Feb 12 16:52:27 2014 +0000 @@ -0,0 +1,19 @@ +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../ui) + +find_package(Qt5Test) + +macro(add_m13_test _source) + set(_test ${_source}) + get_filename_component(_name ${_source} NAME_WE) + add_executable(${_name} ${_test} ${M13UI_SOURCES}) + add_test(m13-${_name} ${_name}) + target_link_libraries(${_name} Qt5::Test Qt5::Widgets ${EXTRA_STATIC_LIBS}) +endmacro() + +# Add the current source dir to the definition +# so that it can be used in file names in the tests. +add_definitions(-DSOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") +add_m13_test(certlistparsertest.cpp) + diff -r 1f6455d46b30 -r 992c0ec57660 tests/certlistparsertest.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/certlistparsertest.cpp Wed Feb 12 16:52:27 2014 +0000 @@ -0,0 +1,79 @@ +#include "certlistparsertest.h" +#include "certificatelist.h" + +#include + + +void CertListTest::testInvalidSig() +{ + const char *fname = "list-invalid-signed.txt"; + CertificateList *certList = testWithFile(fname); + QCOMPARE (certList->getStatus(), InvalidSignature); + delete certList; +} + +void verifyInvalidFile(const char *fName) { + CertificateList *certList = new CertificateList(fName); + QVERIFY (certList->getStatus() != Valid); + delete certList; +} + +void CertListTest::testInvalidFileNames() +{ + verifyInvalidFile("/dev/random"); + verifyInvalidFile("/tmp/"); + verifyInvalidFile(NULL); + verifyInvalidFile("ä"); + verifyInvalidFile("💩 "); +} + +void CertListTest::testGarbage() +{ + const char *fname = "random_500KB"; + CertificateList *certList = testWithFile(fname); + QCOMPARE (certList->getStatus(), InvalidFormat); + delete certList; +} + +void CertListTest::testTooLarge() +{ + const char *fname = "random_2MB"; + CertificateList *certList = testWithFile(fname); + QCOMPARE (certList->getStatus(), TooLarge); + QVERIFY (!certList->isValid()); + delete certList; +} + +void CertListTest::testValidList() +{ + const char *fname = "list-valid-signed.txt"; + CertificateList *certList = testWithFile(fname); + QCOMPARE (certList->getStatus(), Valid); + QVERIFY (certList->isValid()); + delete certList; +} + +void CertListTest::benchmarkValid() +{ + const char *fname = "list-valid-signed.txt"; + + QBENCHMARK { + CertificateList *certList = testWithFile(fname); + delete certList; + } +} + +CertificateList* CertListTest::testWithFile(const char *filename) +{ + QDir dataDir = QDir(SOURCE_DIR"/data/"); + QString fileName = dataDir.absoluteFilePath(filename); + return new CertificateList(fileName.toLocal8Bit().data()); +} + +int main( int argc, char **argv ) +{ + CertListTest tc; + return QTest::qExec( &tc, argc, argv ); +} + + diff -r 1f6455d46b30 -r 992c0ec57660 tests/certlistparsertest.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/certlistparsertest.h Wed Feb 12 16:52:27 2014 +0000 @@ -0,0 +1,23 @@ +#ifndef IMAPSTREAMPARSERTEST_H +#define IMAPSTREAMPARSERTEST_H + +#include +#include + +class CertificateList; + +class CertListTest: public QObject +{ + Q_OBJECT + + CertificateList* testWithFile(const char *filename); + +private Q_SLOTS: + void testInvalidSig(); + void testValidList(); + void testInvalidFileNames(); + void testGarbage(); + void testTooLarge(); + void benchmarkValid(); +}; +#endif diff -r 1f6455d46b30 -r 992c0ec57660 tests/data/random_2MB Binary file tests/data/random_2MB has changed diff -r 1f6455d46b30 -r 992c0ec57660 tests/data/random_500KB Binary file tests/data/random_500KB has changed diff -r 1f6455d46b30 -r 992c0ec57660 ui/certificatelist.cpp --- a/ui/certificatelist.cpp Tue Feb 11 17:57:55 2014 +0000 +++ b/ui/certificatelist.cpp Wed Feb 12 16:52:27 2014 +0000 @@ -1,12 +1,15 @@ #include "certificatelist.h" -CertificateList::CertificateList(char *fileName) +#include + +CertificateList::CertificateList(const char *fileName) { - void *data = NULL; - list_status_t status = Unknown; - int size = 0; + char *data = NULL; + size_t size = 0; - status = readAndVerifyList(fileName, data, &size); + mStatus = readAndVerifyList(fileName, &data, &size); - qDebug() << "Read and verify list finished. Status is: " << status; + if (isValid()) { + mFileContent = QByteArray::fromRawData(data, size); + } } diff -r 1f6455d46b30 -r 992c0ec57660 ui/certificatelist.h --- a/ui/certificatelist.h Tue Feb 11 17:57:55 2014 +0000 +++ b/ui/certificatelist.h Wed Feb 12 16:52:27 2014 +0000 @@ -1,5 +1,5 @@ - - +#ifndef CERTIFICATELIST_H +#define CERTIFICATELIST_H /** * This class handles a certificate list file. * It checks for the validity of that certificate @@ -19,20 +19,24 @@ #include #include +#include -class CertificateList +#include "listutil.h" + +class CertificateList : public QObject { Q_OBJECT public: - CertificateList(wchar_t* fileName); + CertificateList(const char *fileName); - list_status_t getStatus(); + list_status_t getStatus() {return mStatus;} + bool isValid() {return mStatus == Valid;} private: QString mFileName; - QByteArray *mFileContent; - ListStatus mStatus; + QByteArray mFileContent; + list_status_t mStatus; QDate mDate; -} - +}; +#endif diff -r 1f6455d46b30 -r 992c0ec57660 ui/listutil.c --- a/ui/listutil.c Tue Feb 11 17:57:55 2014 +0000 +++ b/ui/listutil.c Wed Feb 12 16:52:27 2014 +0000 @@ -7,6 +7,7 @@ #include #include #include +#include #define MAX_FILESIZE_KB 1024 @@ -15,72 +16,74 @@ printf("Error: %s \n", strerror(errno)); } -list_status_t readList(char *fileName, void *data, size_t *size) +list_status_t readList(const char *fileName, char **data, size_t *size) { int fd = -1; struct stat fileStat; int rc = 0; ssize_t bRead = 0; + + memset(&fileStat, 0, sizeof(fileStat)); + list_status_t retval = UnknownError; fd = open(fileName, O_RDONLY); if (fd == -1) { handle_errno(); retval = StatFailed; - goto failure; + goto cleanup; } rc = fstat(fd, &fileStat); if (rc < 0) { printf ("Stat failed with rc: %i\n", rc); retval = StatFailed; - goto failure; + goto cleanup; } // Check the size of the file - if (fileStat.st_size) { + if (!fileStat.st_size) { printf("Size zero\n"); retval = StatFailed; - goto failure; + goto cleanup; } - if (fileStat.st_size / 1024 > MAX_FILESIZE_KB || - fileStat.st_size >= (size_t)-1) { + if (fileStat.st_size / 1024 > MAX_FILESIZE_KB && + fileStat.st_size > 0) { printf("File too large\n"); retval = TooLarge; - goto failure; + goto cleanup; } - // We can cast here as we already checked - // that this size is not too large for size_t *size = (size_t) fileStat.st_size; - data = malloc(*size); + *data = (char*) malloc(*size); if (data == NULL) { printf("Malloc failed\n"); retval = UnknownError; - goto failure; + goto cleanup; } - bRead = read(fd, data, *size); + bRead = read(fd, *data, *size); - if (bRead != *size) { - printf("Read failed"); + if (bRead < 0 || (size_t) bRead != *size) { + printf("Read failed\n"); if (bRead == -1) { handle_errno(); } retval = UnknownError; *size = 0; - if (data) { - free(data); - data = NULL; + if (*data) { + free(*data); + printf("Nulling data\n"); + *data = NULL; } - goto failure; + goto cleanup; } retval = Unknown; -failure: +cleanup: if (fd && fd != -1) { close(fd); @@ -90,42 +93,44 @@ return retval; } -list_status_t readAndVerifyList(char *fileName, void *data, size_t *size) +list_status_t readAndVerifyList(const char *fileName, char **data, size_t *size) { - int validSig = 0; - char * firstChar = NULL; - int i = 0; +// int validSig = 0; + char ** firstChar = NULL; list_status_t retval = UnknownError; - data = NULL; - size = NULL; + *data = NULL; + *size = 0; retval = readList(fileName, data, size); if (retval != Unknown) { + printf ("Readlist failed\n"); return retval; } - if (!data || !size) { + if (!data || !*size) { // should not have happend if readList works as specified + printf ("No data or no size\n"); + printf ("%ld\n", (long)data); return UnknownError; } - firstChar = (char*) data; + firstChar = (char**) data; - if (*firstChar != 'S') { + if (**firstChar != 'S') { printf("Does not start with S\n"); retval = InvalidFormat; + goto cleanup; } - for (i=0; i < *size; i++) { - printf("%c", firstChar + i); - } +// TODO VERIFIY +retval = Valid; -failure: - if (retval != Valid && data) { - free(data); - data = NULL; +cleanup: + if (retval != Valid && *data) { + free(*data); + *data = NULL; *size = 0; } return retval; diff -r 1f6455d46b30 -r 992c0ec57660 ui/listutil.h --- a/ui/listutil.h Tue Feb 11 17:57:55 2014 +0000 +++ b/ui/listutil.h Wed Feb 12 16:52:27 2014 +0000 @@ -1,14 +1,20 @@ +#ifndef LISTUTIL_H +#define LISTUTIL_H + +#ifdef __cplusplus +extern "C" { +#endif #include /** * @file listutil.h * @brief Functions to work with the certificate list. - * - * This file definies the function */ -/* Status of the List Operations */ +/** + * @brief Status of the List Operations + */ typedef enum { Unknown = 0, // Not yet parsed UnknownError = 1, // The expected unexpected @@ -35,5 +41,8 @@ * * @return status of the operation. */ -list_status_t readAndVerifyList(char* fileName, void *data, size_t *size); - +list_status_t readAndVerifyList(const char *fileName, char **data, size_t *size); +#ifdef __cplusplus +} +#endif +#endif diff -r 1f6455d46b30 -r 992c0ec57660 ui/mainwindow.cpp --- a/ui/mainwindow.cpp Tue Feb 11 17:57:55 2014 +0000 +++ b/ui/mainwindow.cpp Wed Feb 12 16:52:27 2014 +0000 @@ -8,6 +8,8 @@ #include #include +#include "certificatelist.h" + MainWindow::MainWindow() { createActions(); createTrayIcon(); @@ -33,6 +35,7 @@ void MainWindow::showMessage() { + CertificateList * myCertList = new CertificateList((char*)"foo"); mTrayIcon->showMessage("Hello", "World", QSystemTrayIcon::Information, 10000); }