Finish unit tests for the DownloadUpdateTask class

This commit is contained in:
Jan Dalheimer 2013-12-15 18:50:56 +01:00
parent 3e8bcc1cf6
commit 7f884a18a8
3 changed files with 109 additions and 35 deletions

View File

@ -234,15 +234,36 @@ bool DownloadUpdateTask::parseVersionInfo(const QByteArray &data, VersionFileLis
} }
void DownloadUpdateTask::processFileLists() void DownloadUpdateTask::processFileLists()
{
// Create a network job for downloading files.
NetJob* netJob = new NetJob("Update Files");
processFileLists(netJob, m_cVersionFileList, m_nVersionFileList, m_operationList);
// Add listeners to wait for the downloads to finish.
QObject::connect(netJob, &NetJob::succeeded, this, &DownloadUpdateTask::fileDownloadFinished);
QObject::connect(netJob, &NetJob::progress, this, &DownloadUpdateTask::fileDownloadProgressChanged);
QObject::connect(netJob, &NetJob::failed, this, &DownloadUpdateTask::fileDownloadFailed);
// Now start the download.
setStatus(tr("Downloading %1 update files.").arg(QString::number(netJob->size())));
QLOG_DEBUG() << "Begin downloading update files to" << m_updateFilesDir.path();
m_filesNetJob.reset(netJob);
netJob->start();
writeInstallScript(m_operationList, PathCombine(m_updateFilesDir.path(), "file_list.xml"));
}
void DownloadUpdateTask::processFileLists(NetJob *job, const VersionFileList &currentVersion, const VersionFileList &newVersion, DownloadUpdateTask::UpdateOperationList &ops)
{ {
setStatus(tr("Processing file lists. Figuring out how to install the update.")); setStatus(tr("Processing file lists. Figuring out how to install the update."));
// First, if we've loaded the current version's file list, we need to iterate through it and // First, if we've loaded the current version's file list, we need to iterate through it and
// delete anything in the current one version's list that isn't in the new version's list. // delete anything in the current one version's list that isn't in the new version's list.
for (VersionFileEntry entry : m_cVersionFileList) for (VersionFileEntry entry : currentVersion)
{ {
bool keep = false; bool keep = false;
for (VersionFileEntry newEntry : m_nVersionFileList) for (VersionFileEntry newEntry : newVersion)
{ {
if (newEntry.path == entry.path) if (newEntry.path == entry.path)
{ {
@ -253,14 +274,11 @@ void DownloadUpdateTask::processFileLists()
} }
// If the loop reaches the end and we didn't find a match, delete the file. // If the loop reaches the end and we didn't find a match, delete the file.
if(!keep) if(!keep)
m_operationList.append(UpdateOperation::DeleteOp(entry.path)); ops.append(UpdateOperation::DeleteOp(entry.path));
} }
// Create a network job for downloading files.
NetJob* netJob = new NetJob("Update Files");
// Next, check each file in MultiMC's folder and see if we need to update them. // Next, check each file in MultiMC's folder and see if we need to update them.
for (VersionFileEntry entry : m_nVersionFileList) for (VersionFileEntry entry : newVersion)
{ {
// TODO: Let's not MD5sum a ton of files on the GUI thread. We should probably find a way to do this in the background. // TODO: Let's not MD5sum a ton of files on the GUI thread. We should probably find a way to do this in the background.
QString fileMD5; QString fileMD5;
@ -287,31 +305,21 @@ void DownloadUpdateTask::processFileLists()
// Download it to updatedir/<filepath>-<md5> where filepath is the file's path with slashes replaced by underscores. // Download it to updatedir/<filepath>-<md5> where filepath is the file's path with slashes replaced by underscores.
QString dlPath = PathCombine(m_updateFilesDir.path(), QString(entry.path).replace("/", "_")); QString dlPath = PathCombine(m_updateFilesDir.path(), QString(entry.path).replace("/", "_"));
if (job)
{
// We need to download the file to the updatefiles folder and add a task to copy it to its install path. // We need to download the file to the updatefiles folder and add a task to copy it to its install path.
auto download = MD5EtagDownload::make(source.url, dlPath); auto download = MD5EtagDownload::make(source.url, dlPath);
download->m_check_md5 = true; download->m_check_md5 = true;
download->m_expected_md5 = entry.md5; download->m_expected_md5 = entry.md5;
netJob->addNetAction(download); job->addNetAction(download);
}
// Now add a copy operation to our operations list to install the file. // Now add a copy operation to our operations list to install the file.
m_operationList.append(UpdateOperation::CopyOp(dlPath, entry.path, entry.mode)); ops.append(UpdateOperation::CopyOp(dlPath, entry.path, entry.mode));
} }
} }
} }
} }
// Add listeners to wait for the downloads to finish.
QObject::connect(netJob, &NetJob::succeeded, this, &DownloadUpdateTask::fileDownloadFinished);
QObject::connect(netJob, &NetJob::progress, this, &DownloadUpdateTask::fileDownloadProgressChanged);
QObject::connect(netJob, &NetJob::failed, this, &DownloadUpdateTask::fileDownloadFailed);
// Now start the download.
setStatus(tr("Downloading %1 update files.").arg(QString::number(netJob->size())));
QLOG_DEBUG() << "Begin downloading update files to" << m_updateFilesDir.path();
m_filesNetJob.reset(netJob);
netJob->start();
writeInstallScript(m_operationList, PathCombine(m_updateFilesDir.path(), "file_list.xml"));
} }
bool DownloadUpdateTask::writeInstallScript(UpdateOperationList& opsList, QString scriptFile) bool DownloadUpdateTask::writeInstallScript(UpdateOperationList& opsList, QString scriptFile)

