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
33#include <private/qtbluetoothglobal_p.h>
34#include <qbluetoothserver.h>
35#include <qbluetoothsocket.h>
36#include <qbluetoothlocaldevice.h>
37
38QT_USE_NAMESPACE
39
40//same uuid as tests/bttestui
41#define TEST_SERVICE_UUID "e8e10f95-1a70-4b27-9ccf-02010264e9c8"
42
43Q_DECLARE_METATYPE(QBluetooth::SecurityFlags)
44
45// Max time to wait for connection
46static const int MaxConnectTime = 60 * 1000; // 1 minute in ms
47
48class tst_QBluetoothServer : public QObject
49{
50 Q_OBJECT
51
52public:
53 tst_QBluetoothServer();
54 ~tst_QBluetoothServer();
55
56private slots:
57 void initTestCase();
58 void cleanupTestCase();
59
60 void tst_construction();
61
62 void tst_receive_data();
63 void tst_receive();
64
65 void setHostMode(const QBluetoothAddress &localAdapter, QBluetoothLocalDevice::HostMode newHostMode);
66
67private:
68 QBluetoothLocalDevice localDevice;
69 QBluetoothLocalDevice::HostMode initialHostMode;
70};
71
72tst_QBluetoothServer::tst_QBluetoothServer()
73{
74}
75
76tst_QBluetoothServer::~tst_QBluetoothServer()
77{
78}
79
80void tst_QBluetoothServer::setHostMode(const QBluetoothAddress &localAdapter,
81 QBluetoothLocalDevice::HostMode newHostMode)
82{
83 QBluetoothLocalDevice device(localAdapter);
84 QSignalSpy hostModeSpy(&device, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)));
85
86 if (!device.isValid())
87 return;
88
89 if (device.hostMode() == newHostMode)
90 return;
91
92 //We distinguish powerOn() and setHostMode(HostConnectable) because
93 //Android uses different permission levels, we want to avoid interaction with user
94 //which implies usage of powerOn -> unfortunately powerOn() is not equivalent to HostConnectable
95 //Unfortunately the discoverable mode always requires a user confirmation
96 switch (newHostMode) {
97 case QBluetoothLocalDevice::HostPoweredOff:
98 case QBluetoothLocalDevice::HostDiscoverable:
99 case QBluetoothLocalDevice::HostDiscoverableLimitedInquiry:
100 device.setHostMode(newHostMode);
101 break;
102 case QBluetoothLocalDevice::HostConnectable:
103 device.powerOn();
104 break;
105 }
106
107 int connectTime = 5000; // ms
108 while (hostModeSpy.count() < 1 && connectTime > 0) {
109 QTest::qWait(ms: 500);
110 connectTime -= 500;
111 }
112}
113
114void tst_QBluetoothServer::initTestCase()
115{
116 qRegisterMetaType<QBluetooth::SecurityFlags>();
117 qRegisterMetaType<QBluetoothServer::Error>();
118
119 QBluetoothLocalDevice device;
120 if (!device.isValid())
121 return;
122
123 initialHostMode = device.hostMode();
124#ifdef Q_OS_OSX
125 if (initialHostMode == QBluetoothLocalDevice::HostPoweredOff)
126 return;
127#endif
128
129 setHostMode(localAdapter: device.address(), newHostMode: QBluetoothLocalDevice::HostConnectable);
130
131 QBluetoothLocalDevice::HostMode hostMode= localDevice.hostMode();
132
133 QVERIFY(hostMode != QBluetoothLocalDevice::HostPoweredOff);
134}
135
136void tst_QBluetoothServer::cleanupTestCase()
137{
138 QBluetoothLocalDevice device;
139 setHostMode(localAdapter: device.address(), newHostMode: initialHostMode);
140}
141
142void tst_QBluetoothServer::tst_construction()
143{
144 {
145 QBluetoothServer server(QBluetoothServiceInfo::RfcommProtocol);
146
147 QVERIFY(!server.isListening());
148 QCOMPARE(server.maxPendingConnections(), 1);
149 QVERIFY(!server.hasPendingConnections());
150 QVERIFY(server.nextPendingConnection() == 0);
151 QCOMPARE(server.error(), QBluetoothServer::NoError);
152 QCOMPARE(server.serverType(), QBluetoothServiceInfo::RfcommProtocol);
153 }
154
155 {
156 QBluetoothServer server(QBluetoothServiceInfo::L2capProtocol);
157
158 QVERIFY(!server.isListening());
159 QCOMPARE(server.maxPendingConnections(), 1);
160 QVERIFY(!server.hasPendingConnections());
161 QVERIFY(server.nextPendingConnection() == 0);
162 QCOMPARE(server.error(), QBluetoothServer::NoError);
163 QCOMPARE(server.serverType(), QBluetoothServiceInfo::L2capProtocol);
164 }
165}
166
167void tst_QBluetoothServer::tst_receive_data()
168{
169 QTest::addColumn<QBluetoothLocalDevice::HostMode>(name: "hostmode");
170 QTest::newRow(dataTag: "offline mode") << QBluetoothLocalDevice::HostPoweredOff;
171 QTest::newRow(dataTag: "online mode") << QBluetoothLocalDevice::HostConnectable;
172}
173
174void tst_QBluetoothServer::tst_receive()
175{
176 QFETCH(QBluetoothLocalDevice::HostMode, hostmode);
177
178 QBluetoothLocalDevice localDev;
179#ifdef Q_OS_OSX
180 if (localDev.hostMode() == QBluetoothLocalDevice::HostPoweredOff)
181 QSKIP("On OS X this test requires Bluetooth adapter ON");
182#endif
183 const QBluetoothAddress address = localDev.address();
184
185 bool localDeviceAvailable = localDev.isValid();
186
187 if (localDeviceAvailable) {
188 // setHostMode is noop on OS X and winrt.
189 setHostMode(localAdapter: address, newHostMode: hostmode);
190
191 if (hostmode == QBluetoothLocalDevice::HostPoweredOff) {
192#if !defined(Q_OS_OSX) && !QT_CONFIG(winrt_bt)
193 QCOMPARE(localDevice.hostMode(), hostmode);
194#endif
195 } else {
196 QVERIFY(localDevice.hostMode() != QBluetoothLocalDevice::HostPoweredOff);
197 }
198 }
199 QBluetoothServer server(QBluetoothServiceInfo::RfcommProtocol);
200 QSignalSpy errorSpy(&server, SIGNAL(error(QBluetoothServer::Error)));
201
202 bool result = server.listen(address, port: 20); // port == 20
203 QTest::qWait(ms: 1000);
204
205 if (!result) {
206 QCOMPARE(server.serverAddress(), QBluetoothAddress());
207 QCOMPARE(server.serverPort(), quint16(0));
208 QVERIFY(errorSpy.count() > 0);
209 QVERIFY(!server.isListening());
210 if (!localDeviceAvailable) {
211 QVERIFY(server.error() != QBluetoothServer::NoError);
212 } else {
213 //local device but poweredOff
214 QCOMPARE(server.error(), QBluetoothServer::PoweredOffError);
215 }
216 return;
217 }
218
219 QVERIFY(result);
220
221#if !QT_CONFIG(winrt_bt)
222 QVERIFY(QBluetoothLocalDevice::allDevices().count());
223#endif
224 QCOMPARE(server.error(), QBluetoothServer::NoError);
225 QCOMPARE(server.serverAddress(), address);
226 QCOMPARE(server.serverPort(), quint16(20));
227 QVERIFY(server.isListening());
228 QVERIFY(!server.hasPendingConnections());
229
230 server.close();
231 QCOMPARE(server.error(), QBluetoothServer::NoError);
232 QVERIFY(server.serverAddress() == address || server.serverAddress() == QBluetoothAddress());
233 QVERIFY(server.serverPort() == 0);
234 QVERIFY(!server.isListening());
235 QVERIFY(!server.hasPendingConnections());
236}
237
238
239QTEST_MAIN(tst_QBluetoothServer)
240
241#include "tst_qbluetoothserver.moc"
242

source code of qtconnectivity/tests/auto/qbluetoothserver/tst_qbluetoothserver.cpp