diff options
Diffstat (limited to 'tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp')
-rw-r--r-- | tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp | 172 |
1 files changed, 113 insertions, 59 deletions
diff --git a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp index 0c453cd0e5..a32045bbbb 100644 --- a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp +++ b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp @@ -1,32 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation. -** 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$ -** -****************************************************************************/ - -#include <QtTest> +// Copyright (C) 2017 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> #include <qlist.h> #include <qobject.h> #include <qrandom.h> @@ -39,7 +14,6 @@ # define HAVE_FALLBACK_ENGINE #endif -#define COMMA , #define QVERIFY_3TIMES(statement) \ do {\ if (!static_cast<bool>(statement))\ @@ -102,6 +76,10 @@ private slots: void bounded(); void boundedQuality_data() { generate32_data(); } void boundedQuality(); + void bounded64_data(); + void bounded64(); + void bounded64Quality_data() { generate32_data(); } + void bounded64Quality(); void generateReal_data() { generate32_data(); } void generateReal(); @@ -150,6 +128,9 @@ void tst_QRandomGenerator::basics() QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wself-move") QT_WARNING_DISABLE_CLANG("-Wself-assign-overloaded") +#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1301 +QT_WARNING_DISABLE_GCC("-Wself-move") +#endif // copyable && movable rng = rng; rng = std::move(rng); @@ -186,8 +167,8 @@ QT_WARNING_POP QRandomGenerator64 systemRng64 = *system64; systemRng64 = *system64; - static_assert(std::is_same<decltype(rng64.generate()) COMMA quint64>::value); - static_assert(std::is_same<decltype(system64->generate()) COMMA quint64>::value); + static_assert(std::is_same_v<decltype(rng64.generate()), quint64>); + static_assert(std::is_same_v<decltype(system64->generate()), quint64>); } void tst_QRandomGenerator::knownSequence() @@ -567,7 +548,7 @@ void tst_QRandomGenerator::bounded() QVERIFY(value < sup); QCOMPARE(value, expected); - int ivalue = rng.bounded(sup); + int ivalue = rng.bounded(int(sup)); QVERIFY(ivalue < int(sup)); QCOMPARE(ivalue, int(expected)); @@ -590,10 +571,11 @@ void tst_QRandomGenerator::bounded() QVERIFY(ivalue < 0); } -void tst_QRandomGenerator::boundedQuality() +template <typename UInt> static void boundedQuality_template() { - enum { Bound = 283 }; // a prime number - enum { + using Int = std::make_signed_t<UInt>; + constexpr Int Bound = 283; // a prime number + enum : Int { BufferCount = Bound * 32, // if the distribution were perfect, each byte in the buffer would @@ -625,10 +607,13 @@ void tst_QRandomGenerator::boundedQuality() { // test the quality of the generator - QList<quint32> buffer(BufferCount, 0xcdcdcdcd); + UInt filler = 0xcdcdcdcd; + if (sizeof(filler) > sizeof(quint32)) + filler |= filler << (std::numeric_limits<UInt>::digits / 2); + QVector<UInt> buffer(BufferCount, filler); generate(buffer.begin(), buffer.end(), [&] { return rng.bounded(Bound); }); - for (quint32 value : qAsConst(buffer)) { + for (UInt value : std::as_const(buffer)) { QVERIFY(value < Bound); histogram[value]++; } @@ -649,6 +634,75 @@ void tst_QRandomGenerator::boundedQuality() << "at" << std::min_element(begin(histogram), end(histogram)) - histogram; } +void tst_QRandomGenerator::boundedQuality() +{ + boundedQuality_template<quint32>(); +} + +void tst_QRandomGenerator::bounded64Quality() +{ + boundedQuality_template<quint64>(); +} + +void tst_QRandomGenerator::bounded64_data() +{ +#ifndef QT_BUILD_INTERNAL + QSKIP("Test only possible in developer builds"); +#endif + + QTest::addColumn<uint>("control"); + QTest::addColumn<quint64>("sup"); + QTest::addColumn<quint64>("expected"); + + auto newRow = [&](unsigned val, unsigned sup) { + Q_ASSERT((val & ~RandomDataMask) == 0); + + unsigned control = SetRandomData | val; + QTest::addRow("%u,%u", val, sup) << control << quint64(sup) << quint64(val); + }; + + // useless: we can only generate zeroes: + newRow(0, 1); + + newRow(0x10, 200); + newRow(0x20, 200); + newRow(0x80, 200); +} + +void tst_QRandomGenerator::bounded64() +{ + QFETCH(uint, control); + QFETCH(quint64, sup); + QFETCH(quint64, expected); + RandomGenerator rng(control); + + quint64 value = rng.bounded(sup); + QVERIFY(value < sup); + QCOMPARE(value, expected); + + qint64 ivalue = rng.bounded(qint64(sup)); + QVERIFY(ivalue < int(sup)); + QCOMPARE(ivalue, int(expected)); + + // confirm only the bound now + setRNGControl(control & (SkipHWRNG|SkipSystemRNG|UseSystemRNG)); + value = rng.bounded(sup); + QVERIFY(value < sup); + + value = rng.bounded(sup / 2, 3 * sup / 2); + QVERIFY(value >= sup / 2); + QVERIFY(value < 3 * sup / 2); + + ivalue = rng.bounded(-qint64(sup), qint64(sup)); + QVERIFY(ivalue >= -qint64(sup)); + QVERIFY(ivalue < qint64(sup)); + + // wholly negative range + ivalue = rng.bounded(-qint64(sup), qint64(0)); + QVERIFY(ivalue >= -qint64(sup)); + QVERIFY(ivalue < 0); +} + void tst_QRandomGenerator::generateReal() { QFETCH(uint, control); @@ -673,18 +727,16 @@ void tst_QRandomGenerator::qualityReal() return; RandomGenerator rng(control); - enum { - SampleSize = 16000, + constexpr int SampleSize = 16000; - // Expected value: sample size times proportion of the range: - PerfectOctile = SampleSize / 8, - PerfectHalf = SampleSize / 2, + // Expected value: sample size times proportion of the range: + constexpr int PerfectOctile = SampleSize / 8; + constexpr int PerfectHalf = SampleSize / 2; - // Variance is (1 - proportion of range) * expected; sqrt() for standard deviations. - // Should usually be within twice that and almost never outside four times: - RangeHalf = 252, // floor(4 * sqrt((1 - 0.5) * PerfectHalf)) - RangeOctile = 167 // floor(4 * sqrt((1 - 0.125) * PerfectOctile)) - }; + // Variance is (1 - proportion of range) * expected; sqrt() for standard deviations. + // Should usually be within twice that and almost never outside four times: + constexpr int RangeHalf = 252; // floor(4 * sqrt((1 - 0.5) * PerfectHalf)) + constexpr int RangeOctile = 167; // floor(4 * sqrt((1 - 0.125) * PerfectOctile)) double data[SampleSize]; std::generate(std::begin(data), std::end(data), [&rng] { return rng.generateDouble(); }); @@ -845,18 +897,20 @@ void tst_QRandomGenerator::stdGenerateCanonical() { QFETCH(uint, control); RandomGenerator rng(control); + auto generate_canonical = [&rng]() { + return std::generate_canonical<qreal, 32>(rng); + }; for (int i = 0; i < 4; ++i) { QVERIFY_3TIMES([&] { - qreal value = std::generate_canonical<qreal COMMA 32>(rng); + qreal value = generate_canonical(); return value > 0 && value < 1 && value != RandomValueFP; }()); } // and should hopefully be different from repeated calls for (int i = 0; i < 4; ++i) - QVERIFY_3TIMES(std::generate_canonical<qreal COMMA 32>(rng) != - std::generate_canonical<qreal COMMA 32>(rng)); + QVERIFY_3TIMES(generate_canonical() != generate_canonical()); } void tst_QRandomGenerator::stdUniformRealDistribution_data() @@ -923,18 +977,18 @@ template <typename Generator> void stdRandomDistributions_template() { Generator rd; - std::bernoulli_distribution()(rd); + (void)std::bernoulli_distribution()(rd); - std::binomial_distribution<quint32>()(rd); - std::binomial_distribution<quint64>()(rd); + (void)std::binomial_distribution<quint32>()(rd); + (void)std::binomial_distribution<quint64>()(rd); - std::negative_binomial_distribution<quint32>()(rd); - std::negative_binomial_distribution<quint64>()(rd); + (void)std::negative_binomial_distribution<quint32>()(rd); + (void)std::negative_binomial_distribution<quint64>()(rd); - std::poisson_distribution<int>()(rd); - std::poisson_distribution<qint64>()(rd); + (void)std::poisson_distribution<int>()(rd); + (void)std::poisson_distribution<qint64>()(rd); - std::normal_distribution<qreal>()(rd); + (void)std::normal_distribution<qreal>()(rd); { std::discrete_distribution<int> discrete{0, 1, 1, 10000, 2}; |