View File

@ -54,13 +54,11 @@ public:
QString url; QString url;
QString compressionType; QString compressionType;
}; };
typedef QList<FileSource> FileSourceList; typedef QList<FileSource> FileSourceList;
/*! /*!
* Structure that describes an entry in a GoUpdate version's `Files` list. * Structure that describes an entry in a GoUpdate version's `Files` list.
*/ */
struct VersionFileEntry struct VersionFileEntry
{ {
QString path; QString path;
@ -68,12 +66,8 @@ public:
FileSourceList sources; FileSourceList sources;
QString md5; QString md5;
}; };
typedef QList<VersionFileEntry> VersionFileList; typedef QList<VersionFileEntry> VersionFileList;
protected:
friend class DownloadUpdateTaskTest;
/*! /*!
* Structure that describes an operation to perform when installing updates. * Structure that describes an operation to perform when installing updates.
*/ */
@ -104,9 +98,12 @@ protected:
// Yeah yeah, polymorphism blah blah inheritance, blah blah object oriented. I'm lazy, OK? // Yeah yeah, polymorphism blah blah inheritance, blah blah object oriented. I'm lazy, OK?
}; };
typedef QList<UpdateOperation> UpdateOperationList; typedef QList<UpdateOperation> UpdateOperationList;
protected:
friend class DownloadUpdateTaskTest;
/*! /*!
* Used for arguments to parseVersionInfo and friends to specify which version info file to parse. * Used for arguments to parseVersionInfo and friends to specify which version info file to parse.
*/ */
@ -159,6 +156,12 @@ protected:
* Takes a list of file entries for the current version's files and the new version's files * Takes a list of file entries for the current version's files and the new version's files
* and populates the downloadList and operationList with information about how to download and install the update. * and populates the downloadList and operationList with information about how to download and install the update.
*/ */
virtual void processFileLists(NetJob *job, const VersionFileList &currentVersion, const VersionFileList &newVersion, UpdateOperationList &ops);
/*!
* Calls \see processFileLists to populate the \see m_operationList and a NetJob, and then executes
* the NetJob to fetch all needed files
*/
virtual void processFileLists(); virtual void processFileLists();
/*! /*!
@ -166,7 +169,6 @@ protected:
*/ */
virtual bool writeInstallScript(UpdateOperationList& opsList, QString scriptFile); virtual bool writeInstallScript(UpdateOperationList& opsList, QString scriptFile);
VersionFileList m_downloadList;
UpdateOperationList m_operationList; UpdateOperationList m_operationList;
VersionFileList m_nVersionFileList; VersionFileList m_nVersionFileList;

View File

