changeset 7:992c0ec57660

Add unit tests make CertificateList work.
author Andre Heinecke <aheinecke@intevation.de>
date Wed, 12 Feb 2014 16:52:27 +0000
parents 1f6455d46b30
children c7da699f0310
files CMakeLists.txt tests/CMakeLists.txt tests/certlistparsertest.cpp tests/certlistparsertest.h tests/data/random_2MB tests/data/random_500KB ui/certificatelist.cpp ui/certificatelist.h ui/listutil.c ui/listutil.h ui/mainwindow.cpp
diffstat 11 files changed, 216 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- 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)
--- /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)
+
--- /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 <QDebug>
+
+
+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 );
+}
+
+
--- /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 <QObject>
+#include <QtTest/QtTest>
+
+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
Binary file tests/data/random_2MB has changed
Binary file tests/data/random_500KB has changed
--- 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 <QDebug>
+
+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);
+    }
 }
--- 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 <QString>
 #include <QDate>
+#include <QObject>
 
-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
--- 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 <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <string.h>
 
 #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;
--- 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 <stddef.h>
 
 /**
  * @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
--- 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 <QMenu>
 #include <QApplication>
 
+#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);
 }

http://wald.intevation.org/projects/trustbridge/