blob: 66908868a6e9efeb447b9584120826b3ee07205b [file] [log] [blame]
Raymond Hettinger40f62172002-12-29 23:03:38 +00001import unittest
R David Murraye3e1c172013-04-02 12:47:23 -04002import unittest.mock
Tim Peters46c04e12002-05-05 20:40:00 +00003import random
Antoine Pitrou346cbd32017-05-27 17:50:54 +02004import os
Raymond Hettinger40f62172002-12-29 23:03:38 +00005import time
Raymond Hettinger5f078ff2003-06-24 20:29:04 +00006import pickle
Raymond Hettinger2f726e92003-10-05 09:09:15 +00007import warnings
Dong-hee Na6989af02020-06-21 18:44:58 +09008import test.support
9
R David Murraye3e1c172013-04-02 12:47:23 -040010from functools import partial
Victor Stinnerbd1b49a2016-10-19 10:11:37 +020011from math import log, exp, pi, fsum, sin, factorial
Benjamin Petersonee8712c2008-05-20 21:35:26 +000012from test import support
Raymond Hettingere8f1e002016-09-06 17:15:29 -070013from fractions import Fraction
masklinn1e27b572020-12-19 05:33:36 +010014from collections import abc, Counter
csabellaf111fd22017-05-11 11:19:35 -040015
Ezio Melotti3e4a98b2013-04-19 05:45:27 +030016class TestBasicOps:
Raymond Hettinger40f62172002-12-29 23:03:38 +000017 # Superclass with tests common to all generators.
18 # Subclasses must arrange for self.gen to retrieve the Random instance
19 # to be tested.
Tim Peters46c04e12002-05-05 20:40:00 +000020
Raymond Hettinger40f62172002-12-29 23:03:38 +000021 def randomlist(self, n):
22 """Helper function to make a list of random numbers"""
Guido van Rossum805365e2007-05-07 22:24:25 +000023 return [self.gen.random() for i in range(n)]
Tim Peters46c04e12002-05-05 20:40:00 +000024
Raymond Hettinger40f62172002-12-29 23:03:38 +000025 def test_autoseed(self):
26 self.gen.seed()
27 state1 = self.gen.getstate()
Raymond Hettinger3081d592003-08-09 18:30:57 +000028 time.sleep(0.1)
Mike53f7a7c2017-12-14 14:04:53 +030029 self.gen.seed() # different seeds at different times
Raymond Hettinger40f62172002-12-29 23:03:38 +000030 state2 = self.gen.getstate()
31 self.assertNotEqual(state1, state2)
Tim Peters46c04e12002-05-05 20:40:00 +000032
Raymond Hettinger40f62172002-12-29 23:03:38 +000033 def test_saverestore(self):
34 N = 1000
35 self.gen.seed()
36 state = self.gen.getstate()
37 randseq = self.randomlist(N)
38 self.gen.setstate(state) # should regenerate the same sequence
39 self.assertEqual(randseq, self.randomlist(N))
40
41 def test_seedargs(self):
Mark Dickinson95aeae02012-06-24 11:05:30 +010042 # Seed value with a negative hash.
43 class MySeed(object):
44 def __hash__(self):
45 return -1729
Xtreaka06d6832019-09-12 09:13:20 +010046 for arg in [None, 0, 1, -1, 10**20, -(10**20),
Victor Stinner00d7cd82020-03-10 15:15:14 +010047 False, True, 3.14, 'a']:
Raymond Hettinger40f62172002-12-29 23:03:38 +000048 self.gen.seed(arg)
Xtreaka06d6832019-09-12 09:13:20 +010049
50 for arg in [1+2j, tuple('abc'), MySeed()]:
51 with self.assertWarns(DeprecationWarning):
52 self.gen.seed(arg)
53
Guido van Rossum805365e2007-05-07 22:24:25 +000054 for arg in [list(range(3)), dict(one=1)]:
Xtreaka06d6832019-09-12 09:13:20 +010055 with self.assertWarns(DeprecationWarning):
56 self.assertRaises(TypeError, self.gen.seed, arg)
Raymond Hettingerf763a722010-09-07 00:38:15 +000057 self.assertRaises(TypeError, self.gen.seed, 1, 2, 3, 4)
Raymond Hettinger58335872004-07-09 14:26:18 +000058 self.assertRaises(TypeError, type(self.gen), [])
Raymond Hettinger40f62172002-12-29 23:03:38 +000059
R David Murraye3e1c172013-04-02 12:47:23 -040060 @unittest.mock.patch('random._urandom') # os.urandom
61 def test_seed_when_randomness_source_not_found(self, urandom_mock):
62 # Random.seed() uses time.time() when an operating system specific
csabellaf111fd22017-05-11 11:19:35 -040063 # randomness source is not found. To test this on machines where it
R David Murraye3e1c172013-04-02 12:47:23 -040064 # exists, run the above test, test_seedargs(), again after mocking
65 # os.urandom() so that it raises the exception expected when the
66 # randomness source is not available.
67 urandom_mock.side_effect = NotImplementedError
68 self.test_seedargs()
69
Antoine Pitrou5e394332012-11-04 02:10:33 +010070 def test_shuffle(self):
71 shuffle = self.gen.shuffle
72 lst = []
73 shuffle(lst)
74 self.assertEqual(lst, [])
75 lst = [37]
76 shuffle(lst)
77 self.assertEqual(lst, [37])
78 seqs = [list(range(n)) for n in range(10)]
79 shuffled_seqs = [list(range(n)) for n in range(10)]
80 for shuffled_seq in shuffled_seqs:
81 shuffle(shuffled_seq)
82 for (seq, shuffled_seq) in zip(seqs, shuffled_seqs):
83 self.assertEqual(len(seq), len(shuffled_seq))
84 self.assertEqual(set(seq), set(shuffled_seq))
Antoine Pitrou5e394332012-11-04 02:10:33 +010085 # The above tests all would pass if the shuffle was a
86 # no-op. The following non-deterministic test covers that. It
87 # asserts that the shuffled sequence of 1000 distinct elements
88 # must be different from the original one. Although there is
89 # mathematically a non-zero probability that this could
90 # actually happen in a genuinely random shuffle, it is
91 # completely negligible, given that the number of possible
92 # permutations of 1000 objects is 1000! (factorial of 1000),
93 # which is considerably larger than the number of atoms in the
94 # universe...
95 lst = list(range(1000))
96 shuffled_lst = list(range(1000))
97 shuffle(shuffled_lst)
98 self.assertTrue(lst != shuffled_lst)
99 shuffle(lst)
100 self.assertTrue(lst != shuffled_lst)
csabellaf111fd22017-05-11 11:19:35 -0400101 self.assertRaises(TypeError, shuffle, (1, 2, 3))
102
103 def test_shuffle_random_argument(self):
104 # Test random argument to shuffle.
105 shuffle = self.gen.shuffle
106 mock_random = unittest.mock.Mock(return_value=0.5)
107 seq = bytearray(b'abcdefghijk')
Raymond Hettinger190fac92020-05-02 16:45:32 -0700108 with self.assertWarns(DeprecationWarning):
109 shuffle(seq, mock_random)
csabellaf111fd22017-05-11 11:19:35 -0400110 mock_random.assert_called_with()
Antoine Pitrou5e394332012-11-04 02:10:33 +0100111
Raymond Hettingerdc4872e2010-09-07 10:06:56 +0000112 def test_choice(self):
113 choice = self.gen.choice
114 with self.assertRaises(IndexError):
115 choice([])
116 self.assertEqual(choice([50]), 50)
117 self.assertIn(choice([25, 75]), [25, 75])
118
Raymond Hettinger40f62172002-12-29 23:03:38 +0000119 def test_sample(self):
120 # For the entire allowable range of 0 <= k <= N, validate that
121 # the sample is of the correct length and contains only unique items
122 N = 100
Guido van Rossum805365e2007-05-07 22:24:25 +0000123 population = range(N)
124 for k in range(N+1):
Raymond Hettinger40f62172002-12-29 23:03:38 +0000125 s = self.gen.sample(population, k)
126 self.assertEqual(len(s), k)
Raymond Hettingera690a992003-11-16 16:17:49 +0000127 uniq = set(s)
Raymond Hettinger40f62172002-12-29 23:03:38 +0000128 self.assertEqual(len(uniq), k)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000129 self.assertTrue(uniq <= set(population))
Raymond Hettinger8ec78812003-01-04 05:55:11 +0000130 self.assertEqual(self.gen.sample([], 0), []) # test edge case N==k==0
R David Murraye3e1c172013-04-02 12:47:23 -0400131 # Exception raised if size of sample exceeds that of population
132 self.assertRaises(ValueError, self.gen.sample, population, N+1)
Raymond Hettingerbf871262016-11-21 14:34:33 -0800133 self.assertRaises(ValueError, self.gen.sample, [], -1)
Raymond Hettinger40f62172002-12-29 23:03:38 +0000134
Raymond Hettinger7b0cf762003-01-17 17:23:23 +0000135 def test_sample_distribution(self):
136 # For the entire allowable range of 0 <= k <= N, validate that
137 # sample generates all possible permutations
138 n = 5
139 pop = range(n)
140 trials = 10000 # large num prevents false negatives without slowing normal case
Guido van Rossum805365e2007-05-07 22:24:25 +0000141 for k in range(n):
Raymond Hettingerffdb8bb2004-09-27 15:29:05 +0000142 expected = factorial(n) // factorial(n-k)
Raymond Hettinger7b0cf762003-01-17 17:23:23 +0000143 perms = {}
Guido van Rossum805365e2007-05-07 22:24:25 +0000144 for i in range(trials):
Raymond Hettinger7b0cf762003-01-17 17:23:23 +0000145 perms[tuple(self.gen.sample(pop, k))] = None
146 if len(perms) == expected:
147 break
148 else:
149 self.fail()
150
Raymond Hettinger66d09f12003-09-06 04:25:54 +0000151 def test_sample_inputs(self):
152 # SF bug #801342 -- population can be any iterable defining __len__()
Raymond Hettinger66d09f12003-09-06 04:25:54 +0000153 self.gen.sample(range(20), 2)
Guido van Rossum805365e2007-05-07 22:24:25 +0000154 self.gen.sample(range(20), 2)
Raymond Hettinger66d09f12003-09-06 04:25:54 +0000155 self.gen.sample(str('abcdefghijklmnopqrst'), 2)
156 self.gen.sample(tuple('abcdefghijklmnopqrst'), 2)
157
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000158 def test_sample_on_dicts(self):
Raymond Hettinger1acde192008-01-14 01:00:53 +0000159 self.assertRaises(TypeError, self.gen.sample, dict.fromkeys('abcdef'), 2)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000160
Raymond Hettinger4fe00202020-04-19 00:36:42 -0700161 def test_sample_on_sets(self):
162 with self.assertWarns(DeprecationWarning):
163 population = {10, 20, 30, 40, 50, 60, 70}
164 self.gen.sample(population, k=5)
165
masklinn1e27b572020-12-19 05:33:36 +0100166 def test_sample_on_seqsets(self):
167 class SeqSet(abc.Sequence, abc.Set):
168 def __init__(self, items):
169 self._items = items
170
171 def __len__(self):
172 return len(self._items)
173
174 def __getitem__(self, index):
175 return self._items[index]
176
177 population = SeqSet([2, 4, 1, 3])
178 with warnings.catch_warnings():
179 warnings.simplefilter("error", DeprecationWarning)
180 self.gen.sample(population, k=2)
181
Raymond Hettinger81a5fc32020-05-08 07:53:15 -0700182 def test_sample_with_counts(self):
183 sample = self.gen.sample
184
185 # General case
186 colors = ['red', 'green', 'blue', 'orange', 'black', 'brown', 'amber']
187 counts = [500, 200, 20, 10, 5, 0, 1 ]
188 k = 700
189 summary = Counter(sample(colors, counts=counts, k=k))
190 self.assertEqual(sum(summary.values()), k)
191 for color, weight in zip(colors, counts):
192 self.assertLessEqual(summary[color], weight)
193 self.assertNotIn('brown', summary)
194
195 # Case that exhausts the population
196 k = sum(counts)
197 summary = Counter(sample(colors, counts=counts, k=k))
198 self.assertEqual(sum(summary.values()), k)
199 for color, weight in zip(colors, counts):
200 self.assertLessEqual(summary[color], weight)
201 self.assertNotIn('brown', summary)
202
203 # Case with population size of 1
204 summary = Counter(sample(['x'], counts=[10], k=8))
205 self.assertEqual(summary, Counter(x=8))
206
207 # Case with all counts equal.
208 nc = len(colors)
209 summary = Counter(sample(colors, counts=[10]*nc, k=10*nc))
210 self.assertEqual(summary, Counter(10*colors))
211
212 # Test error handling
213 with self.assertRaises(TypeError):
214 sample(['red', 'green', 'blue'], counts=10, k=10) # counts not iterable
215 with self.assertRaises(ValueError):
216 sample(['red', 'green', 'blue'], counts=[-3, -7, -8], k=2) # counts are negative
217 with self.assertRaises(ValueError):
218 sample(['red', 'green', 'blue'], counts=[0, 0, 0], k=2) # counts are zero
219 with self.assertRaises(ValueError):
220 sample(['red', 'green'], counts=[10, 10], k=21) # population too small
221 with self.assertRaises(ValueError):
222 sample(['red', 'green', 'blue'], counts=[1, 2], k=2) # too few counts
223 with self.assertRaises(ValueError):
224 sample(['red', 'green', 'blue'], counts=[1, 2, 3, 4], k=2) # too many counts
225
Raymond Hettinger28aa4a02016-09-07 00:08:44 -0700226 def test_choices(self):
227 choices = self.gen.choices
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700228 data = ['red', 'green', 'blue', 'yellow']
229 str_data = 'abcd'
230 range_data = range(4)
231 set_data = set(range(4))
232
233 # basic functionality
234 for sample in [
Raymond Hettinger9016f282016-09-26 21:45:57 -0700235 choices(data, k=5),
236 choices(data, range(4), k=5),
Raymond Hettinger28aa4a02016-09-07 00:08:44 -0700237 choices(k=5, population=data, weights=range(4)),
238 choices(k=5, population=data, cum_weights=range(4)),
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700239 ]:
240 self.assertEqual(len(sample), 5)
241 self.assertEqual(type(sample), list)
242 self.assertTrue(set(sample) <= set(data))
243
244 # test argument handling
Raymond Hettinger28aa4a02016-09-07 00:08:44 -0700245 with self.assertRaises(TypeError): # missing arguments
246 choices(2)
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700247
Raymond Hettinger9016f282016-09-26 21:45:57 -0700248 self.assertEqual(choices(data, k=0), []) # k == 0
249 self.assertEqual(choices(data, k=-1), []) # negative k behaves like ``[0] * -1``
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700250 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700251 choices(data, k=2.5) # k is a float
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700252
Raymond Hettinger9016f282016-09-26 21:45:57 -0700253 self.assertTrue(set(choices(str_data, k=5)) <= set(str_data)) # population is a string sequence
254 self.assertTrue(set(choices(range_data, k=5)) <= set(range_data)) # population is a range
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700255 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700256 choices(set_data, k=2) # population is not a sequence
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700257
Raymond Hettinger9016f282016-09-26 21:45:57 -0700258 self.assertTrue(set(choices(data, None, k=5)) <= set(data)) # weights is None
259 self.assertTrue(set(choices(data, weights=None, k=5)) <= set(data))
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700260 with self.assertRaises(ValueError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700261 choices(data, [1,2], k=5) # len(weights) != len(population)
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700262 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700263 choices(data, 10, k=5) # non-iterable weights
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700264 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700265 choices(data, [None]*4, k=5) # non-numeric weights
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700266 for weights in [
267 [15, 10, 25, 30], # integer weights
268 [15.1, 10.2, 25.2, 30.3], # float weights
269 [Fraction(1, 3), Fraction(2, 6), Fraction(3, 6), Fraction(4, 6)], # fractional weights
270 [True, False, True, False] # booleans (include / exclude)
271 ]:
Raymond Hettinger9016f282016-09-26 21:45:57 -0700272 self.assertTrue(set(choices(data, weights, k=5)) <= set(data))
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700273
274 with self.assertRaises(ValueError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700275 choices(data, cum_weights=[1,2], k=5) # len(weights) != len(population)
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700276 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700277 choices(data, cum_weights=10, k=5) # non-iterable cum_weights
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700278 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700279 choices(data, cum_weights=[None]*4, k=5) # non-numeric cum_weights
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700280 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700281 choices(data, range(4), cum_weights=range(4), k=5) # both weights and cum_weights
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700282 for weights in [
283 [15, 10, 25, 30], # integer cum_weights
284 [15.1, 10.2, 25.2, 30.3], # float cum_weights
285 [Fraction(1, 3), Fraction(2, 6), Fraction(3, 6), Fraction(4, 6)], # fractional cum_weights
286 ]:
Raymond Hettinger9016f282016-09-26 21:45:57 -0700287 self.assertTrue(set(choices(data, cum_weights=weights, k=5)) <= set(data))
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700288
Raymond Hettinger7b166522016-10-14 01:19:38 -0400289 # Test weight focused on a single element of the population
290 self.assertEqual(choices('abcd', [1, 0, 0, 0]), ['a'])
291 self.assertEqual(choices('abcd', [0, 1, 0, 0]), ['b'])
292 self.assertEqual(choices('abcd', [0, 0, 1, 0]), ['c'])
293 self.assertEqual(choices('abcd', [0, 0, 0, 1]), ['d'])
294
295 # Test consistency with random.choice() for empty population
296 with self.assertRaises(IndexError):
297 choices([], k=1)
298 with self.assertRaises(IndexError):
299 choices([], weights=[], k=1)
300 with self.assertRaises(IndexError):
301 choices([], cum_weights=[], k=5)
302
Raymond Hettingerddf71712018-06-27 01:08:31 -0700303 def test_choices_subnormal(self):
Min ho Kim96e12d52019-07-22 06:12:33 +1000304 # Subnormal weights would occasionally trigger an IndexError
Raymond Hettingerddf71712018-06-27 01:08:31 -0700305 # in choices() when the value returned by random() was large
306 # enough to make `random() * total` round up to the total.
307 # See https://bugs.python.org/msg275594 for more detail.
308 choices = self.gen.choices
309 choices(population=[1, 2], weights=[1e-323, 1e-323], k=5000)
310
Raymond Hettinger041d8b42019-11-23 02:22:13 -0800311 def test_choices_with_all_zero_weights(self):
312 # See issue #38881
313 with self.assertRaises(ValueError):
314 self.gen.choices('AB', [0.0, 0.0])
315
Ram Rachumb0dfc752020-09-29 04:32:10 +0300316 def test_choices_negative_total(self):
317 with self.assertRaises(ValueError):
318 self.gen.choices('ABC', [3, -5, 1])
319
320 def test_choices_infinite_total(self):
321 with self.assertRaises(ValueError):
322 self.gen.choices('A', [float('inf')])
323 with self.assertRaises(ValueError):
324 self.gen.choices('AB', [0.0, float('inf')])
325 with self.assertRaises(ValueError):
326 self.gen.choices('AB', [-float('inf'), 123])
327 with self.assertRaises(ValueError):
328 self.gen.choices('AB', [0.0, float('nan')])
329 with self.assertRaises(ValueError):
330 self.gen.choices('AB', [float('-inf'), float('inf')])
331
Raymond Hettinger40f62172002-12-29 23:03:38 +0000332 def test_gauss(self):
333 # Ensure that the seed() method initializes all the hidden state. In
334 # particular, through 2.2.1 it failed to reset a piece of state used
335 # by (and only by) the .gauss() method.
336
337 for seed in 1, 12, 123, 1234, 12345, 123456, 654321:
338 self.gen.seed(seed)
339 x1 = self.gen.random()
340 y1 = self.gen.gauss(0, 1)
341
342 self.gen.seed(seed)
343 x2 = self.gen.random()
344 y2 = self.gen.gauss(0, 1)
345
346 self.assertEqual(x1, x2)
347 self.assertEqual(y1, y2)
348
Antoine Pitrou75a33782020-04-17 19:32:14 +0200349 def test_getrandbits(self):
350 # Verify ranges
351 for k in range(1, 1000):
352 self.assertTrue(0 <= self.gen.getrandbits(k) < 2**k)
353 self.assertEqual(self.gen.getrandbits(0), 0)
354
355 # Verify all bits active
356 getbits = self.gen.getrandbits
357 for span in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]:
358 all_bits = 2**span-1
359 cum = 0
360 cpl_cum = 0
361 for i in range(100):
362 v = getbits(span)
363 cum |= v
364 cpl_cum |= all_bits ^ v
365 self.assertEqual(cum, all_bits)
366 self.assertEqual(cpl_cum, all_bits)
367
368 # Verify argument checking
369 self.assertRaises(TypeError, self.gen.getrandbits)
370 self.assertRaises(TypeError, self.gen.getrandbits, 1, 2)
371 self.assertRaises(ValueError, self.gen.getrandbits, -1)
372 self.assertRaises(TypeError, self.gen.getrandbits, 10.1)
373
Raymond Hettinger5f078ff2003-06-24 20:29:04 +0000374 def test_pickling(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +0200375 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
376 state = pickle.dumps(self.gen, proto)
377 origseq = [self.gen.random() for i in range(10)]
378 newgen = pickle.loads(state)
379 restoredseq = [newgen.random() for i in range(10)]
380 self.assertEqual(origseq, restoredseq)
Raymond Hettinger40f62172002-12-29 23:03:38 +0000381
Dong-hee Na6989af02020-06-21 18:44:58 +0900382 @test.support.cpython_only
383 def test_bug_41052(self):
384 # _random.Random should not be allowed to serialization
385 import _random
386 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
387 r = _random.Random()
388 self.assertRaises(TypeError, pickle.dumps, r, proto)
389
AMIRb8fde8b2020-12-22 03:15:50 +0330390 @test.support.cpython_only
391 def test_bug_42008(self):
392 # _random.Random should call seed with first element of arg tuple
393 import _random
394 r1 = _random.Random()
395 r1.seed(8675309)
396 r2 = _random.Random(8675309)
397 self.assertEqual(r1.random(), r2.random())
398
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000399 def test_bug_1727780(self):
400 # verify that version-2-pickles can be loaded
401 # fine, whether they are created on 32-bit or 64-bit
402 # platforms, and that version-3-pickles load fine.
403 files = [("randv2_32.pck", 780),
404 ("randv2_64.pck", 866),
405 ("randv3.pck", 343)]
406 for file, value in files:
Serhiy Storchaka5b10b982019-03-05 10:06:26 +0200407 with open(support.findfile(file),"rb") as f:
408 r = pickle.load(f)
Raymond Hettinger05156612010-09-07 04:44:52 +0000409 self.assertEqual(int(r.random()*1000), value)
410
411 def test_bug_9025(self):
412 # Had problem with an uneven distribution in int(n*random())
413 # Verify the fix by checking that distributions fall within expectations.
414 n = 100000
415 randrange = self.gen.randrange
416 k = sum(randrange(6755399441055744) % 3 == 2 for i in range(n))
417 self.assertTrue(0.30 < k/n < .37, (k/n))
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000418
Victor Stinner9f5fe792020-04-17 19:05:35 +0200419 def test_randbytes(self):
420 # Verify ranges
421 for n in range(1, 10):
422 data = self.gen.randbytes(n)
423 self.assertEqual(type(data), bytes)
424 self.assertEqual(len(data), n)
425
426 self.assertEqual(self.gen.randbytes(0), b'')
427
428 # Verify argument checking
429 self.assertRaises(TypeError, self.gen.randbytes)
430 self.assertRaises(TypeError, self.gen.randbytes, 1, 2)
431 self.assertRaises(ValueError, self.gen.randbytes, -1)
432 self.assertRaises(TypeError, self.gen.randbytes, 1.0)
433
434
Ezio Melotti3e4a98b2013-04-19 05:45:27 +0300435try:
436 random.SystemRandom().random()
437except NotImplementedError:
438 SystemRandom_available = False
439else:
440 SystemRandom_available = True
441
442@unittest.skipUnless(SystemRandom_available, "random.SystemRandom not available")
443class SystemRandom_TestBasicOps(TestBasicOps, unittest.TestCase):
Raymond Hettinger23f12412004-09-13 22:23:21 +0000444 gen = random.SystemRandom()
Raymond Hettinger356a4592004-08-30 06:14:31 +0000445
446 def test_autoseed(self):
447 # Doesn't need to do anything except not fail
448 self.gen.seed()
449
450 def test_saverestore(self):
451 self.assertRaises(NotImplementedError, self.gen.getstate)
452 self.assertRaises(NotImplementedError, self.gen.setstate, None)
453
454 def test_seedargs(self):
455 # Doesn't need to do anything except not fail
456 self.gen.seed(100)
457
Raymond Hettinger356a4592004-08-30 06:14:31 +0000458 def test_gauss(self):
459 self.gen.gauss_next = None
460 self.gen.seed(100)
461 self.assertEqual(self.gen.gauss_next, None)
462
463 def test_pickling(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +0200464 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
465 self.assertRaises(NotImplementedError, pickle.dumps, self.gen, proto)
Raymond Hettinger356a4592004-08-30 06:14:31 +0000466
467 def test_53_bits_per_float(self):
468 # This should pass whenever a C double has 53 bit precision.
469 span = 2 ** 53
470 cum = 0
Guido van Rossum805365e2007-05-07 22:24:25 +0000471 for i in range(100):
Raymond Hettinger356a4592004-08-30 06:14:31 +0000472 cum |= int(self.gen.random() * span)
473 self.assertEqual(cum, span-1)
474
475 def test_bigrand(self):
476 # The randrange routine should build-up the required number of bits
477 # in stages so that all bit positions are active.
478 span = 2 ** 500
479 cum = 0
Guido van Rossum805365e2007-05-07 22:24:25 +0000480 for i in range(100):
Raymond Hettinger356a4592004-08-30 06:14:31 +0000481 r = self.gen.randrange(span)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000482 self.assertTrue(0 <= r < span)
Raymond Hettinger356a4592004-08-30 06:14:31 +0000483 cum |= r
484 self.assertEqual(cum, span-1)
485
486 def test_bigrand_ranges(self):
487 for i in [40,80, 160, 200, 211, 250, 375, 512, 550]:
Zachary Warea6edea52013-11-26 14:50:10 -0600488 start = self.gen.randrange(2 ** (i-2))
489 stop = self.gen.randrange(2 ** i)
Raymond Hettinger356a4592004-08-30 06:14:31 +0000490 if stop <= start:
Zachary Warea6edea52013-11-26 14:50:10 -0600491 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000492 self.assertTrue(start <= self.gen.randrange(start, stop) < stop)
Raymond Hettinger356a4592004-08-30 06:14:31 +0000493
494 def test_rangelimits(self):
495 for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
496 self.assertEqual(set(range(start,stop)),
Guido van Rossum805365e2007-05-07 22:24:25 +0000497 set([self.gen.randrange(start,stop) for i in range(100)]))
Raymond Hettinger356a4592004-08-30 06:14:31 +0000498
R David Murraye3e1c172013-04-02 12:47:23 -0400499 def test_randrange_nonunit_step(self):
500 rint = self.gen.randrange(0, 10, 2)
501 self.assertIn(rint, (0, 2, 4, 6, 8))
502 rint = self.gen.randrange(0, 2, 2)
503 self.assertEqual(rint, 0)
504
505 def test_randrange_errors(self):
506 raises = partial(self.assertRaises, ValueError, self.gen.randrange)
507 # Empty range
508 raises(3, 3)
509 raises(-721)
510 raises(0, 100, -12)
511 # Non-integer start/stop
Serhiy Storchakaf066bd92021-01-25 23:02:04 +0200512 self.assertWarns(DeprecationWarning, raises, 3.14159)
513 self.assertWarns(DeprecationWarning, self.gen.randrange, 3.0)
514 self.assertWarns(DeprecationWarning, self.gen.randrange, Fraction(3, 1))
515 self.assertWarns(DeprecationWarning, raises, '3')
516 self.assertWarns(DeprecationWarning, raises, 0, 2.71828)
517 self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 2.0)
518 self.assertWarns(DeprecationWarning, self.gen.randrange, 0, Fraction(2, 1))
519 self.assertWarns(DeprecationWarning, raises, 0, '2')
R David Murraye3e1c172013-04-02 12:47:23 -0400520 # Zero and non-integer step
521 raises(0, 42, 0)
Serhiy Storchakaf066bd92021-01-25 23:02:04 +0200522 self.assertWarns(DeprecationWarning, raises, 0, 42, 0.0)
523 self.assertWarns(DeprecationWarning, raises, 0, 0, 0.0)
524 self.assertWarns(DeprecationWarning, raises, 0, 42, 3.14159)
525 self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 3.0)
526 self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, Fraction(3, 1))
527 self.assertWarns(DeprecationWarning, raises, 0, 42, '3')
528 self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 1.0)
529 self.assertWarns(DeprecationWarning, raises, 0, 0, 1.0)
R David Murraye3e1c172013-04-02 12:47:23 -0400530
Raymond Hettingera9621bb2020-12-28 11:10:34 -0800531 def test_randrange_argument_handling(self):
532 randrange = self.gen.randrange
533 with self.assertWarns(DeprecationWarning):
534 randrange(10.0, 20, 2)
535 with self.assertWarns(DeprecationWarning):
536 randrange(10, 20.0, 2)
537 with self.assertWarns(DeprecationWarning):
538 randrange(10, 20, 1.0)
539 with self.assertWarns(DeprecationWarning):
540 randrange(10, 20, 2.0)
541 with self.assertWarns(DeprecationWarning):
542 with self.assertRaises(ValueError):
543 randrange(10.5)
544 with self.assertWarns(DeprecationWarning):
545 with self.assertRaises(ValueError):
546 randrange(10, 20.5)
547 with self.assertWarns(DeprecationWarning):
548 with self.assertRaises(ValueError):
549 randrange(10, 20, 1.5)
550
Raymond Hettinger768fa142021-01-02 10:24:51 -0800551 def test_randrange_step(self):
552 # bpo-42772: When stop is None, the step argument was being ignored.
553 randrange = self.gen.randrange
554 with self.assertRaises(TypeError):
555 randrange(1000, step=100)
556 with self.assertRaises(TypeError):
557 randrange(1000, None, step=100)
558
Raymond Hettinger356a4592004-08-30 06:14:31 +0000559 def test_randbelow_logic(self, _log=log, int=int):
560 # check bitcount transition points: 2**i and 2**(i+1)-1
561 # show that: k = int(1.001 + _log(n, 2))
562 # is equal to or one greater than the number of bits in n
Guido van Rossum805365e2007-05-07 22:24:25 +0000563 for i in range(1, 1000):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000564 n = 1 << i # check an exact power of two
Raymond Hettinger356a4592004-08-30 06:14:31 +0000565 numbits = i+1
566 k = int(1.00001 + _log(n, 2))
567 self.assertEqual(k, numbits)
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000568 self.assertEqual(n, 2**(k-1))
Raymond Hettinger356a4592004-08-30 06:14:31 +0000569
570 n += n - 1 # check 1 below the next power of two
571 k = int(1.00001 + _log(n, 2))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000572 self.assertIn(k, [numbits, numbits+1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000573 self.assertTrue(2**k > n > 2**(k-2))
Raymond Hettinger356a4592004-08-30 06:14:31 +0000574
575 n -= n >> 15 # check a little farther below the next power of two
576 k = int(1.00001 + _log(n, 2))
577 self.assertEqual(k, numbits) # note the stronger assertion
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000578 self.assertTrue(2**k > n > 2**(k-1)) # note the stronger assertion
Raymond Hettinger356a4592004-08-30 06:14:31 +0000579
580
Ezio Melotti3e4a98b2013-04-19 05:45:27 +0300581class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
Raymond Hettinger40f62172002-12-29 23:03:38 +0000582 gen = random.Random()
583
Raymond Hettingerf763a722010-09-07 00:38:15 +0000584 def test_guaranteed_stable(self):
585 # These sequences are guaranteed to stay the same across versions of python
586 self.gen.seed(3456147, version=1)
587 self.assertEqual([self.gen.random().hex() for i in range(4)],
588 ['0x1.ac362300d90d2p-1', '0x1.9d16f74365005p-1',
589 '0x1.1ebb4352e4c4dp-1', '0x1.1a7422abf9c11p-1'])
Raymond Hettingerf763a722010-09-07 00:38:15 +0000590 self.gen.seed("the quick brown fox", version=2)
591 self.assertEqual([self.gen.random().hex() for i in range(4)],
Raymond Hettinger3fcf0022010-12-08 01:13:53 +0000592 ['0x1.1239ddfb11b7cp-3', '0x1.b3cbb5c51b120p-4',
593 '0x1.8c4f55116b60fp-1', '0x1.63eb525174a27p-1'])
Raymond Hettingerf763a722010-09-07 00:38:15 +0000594
Raymond Hettingerc7bab7c2016-08-31 15:01:08 -0700595 def test_bug_27706(self):
596 # Verify that version 1 seeds are unaffected by hash randomization
597
598 self.gen.seed('nofar', version=1) # hash('nofar') == 5990528763808513177
599 self.assertEqual([self.gen.random().hex() for i in range(4)],
600 ['0x1.8645314505ad7p-1', '0x1.afb1f82e40a40p-5',
601 '0x1.2a59d2285e971p-1', '0x1.56977142a7880p-6'])
602
603 self.gen.seed('rachel', version=1) # hash('rachel') == -9091735575445484789
604 self.assertEqual([self.gen.random().hex() for i in range(4)],
605 ['0x1.0b294cc856fcdp-1', '0x1.2ad22d79e77b8p-3',
606 '0x1.3052b9c072678p-2', '0x1.578f332106574p-3'])
607
608 self.gen.seed('', version=1) # hash('') == 0
609 self.assertEqual([self.gen.random().hex() for i in range(4)],
610 ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1',
611 '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2'])
612
Oren Milmand780b2d2017-09-28 10:50:01 +0300613 def test_bug_31478(self):
614 # There shouldn't be an assertion failure in _random.Random.seed() in
615 # case the argument has a bad __abs__() method.
616 class BadInt(int):
617 def __abs__(self):
618 return None
619 try:
620 self.gen.seed(BadInt())
621 except TypeError:
622 pass
623
Raymond Hettinger132a7d72017-09-17 09:04:30 -0700624 def test_bug_31482(self):
625 # Verify that version 1 seeds are unaffected by hash randomization
626 # when the seeds are expressed as bytes rather than strings.
627 # The hash(b) values listed are the Python2.7 hash() values
628 # which were used for seeding.
629
630 self.gen.seed(b'nofar', version=1) # hash('nofar') == 5990528763808513177
631 self.assertEqual([self.gen.random().hex() for i in range(4)],
632 ['0x1.8645314505ad7p-1', '0x1.afb1f82e40a40p-5',
633 '0x1.2a59d2285e971p-1', '0x1.56977142a7880p-6'])
634
635 self.gen.seed(b'rachel', version=1) # hash('rachel') == -9091735575445484789
636 self.assertEqual([self.gen.random().hex() for i in range(4)],
637 ['0x1.0b294cc856fcdp-1', '0x1.2ad22d79e77b8p-3',
638 '0x1.3052b9c072678p-2', '0x1.578f332106574p-3'])
639
640 self.gen.seed(b'', version=1) # hash('') == 0
641 self.assertEqual([self.gen.random().hex() for i in range(4)],
642 ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1',
643 '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2'])
644
645 b = b'\x00\x20\x40\x60\x80\xA0\xC0\xE0\xF0'
646 self.gen.seed(b, version=1) # hash(b) == 5015594239749365497
647 self.assertEqual([self.gen.random().hex() for i in range(4)],
648 ['0x1.52c2fde444d23p-1', '0x1.875174f0daea4p-2',
649 '0x1.9e9b2c50e5cd2p-1', '0x1.fa57768bd321cp-2'])
650
Raymond Hettinger58335872004-07-09 14:26:18 +0000651 def test_setstate_first_arg(self):
652 self.assertRaises(ValueError, self.gen.setstate, (1, None, None))
653
654 def test_setstate_middle_arg(self):
bladebryan9616a822017-04-21 23:10:46 -0700655 start_state = self.gen.getstate()
Raymond Hettinger58335872004-07-09 14:26:18 +0000656 # Wrong type, s/b tuple
657 self.assertRaises(TypeError, self.gen.setstate, (2, None, None))
658 # Wrong length, s/b 625
659 self.assertRaises(ValueError, self.gen.setstate, (2, (1,2,3), None))
660 # Wrong type, s/b tuple of 625 ints
661 self.assertRaises(TypeError, self.gen.setstate, (2, ('a',)*625, None))
662 # Last element s/b an int also
663 self.assertRaises(TypeError, self.gen.setstate, (2, (0,)*624+('a',), None))
Serhiy Storchaka178f0b62015-07-24 09:02:53 +0300664 # Last element s/b between 0 and 624
665 with self.assertRaises((ValueError, OverflowError)):
666 self.gen.setstate((2, (1,)*624+(625,), None))
667 with self.assertRaises((ValueError, OverflowError)):
668 self.gen.setstate((2, (1,)*624+(-1,), None))
bladebryan9616a822017-04-21 23:10:46 -0700669 # Failed calls to setstate() should not have changed the state.
670 bits100 = self.gen.getrandbits(100)
671 self.gen.setstate(start_state)
672 self.assertEqual(self.gen.getrandbits(100), bits100)
Raymond Hettinger58335872004-07-09 14:26:18 +0000673
R David Murraye3e1c172013-04-02 12:47:23 -0400674 # Little trick to make "tuple(x % (2**32) for x in internalstate)"
675 # raise ValueError. I cannot think of a simple way to achieve this, so
676 # I am opting for using a generator as the middle argument of setstate
677 # which attempts to cast a NaN to integer.
678 state_values = self.gen.getstate()[1]
679 state_values = list(state_values)
680 state_values[-1] = float('nan')
681 state = (int(x) for x in state_values)
682 self.assertRaises(TypeError, self.gen.setstate, (2, state, None))
683
Raymond Hettinger40f62172002-12-29 23:03:38 +0000684 def test_referenceImplementation(self):
685 # Compare the python implementation with results from the original
686 # code. Create 2000 53-bit precision random floats. Compare only
687 # the last ten entries to show that the independent implementations
688 # are tracking. Here is the main() function needed to create the
689 # list of expected random numbers:
690 # void main(void){
691 # int i;
692 # unsigned long init[4]={61731, 24903, 614, 42143}, length=4;
693 # init_by_array(init, length);
694 # for (i=0; i<2000; i++) {
695 # printf("%.15f ", genrand_res53());
696 # if (i%5==4) printf("\n");
697 # }
698 # }
699 expected = [0.45839803073713259,
700 0.86057815201978782,
701 0.92848331726782152,
702 0.35932681119782461,
703 0.081823493762449573,
704 0.14332226470169329,
705 0.084297823823520024,
706 0.53814864671831453,
707 0.089215024911993401,
708 0.78486196105372907]
709
Guido van Rossume2a383d2007-01-15 16:59:06 +0000710 self.gen.seed(61731 + (24903<<32) + (614<<64) + (42143<<96))
Raymond Hettinger40f62172002-12-29 23:03:38 +0000711 actual = self.randomlist(2000)[-10:]
712 for a, e in zip(actual, expected):
713 self.assertAlmostEqual(a,e,places=14)
714
715 def test_strong_reference_implementation(self):
716 # Like test_referenceImplementation, but checks for exact bit-level
717 # equality. This should pass on any box where C double contains
718 # at least 53 bits of precision (the underlying algorithm suffers
719 # no rounding errors -- all results are exact).
720 from math import ldexp
721
Guido van Rossume2a383d2007-01-15 16:59:06 +0000722 expected = [0x0eab3258d2231f,
723 0x1b89db315277a5,
724 0x1db622a5518016,
725 0x0b7f9af0d575bf,
726 0x029e4c4db82240,
727 0x04961892f5d673,
728 0x02b291598e4589,
729 0x11388382c15694,
730 0x02dad977c9e1fe,
731 0x191d96d4d334c6]
732 self.gen.seed(61731 + (24903<<32) + (614<<64) + (42143<<96))
Raymond Hettinger40f62172002-12-29 23:03:38 +0000733 actual = self.randomlist(2000)[-10:]
734 for a, e in zip(actual, expected):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000735 self.assertEqual(int(ldexp(a, 53)), e)
Raymond Hettinger40f62172002-12-29 23:03:38 +0000736
737 def test_long_seed(self):
738 # This is most interesting to run in debug mode, just to make sure
739 # nothing blows up. Under the covers, a dynamically resized array
740 # is allocated, consuming space proportional to the number of bits
741 # in the seed. Unfortunately, that's a quadratic-time algorithm,
742 # so don't make this horribly big.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000743 seed = (1 << (10000 * 8)) - 1 # about 10K bytes
Raymond Hettinger40f62172002-12-29 23:03:38 +0000744 self.gen.seed(seed)
745
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000746 def test_53_bits_per_float(self):
747 # This should pass whenever a C double has 53 bit precision.
748 span = 2 ** 53
749 cum = 0
Guido van Rossum805365e2007-05-07 22:24:25 +0000750 for i in range(100):
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000751 cum |= int(self.gen.random() * span)
752 self.assertEqual(cum, span-1)
753
754 def test_bigrand(self):
755 # The randrange routine should build-up the required number of bits
756 # in stages so that all bit positions are active.
757 span = 2 ** 500
758 cum = 0
Guido van Rossum805365e2007-05-07 22:24:25 +0000759 for i in range(100):
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000760 r = self.gen.randrange(span)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000761 self.assertTrue(0 <= r < span)
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000762 cum |= r
763 self.assertEqual(cum, span-1)
764
765 def test_bigrand_ranges(self):
766 for i in [40,80, 160, 200, 211, 250, 375, 512, 550]:
Zachary Warea6edea52013-11-26 14:50:10 -0600767 start = self.gen.randrange(2 ** (i-2))
768 stop = self.gen.randrange(2 ** i)
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000769 if stop <= start:
Zachary Warea6edea52013-11-26 14:50:10 -0600770 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000771 self.assertTrue(start <= self.gen.randrange(start, stop) < stop)
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000772
773 def test_rangelimits(self):
774 for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
Raymond Hettingera690a992003-11-16 16:17:49 +0000775 self.assertEqual(set(range(start,stop)),
Guido van Rossum805365e2007-05-07 22:24:25 +0000776 set([self.gen.randrange(start,stop) for i in range(100)]))
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000777
Antoine Pitrou75a33782020-04-17 19:32:14 +0200778 def test_getrandbits(self):
779 super().test_getrandbits()
780
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000781 # Verify cross-platform repeatability
782 self.gen.seed(1234567)
783 self.assertEqual(self.gen.getrandbits(100),
Guido van Rossume2a383d2007-01-15 16:59:06 +0000784 97904845777343510404718956115)
Raymond Hettinger58335872004-07-09 14:26:18 +0000785
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200786 def test_randrange_uses_getrandbits(self):
787 # Verify use of getrandbits by randrange
788 # Use same seed as in the cross-platform repeatability test
Antoine Pitrou75a33782020-04-17 19:32:14 +0200789 # in test_getrandbits above.
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200790 self.gen.seed(1234567)
791 # If randrange uses getrandbits, it should pick getrandbits(100)
792 # when called with a 100-bits stop argument.
793 self.assertEqual(self.gen.randrange(2**99),
794 97904845777343510404718956115)
795
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000796 def test_randbelow_logic(self, _log=log, int=int):
797 # check bitcount transition points: 2**i and 2**(i+1)-1
798 # show that: k = int(1.001 + _log(n, 2))
799 # is equal to or one greater than the number of bits in n
Guido van Rossum805365e2007-05-07 22:24:25 +0000800 for i in range(1, 1000):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000801 n = 1 << i # check an exact power of two
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000802 numbits = i+1
803 k = int(1.00001 + _log(n, 2))
804 self.assertEqual(k, numbits)
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000805 self.assertEqual(n, 2**(k-1))
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000806
807 n += n - 1 # check 1 below the next power of two
808 k = int(1.00001 + _log(n, 2))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000809 self.assertIn(k, [numbits, numbits+1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000810 self.assertTrue(2**k > n > 2**(k-2))
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000811
812 n -= n >> 15 # check a little farther below the next power of two
813 k = int(1.00001 + _log(n, 2))
814 self.assertEqual(k, numbits) # note the stronger assertion
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000815 self.assertTrue(2**k > n > 2**(k-1)) # note the stronger assertion
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000816
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200817 def test_randbelow_without_getrandbits(self):
R David Murraye3e1c172013-04-02 12:47:23 -0400818 # Random._randbelow() can only use random() when the built-in one
819 # has been overridden but no new getrandbits() method was supplied.
R David Murraye3e1c172013-04-02 12:47:23 -0400820 maxsize = 1<<random.BPF
821 with warnings.catch_warnings():
822 warnings.simplefilter("ignore", UserWarning)
823 # Population range too large (n >= maxsize)
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200824 self.gen._randbelow_without_getrandbits(
825 maxsize+1, maxsize=maxsize
826 )
827 self.gen._randbelow_without_getrandbits(5640, maxsize=maxsize)
Raymond Hettinger4168f1e2020-05-01 10:34:19 -0700828 # issue 33203: test that _randbelow returns zero on
Wolfgang Maier091e95e2018-04-05 17:19:44 +0200829 # n == 0 also in its getrandbits-independent branch.
Raymond Hettinger4168f1e2020-05-01 10:34:19 -0700830 x = self.gen._randbelow_without_getrandbits(0, maxsize=maxsize)
831 self.assertEqual(x, 0)
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200832
R David Murraye3e1c172013-04-02 12:47:23 -0400833 # This might be going too far to test a single line, but because of our
834 # noble aim of achieving 100% test coverage we need to write a case in
835 # which the following line in Random._randbelow() gets executed:
836 #
837 # rem = maxsize % n
838 # limit = (maxsize - rem) / maxsize
839 # r = random()
840 # while r >= limit:
841 # r = random() # <== *This line* <==<
842 #
843 # Therefore, to guarantee that the while loop is executed at least
844 # once, we need to mock random() so that it returns a number greater
845 # than 'limit' the first time it gets called.
846
847 n = 42
848 epsilon = 0.01
849 limit = (maxsize - (maxsize % n)) / maxsize
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200850 with unittest.mock.patch.object(random.Random, 'random') as random_mock:
851 random_mock.side_effect = [limit + epsilon, limit - epsilon]
852 self.gen._randbelow_without_getrandbits(n, maxsize=maxsize)
853 self.assertEqual(random_mock.call_count, 2)
R David Murraye3e1c172013-04-02 12:47:23 -0400854
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000855 def test_randrange_bug_1590891(self):
856 start = 1000000000000
857 stop = -100000000000000000000
858 step = -200
859 x = self.gen.randrange(start, stop, step)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000860 self.assertTrue(stop < x <= start)
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000861 self.assertEqual((x+stop)%step, 0)
862
Raymond Hettinger30d00e52016-10-29 16:55:36 -0700863 def test_choices_algorithms(self):
Raymond Hettinger24e42392016-11-13 00:42:56 -0500864 # The various ways of specifying weights should produce the same results
Raymond Hettinger30d00e52016-10-29 16:55:36 -0700865 choices = self.gen.choices
Raymond Hettinger6023d332016-11-21 15:32:08 -0800866 n = 104729
Raymond Hettinger30d00e52016-10-29 16:55:36 -0700867
868 self.gen.seed(8675309)
869 a = self.gen.choices(range(n), k=10000)
870
871 self.gen.seed(8675309)
872 b = self.gen.choices(range(n), [1]*n, k=10000)
873 self.assertEqual(a, b)
874
875 self.gen.seed(8675309)
876 c = self.gen.choices(range(n), cum_weights=range(1, n+1), k=10000)
877 self.assertEqual(a, c)
878
penguindustin96466302019-05-06 14:57:17 -0400879 # American Roulette
Raymond Hettinger77d574d2016-10-29 17:42:36 -0700880 population = ['Red', 'Black', 'Green']
881 weights = [18, 18, 2]
882 cum_weights = [18, 36, 38]
883 expanded_population = ['Red'] * 18 + ['Black'] * 18 + ['Green'] * 2
884
885 self.gen.seed(9035768)
886 a = self.gen.choices(expanded_population, k=10000)
887
888 self.gen.seed(9035768)
889 b = self.gen.choices(population, weights, k=10000)
890 self.assertEqual(a, b)
891
892 self.gen.seed(9035768)
893 c = self.gen.choices(population, cum_weights=cum_weights, k=10000)
894 self.assertEqual(a, c)
895
Victor Stinner9f5fe792020-04-17 19:05:35 +0200896 def test_randbytes(self):
897 super().test_randbytes()
898
899 # Mersenne Twister randbytes() is deterministic
900 # and does not depend on the endian and bitness.
901 seed = 8675309
Serhiy Storchaka223221b2020-04-17 23:51:28 +0300902 expected = b'3\xa8\xf9f\xf4\xa4\xd06\x19\x8f\x9f\x82\x02oe\xf0'
Victor Stinner9f5fe792020-04-17 19:05:35 +0200903
904 self.gen.seed(seed)
905 self.assertEqual(self.gen.randbytes(16), expected)
906
907 # randbytes(0) must not consume any entropy
908 self.gen.seed(seed)
909 self.assertEqual(self.gen.randbytes(0), b'')
910 self.assertEqual(self.gen.randbytes(16), expected)
911
912 # Four randbytes(4) calls give the same output than randbytes(16)
913 self.gen.seed(seed)
914 self.assertEqual(b''.join([self.gen.randbytes(4) for _ in range(4)]),
915 expected)
916
Serhiy Storchaka223221b2020-04-17 23:51:28 +0300917 # Each randbytes(1), randbytes(2) or randbytes(3) call consumes
918 # 4 bytes of entropy
Victor Stinner9f5fe792020-04-17 19:05:35 +0200919 self.gen.seed(seed)
Serhiy Storchaka223221b2020-04-17 23:51:28 +0300920 expected1 = expected[3::4]
921 self.assertEqual(b''.join(self.gen.randbytes(1) for _ in range(4)),
922 expected1)
923
924 self.gen.seed(seed)
925 expected2 = b''.join(expected[i + 2: i + 4]
Victor Stinner9f5fe792020-04-17 19:05:35 +0200926 for i in range(0, len(expected), 4))
927 self.assertEqual(b''.join(self.gen.randbytes(2) for _ in range(4)),
928 expected2)
929
930 self.gen.seed(seed)
Serhiy Storchaka223221b2020-04-17 23:51:28 +0300931 expected3 = b''.join(expected[i + 1: i + 4]
Victor Stinner9f5fe792020-04-17 19:05:35 +0200932 for i in range(0, len(expected), 4))
933 self.assertEqual(b''.join(self.gen.randbytes(3) for _ in range(4)),
934 expected3)
935
Serhiy Storchaka223221b2020-04-17 23:51:28 +0300936 def test_randbytes_getrandbits(self):
937 # There is a simple relation between randbytes() and getrandbits()
938 seed = 2849427419
939 gen2 = random.Random()
940 self.gen.seed(seed)
941 gen2.seed(seed)
942 for n in range(9):
943 self.assertEqual(self.gen.randbytes(n),
944 gen2.getrandbits(n * 8).to_bytes(n, 'little'))
945
jonanifrancof7b5bacd2021-01-18 19:04:29 +0100946 def test_sample_counts_equivalence(self):
947 # Test the documented strong equivalence to a sample with repeated elements.
948 # We run this test on random.Random() which makes deterministic selections
949 # for a given seed value.
950 sample = self.gen.sample
951 seed = self.gen.seed
952
953 colors = ['red', 'green', 'blue', 'orange', 'black', 'amber']
954 counts = [500, 200, 20, 10, 5, 1 ]
955 k = 700
956 seed(8675309)
957 s1 = sample(colors, counts=counts, k=k)
958 seed(8675309)
959 expanded = [color for (color, count) in zip(colors, counts) for i in range(count)]
960 self.assertEqual(len(expanded), sum(counts))
961 s2 = sample(expanded, k=k)
962 self.assertEqual(s1, s2)
963
964 pop = 'abcdefghi'
965 counts = [10, 9, 8, 7, 6, 5, 4, 3, 2]
966 seed(8675309)
967 s1 = ''.join(sample(pop, counts=counts, k=30))
968 expanded = ''.join([letter for (letter, count) in zip(pop, counts) for i in range(count)])
969 seed(8675309)
970 s2 = ''.join(sample(expanded, k=30))
971 self.assertEqual(s1, s2)
972
Victor Stinner9f5fe792020-04-17 19:05:35 +0200973
Raymond Hettinger2d0c2562009-02-19 09:53:18 +0000974def gamma(z, sqrt2pi=(2.0*pi)**0.5):
975 # Reflection to right half of complex plane
976 if z < 0.5:
977 return pi / sin(pi*z) / gamma(1.0-z)
978 # Lanczos approximation with g=7
979 az = z + (7.0 - 0.5)
980 return az ** (z-0.5) / exp(az) * sqrt2pi * fsum([
981 0.9999999999995183,
982 676.5203681218835 / z,
983 -1259.139216722289 / (z+1.0),
984 771.3234287757674 / (z+2.0),
985 -176.6150291498386 / (z+3.0),
986 12.50734324009056 / (z+4.0),
987 -0.1385710331296526 / (z+5.0),
988 0.9934937113930748e-05 / (z+6.0),
989 0.1659470187408462e-06 / (z+7.0),
990 ])
Raymond Hettinger3dd990c2003-01-05 09:20:06 +0000991
Raymond Hettinger15ec3732003-01-05 01:08:34 +0000992class TestDistributions(unittest.TestCase):
993 def test_zeroinputs(self):
994 # Verify that distributions can handle a series of zero inputs'
995 g = random.Random()
Guido van Rossum805365e2007-05-07 22:24:25 +0000996 x = [g.random() for i in range(50)] + [0.0]*5
Raymond Hettinger15ec3732003-01-05 01:08:34 +0000997 g.random = x[:].pop; g.uniform(1,10)
998 g.random = x[:].pop; g.paretovariate(1.0)
999 g.random = x[:].pop; g.expovariate(1.0)
1000 g.random = x[:].pop; g.weibullvariate(1.0, 1.0)
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001001 g.random = x[:].pop; g.vonmisesvariate(1.0, 1.0)
Raymond Hettinger15ec3732003-01-05 01:08:34 +00001002 g.random = x[:].pop; g.normalvariate(0.0, 1.0)
1003 g.random = x[:].pop; g.gauss(0.0, 1.0)
1004 g.random = x[:].pop; g.lognormvariate(0.0, 1.0)
1005 g.random = x[:].pop; g.vonmisesvariate(0.0, 1.0)
1006 g.random = x[:].pop; g.gammavariate(0.01, 1.0)
1007 g.random = x[:].pop; g.gammavariate(1.0, 1.0)
1008 g.random = x[:].pop; g.gammavariate(200.0, 1.0)
1009 g.random = x[:].pop; g.betavariate(3.0, 3.0)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001010 g.random = x[:].pop; g.triangular(0.0, 1.0, 1.0/3.0)
Raymond Hettinger15ec3732003-01-05 01:08:34 +00001011
Raymond Hettinger3dd990c2003-01-05 09:20:06 +00001012 def test_avg_std(self):
1013 # Use integration to test distribution average and standard deviation.
1014 # Only works for distributions which do not consume variates in pairs
1015 g = random.Random()
1016 N = 5000
Guido van Rossum805365e2007-05-07 22:24:25 +00001017 x = [i/float(N) for i in range(1,N)]
Raymond Hettinger3dd990c2003-01-05 09:20:06 +00001018 for variate, args, mu, sigmasqrd in [
1019 (g.uniform, (1.0,10.0), (10.0+1.0)/2, (10.0-1.0)**2/12),
Christian Heimesfe337bf2008-03-23 21:54:12 +00001020 (g.triangular, (0.0, 1.0, 1.0/3.0), 4.0/9.0, 7.0/9.0/18.0),
Raymond Hettinger3dd990c2003-01-05 09:20:06 +00001021 (g.expovariate, (1.5,), 1/1.5, 1/1.5**2),
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001022 (g.vonmisesvariate, (1.23, 0), pi, pi**2/3),
Raymond Hettinger3dd990c2003-01-05 09:20:06 +00001023 (g.paretovariate, (5.0,), 5.0/(5.0-1),
1024 5.0/((5.0-1)**2*(5.0-2))),
1025 (g.weibullvariate, (1.0, 3.0), gamma(1+1/3.0),
1026 gamma(1+2/3.0)-gamma(1+1/3.0)**2) ]:
1027 g.random = x[:].pop
1028 y = []
Guido van Rossum805365e2007-05-07 22:24:25 +00001029 for i in range(len(x)):
Raymond Hettinger3dd990c2003-01-05 09:20:06 +00001030 try:
1031 y.append(variate(*args))
1032 except IndexError:
1033 pass
1034 s1 = s2 = 0
1035 for e in y:
1036 s1 += e
1037 s2 += (e - mu) ** 2
1038 N = len(y)
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001039 self.assertAlmostEqual(s1/N, mu, places=2,
1040 msg='%s%r' % (variate.__name__, args))
1041 self.assertAlmostEqual(s2/(N-1), sigmasqrd, places=2,
1042 msg='%s%r' % (variate.__name__, args))
1043
1044 def test_constant(self):
1045 g = random.Random()
1046 N = 100
1047 for variate, args, expected in [
1048 (g.uniform, (10.0, 10.0), 10.0),
1049 (g.triangular, (10.0, 10.0), 10.0),
Raymond Hettinger978c6ab2014-05-25 17:25:27 -07001050 (g.triangular, (10.0, 10.0, 10.0), 10.0),
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001051 (g.expovariate, (float('inf'),), 0.0),
1052 (g.vonmisesvariate, (3.0, float('inf')), 3.0),
1053 (g.gauss, (10.0, 0.0), 10.0),
1054 (g.lognormvariate, (0.0, 0.0), 1.0),
1055 (g.lognormvariate, (-float('inf'), 0.0), 0.0),
1056 (g.normalvariate, (10.0, 0.0), 10.0),
1057 (g.paretovariate, (float('inf'),), 1.0),
1058 (g.weibullvariate, (10.0, float('inf')), 10.0),
1059 (g.weibullvariate, (0.0, 10.0), 0.0),
1060 ]:
1061 for i in range(N):
1062 self.assertEqual(variate(*args), expected)
Raymond Hettinger3dd990c2003-01-05 09:20:06 +00001063
Mark Dickinsonbe5f9192013-02-10 14:16:10 +00001064 def test_von_mises_range(self):
1065 # Issue 17149: von mises variates were not consistently in the
1066 # range [0, 2*PI].
1067 g = random.Random()
1068 N = 100
1069 for mu in 0.0, 0.1, 3.1, 6.2:
1070 for kappa in 0.0, 2.3, 500.0:
1071 for _ in range(N):
1072 sample = g.vonmisesvariate(mu, kappa)
1073 self.assertTrue(
1074 0 <= sample <= random.TWOPI,
1075 msg=("vonmisesvariate({}, {}) produced a result {} out"
1076 " of range [0, 2*pi]").format(mu, kappa, sample))
1077
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001078 def test_von_mises_large_kappa(self):
1079 # Issue #17141: vonmisesvariate() was hang for large kappas
1080 random.vonmisesvariate(0, 1e15)
1081 random.vonmisesvariate(0, 1e100)
1082
R David Murraye3e1c172013-04-02 12:47:23 -04001083 def test_gammavariate_errors(self):
1084 # Both alpha and beta must be > 0.0
1085 self.assertRaises(ValueError, random.gammavariate, -1, 3)
1086 self.assertRaises(ValueError, random.gammavariate, 0, 2)
1087 self.assertRaises(ValueError, random.gammavariate, 2, 0)
1088 self.assertRaises(ValueError, random.gammavariate, 1, -3)
1089
leodema63d15222018-12-24 07:54:25 +01001090 # There are three different possibilities in the current implementation
1091 # of random.gammavariate(), depending on the value of 'alpha'. What we
1092 # are going to do here is to fix the values returned by random() to
1093 # generate test cases that provide 100% line coverage of the method.
R David Murraye3e1c172013-04-02 12:47:23 -04001094 @unittest.mock.patch('random.Random.random')
leodema63d15222018-12-24 07:54:25 +01001095 def test_gammavariate_alpha_greater_one(self, random_mock):
R David Murraye3e1c172013-04-02 12:47:23 -04001096
leodema63d15222018-12-24 07:54:25 +01001097 # #1: alpha > 1.0.
1098 # We want the first random number to be outside the
R David Murraye3e1c172013-04-02 12:47:23 -04001099 # [1e-7, .9999999] range, so that the continue statement executes
1100 # once. The values of u1 and u2 will be 0.5 and 0.3, respectively.
1101 random_mock.side_effect = [1e-8, 0.5, 0.3]
1102 returned_value = random.gammavariate(1.1, 2.3)
1103 self.assertAlmostEqual(returned_value, 2.53)
1104
leodema63d15222018-12-24 07:54:25 +01001105 @unittest.mock.patch('random.Random.random')
1106 def test_gammavariate_alpha_equal_one(self, random_mock):
R David Murraye3e1c172013-04-02 12:47:23 -04001107
leodema63d15222018-12-24 07:54:25 +01001108 # #2.a: alpha == 1.
1109 # The execution body of the while loop executes once.
1110 # Then random.random() returns 0.45,
1111 # which causes while to stop looping and the algorithm to terminate.
1112 random_mock.side_effect = [0.45]
1113 returned_value = random.gammavariate(1.0, 3.14)
1114 self.assertAlmostEqual(returned_value, 1.877208182372648)
1115
1116 @unittest.mock.patch('random.Random.random')
1117 def test_gammavariate_alpha_equal_one_equals_expovariate(self, random_mock):
1118
1119 # #2.b: alpha == 1.
1120 # It must be equivalent of calling expovariate(1.0 / beta).
1121 beta = 3.14
1122 random_mock.side_effect = [1e-8, 1e-8]
1123 gammavariate_returned_value = random.gammavariate(1.0, beta)
1124 expovariate_returned_value = random.expovariate(1.0 / beta)
1125 self.assertAlmostEqual(gammavariate_returned_value, expovariate_returned_value)
1126
1127 @unittest.mock.patch('random.Random.random')
1128 def test_gammavariate_alpha_between_zero_and_one(self, random_mock):
1129
1130 # #3: 0 < alpha < 1.
1131 # This is the most complex region of code to cover,
R David Murraye3e1c172013-04-02 12:47:23 -04001132 # as there are multiple if-else statements. Let's take a look at the
1133 # source code, and determine the values that we need accordingly:
1134 #
1135 # while 1:
1136 # u = random()
1137 # b = (_e + alpha)/_e
1138 # p = b*u
1139 # if p <= 1.0: # <=== (A)
1140 # x = p ** (1.0/alpha)
1141 # else: # <=== (B)
1142 # x = -_log((b-p)/alpha)
1143 # u1 = random()
1144 # if p > 1.0: # <=== (C)
1145 # if u1 <= x ** (alpha - 1.0): # <=== (D)
1146 # break
1147 # elif u1 <= _exp(-x): # <=== (E)
1148 # break
1149 # return x * beta
1150 #
1151 # First, we want (A) to be True. For that we need that:
1152 # b*random() <= 1.0
1153 # r1 = random() <= 1.0 / b
1154 #
1155 # We now get to the second if-else branch, and here, since p <= 1.0,
1156 # (C) is False and we take the elif branch, (E). For it to be True,
1157 # so that the break is executed, we need that:
1158 # r2 = random() <= _exp(-x)
1159 # r2 <= _exp(-(p ** (1.0/alpha)))
1160 # r2 <= _exp(-((b*r1) ** (1.0/alpha)))
1161
1162 _e = random._e
1163 _exp = random._exp
1164 _log = random._log
1165 alpha = 0.35
1166 beta = 1.45
1167 b = (_e + alpha)/_e
1168 epsilon = 0.01
1169
1170 r1 = 0.8859296441566 # 1.0 / b
1171 r2 = 0.3678794411714 # _exp(-((b*r1) ** (1.0/alpha)))
1172
1173 # These four "random" values result in the following trace:
1174 # (A) True, (E) False --> [next iteration of while]
1175 # (A) True, (E) True --> [while loop breaks]
1176 random_mock.side_effect = [r1, r2 + epsilon, r1, r2]
1177 returned_value = random.gammavariate(alpha, beta)
1178 self.assertAlmostEqual(returned_value, 1.4499999999997544)
1179
1180 # Let's now make (A) be False. If this is the case, when we get to the
1181 # second if-else 'p' is greater than 1, so (C) evaluates to True. We
1182 # now encounter a second if statement, (D), which in order to execute
1183 # must satisfy the following condition:
1184 # r2 <= x ** (alpha - 1.0)
1185 # r2 <= (-_log((b-p)/alpha)) ** (alpha - 1.0)
1186 # r2 <= (-_log((b-(b*r1))/alpha)) ** (alpha - 1.0)
1187 r1 = 0.8959296441566 # (1.0 / b) + epsilon -- so that (A) is False
1188 r2 = 0.9445400408898141
1189
1190 # And these four values result in the following trace:
1191 # (B) and (C) True, (D) False --> [next iteration of while]
1192 # (B) and (C) True, (D) True [while loop breaks]
1193 random_mock.side_effect = [r1, r2 + epsilon, r1, r2]
1194 returned_value = random.gammavariate(alpha, beta)
1195 self.assertAlmostEqual(returned_value, 1.5830349561760781)
1196
1197 @unittest.mock.patch('random.Random.gammavariate')
1198 def test_betavariate_return_zero(self, gammavariate_mock):
1199 # betavariate() returns zero when the Gamma distribution
1200 # that it uses internally returns this same value.
1201 gammavariate_mock.return_value = 0.0
1202 self.assertEqual(0.0, random.betavariate(2.71828, 3.14159))
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001203
Serhiy Storchakaec1622d2018-05-08 15:45:15 +03001204
Wolfgang Maierba3a87a2018-04-17 17:16:17 +02001205class TestRandomSubclassing(unittest.TestCase):
1206 def test_random_subclass_with_kwargs(self):
1207 # SF bug #1486663 -- this used to erroneously raise a TypeError
1208 class Subclass(random.Random):
1209 def __init__(self, newarg=None):
1210 random.Random.__init__(self)
1211 Subclass(newarg=1)
1212
1213 def test_subclasses_overriding_methods(self):
1214 # Subclasses with an overridden random, but only the original
1215 # getrandbits method should not rely on getrandbits in for randrange,
1216 # but should use a getrandbits-independent implementation instead.
1217
1218 # subclass providing its own random **and** getrandbits methods
1219 # like random.SystemRandom does => keep relying on getrandbits for
1220 # randrange
1221 class SubClass1(random.Random):
1222 def random(self):
Serhiy Storchakaec1622d2018-05-08 15:45:15 +03001223 called.add('SubClass1.random')
1224 return random.Random.random(self)
Wolfgang Maierba3a87a2018-04-17 17:16:17 +02001225
1226 def getrandbits(self, n):
Serhiy Storchakaec1622d2018-05-08 15:45:15 +03001227 called.add('SubClass1.getrandbits')
1228 return random.Random.getrandbits(self, n)
1229 called = set()
1230 SubClass1().randrange(42)
1231 self.assertEqual(called, {'SubClass1.getrandbits'})
Wolfgang Maierba3a87a2018-04-17 17:16:17 +02001232
1233 # subclass providing only random => can only use random for randrange
1234 class SubClass2(random.Random):
1235 def random(self):
Serhiy Storchakaec1622d2018-05-08 15:45:15 +03001236 called.add('SubClass2.random')
1237 return random.Random.random(self)
1238 called = set()
1239 SubClass2().randrange(42)
1240 self.assertEqual(called, {'SubClass2.random'})
Wolfgang Maierba3a87a2018-04-17 17:16:17 +02001241
1242 # subclass defining getrandbits to complement its inherited random
1243 # => can now rely on getrandbits for randrange again
1244 class SubClass3(SubClass2):
1245 def getrandbits(self, n):
Serhiy Storchakaec1622d2018-05-08 15:45:15 +03001246 called.add('SubClass3.getrandbits')
1247 return random.Random.getrandbits(self, n)
1248 called = set()
1249 SubClass3().randrange(42)
1250 self.assertEqual(called, {'SubClass3.getrandbits'})
1251
1252 # subclass providing only random and inherited getrandbits
1253 # => random takes precedence
1254 class SubClass4(SubClass3):
1255 def random(self):
1256 called.add('SubClass4.random')
1257 return random.Random.random(self)
1258 called = set()
1259 SubClass4().randrange(42)
1260 self.assertEqual(called, {'SubClass4.random'})
1261
1262 # Following subclasses don't define random or getrandbits directly,
1263 # but inherit them from classes which are not subclasses of Random
1264 class Mixin1:
1265 def random(self):
1266 called.add('Mixin1.random')
1267 return random.Random.random(self)
1268 class Mixin2:
1269 def getrandbits(self, n):
1270 called.add('Mixin2.getrandbits')
1271 return random.Random.getrandbits(self, n)
1272
1273 class SubClass5(Mixin1, random.Random):
1274 pass
1275 called = set()
1276 SubClass5().randrange(42)
1277 self.assertEqual(called, {'Mixin1.random'})
1278
1279 class SubClass6(Mixin2, random.Random):
1280 pass
1281 called = set()
1282 SubClass6().randrange(42)
1283 self.assertEqual(called, {'Mixin2.getrandbits'})
1284
1285 class SubClass7(Mixin1, Mixin2, random.Random):
1286 pass
1287 called = set()
1288 SubClass7().randrange(42)
1289 self.assertEqual(called, {'Mixin1.random'})
1290
1291 class SubClass8(Mixin2, Mixin1, random.Random):
1292 pass
1293 called = set()
1294 SubClass8().randrange(42)
1295 self.assertEqual(called, {'Mixin2.getrandbits'})
1296
Wolfgang Maierba3a87a2018-04-17 17:16:17 +02001297
Raymond Hettinger40f62172002-12-29 23:03:38 +00001298class TestModule(unittest.TestCase):
1299 def testMagicConstants(self):
1300 self.assertAlmostEqual(random.NV_MAGICCONST, 1.71552776992141)
1301 self.assertAlmostEqual(random.TWOPI, 6.28318530718)
1302 self.assertAlmostEqual(random.LOG4, 1.38629436111989)
1303 self.assertAlmostEqual(random.SG_MAGICCONST, 2.50407739677627)
1304
1305 def test__all__(self):
1306 # tests validity but not completeness of the __all__ list
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001307 self.assertTrue(set(random.__all__) <= set(dir(random)))
Raymond Hettinger40f62172002-12-29 23:03:38 +00001308
Antoine Pitrou346cbd32017-05-27 17:50:54 +02001309 @unittest.skipUnless(hasattr(os, "fork"), "fork() required")
1310 def test_after_fork(self):
1311 # Test the global Random instance gets reseeded in child
1312 r, w = os.pipe()
Victor Stinnerda5e9302017-08-09 17:59:05 +02001313 pid = os.fork()
1314 if pid == 0:
1315 # child process
Antoine Pitrou346cbd32017-05-27 17:50:54 +02001316 try:
1317 val = random.getrandbits(128)
1318 with open(w, "w") as f:
1319 f.write(str(val))
1320 finally:
1321 os._exit(0)
1322 else:
Victor Stinnerda5e9302017-08-09 17:59:05 +02001323 # parent process
Antoine Pitrou346cbd32017-05-27 17:50:54 +02001324 os.close(w)
1325 val = random.getrandbits(128)
1326 with open(r, "r") as f:
1327 child_val = eval(f.read())
1328 self.assertNotEqual(val, child_val)
1329
Victor Stinner278c1e12020-03-31 20:08:12 +02001330 support.wait_process(pid, exitcode=0)
Victor Stinnerda5e9302017-08-09 17:59:05 +02001331
Thomas Woutersb2137042007-02-01 18:02:27 +00001332
Raymond Hettinger40f62172002-12-29 23:03:38 +00001333if __name__ == "__main__":
Ezio Melotti3e4a98b2013-04-19 05:45:27 +03001334 unittest.main()