2
* This file is part of system-settings
4
* Copyright (C) 2016 Canonical Ltd.
6
* This program is free software: you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License version 3, as published
8
* by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful, but
11
* WITHOUT ANY WARRANTY; without even the implied warranties of
12
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13
* PURPOSE. See the GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License along
16
* with this program. If not, see <http://www.gnu.org/licenses/>.
20
#include "systemimage.h"
21
#include "image/imagemanager_impl.h"
23
#include "system-image-dbus/fakesystemimagedbus.h"
25
#include <libqtdbusmock/MethodCall.h>
29
#include <QVariantMap>
31
using namespace UpdatePlugin;
33
Q_DECLARE_METATYPE(Update::State)
35
class TstImageManager : public QObject
41
m_model = new UpdateModel(":memory:");
43
QVariantMap parameters;
44
parameters["build_number"] = 1;
45
parameters["target_build_number"] = 2;
46
m_siMock = new FakeSystemImageDbus(parameters);
47
m_dbus = new QDBusConnection(m_siMock->dbus());
48
m_systemImage = new QSystemImage(*m_dbus);
49
m_mock = new QDBusInterface(SI_SERVICE,
51
"org.freedesktop.DBus.Mock",
54
m_instance = new Image::ManagerImpl(m_systemImage, m_model);
56
m_methodSpy = new QSignalSpy(
57
m_mock, SIGNAL(MethodCalled(const QString &, const QVariantList &))
60
connect(this, SIGNAL(mockCheckingForUpdatesChanged()),
61
m_instance, SLOT(handleCheckingForUpdatesChanged()));
63
SIGNAL(mockUpdateAvailableStatus(const bool, const bool, const QString&,
64
const int&, const QString&,
67
SLOT(handleUpdateAvailableStatus(const bool, const bool, const QString&,
68
const int&, const QString&,
71
connect(this, SIGNAL(mockDownloadStarted()),
72
m_instance, SLOT(handleDownloadStarted()));
73
connect(this, SIGNAL(mockUpdateProgress(const int&, const double&)),
74
m_instance, SLOT(handleUpdateProgress(const int&, const double&)));
75
connect(this, SIGNAL(mockUpdatePaused(const int&)),
76
m_instance, SLOT(handleUpdatePaused(const int&)));
77
connect(this, SIGNAL(mockUpdateDownloaded()),
78
m_instance, SLOT(handleUpdateDownloaded()));
79
connect(this, SIGNAL(mockUpdateFailed(const int&, const QString&)),
80
m_instance, SLOT(handleUpdateFailed(const int&, const QString&)));
81
connect(this, SIGNAL(mockCurrentBuildNumberChanged()),
82
m_instance, SLOT(handleCurrentBuildNumberChanged()));
83
connect(this, SIGNAL(mockRebooting(const bool)),
84
m_instance, SLOT(handleRebooting(const bool)));
85
connect(this, SIGNAL(mockUpdateProcessing()),
86
m_instance, SLOT(handleUpdateProcessing()));
87
connect(this, SIGNAL(mockUpdateProcessFailed(const QString&)),
88
m_instance, SLOT(handleUpdateProcessFailed(const QString&)));
93
QSignalSpy destroyedSpy(m_instance, SIGNAL(destroyed(QObject*)));
94
m_instance->deleteLater();
95
QTRY_COMPARE(destroyedSpy.count(), 1);
105
QVERIFY(m_methodSpy->wait());
106
QDBusReply<QList<MethodCall>> reply = m_mock->call("GetMethodCalls", "CheckForUpdate");
107
QVERIFY2(reply.isValid(), "Method was not called correctly.");
108
QCOMPARE(reply.value().size(), 1); // Called once.
112
m_instance->cancel();
113
QVERIFY(m_methodSpy->wait());
114
QDBusReply<QList<MethodCall>> reply = m_mock->call("GetMethodCalls", "CancelUpdate");
115
QVERIFY2(reply.isValid(), "Method was not called correctly.");
116
QCOMPARE(reply.value().size(), 1); // Called once.
118
void testUpdateAvailableStatus_data()
120
QTest::addColumn<bool>("isAvailable");
121
QTest::addColumn<bool>("downloading");
122
QTest::addColumn<QString>("availableVersion");
123
QTest::addColumn<QString>("errorReason");
124
QTest::addColumn<int>("downloadMode");
125
QTest::addColumn<Update::State>("targetState");
127
QTest::newRow("update") << true << false << "50" << "" << 0 << Update::State::StateAvailable;
128
QTest::newRow("no update") << false << false << "50" << "" << 0 << Update::State::StateAvailable;
129
QTest::newRow("downloading") << true << true << "50" << "" << 0 << Update::State::StateDownloading;
130
QTest::newRow("paused") << true << false << "50" << "paused" << 0 << Update::State::StateDownloadPaused;
131
QTest::newRow("(auto) downloading") << true << true << "50" << "" << 1 << Update::State::StateDownloadingAutomatically;
132
QTest::newRow("(auto) paused") << true << false << "50" << "paused" << 1 << Update::State::StateAutomaticDownloadPaused;
134
void testUpdateAvailableStatus()
136
QFETCH(bool, isAvailable);
137
QFETCH(bool, downloading);
138
QFETCH(QString, availableVersion);
139
QFETCH(QString, errorReason);
140
QFETCH(int, downloadMode);
141
QFETCH(Update::State, targetState);
143
// Decides whether or not a download is automatic.
144
m_systemImage->setDownloadMode(downloadMode);
146
Q_EMIT mockUpdateAvailableStatus(isAvailable, downloading,
147
availableVersion, 0, "", errorReason);
149
QSharedPointer<Update> u = m_model->fetch(Image::ManagerImpl::ubuntuId, 50);
151
QVERIFY(!u.isNull());
155
QCOMPARE(u->identifier(), Image::ManagerImpl::ubuntuId);
156
QCOMPARE(u->state(), targetState);
159
void testDownloadStarted()
161
m_model->setImageUpdate(Image::ManagerImpl::ubuntuId, 2, 0);
162
Q_EMIT mockDownloadStarted();
163
QSharedPointer<Update> u = m_model->fetch(Image::ManagerImpl::ubuntuId, 2);
164
QCOMPARE(u->state(), Update::State::StateDownloading);
166
void testUpdateProgress()
168
m_model->setImageUpdate(Image::ManagerImpl::ubuntuId, 2, 0);
169
Q_EMIT mockUpdateProgress(50, 0);
170
QSharedPointer<Update> u = m_model->fetch(Image::ManagerImpl::ubuntuId, 2);
171
QCOMPARE(u->state(), Update::State::StateDownloading);
172
QCOMPARE(u->progress(), 50);
174
void testUpdatePaused()
176
m_model->setImageUpdate(Image::ManagerImpl::ubuntuId, 2, 0);
177
Q_EMIT mockUpdatePaused(50);
178
QSharedPointer<Update> u = m_model->fetch(Image::ManagerImpl::ubuntuId, 2);
179
QCOMPARE(u->state(), Update::State::StateDownloadPaused);
180
QCOMPARE(u->progress(), 50);
182
void testUpdateDownloaded()
184
m_model->setImageUpdate(Image::ManagerImpl::ubuntuId, 2, 0);
185
Q_EMIT mockUpdateDownloaded();
186
QSharedPointer<Update> u = m_model->fetch(Image::ManagerImpl::ubuntuId, 2);
187
QCOMPARE(u->state(), Update::State::StateDownloaded);
189
void testUpdateFailed()
191
m_model->setImageUpdate(Image::ManagerImpl::ubuntuId, 2, 0);
192
Q_EMIT mockUpdateFailed(1, "failure");
193
QSharedPointer<Update> u = m_model->fetch(Image::ManagerImpl::ubuntuId, 2);
194
QCOMPARE(u->error(), QString("failure"));
196
void testCurrentBuildNumberChanged()
198
/* Makes sure any updates that has the current build number are marked
200
m_model->setImageUpdate(Image::ManagerImpl::ubuntuId, 1, 0);
201
Q_EMIT mockCurrentBuildNumberChanged();
202
QSharedPointer<Update> u = m_model->fetch(Image::ManagerImpl::ubuntuId, 1);
203
QVERIFY(u->installed());
205
void testRebooting_data()
207
/* status: A boolean indicating whether the device has initiated a reboot
209
QTest::addColumn<bool>("status");
210
QTest::newRow("initiated") << true;
211
QTest::newRow("not initiated") << false;
215
QFETCH(bool, status);
216
m_model->setImageUpdate(Image::ManagerImpl::ubuntuId, 2, 0);
217
Q_EMIT mockRebooting(status);
218
QSharedPointer<Update> u = m_model->fetch(Image::ManagerImpl::ubuntuId, 2);
220
QCOMPARE(u->state(), Update::State::StateInstalling);
222
QCOMPARE(u->state(), Update::State::StateFailed);
225
void testUpdateProcessing()
227
m_model->setImageUpdate(Image::ManagerImpl::ubuntuId, 2, 0);
228
Q_EMIT mockUpdateProcessing();
229
QSharedPointer<Update> u = m_model->fetch(Image::ManagerImpl::ubuntuId, 2);
230
QCOMPARE(u->state(), Update::State::StateInstalling);
232
void testUpdateProcessFailed()
234
m_model->setImageUpdate(Image::ManagerImpl::ubuntuId, 2, 0);
235
Q_EMIT mockUpdateProcessFailed("failure");
236
QSharedPointer<Update> u = m_model->fetch(Image::ManagerImpl::ubuntuId, 2);
237
QCOMPARE(u->state(), Update::State::StateFailed);
238
QCOMPARE(u->error(), QString("failure"));
241
void mockUpdateAvailableStatus(const bool isAvailable,
242
const bool downloading,
243
const QString &availableVersion,
244
const int &updateSize,
245
const QString &lastUpdateDate,
246
const QString &errorReason);
247
void mockDownloadStarted();
248
void mockUpdateProgress(const int &percentage, const double &eta);
249
void mockUpdatePaused(const int &percentage);
250
void mockUpdateDownloaded();
251
void mockUpdateFailed(const int &consecutiveFailureCount, const QString &lastReason);
252
void mockCurrentBuildNumberChanged();
253
void mockRebooting(const bool status);
254
void mockUpdateProcessing();
255
void mockUpdateProcessFailed(const QString &reason);
256
void mockCheckingForUpdatesChanged();
259
QSignalSpy *m_methodSpy;
260
FakeSystemImageDbus *m_siMock = nullptr;
261
QDBusConnection *m_dbus = nullptr;
262
QSystemImage *m_systemImage = nullptr;
263
QDBusInterface *m_mock = nullptr;
264
Image::Manager *m_instance = nullptr;
265
UpdateModel *m_model = nullptr;
268
QTEST_GUILESS_MAIN(TstImageManager)
269
#include "tst_imagemanager.moc"