/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QT_NO_NATIVE_POLL #define QT_NO_NATIVE_POLL #endif #include #include #include QT_BEGIN_NAMESPACE // defined in qpoll.cpp int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts); QT_END_NAMESPACE class tst_qt_poll : public QObject { Q_OBJECT private slots: void pollout(); void pollin(); void pollnval(); void pollprihup(); }; void tst_qt_poll::pollout() { int fds[2]; QCOMPARE(pipe(fds), 0); struct pollfd pfd = { fds[1], POLLOUT, 0 }; const int nready = qt_poll(&pfd, 1, NULL); QCOMPARE(nready, 1); QCOMPARE(pfd.revents, short(POLLOUT)); qt_safe_close(fds[0]); qt_safe_close(fds[1]); } void tst_qt_poll::pollin() { int fds[2]; QCOMPARE(pipe(fds), 0); const char data = 'Q'; QCOMPARE(qt_safe_write(fds[1], &data, 1), 1); struct pollfd pfd = { fds[0], POLLIN, 0 }; const int nready = qt_poll(&pfd, 1, NULL); QCOMPARE(nready, 1); QCOMPARE(pfd.revents, short(POLLIN)); qt_safe_close(fds[0]); qt_safe_close(fds[1]); } void tst_qt_poll::pollnval() { struct pollfd pfd = { 42, POLLOUT, 0 }; int nready = qt_poll(&pfd, 1, NULL); QCOMPARE(nready, 1); QCOMPARE(pfd.revents, short(POLLNVAL)); pfd.events = 0; pfd.revents = 0; nready = qt_poll(&pfd, 1, NULL); QCOMPARE(nready, 1); QCOMPARE(pfd.revents, short(POLLNVAL)); } void tst_qt_poll::pollprihup() { QTcpServer server; QTcpSocket client_socket; QVERIFY(server.listen(QHostAddress::LocalHost)); const quint16 server_port = server.serverPort(); client_socket.connectToHost(server.serverAddress(), server_port); QVERIFY(client_socket.waitForConnected()); QVERIFY(server.waitForNewConnection()); QTcpSocket *server_socket = server.nextPendingConnection(); server.close(); // TCP supports only a single byte of urgent data static const char oob_out = 'Q'; QCOMPARE(::send(server_socket->socketDescriptor(), &oob_out, 1, MSG_OOB), ssize_t(1)); struct pollfd pfd = { int(client_socket.socketDescriptor()), POLLPRI | POLLIN, 0 }; int res = qt_poll(&pfd, 1, NULL); QCOMPARE(res, 1); QCOMPARE(pfd.revents, short(POLLPRI | POLLIN)); char oob_in = 0; // We do not specify MSG_OOB here as SO_OOBINLINE is turned on by default // in the native socket engine QCOMPARE(::recv(client_socket.socketDescriptor(), &oob_in, 1, 0), ssize_t(1)); QCOMPARE(oob_in, oob_out); server_socket->close(); pfd.events = POLLIN; res = qt_poll(&pfd, 1, NULL); QCOMPARE(res, 1); QCOMPARE(pfd.revents, short(POLLHUP)); } QTEST_APPLESS_MAIN(tst_qt_poll) #include "tst_qt_poll.moc"