1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtBluetooth module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30
31#include <QDebug>
32#include <QMap>
33#include <QTextStream>
34
35#include <qbluetoothtransferrequest.h>
36#include <qbluetoothtransfermanager.h>
37#include <qbluetoothtransferreply.h>
38#include <qbluetoothaddress.h>
39#include <qbluetoothlocaldevice.h>
40
41#include <qbluetoothdeviceinfo.h>
42#include <qbluetoothserviceinfo.h>
43#include <qbluetoothservicediscoveryagent.h>
44
45/*
46 * Some tests require a Bluetooth device within the vincinity of the test
47 * machine executing this test. The tests require manual interaction
48 * as pairing and file transfer requests must be accepted.
49 * The remote device's address must be passed
50 * via the BT_TEST_DEVICE env variable. The remote device must be
51 * discoverable and the object push service must be accessible. Any
52 **/
53
54QT_USE_NAMESPACE
55
56typedef QMap<QBluetoothTransferRequest::Attribute,QVariant> tst_QBluetoothTransferManager_QParameterMap;
57Q_DECLARE_METATYPE(tst_QBluetoothTransferManager_QParameterMap)
58
59static const int MaxConnectTime = 60 * 1000; // 1 minute in ms
60
61class tst_QBluetoothTransferManager : public QObject
62{
63 Q_OBJECT
64
65public:
66 tst_QBluetoothTransferManager();
67 ~tst_QBluetoothTransferManager();
68
69private slots:
70 void initTestCase();
71
72 void tst_construction();
73
74 void tst_request_data();
75 void tst_request();
76
77 void tst_sendFile_data();
78 void tst_sendFile();
79
80 void tst_sendBuffer_data();
81 void tst_sendBuffer();
82
83 void tst_sendNullPointer();
84private:
85 QBluetoothAddress remoteAddress;
86};
87
88tst_QBluetoothTransferManager::tst_QBluetoothTransferManager()
89{
90}
91
92tst_QBluetoothTransferManager::~tst_QBluetoothTransferManager()
93{
94}
95
96void tst_QBluetoothTransferManager::initTestCase()
97{
98 const QString remote = qgetenv(varName: "BT_TEST_DEVICE");
99 if (!remote.isEmpty()) {
100 remoteAddress = QBluetoothAddress(remote);
101 QVERIFY(!remoteAddress.isNull());
102 qWarning() << "Using remote device " << remote << " for testing. Ensure that the device is discoverable for pairing requests";
103 } else {
104 qWarning() << "Not using any remote device for testing. Set BT_TEST_DEVICE env to run manual tests involving a remote device";
105 QSKIP("Remote upload test not possible. Set BT_TEST_DEVICE");
106 }
107
108 if (!QBluetoothLocalDevice::allDevices().count())
109 QSKIP("Skipping test due to missing Bluetooth device");
110
111 // start Bluetooth if not started
112 QBluetoothLocalDevice *device = new QBluetoothLocalDevice();
113 device->powerOn();
114 delete device;
115}
116
117void tst_QBluetoothTransferManager::tst_construction()
118{
119 QBluetoothTransferManager *manager = new QBluetoothTransferManager();
120
121 QVERIFY(manager);
122 delete manager;
123}
124
125void tst_QBluetoothTransferManager::tst_request_data()
126{
127 QTest::addColumn<QBluetoothAddress>(name: "address");
128 QTest::addColumn<QMap<QBluetoothTransferRequest::Attribute, QVariant> >(name: "parameters");
129
130 QMap<QBluetoothTransferRequest::Attribute, QVariant> inparameters;
131 inparameters.insert(akey: QBluetoothTransferRequest::DescriptionAttribute, avalue: "Description");
132 inparameters.insert(akey: QBluetoothTransferRequest::LengthAttribute, avalue: QVariant(1024));
133 inparameters.insert(akey: QBluetoothTransferRequest::TypeAttribute, avalue: "OPP");
134 inparameters.insert(akey: QBluetoothTransferRequest::NameAttribute, avalue: "name");
135 inparameters.insert(akey: QBluetoothTransferRequest::TimeAttribute, avalue: QDateTime::currentDateTime());
136
137 QTest::newRow(dataTag: "TESTDATA") << QBluetoothAddress("00:11:22:33:44:55:66") << inparameters;
138}
139
140void tst_QBluetoothTransferManager::tst_request()
141{
142 QFETCH(QBluetoothAddress, address);
143 QFETCH(tst_QBluetoothTransferManager_QParameterMap, parameters);
144
145 QBluetoothTransferRequest transferRequest(address);
146 const QList<QBluetoothTransferRequest::Attribute> attributes = parameters.keys();
147 for (QBluetoothTransferRequest::Attribute key : attributes)
148 QCOMPARE(transferRequest.attribute(key), QVariant());
149
150 for (QBluetoothTransferRequest::Attribute key : attributes)
151 transferRequest.setAttribute(code: (QBluetoothTransferRequest::Attribute)key, value: parameters[key]);
152
153 QCOMPARE(transferRequest.address(), address);
154 for (QBluetoothTransferRequest::Attribute key : attributes)
155 QCOMPARE(transferRequest.attribute(key), parameters[key]);
156
157 //test copy constructor
158 QBluetoothTransferRequest constructorCopy = transferRequest;
159 QVERIFY(constructorCopy == transferRequest);
160 QVERIFY(!(constructorCopy != transferRequest));
161 QCOMPARE(constructorCopy.address(), address);
162 for (QBluetoothTransferRequest::Attribute key : attributes)
163 QCOMPARE(constructorCopy.attribute(key), parameters[key]);
164
165 //test assignment operator
166 QBluetoothTransferRequest request;
167 QVERIFY(request.address().isNull());
168 for (QBluetoothTransferRequest::Attribute key : attributes)
169 QCOMPARE(request.attribute(key), QVariant());
170 request = transferRequest;
171 QCOMPARE(request.address(), address);
172 for (QBluetoothTransferRequest::Attribute key : attributes)
173 QCOMPARE(request.attribute(key), parameters[key]);
174
175 //test that it's a true and independent copy
176 constructorCopy.setAttribute(code: QBluetoothTransferRequest::DescriptionAttribute, value: "newDescription");
177 request.setAttribute(code: QBluetoothTransferRequest::TypeAttribute, value: "FTP");
178
179 QCOMPARE(constructorCopy.attribute(QBluetoothTransferRequest::DescriptionAttribute).toString(),QString("newDescription"));
180 QCOMPARE(request.attribute(QBluetoothTransferRequest::DescriptionAttribute).toString(),QString("Description"));
181 QCOMPARE(transferRequest.attribute(QBluetoothTransferRequest::DescriptionAttribute).toString(),QString("Description"));
182
183 QCOMPARE(constructorCopy.attribute(QBluetoothTransferRequest::TypeAttribute).toString(),QString("OPP"));
184 QCOMPARE(request.attribute(QBluetoothTransferRequest::TypeAttribute).toString(),QString("FTP"));
185 QCOMPARE(transferRequest.attribute(QBluetoothTransferRequest::TypeAttribute).toString(),QString("OPP"));
186}
187
188void tst_QBluetoothTransferManager::tst_sendFile_data()
189{
190 QTest::addColumn<QBluetoothAddress>(name: "deviceAddress");
191 QTest::addColumn<bool>(name: "expectSuccess");
192 QTest::addColumn<bool>(name: "isInvalidFile");
193
194 QTest::newRow(dataTag: "Push to remote test device") << remoteAddress << true << false;
195 QTest::newRow(dataTag: "Push of non-existing file") << remoteAddress << false << true;
196 QTest::newRow(dataTag: "Push to invalid address") << QBluetoothAddress() << false << false;
197 QTest::newRow(dataTag: "Push to non-existend device") << QBluetoothAddress("11:22:33:44:55:66") << false << false;
198
199}
200
201void tst_QBluetoothTransferManager::tst_sendFile()
202{
203 QFETCH(QBluetoothAddress, deviceAddress);
204 QFETCH(bool, expectSuccess);
205 QFETCH(bool, isInvalidFile);
206
207 QBluetoothLocalDevice dev;
208 if (expectSuccess) {
209 dev.requestPairing(address: deviceAddress, pairing: QBluetoothLocalDevice::Paired);
210 QTest::qWait(ms: 5000);
211 QCOMPARE(dev.pairingStatus(deviceAddress), QBluetoothLocalDevice::Paired);
212 }
213
214 QBluetoothTransferRequest request(deviceAddress);
215 QCOMPARE(request.address(), deviceAddress);
216
217 QBluetoothTransferManager manager;
218 QString fileHandle;
219 if (!isInvalidFile) {
220 fileHandle = QFINDTESTDATA("testfile.txt");
221 QVERIFY(!fileHandle.isEmpty());
222 } else {
223 fileHandle = ("arbitraryFileName.txt"); //file doesn't exist
224 }
225 QFile f(fileHandle);
226 QCOMPARE(f.exists(), !isInvalidFile);
227
228
229 qDebug() << "Transferring file to " << deviceAddress.toString();
230 if (expectSuccess)
231 qDebug() << "Please accept Object push request on remote device";
232 QBluetoothTransferReply* reply = manager.put(request, data: &f);
233 QSignalSpy finishedSpy(reply, SIGNAL(finished(QBluetoothTransferReply*)));
234 QSignalSpy progressSpy(reply, SIGNAL(transferProgress(qint64,qint64)));
235 QSignalSpy errorSpy(reply, SIGNAL(error(QBluetoothTransferReply::TransferError)));
236
237 QCOMPARE(reply->request(), request);
238 QVERIFY(reply->manager() == &manager);
239 QVERIFY(!reply->isFinished());
240 QVERIFY(reply->isRunning());
241
242 const int maxWaitTime = 20 * 1000; //20s
243 for (int time = 0;
244 time<maxWaitTime && (finishedSpy.count()==0);
245 time+=1000) {
246 QTest::qWait(ms: 1000); //if interval
247 }
248
249 QVERIFY(finishedSpy.count()>0);
250 if (expectSuccess) {
251 QVERIFY(progressSpy.count()>0);
252 QCOMPARE(reply->error(), QBluetoothTransferReply::NoError);
253 QCOMPARE(reply->errorString(), QString());
254 QVERIFY(errorSpy.isEmpty());
255 } else {
256 QVERIFY(progressSpy.count() == 0);
257 if (isInvalidFile)
258 QVERIFY(reply->error() == QBluetoothTransferReply::FileNotFoundError);
259 else
260 QVERIFY(reply->error() != QBluetoothTransferReply::NoError);
261 QVERIFY(!reply->errorString().isEmpty());
262 QCOMPARE(errorSpy.count(), 1);
263 }
264
265 QVERIFY(reply->isFinished());
266 QVERIFY(!reply->isRunning());
267}
268
269void tst_QBluetoothTransferManager::tst_sendBuffer_data()
270{
271
272 QTest::addColumn<QBluetoothAddress>(name: "deviceAddress");
273 QTest::addColumn<bool>(name: "expectSuccess");
274 QTest::addColumn<QByteArray>(name: "data");
275
276 QTest::newRow(dataTag: "Push to remote test device") << remoteAddress << true <<
277 QByteArray("This is a very long byte array which we are going to access via a QBuffer"); ;
278 QTest::newRow(dataTag: "Push to invalid address") << QBluetoothAddress() << false << QByteArray("test");
279 QTest::newRow(dataTag: "Push to non-existend device") << QBluetoothAddress("11:22:33:44:55:66") << false << QByteArray("test");
280}
281
282
283
284void tst_QBluetoothTransferManager::tst_sendBuffer()
285{
286 QFETCH(QBluetoothAddress, deviceAddress);
287 QFETCH(bool, expectSuccess);
288 QFETCH(QByteArray, data);
289
290 QBuffer buffer;
291 buffer.setData(data);
292 buffer.open(openMode: QIODevice::ReadOnly);
293 buffer.seek(off: 0);
294
295 QBluetoothLocalDevice dev;
296 if (expectSuccess) {
297 dev.requestPairing(address: deviceAddress, pairing: QBluetoothLocalDevice::Paired);
298 QTest::qWait(ms: 2000);
299 QCOMPARE(dev.pairingStatus(deviceAddress), QBluetoothLocalDevice::Paired);
300 }
301
302 QBluetoothTransferRequest request(deviceAddress);
303 QCOMPARE(request.address(), deviceAddress);
304
305 QBluetoothTransferManager manager;
306
307 qDebug() << "Transferring test buffer to " << deviceAddress.toString();
308 if (expectSuccess)
309 qDebug() << "Please accept Object push request on remote device";
310 QBluetoothTransferReply* reply = manager.put(request, data: &buffer);
311 QSignalSpy finishedSpy(reply, SIGNAL(finished(QBluetoothTransferReply*)));
312 QSignalSpy progressSpy(reply, SIGNAL(transferProgress(qint64,qint64)));
313 QSignalSpy errorSpy(reply, SIGNAL(error(QBluetoothTransferReply::TransferError)));
314
315 QCOMPARE(reply->request(), request);
316 QVERIFY(reply->manager() == &manager);
317 QVERIFY(!reply->isFinished());
318 QVERIFY(reply->isRunning());
319
320 const int maxWaitTime = 20 * 1000; //20s
321 for (int time = 0;
322 time<maxWaitTime && (finishedSpy.count()==0);
323 time+=10000) {
324 QTest::qWait(ms: 10000); //if interval
325 }
326
327 QVERIFY(finishedSpy.count()>0);
328 if (expectSuccess) {
329 QVERIFY(progressSpy.count()>0);
330 QVERIFY(errorSpy.isEmpty());
331 QCOMPARE(reply->error(), QBluetoothTransferReply::NoError);
332 QCOMPARE(reply->errorString(), QString());
333 } else {
334 QVERIFY(progressSpy.count() == 0);
335 QVERIFY(reply->error() != QBluetoothTransferReply::NoError);
336 QVERIFY(!reply->errorString().isEmpty());
337 QCOMPARE(errorSpy.count(), 1);
338 }
339
340 QVERIFY(reply->isFinished());
341 QVERIFY(!reply->isRunning());
342}
343
344void tst_QBluetoothTransferManager::tst_sendNullPointer()
345{
346 QBluetoothTransferRequest request(remoteAddress);
347 QBluetoothTransferManager manager;
348 QBluetoothTransferReply *reply = manager.put(request, data: 0);
349
350 QVERIFY(reply);
351 QCOMPARE(reply->isFinished(), true);
352 QCOMPARE(reply->isRunning(), false);
353 QCOMPARE(reply->manager(), &manager);
354 QCOMPARE(reply->request(), request);
355 QCOMPARE(reply->error(), QBluetoothTransferReply::FileNotFoundError);
356}
357
358QTEST_MAIN(tst_QBluetoothTransferManager)
359
360#include "tst_qbluetoothtransfermanager.moc"
361

source code of qtconnectivity/tests/auto/qbluetoothtransfermanager/tst_qbluetoothtransfermanager.cpp