diff options
Diffstat (limited to 'src/VBox/Runtime/testcase/tstRand.cpp')
-rw-r--r-- | src/VBox/Runtime/testcase/tstRand.cpp | 615 |
1 files changed, 615 insertions, 0 deletions
diff --git a/src/VBox/Runtime/testcase/tstRand.cpp b/src/VBox/Runtime/testcase/tstRand.cpp new file mode 100644 index 00000000..f292eaff --- /dev/null +++ b/src/VBox/Runtime/testcase/tstRand.cpp @@ -0,0 +1,615 @@ +/* $Id: tstRand.cpp $ */ +/** @file + * IPRT - Testcase for the RTRand API. + */ + +/* + * Copyright (C) 2008-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <iprt/rand.h> +#include <iprt/errcore.h> +#include <iprt/stream.h> +#include <iprt/initterm.h> +#include <iprt/string.h> +#include <iprt/assert.h> + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +typedef struct TSTMEMAUTOPTRSTRUCT +{ + uint32_t a; + uint32_t b; + uint32_t c; +} TSTMEMAUTOPTRSTRUCT; + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#define CHECK_EXPR(expr) \ + do { bool const f = !!(expr); if (RT_UNLIKELY(!f)) { RTPrintf("tstRand(%d): %s!\n", __LINE__, #expr); g_cErrors++; } } while (0) +#define CHECK_EXPR_MSG(expr, msg) \ + do { \ + bool const f = !!(expr); \ + if (RT_UNLIKELY(!f)) { \ + RTPrintf("tstRand(%d): %s!\n", __LINE__, #expr); \ + RTPrintf("tstRand: "); \ + RTPrintf msg; \ + if (++g_cErrors > 25) return 1; \ + } \ + } while (0) + + +#define TST_RAND_SAMPLE_RANGES 16 + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +static unsigned g_cErrors = 0; + + +static void tstRandCheckDist(uint32_t *pacHits, unsigned iTest) +{ + RTPrintf("tstRand:"); + uint32_t iMin = UINT32_MAX; + uint32_t iMax = 0; + uint32_t iAvg = 0; + for (unsigned iRange = 0; iRange < TST_RAND_SAMPLE_RANGES; iRange++) + { + RTPrintf(" %04RX32", pacHits[iRange]); + if (iMax < pacHits[iRange]) + iMax = pacHits[iRange]; + if (iMin > pacHits[iRange]) + iMin = pacHits[iRange]; + iAvg += pacHits[iRange]; + } + iAvg /= TST_RAND_SAMPLE_RANGES; + RTPrintf(" min=%RX32 (%%%d) max=%RX32 (%%%d) calc avg=%RX32 [test=%d]\n", + iMin, (iAvg - iMin) * 100 / iAvg, iMax, + (iMax - iAvg) * 100 / iAvg, + iAvg, + iTest); + CHECK_EXPR(iMin >= iAvg - iAvg / 4); + CHECK_EXPR(iMax <= iAvg + iAvg / 4); +} + + +static int tstRandAdv(RTRAND hRand) +{ + /* + * Test distribution. + */ +#if 1 + /* unsigned 32-bit */ + static const struct + { + uint32_t u32First; + uint32_t u32Last; + } s_aU32Tests[] = + { + { 0, UINT32_MAX }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 4 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 8 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 16 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 64 }, + { 0, UINT32_MAX / 2 }, + { UINT32_MAX / 4, UINT32_MAX / 4 * 3 }, + { 0, TST_RAND_SAMPLE_RANGES - 1 }, + { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 }, + }; + for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU32Tests); iTest++) + { + uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; + uint32_t const uFirst = s_aU32Tests[iTest].u32First; + uint32_t const uLast = s_aU32Tests[iTest].u32Last; + uint32_t const uRange = uLast - uFirst; Assert(uLast >= uFirst); + uint32_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; + RTPrintf("tstRand: TESTING RTRandAdvU32Ex(,%#RX32, %#RX32) distribution... [div=%#RX32 range=%#RX32]\n", uFirst, uLast, uDivisor, uRange); + for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) + { + uint32_t uRand = RTRandAdvU32Ex(hRand, uFirst, uLast); + CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX32 %#RX32\n", uRand, uFirst)); + CHECK_EXPR_MSG(uRand <= uLast, ("%#RX32 %#RX32\n", uRand, uLast)); + uint32_t off = uRand - uFirst; + acHits[off / uDivisor]++; + } + tstRandCheckDist(acHits, iTest); + } +#endif + +#if 1 + /* unsigned 64-bit */ + static const struct + { + uint64_t u64First; + uint64_t u64Last; + } s_aU64Tests[] = + { + { 0, UINT64_MAX }, + { 0, UINT64_MAX / 2 + UINT64_MAX / 4 }, + { 0, UINT64_MAX / 2 + UINT64_MAX / 8 }, + { 0, UINT64_MAX / 2 + UINT64_MAX / 16 }, + { 0, UINT64_MAX / 2 + UINT64_MAX / 64 }, + { 0, UINT64_MAX / 2 }, + { UINT64_MAX / 4, UINT64_MAX / 4 * 3 }, + { 0, UINT32_MAX }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 4 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 8 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 16 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 64 }, + { 0, UINT32_MAX / 2 }, + { UINT32_MAX / 4, UINT32_MAX / 4 * 3 }, + { 0, TST_RAND_SAMPLE_RANGES - 1 }, + { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 }, + }; + for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU64Tests); iTest++) + { + uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; + uint64_t const uFirst = s_aU64Tests[iTest].u64First; + uint64_t const uLast = s_aU64Tests[iTest].u64Last; + uint64_t const uRange = uLast - uFirst; Assert(uLast >= uFirst); + uint64_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; + RTPrintf("tstRand: TESTING RTRandAdvU64Ex(,%#RX64, %#RX64) distribution... [div=%#RX64 range=%#RX64]\n", uFirst, uLast, uDivisor, uRange); + for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) + { + uint64_t uRand = RTRandAdvU64Ex(hRand, uFirst, uLast); + CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX64 %#RX64\n", uRand, uFirst)); + CHECK_EXPR_MSG(uRand <= uLast, ("%#RX64 %#RX64\n", uRand, uLast)); + uint64_t off = uRand - uFirst; + acHits[off / uDivisor]++; + } + tstRandCheckDist(acHits, iTest); + } +#endif + +#if 1 + /* signed 32-bit */ + static const struct + { + int32_t i32First; + int32_t i32Last; + } s_aS32Tests[] = + { + { -429496729, 429496729 }, + { INT32_MIN, INT32_MAX }, + { INT32_MIN, INT32_MAX / 2 }, + { -0x20000000, INT32_MAX }, + { -0x10000000, INT32_MAX }, + { -0x08000000, INT32_MAX }, + { -0x00800000, INT32_MAX }, + { -0x00080000, INT32_MAX }, + { -0x00008000, INT32_MAX }, + { -0x00000800, INT32_MAX }, + { 2, INT32_MAX / 2 }, + { 4000000, INT32_MAX / 2 }, + { -4000000, INT32_MAX / 2 }, + { INT32_MIN / 2, INT32_MAX / 2 }, + { INT32_MIN / 3, INT32_MAX / 2 }, + { INT32_MIN / 3, INT32_MAX / 3 }, + { INT32_MIN / 3, INT32_MAX / 4 }, + { INT32_MIN / 4, INT32_MAX / 4 }, + { INT32_MIN / 5, INT32_MAX / 5 }, + { INT32_MIN / 6, INT32_MAX / 6 }, + { INT32_MIN / 7, INT32_MAX / 6 }, + { INT32_MIN / 7, INT32_MAX / 7 }, + { INT32_MIN / 7, INT32_MAX / 8 }, + { INT32_MIN / 8, INT32_MAX / 8 }, + { INT32_MIN / 9, INT32_MAX / 9 }, + { INT32_MIN / 9, INT32_MAX / 12 }, + { INT32_MIN / 12, INT32_MAX / 12 }, + { 0, TST_RAND_SAMPLE_RANGES - 1 }, + { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 }, + }; + for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS32Tests); iTest++) + { + uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; + int32_t const iFirst = s_aS32Tests[iTest].i32First; + int32_t const iLast = s_aS32Tests[iTest].i32Last; + uint32_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); + uint32_t const uDivisor = (uRange ? uRange : UINT32_MAX) / TST_RAND_SAMPLE_RANGES + 1; + RTPrintf("tstRand: TESTING RTRandAdvS32Ex(,%#RI32, %#RI32) distribution... [div=%#RX32 range=%#RX32]\n", iFirst, iLast, uDivisor, uRange); + for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) + { + int32_t iRand = RTRandAdvS32Ex(hRand, iFirst, iLast); + CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI32 %#RI32\n", iRand, iFirst)); + CHECK_EXPR_MSG(iRand <= iLast, ("%#RI32 %#RI32\n", iRand, iLast)); + uint32_t off = iRand - iFirst; + acHits[off / uDivisor]++; + } + tstRandCheckDist(acHits, iTest); + } +#endif + +#if 1 + /* signed 64-bit */ + static const struct + { + int64_t i64First; + int64_t i64Last; + } s_aS64Tests[] = + { + { INT64_MIN, INT64_MAX }, + { INT64_MIN, INT64_MAX / 2 }, + { INT64_MIN / 2, INT64_MAX / 2 }, + { INT64_MIN / 2 + INT64_MIN / 4, INT64_MAX / 2 }, + { INT64_MIN / 2 + INT64_MIN / 8, INT64_MAX / 2 }, + { INT64_MIN / 2 + INT64_MIN / 16, INT64_MAX / 2 }, + { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 }, + { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 + INT64_MAX / 64 }, + { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 64 }, + { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 8 }, + { INT64_MIN / 2, INT64_MAX / 2 - INT64_MAX / 8 }, + { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 4 }, + { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 8 }, + { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 - INT64_MAX / 8 }, + { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 8 }, + { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 16 }, + { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 16 }, + { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 32 }, + { INT64_MIN / 2 - INT64_MIN / 64, INT64_MAX / 2 - INT64_MAX / 64 }, + { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 }, + { INT64_MIN / 4, INT64_MAX / 4 }, + { INT64_MIN / 5, INT64_MAX / 5 }, + { INT64_MIN / 6, INT64_MAX / 6 }, + { INT64_MIN / 7, INT64_MAX / 7 }, + { INT64_MIN / 8, INT64_MAX / 8 }, + { INT32_MIN, INT32_MAX }, + { INT32_MIN, INT32_MAX / 2 }, + { -0x20000000, INT32_MAX }, + { -0x10000000, INT32_MAX }, + { -0x7f000000, INT32_MAX }, + { -0x08000000, INT32_MAX }, + { -0x00800000, INT32_MAX }, + { -0x00080000, INT32_MAX }, + { -0x00008000, INT32_MAX }, + { 2, INT32_MAX / 2 }, + { 4000000, INT32_MAX / 2 }, + { -4000000, INT32_MAX / 2 }, + { INT32_MIN / 2, INT32_MAX / 2 }, + { 0, TST_RAND_SAMPLE_RANGES - 1 }, + { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 } + }; + for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS64Tests); iTest++) + { + uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; + int64_t const iFirst = s_aS64Tests[iTest].i64First; + int64_t const iLast = s_aS64Tests[iTest].i64Last; + uint64_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); + uint64_t const uDivisor = (uRange ? uRange : UINT64_MAX) / TST_RAND_SAMPLE_RANGES + 1; + RTPrintf("tstRand: TESTING RTRandAdvS64Ex(,%#RI64, %#RI64) distribution... [div=%#RX64 range=%#016RX64]\n", iFirst, iLast, uDivisor, uRange); + for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) + { + int64_t iRand = RTRandAdvS64Ex(hRand, iFirst, iLast); + CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI64 %#RI64\n", iRand, iFirst)); + CHECK_EXPR_MSG(iRand <= iLast, ("%#RI64 %#RI64\n", iRand, iLast)); + uint64_t off = iRand - iFirst; + acHits[off / uDivisor]++; + } + tstRandCheckDist(acHits, iTest); + } +#endif + + /* + * Test saving and restoring the state. + */ + RTPrintf("tstRand: TESTING RTRandAdvSave/RestoreSave\n"); + char szState[256]; + size_t cbState = sizeof(szState); + int rc = RTRandAdvSaveState(hRand, szState, &cbState); + if (rc != VERR_NOT_SUPPORTED) + { + CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("RTRandAdvSaveState(%p,,256) -> %Rrc (%d)\n", (uintptr_t)hRand, rc, rc)); + uint32_t const u32A1 = RTRandAdvU32(hRand); + uint32_t const u32B1 = RTRandAdvU32(hRand); + RTPrintf("tstRand: state:\"%s\" A=%RX32 B=%RX32\n", szState, u32A1, u32B1); + + rc = RTRandAdvRestoreState(hRand, szState); + CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("RTRandAdvRestoreState(%p,\"%s\") -> %Rrc (%d)\n", (uintptr_t)hRand, szState, rc, rc)); + uint32_t const u32A2 = RTRandAdvU32(hRand); + uint32_t const u32B2 = RTRandAdvU32(hRand); + CHECK_EXPR_MSG(u32A1 == u32A2, ("u32A1=%RX32 u32A2=%RX32\n", u32A1, u32A2)); + CHECK_EXPR_MSG(u32B1 == u32B2, ("u32B1=%RX32 u32B2=%RX32\n", u32B1, u32B2)); + } + else + { + szState[0] = '\0'; + rc = RTRandAdvRestoreState(hRand, szState); + CHECK_EXPR_MSG(rc == VERR_NOT_SUPPORTED, ("RTRandAdvRestoreState(%p,\"\") -> %Rrc (%d)\n", (uintptr_t)hRand, rc, rc)); + } + + + /* + * Destroy it. + */ + rc = RTRandAdvDestroy(hRand); + CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("RTRandAdvDestroy(%p) -> %Rrc (%d)\n", (uintptr_t)hRand, rc, rc)); + + return 0; +} + + + +int main() +{ + RTR3InitExeNoArguments(0); + RTPrintf("tstRand: TESTING...\n"); + + /* + * Do some smoke tests first? + */ + /** @todo RTRand smoke testing. */ + +#if 1 + /* + * Test distribution. + */ +#if 1 + /* unsigned 32-bit */ + static const struct + { + uint32_t u32First; + uint32_t u32Last; + } s_aU32Tests[] = + { + { 0, UINT32_MAX }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 4 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 8 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 16 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 64 }, + { 0, UINT32_MAX / 2 }, + { UINT32_MAX / 4, UINT32_MAX / 4 * 3 }, + { 0, TST_RAND_SAMPLE_RANGES - 1 }, + { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 }, + }; + for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU32Tests); iTest++) + { + uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; + uint32_t const uFirst = s_aU32Tests[iTest].u32First; + uint32_t const uLast = s_aU32Tests[iTest].u32Last; + uint32_t const uRange = uLast - uFirst; Assert(uLast >= uFirst); + uint32_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; + RTPrintf("tstRand: TESTING RTRandU32Ex(%#RX32, %#RX32) distribution... [div=%#RX32 range=%#RX32]\n", uFirst, uLast, uDivisor, uRange); + for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) + { + uint32_t uRand = RTRandU32Ex(uFirst, uLast); + CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX32 %#RX32\n", uRand, uFirst)); + CHECK_EXPR_MSG(uRand <= uLast, ("%#RX32 %#RX32\n", uRand, uLast)); + uint32_t off = uRand - uFirst; + acHits[off / uDivisor]++; + } + tstRandCheckDist(acHits, iTest); + } +#endif + +#if 1 + /* unsigned 64-bit */ + static const struct + { + uint64_t u64First; + uint64_t u64Last; + } s_aU64Tests[] = + { + { 0, UINT64_MAX }, + { 0, UINT64_MAX / 2 + UINT64_MAX / 4 }, + { 0, UINT64_MAX / 2 + UINT64_MAX / 8 }, + { 0, UINT64_MAX / 2 + UINT64_MAX / 16 }, + { 0, UINT64_MAX / 2 + UINT64_MAX / 64 }, + { 0, UINT64_MAX / 2 }, + { UINT64_MAX / 4, UINT64_MAX / 4 * 3 }, + { 0, UINT32_MAX }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 4 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 8 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 16 }, + { 0, UINT32_MAX / 2 + UINT32_MAX / 64 }, + { 0, UINT32_MAX / 2 }, + { UINT32_MAX / 4, UINT32_MAX / 4 * 3 }, + { 0, TST_RAND_SAMPLE_RANGES - 1 }, + { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 }, + }; + for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU64Tests); iTest++) + { + uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; + uint64_t const uFirst = s_aU64Tests[iTest].u64First; + uint64_t const uLast = s_aU64Tests[iTest].u64Last; + uint64_t const uRange = uLast - uFirst; Assert(uLast >= uFirst); + uint64_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; + RTPrintf("tstRand: TESTING RTRandU64Ex(%#RX64, %#RX64) distribution... [div=%#RX64 range=%#RX64]\n", uFirst, uLast, uDivisor, uRange); + for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) + { + uint64_t uRand = RTRandU64Ex(uFirst, uLast); + CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX64 %#RX64\n", uRand, uFirst)); + CHECK_EXPR_MSG(uRand <= uLast, ("%#RX64 %#RX64\n", uRand, uLast)); + uint64_t off = uRand - uFirst; + acHits[off / uDivisor]++; + } + tstRandCheckDist(acHits, iTest); + } +#endif + +#if 1 + /* signed 32-bit */ + static const struct + { + int32_t i32First; + int32_t i32Last; + } s_aS32Tests[] = + { + { -429496729, 429496729 }, + { INT32_MIN, INT32_MAX }, + { INT32_MIN, INT32_MAX / 2 }, + { -0x20000000, INT32_MAX }, + { -0x10000000, INT32_MAX }, + { -0x08000000, INT32_MAX }, + { -0x00800000, INT32_MAX }, + { -0x00080000, INT32_MAX }, + { -0x00008000, INT32_MAX }, + { -0x00000800, INT32_MAX }, + { 2, INT32_MAX / 2 }, + { 4000000, INT32_MAX / 2 }, + { -4000000, INT32_MAX / 2 }, + { INT32_MIN / 2, INT32_MAX / 2 }, + { INT32_MIN / 3, INT32_MAX / 2 }, + { INT32_MIN / 3, INT32_MAX / 3 }, + { INT32_MIN / 3, INT32_MAX / 4 }, + { INT32_MIN / 4, INT32_MAX / 4 }, + { INT32_MIN / 5, INT32_MAX / 5 }, + { INT32_MIN / 6, INT32_MAX / 6 }, + { INT32_MIN / 7, INT32_MAX / 6 }, + { INT32_MIN / 7, INT32_MAX / 7 }, + { INT32_MIN / 7, INT32_MAX / 8 }, + { INT32_MIN / 8, INT32_MAX / 8 }, + { INT32_MIN / 9, INT32_MAX / 9 }, + { INT32_MIN / 9, INT32_MAX / 12 }, + { INT32_MIN / 12, INT32_MAX / 12 }, + { 0, TST_RAND_SAMPLE_RANGES - 1 }, + { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 }, + }; + for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS32Tests); iTest++) + { + uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; + int32_t const iFirst = s_aS32Tests[iTest].i32First; + int32_t const iLast = s_aS32Tests[iTest].i32Last; + uint32_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); + uint32_t const uDivisor = (uRange ? uRange : UINT32_MAX) / TST_RAND_SAMPLE_RANGES + 1; + RTPrintf("tstRand: TESTING RTRandS32Ex(%#RI32, %#RI32) distribution... [div=%#RX32 range=%#RX32]\n", iFirst, iLast, uDivisor, uRange); + for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) + { + int32_t iRand = RTRandS32Ex(iFirst, iLast); + CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI32 %#RI32\n", iRand, iFirst)); + CHECK_EXPR_MSG(iRand <= iLast, ("%#RI32 %#RI32\n", iRand, iLast)); + uint32_t off = iRand - iFirst; + acHits[off / uDivisor]++; + } + tstRandCheckDist(acHits, iTest); + } +#endif + +#if 1 + /* signed 64-bit */ + static const struct + { + int64_t i64First; + int64_t i64Last; + } s_aS64Tests[] = + { + { INT64_MIN, INT64_MAX }, + { INT64_MIN, INT64_MAX / 2 }, + { INT64_MIN / 2, INT64_MAX / 2 }, + { INT64_MIN / 2 + INT64_MIN / 4, INT64_MAX / 2 }, + { INT64_MIN / 2 + INT64_MIN / 8, INT64_MAX / 2 }, + { INT64_MIN / 2 + INT64_MIN / 16, INT64_MAX / 2 }, + { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 }, + { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 + INT64_MAX / 64 }, + { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 64 }, + { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 8 }, + { INT64_MIN / 2, INT64_MAX / 2 - INT64_MAX / 8 }, + { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 4 }, + { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 8 }, + { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 - INT64_MAX / 8 }, + { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 8 }, + { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 16 }, + { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 16 }, + { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 32 }, + { INT64_MIN / 2 - INT64_MIN / 64, INT64_MAX / 2 - INT64_MAX / 64 }, + { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 }, + { INT64_MIN / 4, INT64_MAX / 4 }, + { INT64_MIN / 5, INT64_MAX / 5 }, + { INT64_MIN / 6, INT64_MAX / 6 }, + { INT64_MIN / 7, INT64_MAX / 7 }, + { INT64_MIN / 8, INT64_MAX / 8 }, + { INT32_MIN, INT32_MAX }, + { INT32_MIN, INT32_MAX / 2 }, + { -0x20000000, INT32_MAX }, + { -0x10000000, INT32_MAX }, + { -0x7f000000, INT32_MAX }, + { -0x08000000, INT32_MAX }, + { -0x00800000, INT32_MAX }, + { -0x00080000, INT32_MAX }, + { -0x00008000, INT32_MAX }, + { 2, INT32_MAX / 2 }, + { 4000000, INT32_MAX / 2 }, + { -4000000, INT32_MAX / 2 }, + { INT32_MIN / 2, INT32_MAX / 2 }, + { 0, TST_RAND_SAMPLE_RANGES - 1 }, + { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 } + }; + for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS64Tests); iTest++) + { + uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; + int64_t const iFirst = s_aS64Tests[iTest].i64First; + int64_t const iLast = s_aS64Tests[iTest].i64Last; + uint64_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); + uint64_t const uDivisor = (uRange ? uRange : UINT64_MAX) / TST_RAND_SAMPLE_RANGES + 1; + RTPrintf("tstRand: TESTING RTRandS64Ex(%#RI64, %#RI64) distribution... [div=%#RX64 range=%#016RX64]\n", iFirst, iLast, uDivisor, uRange); + for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) + { + int64_t iRand = RTRandS64Ex(iFirst, iLast); + CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI64 %#RI64\n", iRand, iFirst)); + CHECK_EXPR_MSG(iRand <= iLast, ("%#RI64 %#RI64\n", iRand, iLast)); + uint64_t off = iRand - iFirst; + acHits[off / uDivisor]++; + } + tstRandCheckDist(acHits, iTest); + } +#endif +#endif /* Testing RTRand */ + +#if 1 + /* + * Test the various random generators. + */ + RTPrintf("tstRand: TESTING RTRandAdvCreateParkerMiller\n"); + RTRAND hRand; + int rc = RTRandAdvCreateParkMiller(&hRand); + CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); + if (RT_SUCCESS(rc)) + if (tstRandAdv(hRand)) + return 1; + +#endif /* Testing RTRandAdv */ + + /* + * Summary. + */ + if (!g_cErrors) + RTPrintf("tstRand: SUCCESS\n"); + else + RTPrintf("tstRand: FAILED - %d errors\n", g_cErrors); + return !!g_cErrors; +} + |