@ -5,8 +5,10 @@
#include "logic/updater/DownloadUpdateTask.h" #include "logic/updater/DownloadUpdateTask.h"
#include "logic/updater/UpdateChecker.h" #include "logic/updater/UpdateChecker.h"
#include "depends/util/include/pathutils.h"
Q_DECLARE_METATYPE(DownloadUpdateTask::VersionFileList) Q_DECLARE_METATYPE(DownloadUpdateTask::VersionFileList)
Q_DECLARE_METATYPE(DownloadUpdateTask::UpdateOperation)
bool operator==(const DownloadUpdateTask::FileSource &f1, const DownloadUpdateTask::FileSource &f2) bool operator==(const DownloadUpdateTask::FileSource &f1, const DownloadUpdateTask::FileSource &f2)
{ {
@ -21,6 +23,13 @@ bool operator==(const DownloadUpdateTask::VersionFileEntry &v1, const DownloadUp
v1.sources == v2.sources && v1.sources == v2.sources &&
v1.md5 == v2.md5; v1.md5 == v2.md5;
} }
bool operator==(const DownloadUpdateTask::UpdateOperation &u1, const DownloadUpdateTask::UpdateOperation &u2)
{
return u1.type == u2.type &&
u1.file == u2.file &&
u1.dest == u2.dest &&
u1.mode == u2.mode;
}
QDebug operator<<(QDebug dbg, const DownloadUpdateTask::FileSource &f) QDebug operator<<(QDebug dbg, const DownloadUpdateTask::FileSource &f)
{ {
@ -32,6 +41,22 @@ QDebug operator<<(QDebug dbg, const DownloadUpdateTask::VersionFileEntry &v)
dbg.nospace() << "VersionFileEntry(path=" << v.path << " mode=" << v.mode << " md5=" << v.md5 << " sources=" << v.sources << ")"; dbg.nospace() << "VersionFileEntry(path=" << v.path << " mode=" << v.mode << " md5=" << v.md5 << " sources=" << v.sources << ")";
return dbg.maybeSpace(); return dbg.maybeSpace();
} }
QDebug operator<<(QDebug dbg, const DownloadUpdateTask::UpdateOperation::Type &t)
{
switch (t)
{
case DownloadUpdateTask::UpdateOperation::OP_COPY: dbg << "OP_COPY"; break;
case DownloadUpdateTask::UpdateOperation::OP_DELETE: dbg << "OP_DELETE"; break;
case DownloadUpdateTask::UpdateOperation::OP_MOVE: dbg << "OP_MOVE"; break;
case DownloadUpdateTask::UpdateOperation::OP_CHMOD: dbg << "OP_CHMOD"; break;
}
return dbg.maybeSpace();
}
QDebug operator<<(QDebug dbg, const DownloadUpdateTask::UpdateOperation &u)
{
dbg.nospace() << "UpdateOperation(type=" << u.type << " file=" << u.file << " dest=" << u.dest << " mode=" << u.mode << ")";
return dbg.maybeSpace();
}
class DownloadUpdateTaskTest : public QObject class DownloadUpdateTaskTest : public QObject
{ {
@ -108,9 +133,48 @@ slots:
QCOMPARE(outError, error); QCOMPARE(outError, error);
} }
void test_processFileLists_data()
{
QTest::addColumn<DownloadUpdateTask *>("downloader");
QTest::addColumn<DownloadUpdateTask::VersionFileList>("currentVersion");
QTest::addColumn<DownloadUpdateTask::VersionFileList>("newVersion");
QTest::addColumn<DownloadUpdateTask::UpdateOperationList>("expectedOperations");
DownloadUpdateTask *downloader = new DownloadUpdateTask(QString(), -1);
// update fileOne, keep fileTwo, remove fileThree
QTest::newRow("test 1") << downloader
<< (DownloadUpdateTask::VersionFileList()
<< DownloadUpdateTask::VersionFileEntry{QFINDTESTDATA("tests/data/fileOne"), 493, DownloadUpdateTask::FileSourceList()
<< DownloadUpdateTask::FileSource("http", "http://host/path/fileOne-1"), "9eb84090956c484e32cb6c08455a667b"}
<< DownloadUpdateTask::VersionFileEntry{QFINDTESTDATA("tests/data/fileTwo"), 644, DownloadUpdateTask::FileSourceList()
<< DownloadUpdateTask::FileSource("http", "http://host/path/fileTwo-1"), "38f94f54fa3eb72b0ea836538c10b043"}
<< DownloadUpdateTask::VersionFileEntry{QFINDTESTDATA("tests/data/fileThree"), 420, DownloadUpdateTask::FileSourceList()
<< DownloadUpdateTask::FileSource("http", "http://host/path/fileThree-1"), "f12df554b21e320be6471d7154130e70"})
<< (DownloadUpdateTask::VersionFileList()
<< DownloadUpdateTask::VersionFileEntry{QFINDTESTDATA("tests/data/fileOne"), 493, DownloadUpdateTask::FileSourceList()
<< DownloadUpdateTask::FileSource("http", "http://host/path/fileOne-2"), "42915a71277c9016668cce7b82c6b577"}
<< DownloadUpdateTask::VersionFileEntry{QFINDTESTDATA("tests/data/fileTwo"), 644, DownloadUpdateTask::FileSourceList()
<< DownloadUpdateTask::FileSource("http", "http://host/path/fileTwo-2"), "38f94f54fa3eb72b0ea836538c10b043"})
<< (DownloadUpdateTask::UpdateOperationList()
<< DownloadUpdateTask::UpdateOperation::DeleteOp(QFINDTESTDATA("tests/data/fileThree"))
<< DownloadUpdateTask::UpdateOperation::CopyOp(PathCombine(downloader->updateFilesDir(), QFINDTESTDATA("tests/data/fileOne").replace("/", "_")),
QFINDTESTDATA("tests/data/fileOne"), 493));
}
void test_processFileLists() void test_processFileLists()
{ {
// TODO create unit test for this QFETCH(DownloadUpdateTask *, downloader);
QFETCH(DownloadUpdateTask::VersionFileList, currentVersion);
QFETCH(DownloadUpdateTask::VersionFileList, newVersion);
QFETCH(DownloadUpdateTask::UpdateOperationList, expectedOperations);
DownloadUpdateTask::UpdateOperationList operations;
downloader->processFileLists(new NetJob("Dummy"), currentVersion, newVersion, operations);
qDebug() << (operations == expectedOperations);
qDebug() << operations;
qDebug() << expectedOperations;
QCOMPARE(operations, expectedOperations);
} }
void test_masterTest() void test_masterTest()