1 | /* |
2 | * SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com> |
3 | * |
4 | * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
5 | */ |
6 | |
7 | #include "autotests.h" |
8 | #include "adapter.h" |
9 | #include "battery.h" |
10 | #include "bluezqt_dbustypes.h" |
11 | #include "device.h" |
12 | #include "gattserviceremote.h" |
13 | #include "gattcharacteristicremote.h" |
14 | #include "gattdescriptorremote.h" |
15 | #include "mediaplayer.h" |
16 | #include "mediaplayertrack.h" |
17 | #include "mediatransport.h" |
18 | |
19 | #include <QCoreApplication> |
20 | #include <QDebug> |
21 | #include <QEventLoop> |
22 | |
23 | #include <QDBusConnectionInterface> |
24 | #include <QDBusServiceWatcher> |
25 | |
26 | QProcess *FakeBluez::s_process = nullptr; |
27 | |
28 | class StartJob : public QObject |
29 | { |
30 | Q_OBJECT |
31 | |
32 | public: |
33 | explicit StartJob(); |
34 | |
35 | void exec(); |
36 | |
37 | bool foundFakeBluez() const |
38 | { |
39 | return !m_fakebluezPath.isEmpty(); |
40 | } |
41 | |
42 | private Q_SLOTS: |
43 | void processError(QProcess::ProcessError error); |
44 | void processFinished(int code, QProcess::ExitStatus status); |
45 | |
46 | private: |
47 | QString m_fakebluezPath; |
48 | QEventLoop m_eventLoop; |
49 | }; |
50 | |
51 | StartJob::StartJob() |
52 | : QObject(nullptr) |
53 | , m_fakebluezPath(QCoreApplication::applicationDirPath() + QStringLiteral("/fakebluez" )) |
54 | { |
55 | } |
56 | |
57 | void StartJob::exec() |
58 | { |
59 | QDBusServiceWatcher watcher(QStringLiteral("org.kde.bluezqt.test" ), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration); |
60 | |
61 | connect(&watcher, &QDBusServiceWatcher::serviceRegistered, &m_eventLoop, &QEventLoop::quit); |
62 | connect(FakeBluez::s_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError))); |
63 | connect(FakeBluez::s_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus))); |
64 | |
65 | FakeBluez::s_process->start(m_fakebluezPath, QStringList()); |
66 | |
67 | m_eventLoop.exec(); |
68 | } |
69 | |
70 | void StartJob::processError(QProcess::ProcessError error) |
71 | { |
72 | QString errorString; |
73 | switch (error) { |
74 | case QProcess::FailedToStart: |
75 | errorString = QStringLiteral("Failed to Start" ); |
76 | break; |
77 | case QProcess::Crashed: |
78 | errorString = QStringLiteral("Crashed" ); |
79 | break; |
80 | case QProcess::Timedout: |
81 | errorString = QStringLiteral("Timedout" ); |
82 | break; |
83 | default: |
84 | errorString = QStringLiteral("Unknown" ); |
85 | } |
86 | |
87 | qWarning() << "Fakebluez binary:" << m_fakebluezPath; |
88 | qWarning() << "Process error:" << error << errorString; |
89 | qWarning() << "Error output:" << FakeBluez::s_process->readAllStandardError(); |
90 | |
91 | m_eventLoop.quit(); |
92 | } |
93 | |
94 | void StartJob::processFinished(int code, QProcess::ExitStatus status) |
95 | { |
96 | QString statusString = status == QProcess::NormalExit ? QStringLiteral("Normal Exit" ) : QStringLiteral("Crash Exit" ); |
97 | |
98 | qWarning() << "Fakebluez binary:" << m_fakebluezPath; |
99 | qWarning() << "Process finished:" << code << statusString; |
100 | qWarning() << "Error output:" << FakeBluez::s_process->readAllStandardError(); |
101 | |
102 | m_eventLoop.quit(); |
103 | } |
104 | |
105 | void FakeBluez::start() |
106 | { |
107 | if (isRunning()) { |
108 | return; |
109 | } |
110 | if (!s_process) { |
111 | s_process = new QProcess(); |
112 | } |
113 | |
114 | StartJob job; |
115 | QVERIFY(job.foundFakeBluez()); |
116 | job.exec(); |
117 | } |
118 | |
119 | void FakeBluez::stop() |
120 | { |
121 | if (s_process && s_process->state() == QProcess::Running) { |
122 | s_process->terminate(); |
123 | s_process->waitForFinished(); |
124 | } |
125 | } |
126 | |
127 | bool FakeBluez::isRunning() |
128 | { |
129 | return s_process && s_process->state() == QProcess::Running; |
130 | } |
131 | |
132 | void FakeBluez::runTest(const QString &testName) |
133 | { |
134 | if (!isRunning()) { |
135 | return; |
136 | } |
137 | |
138 | QDBusMessage call = QDBusMessage::createMethodCall(QStringLiteral("org.kde.bluezqt.test" ), |
139 | QStringLiteral("/" ), |
140 | QStringLiteral("org.kde.bluezqt.fakebluez.Test" ), |
141 | QStringLiteral("runTest" )); |
142 | |
143 | call << testName; |
144 | QDBusConnection::sessionBus().call(call); |
145 | } |
146 | |
147 | void FakeBluez::runAction(const QString &object, const QString &actionName, const QVariantMap &properties) |
148 | { |
149 | if (!isRunning()) { |
150 | return; |
151 | } |
152 | |
153 | QDBusMessage call = QDBusMessage::createMethodCall(QStringLiteral("org.kde.bluezqt.test" ), |
154 | QStringLiteral("/" ), |
155 | QStringLiteral("org.kde.bluezqt.fakebluez.Test" ), |
156 | QStringLiteral("runAction" )); |
157 | |
158 | call << object; |
159 | call << actionName; |
160 | call << properties; |
161 | |
162 | QDBusConnection::sessionBus().call(call); |
163 | } |
164 | |
165 | void Autotests::registerMetatypes() |
166 | { |
167 | qRegisterMetaType<BluezQt::GattDescriptorRemotePtr>("GattDescriptorRemotePtr" ); |
168 | qRegisterMetaType<BluezQt::GattCharacteristicRemotePtr>("GattCharacteristicRemotePtr" ); |
169 | qRegisterMetaType<BluezQt::GattServiceRemotePtr>("GattServiceRemotePtr" ); |
170 | qRegisterMetaType<BluezQt::DevicePtr>("DevicePtr" ); |
171 | qRegisterMetaType<BluezQt::AdapterPtr>("AdapterPtr" ); |
172 | qRegisterMetaType<BluezQt::BatteryPtr>("BatteryPtr" ); |
173 | qRegisterMetaType<BluezQt::MediaPlayerPtr>("MediaPlayerPtr" ); |
174 | qRegisterMetaType<BluezQt::MediaTransportPtr>("MediaTransportPtr" ); |
175 | } |
176 | |
177 | void Autotests::verifyPropertiesChangedSignal(const QSignalSpy &spy, const QString &propertyName, const QVariant &propertyValue) |
178 | { |
179 | int changes = 0; |
180 | |
181 | for (int i = 0; i < spy.count(); ++i) { |
182 | QList<QVariant> arguments = spy.at(i); |
183 | QVariantMap properties = arguments.at(1).toMap(); |
184 | |
185 | QVariantMap::const_iterator it; |
186 | for (it = properties.constBegin(); it != properties.constEnd(); ++it) { |
187 | const QVariant &changedValue = it.value(); |
188 | const QString &property = it.key(); |
189 | if (property == propertyName && changedValue == propertyValue) { |
190 | changes++; |
191 | } |
192 | } |
193 | } |
194 | |
195 | QCOMPARE(changes, 1); |
196 | } |
197 | |
198 | #include "autotests.moc" |
199 | |