[Pkg-owncloud-commits] [owncloud-client] 63/175: Add a class TransmissionChecksumValidator, incl. unit test.

Sandro Knauß hefee-guest at moszumanska.debian.org
Sat Aug 8 10:36:27 UTC 2015


This is an automated email from the git hooks/post-receive script.

hefee-guest pushed a commit to branch master
in repository owncloud-client.

commit 830daa40d1dae9064975e20c9295660fb8337fce
Author: Klaas Freitag <freitag at owncloud.com>
Date:   Fri May 15 15:34:17 2015 +0200

    Add a class TransmissionChecksumValidator, incl. unit test.
    
    This does all needed to manage checksums that go with http headers
    ensuring that the transmission was correct.
---
 src/libsync/CMakeLists.txt                    |   1 +
 src/libsync/transmissionchecksumvalidator.cpp | 152 ++++++++++++++++++++++++
 src/libsync/transmissionchecksumvalidator.h   |  54 +++++++++
 test/CMakeLists.txt                           |   1 +
 test/testtranschecksumvalidator.h             | 159 ++++++++++++++++++++++++++
 5 files changed, 367 insertions(+)

diff --git a/src/libsync/CMakeLists.txt b/src/libsync/CMakeLists.txt
index aaa1d93..7247d16 100644
--- a/src/libsync/CMakeLists.txt
+++ b/src/libsync/CMakeLists.txt
@@ -61,6 +61,7 @@ set(libsync_SRCS
     theme.cpp
     utility.cpp
     ownsql.cpp
+    transmissionchecksumvalidator.cpp
     creds/dummycredentials.cpp
     creds/abstractcredentials.cpp
     creds/credentialsfactory.cpp
diff --git a/src/libsync/transmissionchecksumvalidator.cpp b/src/libsync/transmissionchecksumvalidator.cpp
new file mode 100644
index 0000000..e6fd6f3
--- /dev/null
+++ b/src/libsync/transmissionchecksumvalidator.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) by Klaas Freitag <freitag at owncloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#include "config.h"
+#include "filesystem.h"
+#include "transmissionchecksumvalidator.h"
+#include "syncfileitem.h"
+#include "propagatorjobs.h"
+#include "configfile.h"
+
+#include <QtConcurrent>
+
+namespace OCC {
+
+TransmissionChecksumValidator::TransmissionChecksumValidator(const QString& filePath, QObject *parent)
+  :QObject(parent),
+    _filePath(filePath)
+{
+
+}
+
+void TransmissionChecksumValidator::setChecksumType( const QByteArray& type )
+{
+    _checksumType = type;
+}
+
+QString TransmissionChecksumValidator::checksumType()
+{
+    return _checksumType;
+}
+
+
+void TransmissionChecksumValidator::uploadValidation( SyncFileItem *item )
+{
+    QString checksumType = _checksumType;
+    if( checksumType.isEmpty() ) {
+        ConfigFile cfg;
+        checksumType = cfg.transmissionChecksum();
+    }
+
+    if( checksumType.isEmpty() || !item ) {
+        // if there is no checksum defined, continue to upload
+        emit validated();
+    } else {
+        _item = item;
+        // Calculate the checksum in a different thread first.
+        connect( &_watcher, SIGNAL(finished()),
+                 this, SLOT(slotUploadChecksumCalculated()));
+        if( checksumType == checkSumMD5C ) {
+            item->_checksum = checkSumMD5C;
+            item->_checksum += ":";
+            _watcher.setFuture(QtConcurrent::run(FileSystem::calcMd5Worker, _filePath));
+
+        } else if( checksumType == checkSumSHA1C ) {
+            item->_checksum = checkSumSHA1C;
+            item->_checksum += ":";
+            _watcher.setFuture(QtConcurrent::run( FileSystem::calcSha1Worker, _filePath));
+        }
+#ifdef ZLIB_FOUND
+        else if( checksumType == checkSumAdlerC) {
+            item->_checksum = checkSumAdlerC;
+            item->_checksum += ":";
+            _watcher.setFuture(QtConcurrent::run(FileSystem::calcAdler32Worker, _filePath));
+        }
+#endif
+        else {
+            // for an unknown checksum, continue to upload
+            emit validated();
+        }
+    }
+}
+
+void TransmissionChecksumValidator::slotUploadChecksumCalculated( )
+{
+    QByteArray checksum = _watcher.future().result();
+
+    if( !checksum.isEmpty() ) {
+        _item->_checksum.append(checksum);
+    } else {
+        _item->_checksum.clear();
+    }
+
+    emit validated();
+}
+
+
+void TransmissionChecksumValidator::downloadValidation( const QByteArray& checksumHeader )
+{
+    // if the incoming header is empty, there was no checksum header, and
+    // no validation can happen. Just continue.
+    if( checksumHeader.isEmpty() ) {
+        emit validated();
+        return;
+    }
+
+    bool ok = true;
+
+    int indx = checksumHeader.indexOf(':');
+    if( indx < 0 ) {
+        qDebug() << "Checksum header malformed:" << checksumHeader;
+        emit validated(); // show must go on - even not validated.
+    }
+
+    if( ok ) {
+        const QByteArray type = checksumHeader.left(indx).toUpper();
+        _expectedHash = checksumHeader.mid(indx+1);
+
+        connect( &_watcher, SIGNAL(finished()), this, SLOT(slotDownloadChecksumCalculated()) );
+
+        // start the calculation in different thread
+        if( type == checkSumMD5C ) {
+            _watcher.setFuture(QtConcurrent::run(FileSystem::calcMd5Worker, _filePath));
+        } else if( type == checkSumSHA1C ) {
+            _watcher.setFuture(QtConcurrent::run(FileSystem::calcSha1Worker, _filePath));
+        }
+#ifdef ZLIB_FOUND
+        else if( type == checkSumAdlerUpperC ) {
+            _watcher.setFuture(QtConcurrent::run(FileSystem::calcAdler32Worker, _filePath));
+        }
+#endif
+        else {
+            qDebug() << "Unknown checksum type" << type;
+            emit validationFailed(tr("The checksum header was malformed."));
+            return;
+        }
+    }
+}
+
+void TransmissionChecksumValidator::slotDownloadChecksumCalculated()
+{
+    const QByteArray hash = _watcher.future().result();
+
+    if( hash != _expectedHash ) {
+        emit validationFailed(tr("The file downloaded with a broken checksum, will be redownloaded."));
+    } else {
+        qDebug() << "Checksum checked and matching: " << _expectedHash;
+        emit validated();
+    }
+}
+
+
+}
diff --git a/src/libsync/transmissionchecksumvalidator.h b/src/libsync/transmissionchecksumvalidator.h
new file mode 100644
index 0000000..dc9f7ef
--- /dev/null
+++ b/src/libsync/transmissionchecksumvalidator.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) by Klaas Freitag <freitag at owncloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#pragma once
+
+#include <QObject>
+#include <QByteArray>
+#include <QFutureWatcher>
+
+namespace OCC {
+class SyncFileItem;
+
+class TransmissionChecksumValidator : public QObject
+{
+    Q_OBJECT
+public:
+    explicit TransmissionChecksumValidator(const QString& filePath, QObject *parent = 0);
+
+    void uploadValidation( SyncFileItem *item );
+    void downloadValidation( const QByteArray& checksumHeader );
+
+    void setChecksumType(const QByteArray &type );
+    QString checksumType();
+
+signals:
+    void validated();
+    void validationFailed( const QString& errMsg );
+
+private slots:
+    void slotUploadChecksumCalculated();
+    void slotDownloadChecksumCalculated();
+
+private:
+    QByteArray    _checksumType;
+    QByteArray    _expectedHash;
+    QString       _filePath;
+    SyncFileItem *_item;
+
+    // watcher for the checksum calculation thread
+    QFutureWatcher<QByteArray> _watcher;
+};
+
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index ac3b34e..ef64f5d 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -34,4 +34,5 @@ owncloud_add_test(ConcatUrl "")
 
 owncloud_add_test(XmlParse "")
 owncloud_add_test(FileSystem "")
+owncloud_add_test(TransChecksumValidator "")
 
diff --git a/test/testtranschecksumvalidator.h b/test/testtranschecksumvalidator.h
new file mode 100644
index 0000000..6d3c37c
--- /dev/null
+++ b/test/testtranschecksumvalidator.h
@@ -0,0 +1,159 @@
+/*
+ * This software is in the public domain, furnished "as is", without technical
+ * support, and with no warranty, express or implied, as to its usefulness for
+ * any purpose.
+ *
+ */
+
+#pragma once
+
+#include <QtTest>
+#include <QDir>
+#include <QString>
+
+#include "transmissionchecksumvalidator.h"
+#include "networkjobs.h"
+#include "syncfileitem.h"
+#include "utility.h"
+#include "filesystem.h"
+#include "propagatorjobs.h"
+
+using namespace OCC;
+
+    class TestTransChecksumValidator : public QObject
+    {
+        Q_OBJECT
+
+    private:
+        QString _root;
+        QString _testfile;
+        QString _expectedError;
+        SyncFileItem *_item;
+        QEventLoop     _loop;
+        QByteArray     _expected;
+        bool           _successDown;
+        bool           _errorSeen;
+
+    void processAndWait() {
+            _loop.processEvents();
+            Utility::usleep(200000);
+            _loop.processEvents();
+    }
+
+    public slots:
+
+    void slotUpValidated() {
+         qDebug() << "Checksum: " << _item->_checksum;
+         QVERIFY(_expected == _item->_checksum );
+    }
+
+    void slotDownValidated() {
+         _successDown = true;
+    }
+
+    void slotDownError( const QString& errMsg ) {
+         QVERIFY(_expectedError == errMsg );
+         _errorSeen = true;
+    }
+
+    private slots:
+
+    void initTestCase() {
+        qDebug() << Q_FUNC_INFO;
+        _root = QDir::tempPath() + "/" + "test_" + QString::number(qrand());
+        QDir rootDir(_root);
+
+        rootDir.mkpath(_root );
+        _testfile = _root+"/csFile";
+        Utility::writeRandomFile( _testfile);
+
+        _item = new SyncFileItem;
+    }
+
+    void testUploadChecksummingAdler() {
+
+        TransmissionChecksumValidator *vali = new TransmissionChecksumValidator(_testfile);
+        connect(vali, SIGNAL(validated()), this, SLOT(slotUpValidated()));
+
+        _expected = "Adler32:"+FileSystem::calcAdler32( _testfile );
+        qDebug() << "XX Expected Checksum: " << _expected;
+        vali->uploadValidation(_item);
+
+        usleep(5000);
+
+        _loop.processEvents();
+        vali->deleteLater();
+    }
+
+    void testUploadChecksummingMd5() {
+
+        TransmissionChecksumValidator *vali = new TransmissionChecksumValidator(_testfile);
+        vali->setChecksumType( OCC::checkSumMD5C );
+        connect(vali, SIGNAL(validated()), this, SLOT(slotUpValidated()));
+
+        _expected = checkSumMD5C;
+        _expected.append(":"+FileSystem::calcMd5( _testfile ));
+        vali->uploadValidation(_item);
+
+        usleep(2000);
+
+        _loop.processEvents();
+        vali->deleteLater();
+    }
+
+    void testUploadChecksummingSha1() {
+
+        TransmissionChecksumValidator *vali = new TransmissionChecksumValidator(_testfile);
+        vali->setChecksumType( OCC::checkSumSHA1C );
+        connect(vali, SIGNAL(validated()), this, SLOT(slotUpValidated()));
+
+        _expected = checkSumSHA1C;
+        _expected.append(":"+FileSystem::calcSha1( _testfile ));
+
+        vali->uploadValidation(_item);
+
+        usleep(2000);
+
+        _loop.processEvents();
+        vali->deleteLater();
+    }
+
+    void testDownloadChecksummingAdler() {
+
+        QByteArray adler =  checkSumAdlerC;
+        adler.append(":");
+        adler.append(FileSystem::calcAdler32( _testfile ));
+        _successDown = false;
+
+        TransmissionChecksumValidator *vali = new TransmissionChecksumValidator(_testfile);
+        connect(vali, SIGNAL(validated()), this, SLOT(slotDownValidated()));
+        connect(vali, SIGNAL(validationFailed(QString)), this, SLOT(slotDownError(QString)));
+        vali->downloadValidation(adler);
+
+        usleep(2000);
+
+        _loop.processEvents();
+        QVERIFY(_successDown);
+
+        _expectedError = QLatin1String("The file downloaded with a broken checksum, will be redownloaded.");
+        _errorSeen = false;
+        vali->downloadValidation("Adler32:543345");
+        usleep(2000);
+        _loop.processEvents();
+        QVERIFY(_errorSeen);
+
+        _expectedError = QLatin1String("The checksum header was malformed.");
+        _errorSeen = false;
+        vali->downloadValidation("Klaas32:543345");
+        usleep(2000);
+        _loop.processEvents();
+        QVERIFY(_errorSeen);
+
+        vali->deleteLater();
+    }
+
+
+    void cleanupTestCase() {
+        delete _item;
+    }
+};

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud-client.git



More information about the Pkg-owncloud-commits mailing list