From: Kurt Pattyn Date: Wed, 12 Feb 2014 14:17:58 +0000 (+0100) Subject: Add user configurable mask generation X-Git-Tag: v5.3.0-alpha1~7 X-Git-Url: http://review.tizen.org/git/?p=contrib%2Fqtwebsockets.git;a=commitdiff_plain;h=45eadd663ff22df46fadf03c45db7e058e71e476 Add user configurable mask generation Created a QMaskGenerator abstract base class to serve as a basis for user specific mask generators. Added the possibility to override the default mask generation in QWebSocket. Change-Id: Iaa02b44193f854d103b5f352617789175fe61f89 Reviewed-by: Kurt Pattyn --- diff --git a/src/websockets/qdefaultmaskgenerator_p.cpp b/src/websockets/qdefaultmaskgenerator_p.cpp new file mode 100644 index 0000000..2d8b1a2 --- /dev/null +++ b/src/websockets/qdefaultmaskgenerator_p.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebSockets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdefaultmaskgenerator_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +QDefaultMaskGenerator::QDefaultMaskGenerator(QObject *parent) : + QMaskGenerator(parent) +{ +} + +QDefaultMaskGenerator::~QDefaultMaskGenerator() +{ +} + +bool QDefaultMaskGenerator::seed() +{ + qsrand(static_cast(QDateTime::currentMSecsSinceEpoch())); + return true; +} + +quint32 QDefaultMaskGenerator::nextMask() +{ + return quint32((double(qrand()) / RAND_MAX) * std::numeric_limits::max()); +} + +QT_END_NAMESPACE diff --git a/src/websockets/qdefaultmaskgenerator_p.h b/src/websockets/qdefaultmaskgenerator_p.h new file mode 100644 index 0000000..5050a4a --- /dev/null +++ b/src/websockets/qdefaultmaskgenerator_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebSockets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDEFAULTMASKGENERATOR_P_H +#define QDEFAULTMASKGENERATOR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_NAMESPACE +class QObject; + +class Q_AUTOTEST_EXPORT QDefaultMaskGenerator : public QMaskGenerator +{ + Q_DISABLE_COPY(QDefaultMaskGenerator) + +public: + explicit QDefaultMaskGenerator(QObject *parent = 0); + virtual ~QDefaultMaskGenerator(); + + bool seed() Q_DECL_NOEXCEPT Q_DECL_OVERRIDE; + quint32 nextMask() Q_DECL_NOEXCEPT Q_DECL_OVERRIDE; +}; + +QT_END_NAMESPACE + +#endif // QDEFAULTMASKGENERATOR_P_H diff --git a/src/websockets/qmaskgenerator.cpp b/src/websockets/qmaskgenerator.cpp new file mode 100644 index 0000000..9c678b5 --- /dev/null +++ b/src/websockets/qmaskgenerator.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebSockets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QMaskGenerator + The QMaskGenerator class provides an abstract base for custom 32-bit mask generators. + + The WebSockets specification as outlined in {http://tools.ietf.org/html/rfc6455}{RFC 6455} + requires that all communication from client to server must be masked. This is to prevent + malicious scripts to attack bad behaving proxies. + For more information about the importance of good masking, + see \l {http://w2spconf.com/2011/papers/websocket.pdf}. + By default QWebSocket uses the cryptographically insecure qrand() function. + The best measure against attacks mentioned in the document above, + is to use QWebSocket over a secure connection (\e wss://). + In general, always be careful to not have 3rd party script access to + a QWebSocket in your application. +*/ + +/*! + \fn bool QMaskGenerator::seed() + + Initializes the QMaskGenerator by seeding the randomizer. + When seed() is not called, it depends on the specific implementation of a subclass if + a default seed is used or no seed is used at all. +*/ + +/*! + \fn quint32 QMaskGenerator::nextMask() + + Returns a new random 32-bit mask. The randomness depends on the RNG used to created the + mask. +*/ + +#include "qmaskgenerator.h" + +QT_BEGIN_NAMESPACE + +/*! + Creates a new QMaskGenerator object. + */ +QMaskGenerator::QMaskGenerator(QObject *parent) : + QObject(parent) +{ +} + +/*! + Destroys the QMaskGenerator object. + */ +QMaskGenerator::~QMaskGenerator() +{} + +QT_END_NAMESPACE diff --git a/src/websockets/qmaskgenerator.h b/src/websockets/qmaskgenerator.h new file mode 100644 index 0000000..00cadba --- /dev/null +++ b/src/websockets/qmaskgenerator.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebSockets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMASKGENERATOR_H +#define QMASKGENERATOR_H + +#include +#include "QtWebSockets/qwebsockets_global.h" + +QT_BEGIN_NAMESPACE + +class Q_WEBSOCKETS_EXPORT QMaskGenerator : public QObject +{ + Q_DISABLE_COPY(QMaskGenerator) + +public: + explicit QMaskGenerator(QObject *parent = Q_NULLPTR); + virtual ~QMaskGenerator(); + + virtual bool seed() = 0; + virtual quint32 nextMask() = 0; +}; + +QT_END_NAMESPACE + +#endif // QMASKGENERATOR_H diff --git a/src/websockets/qwebsocket.cpp b/src/websockets/qwebsocket.cpp index 0a0c420..ca8ae08 100644 --- a/src/websockets/qwebsocket.cpp +++ b/src/websockets/qwebsocket.cpp @@ -57,7 +57,17 @@ \l {http://tools.ietf.org/html/rfc6455#page-39} {extensions} and \l {http://tools.ietf.org/html/rfc6455#page-12} {subprotocols}. - QWebSocket only supports version 13 of the WebSocket protocol, as outlined in RFC 6455. + QWebSocket only supports version 13 of the WebSocket protocol, as outlined in + \l {http://tools.ietf.org/html/rfc6455}{RFC 6455}. + + \warning To generate masks, this implementation of WebSockets uses the cryptographically + insecure qrand() function. + For more information about the importance of good masking, + see \l {http://w2spconf.com/2011/papers/websocket.pdf}. + The best measure against attacks mentioned in the document above, + is to use QWebSocket over a secure connection (\e wss://). + In general, always be careful to not have 3rd party script access to + a QWebSocket in your application. \sa QAbstractSocket, QTcpSocket @@ -621,6 +631,26 @@ void QWebSocket::setProxy(const QNetworkProxy &networkProxy) #endif /*! + Sets the generator to use for creating masks to \a maskGenerator. + The default QWebSocket generator can be reset by supplying a \e Q_NULLPTR. + The mask generator can be changed at any time, even while the connection is open. + */ +void QWebSocket::setMaskGenerator(const QMaskGenerator *maskGenerator) +{ + Q_D(QWebSocket); + d->setMaskGenerator(maskGenerator); +} + +/*! + Returns the mask generator that is currently used by this QWebSocket. + */ +const QMaskGenerator *QWebSocket::maskGenerator() const +{ + Q_D(const QWebSocket); + return d->maskGenerator(); +} + +/*! Returns the size in bytes of the readbuffer that is used by the socket. */ qint64 QWebSocket::readBufferSize() const diff --git a/src/websockets/qwebsocket.h b/src/websockets/qwebsocket.h index 660b3a3..bb9f2db 100644 --- a/src/websockets/qwebsocket.h +++ b/src/websockets/qwebsocket.h @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE class QTcpSocket; class QWebSocketPrivate; +class QMaskGenerator; class Q_WEBSOCKETS_EXPORT QWebSocket : public QObject { @@ -85,6 +86,8 @@ public: QNetworkProxy proxy() const; void setProxy(const QNetworkProxy &networkProxy); #endif + void setMaskGenerator(const QMaskGenerator *maskGenerator); + const QMaskGenerator *maskGenerator() const; qint64 readBufferSize() const; void setReadBufferSize(qint64 size); diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp index 338e581..bff060f 100644 --- a/src/websockets/qwebsocket_p.cpp +++ b/src/websockets/qwebsocket_p.cpp @@ -44,6 +44,7 @@ #include "qwebsocketprotocol_p.h" #include "qwebsockethandshakerequest_p.h" #include "qwebsockethandshakeresponse_p.h" +#include "qdefaultmaskgenerator_p.h" #include #include @@ -109,7 +110,9 @@ QWebSocketPrivate::QWebSocketPrivate(const QString &origin, QWebSocketProtocol:: m_closeReason(), m_pingTimer(), m_dataProcessor(), - m_configuration() + m_configuration(), + m_pMaskGenerator(&m_defaultMaskGenerator), + m_defaultMaskGenerator() { } @@ -139,7 +142,9 @@ QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol: m_closeReason(), m_pingTimer(), m_dataProcessor(), - m_configuration() + m_configuration(), + m_pMaskGenerator(&m_defaultMaskGenerator), + m_defaultMaskGenerator() { } @@ -149,8 +154,9 @@ QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol: void QWebSocketPrivate::init() { Q_ASSERT(q_ptr); - //TODO: need a better randomizer - qsrand(static_cast(QDateTime::currentMSecsSinceEpoch())); + Q_ASSERT(m_pMaskGenerator); + + m_pMaskGenerator->seed(); if (m_pSocket) { makeConnections(m_pSocket.data()); @@ -762,20 +768,11 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary) } /*! - * \internal - */ -quint32 QWebSocketPrivate::generateRandomNumber() const -{ - //TODO: need a better randomizer - return quint32((double(qrand()) / RAND_MAX) * std::numeric_limits::max()); -} - -/*! \internal */ quint32 QWebSocketPrivate::generateMaskingKey() const { - return generateRandomNumber(); + return m_pMaskGenerator->nextMask(); } /*! @@ -786,7 +783,7 @@ QByteArray QWebSocketPrivate::generateKey() const QByteArray key; for (int i = 0; i < 4; ++i) { - const quint32 tmp = generateRandomNumber(); + const quint32 tmp = m_pMaskGenerator->nextMask(); key.append(static_cast(static_cast(&tmp)), sizeof(quint32)); } @@ -1235,6 +1232,26 @@ void QWebSocketPrivate::setProxy(const QNetworkProxy &networkProxy) /*! \internal */ +void QWebSocketPrivate::setMaskGenerator(const QMaskGenerator *maskGenerator) +{ + if (!maskGenerator) + m_pMaskGenerator = &m_defaultMaskGenerator; + else if (maskGenerator != m_pMaskGenerator) + m_pMaskGenerator = const_cast(maskGenerator); +} + +/*! + \internal + */ +const QMaskGenerator *QWebSocketPrivate::maskGenerator() const +{ + Q_ASSERT(m_pMaskGenerator); + return m_pMaskGenerator; +} + +/*! + \internal + */ qint64 QWebSocketPrivate::readBufferSize() const { return m_readBufferSize; diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h index 3bd9918..c1128c5 100644 --- a/src/websockets/qwebsocket_p.h +++ b/src/websockets/qwebsocket_p.h @@ -68,6 +68,7 @@ #include "qwebsocketprotocol.h" #include "qwebsocketdataprocessor_p.h" +#include "qdefaultmaskgenerator_p.h" QT_BEGIN_NAMESPACE @@ -75,6 +76,7 @@ class QWebSocketHandshakeRequest; class QWebSocketHandshakeResponse; class QTcpSocket; class QWebSocket; +class QMaskGenerator; struct QWebSocketConfiguration { @@ -122,6 +124,8 @@ public: QNetworkProxy proxy() const; void setProxy(const QNetworkProxy &networkProxy); #endif + void setMaskGenerator(const QMaskGenerator *maskGenerator); + const QMaskGenerator *maskGenerator() const; qint64 readBufferSize() const; void resume(); void setPauseMode(QAbstractSocket::PauseModes pauseMode); @@ -195,7 +199,6 @@ private: quint32 generateMaskingKey() const; QByteArray generateKey() const; - quint32 generateRandomNumber() const; qint64 writeFrames(const QList &frames) Q_REQUIRED_RESULT; qint64 writeFrame(const QByteArray &frame) Q_REQUIRED_RESULT; @@ -226,6 +229,9 @@ private: QWebSocketDataProcessor m_dataProcessor; QWebSocketConfiguration m_configuration; + QMaskGenerator *m_pMaskGenerator; + QDefaultMaskGenerator m_defaultMaskGenerator; + friend class QWebSocketServerPrivate; }; diff --git a/src/websockets/websockets.pro b/src/websockets/websockets.pro index 04bee8e..99e84b6 100644 --- a/src/websockets/websockets.pro +++ b/src/websockets/websockets.pro @@ -1,7 +1,7 @@ load(qt_build_config) TARGET = QtWebSockets -QT = core network core-private +QT = core network core-private sql TEMPLATE = lib @@ -17,7 +17,8 @@ PUBLIC_HEADERS += \ $$PWD/qwebsocket.h \ $$PWD/qwebsocketserver.h \ $$PWD/qwebsocketprotocol.h \ - $$PWD/qwebsocketcorsauthenticator.h + $$PWD/qwebsocketcorsauthenticator.h \ + $$PWD/qmaskgenerator.h PRIVATE_HEADERS += \ $$PWD/qwebsocket_p.h \ @@ -27,7 +28,8 @@ PRIVATE_HEADERS += \ $$PWD/qwebsockethandshakeresponse_p.h \ $$PWD/qwebsocketdataprocessor_p.h \ $$PWD/qwebsocketcorsauthenticator_p.h \ - $$PWD/qwebsocketframe_p.h + $$PWD/qwebsocketframe_p.h \ + $$PWD/qdefaultmaskgenerator_p.h SOURCES += \ $$PWD/qwebsocket.cpp \ @@ -39,7 +41,9 @@ SOURCES += \ $$PWD/qwebsockethandshakeresponse.cpp \ $$PWD/qwebsocketdataprocessor.cpp \ $$PWD/qwebsocketcorsauthenticator.cpp \ - $$PWD/qwebsocketframe.cpp + $$PWD/qwebsocketframe.cpp \ + $$PWD/qmaskgenerator.cpp \ + $$PWD/qdefaultmaskgenerator_p.cpp contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { SOURCES += $$PWD/qsslserver.cpp diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 34b232b..31900a4 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -7,7 +7,8 @@ contains(QT_CONFIG, private_tests): SUBDIRS += \ websocketprotocol \ dataprocessor \ websocketframe \ - handshakerequest + handshakerequest \ + qdefaultmaskgenerator SUBDIRS += \ qwebsocket \ diff --git a/tests/auto/qdefaultmaskgenerator/qdefaultmaskgenerator.pro b/tests/auto/qdefaultmaskgenerator/qdefaultmaskgenerator.pro new file mode 100644 index 0000000..1ddccb3 --- /dev/null +++ b/tests/auto/qdefaultmaskgenerator/qdefaultmaskgenerator.pro @@ -0,0 +1,14 @@ +CONFIG += console +CONFIG += testcase c++11 +CONFIG -= app_bundle + +TEMPLATE = app + +TARGET = tst_defaultmaskgenerator + +QT = core testlib websockets websockets-private + +SOURCES += tst_defaultmaskgenerator.cpp + +requires(contains(QT_CONFIG, private_tests)) +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/qdefaultmaskgenerator/tst_defaultmaskgenerator.cpp b/tests/auto/qdefaultmaskgenerator/tst_defaultmaskgenerator.cpp new file mode 100644 index 0000000..46e6d61 --- /dev/null +++ b/tests/auto/qdefaultmaskgenerator/tst_defaultmaskgenerator.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "private/qdefaultmaskgenerator_p.h" + +QT_USE_NAMESPACE + +class tst_QDefaultMaskGenerator : public QObject +{ + Q_OBJECT + +public: + tst_QDefaultMaskGenerator(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + + void tst_randomnessWithoutSeed(); + void tst_randomnessWithSeed(); + +private: +}; + + + +tst_QDefaultMaskGenerator::tst_QDefaultMaskGenerator() +{ +} + +void tst_QDefaultMaskGenerator::initTestCase() +{ +} + +void tst_QDefaultMaskGenerator::cleanupTestCase() +{ +} + +void tst_QDefaultMaskGenerator::init() +{ +} + +void tst_QDefaultMaskGenerator::cleanup() +{ +} + +void tst_QDefaultMaskGenerator::tst_randomnessWithoutSeed() +{ + //generate two series of data, and see if they differ + { + QDefaultMaskGenerator generator; + + QVector series1, series2; + for (int i = 0; i < 1000; ++i) + series1 << generator.nextMask(); + for (int i = 0; i < 1000; ++i) + series2 << generator.nextMask(); + + QVERIFY(series1 != series2); + } +} + +void tst_QDefaultMaskGenerator::tst_randomnessWithSeed() +{ + //generate two series of data, and see if they differ + //the generator is seeded + { + QDefaultMaskGenerator generator; + generator.seed(); + + QVector series1, series2; + for (int i = 0; i < 1000; ++i) + series1 << generator.nextMask(); + for (int i = 0; i < 1000; ++i) + series2 << generator.nextMask(); + + QVERIFY(series1 != series2); + } + //generates two series of data with 2 distinct generators + //both generators are seeded + { + QDefaultMaskGenerator generator1, generator2; + generator1.seed(); + generator2.seed(); + + QVector series1, series2; + for (int i = 0; i < 1000; ++i) { + series1 << generator1.nextMask(); + series2 << generator2.nextMask(); + } + + QVERIFY(series1 != series2); + } + //generates two series of data with 2 distinct generators + //only one of the two is seeded + { + QDefaultMaskGenerator generator1, generator2; + generator1.seed(); + + QVector series1, series2; + for (int i = 0; i < 1000; ++i) { + series1 << generator1.nextMask(); + series2 << generator2.nextMask(); + } + + QVERIFY(series1 != series2); + } +} + +QTEST_MAIN(tst_QDefaultMaskGenerator) + +#include "tst_defaultmaskgenerator.moc"