VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRand.cpp@ 11280

Last change on this file since 11280 was 11064, checked in by vboxsync, 16 years ago

iprt/RTRandUxy: Improved the distribution when not using the max ranges. Changed the pseudo/cpuid fallback so it makes sure the cpuid has changed sufficiently and then only takes 3-bits from it, dropping the lower 5 since some of these are no longer reliable (5 is a bit too high, hopefully). Added tstRand for testing the distribution and limits.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
Line 
1/* $Id: tstRand.cpp 11064 2008-08-01 14:12:37Z vboxsync $ */
2/** @file
3 * IPRT - Testcase for the RTRand API.
4 */
5
6/*
7 * Copyright (C) 2008 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#include <iprt/rand.h>
35#include <iprt/stream.h>
36#include <iprt/initterm.h>
37#include <iprt/string.h>
38#include <iprt/assert.h>
39
40
41/*******************************************************************************
42* Structures and Typedefs *
43*******************************************************************************/
44typedef struct TSTMEMAUTOPTRSTRUCT
45{
46 uint32_t a;
47 uint32_t b;
48 uint32_t c;
49} TSTMEMAUTOPTRSTRUCT;
50
51
52/*******************************************************************************
53* Defined Constants And Macros *
54*******************************************************************************/
55#define CHECK_EXPR(expr) \
56 do { bool const f = !!(expr); if (RT_UNLIKELY(!f)) { RTPrintf("tstRand(%d): %s!\n", __LINE__, #expr); g_cErrors++; } } while (0)
57#define CHECK_EXPR_MSG(expr, msg) \
58 do { \
59 bool const f = !!(expr); \
60 if (RT_UNLIKELY(!f)) { \
61 RTPrintf("tstRand(%d): %s!\n", __LINE__, #expr); \
62 RTPrintf("tstRand: "); \
63 RTPrintf msg; \
64 if (++g_cErrors > 25) return 1; \
65 } \
66 } while (0)
67
68
69#define TST_RAND_SAMPLE_RANGES 16
70
71/*******************************************************************************
72* Global Variables *
73*******************************************************************************/
74static unsigned g_cErrors = 0;
75
76
77static void tstRandCheckDist(uint32_t *pacHits, unsigned iTest)
78{
79 RTPrintf("tstRand:");
80 uint32_t iMin = UINT32_MAX;
81 uint32_t iMax = 0;
82 uint32_t iAvg = 0;
83 for (unsigned iRange = 0; iRange < TST_RAND_SAMPLE_RANGES; iRange++)
84 {
85 RTPrintf(" %04RX32", pacHits[iRange]);
86 if (iMax < pacHits[iRange])
87 iMax = pacHits[iRange];
88 if (iMin > pacHits[iRange])
89 iMin = pacHits[iRange];
90 iAvg += pacHits[iRange];
91 }
92 iAvg /= TST_RAND_SAMPLE_RANGES;
93 RTPrintf(" min=%RX32 (%%%d) max=%RX32 (%%%d) calc avg=%RX32 [test=%d]\n",
94 iMin, (iAvg - iMin) * 100 / iAvg, iMax,
95 (iMax - iAvg) * 100 / iAvg,
96 iAvg,
97 iTest);
98 CHECK_EXPR(iMin >= iAvg - iAvg / 4);
99 CHECK_EXPR(iMax <= iAvg + iAvg / 4);
100}
101
102
103int main()
104{
105 RTR3Init(false);
106 RTPrintf("tstRand: TESTING...\n");
107
108 /*
109 * Do some smoke tests first?
110 */
111 /** @todo RTRand smoke testing. */
112
113 /*
114 * Test distribution.
115 */
116#if 1
117 /* unsigned 32-bit */
118 static const struct
119 {
120 uint32_t u32First;
121 uint32_t u32Last;
122 } s_aU32Tests[] =
123 {
124 { 0, UINT32_MAX },
125 { 0, UINT32_MAX / 2 + UINT32_MAX / 4 },
126 { 0, UINT32_MAX / 2 + UINT32_MAX / 8 },
127 { 0, UINT32_MAX / 2 + UINT32_MAX / 16 },
128 { 0, UINT32_MAX / 2 + UINT32_MAX / 64 },
129 { 0, UINT32_MAX / 2 },
130 { UINT32_MAX / 4, UINT32_MAX / 4 * 3 },
131 { 0, TST_RAND_SAMPLE_RANGES - 1 },
132 { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 },
133 };
134 for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU32Tests); iTest++)
135 {
136 uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0};
137 uint32_t const uFirst = s_aU32Tests[iTest].u32First;
138 uint32_t const uLast = s_aU32Tests[iTest].u32Last;
139 uint32_t const uRange = uLast - uFirst; Assert(uLast >= uFirst);
140 uint32_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1;
141 RTPrintf("tstRand: TESTING RTRandU32Ex(%#RX32, %#RX32) distribution... [div=%#RX32 range=%#RX32]\n", uFirst, uLast, uDivisor, uRange);
142 for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++)
143 {
144 uint32_t uRand = RTRandU32Ex(uFirst, uLast);
145 CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX32 %#RX32\n", uRand, uFirst));
146 CHECK_EXPR_MSG(uRand <= uLast, ("%#RX32 %#RX32\n", uRand, uLast));
147 uint32_t off = uRand - uFirst;
148 acHits[off / uDivisor]++;
149 }
150 tstRandCheckDist(acHits, iTest);
151 }
152#endif
153
154#if 1
155 /* unsigned 64-bit */
156 static const struct
157 {
158 uint64_t u64First;
159 uint64_t u64Last;
160 } s_aU64Tests[] =
161 {
162 { 0, UINT64_MAX },
163 { 0, UINT64_MAX / 2 + UINT64_MAX / 4 },
164 { 0, UINT64_MAX / 2 + UINT64_MAX / 8 },
165 { 0, UINT64_MAX / 2 + UINT64_MAX / 16 },
166 { 0, UINT64_MAX / 2 + UINT64_MAX / 64 },
167 { 0, UINT64_MAX / 2 },
168 { UINT64_MAX / 4, UINT64_MAX / 4 * 3 },
169 { 0, UINT32_MAX },
170 { 0, UINT32_MAX / 2 + UINT32_MAX / 4 },
171 { 0, UINT32_MAX / 2 + UINT32_MAX / 8 },
172 { 0, UINT32_MAX / 2 + UINT32_MAX / 16 },
173 { 0, UINT32_MAX / 2 + UINT32_MAX / 64 },
174 { 0, UINT32_MAX / 2 },
175 { UINT32_MAX / 4, UINT32_MAX / 4 * 3 },
176 { 0, TST_RAND_SAMPLE_RANGES - 1 },
177 { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 },
178 };
179 for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU64Tests); iTest++)
180 {
181 uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0};
182 uint64_t const uFirst = s_aU64Tests[iTest].u64First;
183 uint64_t const uLast = s_aU64Tests[iTest].u64Last;
184 uint64_t const uRange = uLast - uFirst; Assert(uLast >= uFirst);
185 uint64_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1;
186 RTPrintf("tstRand: TESTING RTRandU64Ex(%#RX64, %#RX64) distribution... [div=%#RX64 range=%#RX64]\n", uFirst, uLast, uDivisor, uRange);
187 for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++)
188 {
189 uint64_t uRand = RTRandU64Ex(uFirst, uLast);
190 CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX64 %#RX64\n", uRand, uFirst));
191 CHECK_EXPR_MSG(uRand <= uLast, ("%#RX64 %#RX64\n", uRand, uLast));
192 uint64_t off = uRand - uFirst;
193 acHits[off / uDivisor]++;
194 }
195 tstRandCheckDist(acHits, iTest);
196 }
197#endif
198
199#if 1
200 /* signed 32-bit */
201 static const struct
202 {
203 int32_t i32First;
204 int32_t i32Last;
205 } s_aS32Tests[] =
206 {
207 { -429496729, 429496729 },
208 { INT32_MIN, INT32_MAX },
209 { INT32_MIN, INT32_MAX / 2 },
210 { -0x20000000, INT32_MAX },
211 { -0x10000000, INT32_MAX },
212 { -0x080000000, INT32_MAX },
213 { -0x008000000, INT32_MAX },
214 { -0x000800000, INT32_MAX },
215 { -0x000080000, INT32_MAX },
216 { -0x000008000, INT32_MAX },
217 { 2, INT32_MAX / 2 },
218 { 4000000, INT32_MAX / 2 },
219 { -4000000, INT32_MAX / 2 },
220 { INT32_MIN / 2, INT32_MAX / 2 },
221 { INT32_MIN / 3, INT32_MAX / 2 },
222 { INT32_MIN / 3, INT32_MAX / 3 },
223 { INT32_MIN / 3, INT32_MAX / 4 },
224 { INT32_MIN / 4, INT32_MAX / 4 },
225 { INT32_MIN / 5, INT32_MAX / 5 },
226 { INT32_MIN / 6, INT32_MAX / 6 },
227 { INT32_MIN / 7, INT32_MAX / 6 },
228 { INT32_MIN / 7, INT32_MAX / 7 },
229 { INT32_MIN / 7, INT32_MAX / 8 },
230 { INT32_MIN / 8, INT32_MAX / 8 },
231 { INT32_MIN / 9, INT32_MAX / 9 },
232 { INT32_MIN / 9, INT32_MAX / 12 },
233 { INT32_MIN / 12, INT32_MAX / 12 },
234 { 0, TST_RAND_SAMPLE_RANGES - 1 },
235 { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 },
236 };
237 for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS32Tests); iTest++)
238 {
239 uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0};
240 int32_t const iFirst = s_aS32Tests[iTest].i32First;
241 int32_t const iLast = s_aS32Tests[iTest].i32Last;
242 uint32_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest));
243 uint32_t const uDivisor = (uRange ? uRange : UINT32_MAX) / TST_RAND_SAMPLE_RANGES + 1;
244 RTPrintf("tstRand: TESTING RTRandS32Ex(%#RI32, %#RI32) distribution... [div=%#RX32 range=%#RX32]\n", iFirst, iLast, uDivisor, uRange);
245 for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++)
246 {
247 int32_t iRand = RTRandS32Ex(iFirst, iLast);
248 CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI32 %#RI32\n", iRand, iFirst));
249 CHECK_EXPR_MSG(iRand <= iLast, ("%#RI32 %#RI32\n", iRand, iLast));
250 uint32_t off = iRand - iFirst;
251 acHits[off / uDivisor]++;
252 }
253 tstRandCheckDist(acHits, iTest);
254 }
255#endif
256
257#if 1
258 /* signed 64-bit */
259 static const struct
260 {
261 int64_t i64First;
262 int64_t i64Last;
263 } s_aS64Tests[] =
264 {
265 { INT64_MIN, INT64_MAX },
266 { INT64_MIN, INT64_MAX / 2 },
267 { INT64_MIN / 2, INT64_MAX / 2 },
268 { INT64_MIN / 2 + INT64_MIN / 4, INT64_MAX / 2 },
269 { INT64_MIN / 2 + INT64_MIN / 8, INT64_MAX / 2 },
270 { INT64_MIN / 2 + INT64_MIN / 16, INT64_MAX / 2 },
271 { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 },
272 { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 + INT64_MAX / 64 },
273 { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 64 },
274 { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 8 },
275 { INT64_MIN / 2, INT64_MAX / 2 - INT64_MAX / 8 },
276 { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 4 },
277 { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 8 },
278 { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 - INT64_MAX / 8 },
279 { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 8 },
280 { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 16 },
281 { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 16 },
282 { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 32 },
283 { INT64_MIN / 2 - INT64_MIN / 64, INT64_MAX / 2 - INT64_MAX / 64 },
284 { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 },
285 { INT64_MIN / 4, INT64_MAX / 4 },
286 { INT64_MIN / 5, INT64_MAX / 5 },
287 { INT64_MIN / 6, INT64_MAX / 6 },
288 { INT64_MIN / 7, INT64_MAX / 7 },
289 { INT64_MIN / 8, INT64_MAX / 8 },
290 { INT32_MIN, INT32_MAX },
291 { INT32_MIN, INT32_MAX / 2 },
292 { -0x20000000, INT32_MAX },
293 { -0x10000000, INT32_MAX },
294 { -0x7f000000, INT32_MAX },
295 { -0x08000000, INT32_MAX },
296 { -0x00800000, INT32_MAX },
297 { -0x00080000, INT32_MAX },
298 { -0x00008000, INT32_MAX },
299 { 2, INT32_MAX / 2 },
300 { 4000000, INT32_MAX / 2 },
301 { -4000000, INT32_MAX / 2 },
302 { INT32_MIN / 2, INT32_MAX / 2 },
303 { 0, TST_RAND_SAMPLE_RANGES - 1 },
304 { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 }
305 };
306 for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS64Tests); iTest++)
307 {
308 uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0};
309 int64_t const iFirst = s_aS64Tests[iTest].i64First;
310 int64_t const iLast = s_aS64Tests[iTest].i64Last;
311 uint64_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest));
312 uint64_t const uDivisor = (uRange ? uRange : UINT64_MAX) / TST_RAND_SAMPLE_RANGES + 1;
313 RTPrintf("tstRand: TESTING RTRandS64Ex(%#RI64, %#RI64) distribution... [div=%#RX64 range=%#016RX64]\n", iFirst, iLast, uDivisor, uRange);
314 for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++)
315 {
316 int64_t iRand = RTRandS64Ex(iFirst, iLast);
317 CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI64 %#RI64\n", iRand, iFirst));
318 CHECK_EXPR_MSG(iRand <= iLast, ("%#RI64 %#RI64\n", iRand, iLast));
319 uint64_t off = iRand - iFirst;
320 acHits[off / uDivisor]++;
321 }
322 tstRandCheckDist(acHits, iTest);
323 }
324#endif
325
326 /*
327 * Summary.
328 */
329 if (!g_cErrors)
330 RTPrintf("tstRand: SUCCESS\n");
331 else
332 RTPrintf("tstRand: FAILED - %d errors\n", g_cErrors);
333 return !!g_cErrors;
334}
335
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette