[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