summaryrefslogtreecommitdiffstats
path: root/tests/auto/network/socket
diff options
context:
space:
mode:
authorPiotr Mikolajczyk <piotr.mikolajczyk@qt.io>2021-01-14 11:29:06 +0100
committerPiotr Mikolajczyk <piotr.mikolajczyk@qt.io>2021-04-01 06:57:04 +0100
commit2e3f48637e2e4fbd99424a98f361a0df277ea351 (patch)
tree274ad045334d025b87bb8973fb4afb47b6c3f8c9 /tests/auto/network/socket
parentaa84de1afa78cf4b63239b35a4b65f1c9c4eab6c (diff)
Linux: Add abstract address support for QLocal{Socket,Server}
Takes advantage of Linux's and Android's support for abstract namespace when binding sockets, which is independent of the filesystem (see man entry for unix domain sockets). To make QLocalServer and QLocalSocket use an abstract socket address, one needs to set the socket options to QLocalServer::AbstractNamespaceOption. Fixes: QTBUG-16090 Change-Id: Ia9f9c9cc1ac5c28f9d44b0a48d854a7cfbd39b11 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/network/socket')
-rw-r--r--tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp136
1 files changed, 126 insertions, 10 deletions
diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
index 8b2b4ea4da..f20f82ff88 100644
--- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
+++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
@@ -56,6 +56,7 @@
Q_DECLARE_METATYPE(QLocalSocket::LocalSocketError)
Q_DECLARE_METATYPE(QLocalSocket::LocalSocketState)
Q_DECLARE_METATYPE(QLocalServer::SocketOption)
+Q_DECLARE_METATYPE(QLocalSocket::SocketOption)
Q_DECLARE_METATYPE(QFile::Permissions)
class tst_QLocalSocket : public QObject
@@ -77,6 +78,12 @@ private slots:
void listenAndConnect_data();
void listenAndConnect();
+ void listenAndConnectAbstractNamespace_data();
+ void listenAndConnectAbstractNamespace();
+
+ void listenAndConnectAbstractNamespaceTrailingZeros_data();
+ void listenAndConnectAbstractNamespaceTrailingZeros();
+
void connectWithOpen();
void connectWithOldOpen();
@@ -135,6 +142,7 @@ tst_QLocalSocket::tst_QLocalSocket()
qRegisterMetaType<QLocalSocket::LocalSocketState>("QLocalSocket::LocalSocketState");
qRegisterMetaType<QLocalSocket::LocalSocketError>("QLocalSocket::LocalSocketError");
qRegisterMetaType<QLocalServer::SocketOption>("QLocalServer::SocketOption");
+ qRegisterMetaType<QLocalServer::SocketOption>("QLocalSocket::SocketOption");
qRegisterMetaType<QFile::Permissions>("QFile::Permissions");
}
@@ -483,6 +491,105 @@ void tst_QLocalSocket::connectWithOpen()
server.close();
}
+void tst_QLocalSocket::listenAndConnectAbstractNamespaceTrailingZeros_data()
+{
+#ifdef Q_OS_LINUX
+ QTest::addColumn<bool>("server_0");
+ QTest::addColumn<bool>("client_0");
+ QTest::addColumn<bool>("success");
+ QTest::newRow("srv0_cli0") << true << true << true;
+ QTest::newRow("srv_cli0") << false << true << false;
+ QTest::newRow("srv0_cli") << true << false << false;
+ QTest::newRow("srv_cli") << false << false << true;
+#else
+ return;
+#endif
+}
+
+void tst_QLocalSocket::listenAndConnectAbstractNamespaceTrailingZeros()
+{
+#ifdef Q_OS_LINUX
+ QFETCH(bool, server_0);
+ QFETCH(bool, client_0);
+ QFETCH(bool, success);
+ bool expectedTimeOut = !success;
+ QString server_path("tst_qlocalsocket");
+ QString client_path("tst_qlocalsocket");
+
+ if (server_0)
+ server_path.append(QChar('\0'));
+ if (client_0)
+ client_path.append(QChar('\0'));
+ LocalServer server;
+ server.setSocketOptions(QLocalServer::AbstractNamespaceOption);
+ QVERIFY(server.listen(server_path));
+ QCOMPARE(server.fullServerName(), server_path);
+
+ LocalSocket socket;
+ socket.setSocketOptions(QLocalSocket::AbstractNamespaceOption);
+ socket.setServerName(client_path);
+ QCOMPARE(socket.open(), success);
+ if (success)
+ QCOMPARE(socket.fullServerName(), client_path);
+ else
+ QVERIFY(socket.fullServerName().isEmpty());
+
+ bool timedOut = true;
+ QCOMPARE(server.waitForNewConnection(3000, &timedOut), success);
+
+#if defined(QT_LOCALSOCKET_TCP)
+ QTest::qWait(250);
+#endif
+ QCOMPARE(timedOut, expectedTimeOut);
+
+ socket.close();
+ server.close();
+#else
+ return;
+#endif
+}
+
+void tst_QLocalSocket::listenAndConnectAbstractNamespace_data()
+{
+ QTest::addColumn<QLocalServer::SocketOption>("serverOption");
+ QTest::addColumn<QLocalSocket::SocketOption>("socketOption");
+ QTest::addColumn<bool>("success");
+ QTest::newRow("abs_abs") << QLocalServer::AbstractNamespaceOption << QLocalSocket::AbstractNamespaceOption << true;
+ QTest::newRow("reg_reg") << QLocalServer::NoOptions << QLocalSocket::NoOptions << true;
+#ifdef Q_OS_LINUX
+ QTest::newRow("reg_abs") << QLocalServer::UserAccessOption << QLocalSocket::AbstractNamespaceOption << false;
+ QTest::newRow("abs_reg") << QLocalServer::AbstractNamespaceOption << QLocalSocket::NoOptions << false;
+#endif
+}
+
+void tst_QLocalSocket::listenAndConnectAbstractNamespace()
+{
+ QFETCH(QLocalServer::SocketOption, serverOption);
+ QFETCH(QLocalSocket::SocketOption, socketOption);
+ QFETCH(bool, success);
+ bool expectedTimeOut = !success;
+
+ LocalServer server;
+ server.setSocketOptions(serverOption);
+ QVERIFY(server.listen("tst_qlocalsocket"));
+
+ LocalSocket socket;
+ socket.setSocketOptions(socketOption);
+ socket.setServerName("tst_qlocalsocket");
+ QCOMPARE(socket.open(), success);
+
+ bool timedOut = true;
+ QCOMPARE(server.waitForNewConnection(3000, &timedOut), success);
+
+#if defined(QT_LOCALSOCKET_TCP)
+ QTest::qWait(250);
+#endif
+ QCOMPARE(timedOut, expectedTimeOut);
+
+ socket.close();
+ server.close();
+}
+
void tst_QLocalSocket::connectWithOldOpen()
{
class OverriddenOpen : public LocalSocket
@@ -1331,15 +1438,15 @@ void tst_QLocalSocket::verifyListenWithDescriptor()
int listenSocket;
+ // Construct the unix address
+ struct ::sockaddr_un addr;
+ addr.sun_family = PF_UNIX;
+
if (bound) {
// create the unix socket
listenSocket = ::socket(PF_UNIX, SOCK_STREAM, 0);
QVERIFY2(listenSocket != -1, "failed to create test socket");
- // Construct the unix address
- struct ::sockaddr_un addr;
- addr.sun_family = PF_UNIX;
-
QVERIFY2(sizeof(addr.sun_path) > ((uint)path.size() + 1), "path to large to create socket");
::memset(addr.sun_path, 0, sizeof(addr.sun_path));
@@ -1368,12 +1475,12 @@ void tst_QLocalSocket::verifyListenWithDescriptor()
QVERIFY2(server.listen(listenSocket), "failed to start create QLocalServer with local socket");
#ifdef Q_OS_LINUX
- const QChar at(QLatin1Char('@'));
if (!bound) {
- QCOMPARE(server.serverName().at(0), at);
- QCOMPARE(server.fullServerName().at(0), at);
+ QCOMPARE(server.serverName().isEmpty(), true);
+ QCOMPARE(server.fullServerName().isEmpty(), true);
} else if (abstract) {
- QVERIFY2(server.fullServerName().at(0) == at, "abstract sockets should start with a '@'");
+ QVERIFY2(server.fullServerName().at(0) == addr.sun_path[1],
+ "abstract sockets should match server path without leading null");
} else {
QCOMPARE(server.fullServerName(), path);
if (path.contains(QLatin1Char('/'))) {
@@ -1383,8 +1490,17 @@ void tst_QLocalSocket::verifyListenWithDescriptor()
}
}
#else
- QVERIFY(server.serverName().isEmpty());
- QVERIFY(server.fullServerName().isEmpty());
+ if (bound) {
+ QCOMPARE(server.fullServerName(), path);
+ if (path.contains(QLatin1Char('/'))) {
+ QVERIFY2(server.serverName() == path.mid(path.lastIndexOf(QLatin1Char('/'))+1), "server name invalid short name");
+ } else {
+ QVERIFY2(server.serverName() == path, "server name doesn't match the path provided");
+ }
+ } else {
+ QVERIFY(server.serverName().isEmpty());
+ QVERIFY(server.fullServerName().isEmpty());
+ }
#endif