diff options
Diffstat (limited to 'mps/code/testlib.c')
| -rw-r--r-- | mps/code/testlib.c | 88 |
1 files changed, 70 insertions, 18 deletions
diff --git a/mps/code/testlib.c b/mps/code/testlib.c index 71cc05d330e..0bc8771f134 100644 --- a/mps/code/testlib.c +++ b/mps/code/testlib.c | |||
| @@ -221,48 +221,100 @@ mps_addr_t rnd_addr(void) | |||
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | 223 | ||
| 224 | /* randomize -- randomize the generator, or initialize to replay */ | 224 | /* randomize -- randomize the generator, or initialize to replay |
| 225 | * | ||
| 226 | * There have been 3 versions of the rnd-states reported by this | ||
| 227 | * function: | ||
| 228 | * | ||
| 229 | * 1. before RHSK got his hands on rnd(). These seed values are not | ||
| 230 | * currently supported, but it might be easy to add support. | ||
| 231 | * | ||
| 232 | * 2. v2 states: the published "seed" (state) value was the seed | ||
| 233 | * *before* the 10 rnds to churn up and separate nearby values | ||
| 234 | * from time(). This is unfortunate: you can't write a rnd_state | ||
| 235 | * getter, because it would have to go 10 steps back in time. | ||
| 236 | * | ||
| 237 | * 3. v3 states: when autogenerated from time(), the published | ||
| 238 | * state is that *after* the 10 rnds. Therefore you can get this | ||
| 239 | * easily, store it, re-use it, etc. | ||
| 240 | */ | ||
| 225 | 241 | ||
| 226 | void randomize(int argc, char **argv) | 242 | void randomize(int argc, char **argv) |
| 227 | { | 243 | { |
| 244 | int i; | ||
| 228 | int n; | 245 | int n; |
| 246 | unsigned long seedt; | ||
| 229 | unsigned long seed0; | 247 | unsigned long seed0; |
| 230 | int i; | ||
| 231 | 248 | ||
| 232 | if (argc > 1) { | 249 | if (argc > 1) { |
| 233 | n = sscanf(argv[1], "%lu", &seed0); | 250 | n = sscanf(argv[1], "%lu", &seed0); |
| 234 | Insist(n == 1); | 251 | Insist(n == 1); |
| 235 | printf("randomize(): resetting initial seed to: %lu.\n", seed0); | 252 | printf("randomize(): resetting initial state (v3) to: %lu.\n", seed0); |
| 253 | rnd_state_set(seed0); | ||
| 236 | } else { | 254 | } else { |
| 237 | /* time_t uses an arbitrary encoding, but hopefully the low order */ | 255 | /* time_t uses an arbitrary encoding, but hopefully the low order */ |
| 238 | /* 31 bits will have at least one bit changed from run to run. */ | 256 | /* 31 bits will have at least one bit changed from run to run. */ |
| 239 | seed0 = 1 + time(NULL) % (R_m - 1); | 257 | seedt = 1 + time(NULL) % (R_m - 1); |
| 240 | printf("randomize(): choosing initial seed: %lu.\n", seed0); | 258 | |
| 259 | /* The value returned by time() on some OSs may simply be a | ||
| 260 | * count of seconds: therefore successive runs may start with | ||
| 261 | * nearby seeds, possibly differing only by 1. So the first value | ||
| 262 | * returned by rnd() may differ by only 48271. It is conceivable | ||
| 263 | * that some tests might be able to 'spot' this pattern (for | ||
| 264 | * example: by using the first rnd() value, mod 100M and rounded | ||
| 265 | * to multiple of 1024K, as arena size in bytes). | ||
| 266 | * | ||
| 267 | * So to mix it up a bit, we do a few iterations now. How many? | ||
| 268 | * Very roughly, 48271^2 is of the same order as 2^31, so two | ||
| 269 | * iterations would make the characteristic difference similar to | ||
| 270 | * the period. Hey, let's go wild and do 10. | ||
| 271 | */ | ||
| 272 | rnd_state_set(seedt); | ||
| 273 | for(i = 0; i < 10; i += 1) { | ||
| 274 | (void)rnd(); | ||
| 275 | } | ||
| 276 | |||
| 277 | seed0 = rnd_state(); | ||
| 278 | printf("randomize(): choosing initial state (v3): %lu.\n", seed0); | ||
| 279 | rnd_state_set(seed0); | ||
| 241 | } | 280 | } |
| 281 | } | ||
| 282 | |||
| 283 | unsigned long rnd_state(void) | ||
| 284 | { | ||
| 285 | return seed; | ||
| 286 | } | ||
| 242 | 287 | ||
| 288 | void rnd_state_set(unsigned long seed0) | ||
| 289 | { | ||
| 243 | Insist(seed0 < R_m); | 290 | Insist(seed0 < R_m); |
| 244 | Insist(seed0 != 0); | 291 | Insist(seed0 != 0); |
| 245 | seed = seed0; | 292 | seed = seed0; |
| 246 | 293 | ||
| 247 | rnd_verify(0); | 294 | rnd_verify(0); |
| 248 | Insist(seed == seed0); | 295 | Insist(seed == seed0); |
| 296 | } | ||
| 297 | |||
| 298 | /* rnd_state_set_2 -- legacy support for v2 rnd states | ||
| 299 | * | ||
| 300 | * In v2, the published "seed" (state) value was the seed *before* | ||
| 301 | * the 10 rnds to churn up and separate nearby values from time(). | ||
| 302 | * | ||
| 303 | * Set the seed, then convert it to a v3 state by doing those 10 rnds. | ||
| 304 | */ | ||
| 305 | void rnd_state_set_v2(unsigned long seed0_v2) | ||
| 306 | { | ||
| 307 | int i; | ||
| 308 | unsigned long seed0; | ||
| 249 | 309 | ||
| 250 | /* The 'random' seed is taken from time(), which may simply be a | 310 | rnd_state_set(seed0_v2); |
| 251 | * count of seconds: therefore successive runs may start with | ||
| 252 | * nearby seeds, possibly differing only by 1. So the first value | ||
| 253 | * returned by rnd() may differ by only 48271. It is conceivable | ||
| 254 | * that some tests might be able to 'spot' this pattern (for | ||
| 255 | * example: by using the first rnd() value, mod 100M and rounded | ||
| 256 | * to multiple of 1024K, as arena size in bytes). | ||
| 257 | * | ||
| 258 | * So to mix it up a bit, we do a few iterations now. How many? | ||
| 259 | * Very roughly, 48271^2 is of the same order as 2^31, so two | ||
| 260 | * iterations would make the characteristic difference similar to | ||
| 261 | * the period. Hey, let's go wild and do 10. | ||
| 262 | */ | ||
| 263 | for(i = 0; i < 10; i += 1) { | 311 | for(i = 0; i < 10; i += 1) { |
| 264 | (void)rnd(); | 312 | (void)rnd(); |
| 265 | } | 313 | } |
| 314 | |||
| 315 | seed0 = rnd_state(); | ||
| 316 | printf("rnd_state_set_v2(): seed0_v2 = %lu, converted to state_v3 = %lu.\n", seed0_v2, seed0); | ||
| 317 | rnd_state_set(seed0); | ||
| 266 | } | 318 | } |
| 267 | 319 | ||
| 268 | 320 | ||