diff options
Diffstat (limited to 'tests/auto/corelib/global/qrandomgenerator')
3 files changed, 140 insertions, 68 deletions
diff --git a/tests/auto/corelib/global/qrandomgenerator/CMakeLists.txt b/tests/auto/corelib/global/qrandomgenerator/CMakeLists.txt new file mode 100644 index 0000000000..3d8f892414 --- /dev/null +++ b/tests/auto/corelib/global/qrandomgenerator/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qrandomgenerator Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qrandomgenerator LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qrandomgenerator + SOURCES + tst_qrandomgenerator.cpp + LIBRARIES + Qt::CorePrivate +) diff --git a/tests/auto/corelib/global/qrandomgenerator/qrandomgenerator.pro b/tests/auto/corelib/global/qrandomgenerator/qrandomgenerator.pro deleted file mode 100644 index 0307b0c1eb..0000000000 --- a/tests/auto/corelib/global/qrandomgenerator/qrandomgenerator.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qrandomgenerator -QT = core-private testlib -SOURCES = tst_qrandomgenerator.cpp diff --git a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp index 6f9dcc08f9..a32045bbbb 100644 --- a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp +++ b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp @@ -1,36 +1,10 @@ -/**************************************************************************** -** -** 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> -#include <qlinkedlist.h> +// 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> -#include <qvector.h> #include <private/qrandom_p.h> #include <algorithm> @@ -40,7 +14,6 @@ # define HAVE_FALLBACK_ENGINE #endif -#define COMMA , #define QVERIFY_3TIMES(statement) \ do {\ if (!static_cast<bool>(statement))\ @@ -103,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(); @@ -148,6 +125,12 @@ void tst_QRandomGenerator::basics() // default constructible QRandomGenerator rng; +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); @@ -156,6 +139,7 @@ void tst_QRandomGenerator::basics() QRandomGenerator64 rng64; rng64 = rng64; rng64 = std::move(rng64); +QT_WARNING_POP // 32- and 64-bit should be interchangeable: rng = rng64; @@ -183,8 +167,8 @@ void tst_QRandomGenerator::basics() QRandomGenerator64 systemRng64 = *system64; systemRng64 = *system64; - Q_STATIC_ASSERT(std::is_same<decltype(rng64.generate()) COMMA quint64>::value); - Q_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() @@ -391,7 +375,7 @@ void tst_QRandomGenerator::quality() AcceptableThreshold = 4 * PerfectDistribution, FailureThreshold = 16 * PerfectDistribution }; - Q_STATIC_ASSERT(FailureThreshold > AcceptableThreshold); + static_assert(FailureThreshold > AcceptableThreshold); QFETCH(uint, control); if (control & RandomDataMask) @@ -564,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)); @@ -587,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 @@ -610,7 +595,7 @@ void tst_QRandomGenerator::boundedQuality() AcceptableThreshold = 4 * PerfectDistribution, FailureThreshold = 16 * PerfectDistribution }; - Q_STATIC_ASSERT(FailureThreshold > AcceptableThreshold); + static_assert(FailureThreshold > AcceptableThreshold); QFETCH(uint, control); if (control & RandomDataMask) @@ -622,10 +607,13 @@ void tst_QRandomGenerator::boundedQuality() { // test the quality of the generator - QVector<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]++; } @@ -646,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); @@ -670,18 +727,16 @@ void tst_QRandomGenerator::qualityReal() return; RandomGenerator rng(control); - enum { - SampleSize = 160, + 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 = 25, // floor(4 * sqrt((1 - 0.5) * PerfectHalf)) - RangeOctile = 16 // 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(); }); @@ -842,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() @@ -882,7 +939,7 @@ void tst_QRandomGenerator::stdUniformRealDistribution_data() newRow(0, 1); // canonical newRow(0, 200); newRow(0, numeric_limits<quint32>::max() + 1.); - newRow(0, numeric_limits<quint64>::max() + 1.); + newRow(0, double(numeric_limits<quint64>::max()) + 1.); newRow(-1, 1.6); } @@ -920,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}; |