blob: 5354eddab6958e8e39fa0c66a9f40cfced34561c [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
Miss Islington (bot)2995bff2021-05-03 19:45:30 -070060 def test_seed_no_mutate_bug_44018(self):
61 a = bytearray(b'1234')
62 self.gen.seed(a)
63 self.assertEqual(a, bytearray(b'1234'))
64
R David Murraye3e1c172013-04-02 12:47:23 -040065 @unittest.mock.patch('random._urandom') # os.urandom
66 def test_seed_when_randomness_source_not_found(self, urandom_mock):
67 # Random.seed() uses time.time() when an operating system specific
csabellaf111fd22017-05-11 11:19:35 -040068 # randomness source is not found. To test this on machines where it
R David Murraye3e1c172013-04-02 12:47:23 -040069 # exists, run the above test, test_seedargs(), again after mocking
70 # os.urandom() so that it raises the exception expected when the
71 # randomness source is not available.
72 urandom_mock.side_effect = NotImplementedError
73 self.test_seedargs()
74
Antoine Pitrou5e394332012-11-04 02:10:33 +010075 def test_shuffle(self):
76 shuffle = self.gen.shuffle
77 lst = []
78 shuffle(lst)
79 self.assertEqual(lst, [])
80 lst = [37]
81 shuffle(lst)
82 self.assertEqual(lst, [37])
83 seqs = [list(range(n)) for n in range(10)]
84 shuffled_seqs = [list(range(n)) for n in range(10)]
85 for shuffled_seq in shuffled_seqs:
86 shuffle(shuffled_seq)
87 for (seq, shuffled_seq) in zip(seqs, shuffled_seqs):
88 self.assertEqual(len(seq), len(shuffled_seq))
89 self.assertEqual(set(seq), set(shuffled_seq))
Antoine Pitrou5e394332012-11-04 02:10:33 +010090 # The above tests all would pass if the shuffle was a
91 # no-op. The following non-deterministic test covers that. It
92 # asserts that the shuffled sequence of 1000 distinct elements
93 # must be different from the original one. Although there is
94 # mathematically a non-zero probability that this could
95 # actually happen in a genuinely random shuffle, it is
96 # completely negligible, given that the number of possible
97 # permutations of 1000 objects is 1000! (factorial of 1000),
98 # which is considerably larger than the number of atoms in the
99 # universe...
100 lst = list(range(1000))
101 shuffled_lst = list(range(1000))
102 shuffle(shuffled_lst)
103 self.assertTrue(lst != shuffled_lst)
104 shuffle(lst)
105 self.assertTrue(lst != shuffled_lst)
csabellaf111fd22017-05-11 11:19:35 -0400106 self.assertRaises(TypeError, shuffle, (1, 2, 3))
107
108 def test_shuffle_random_argument(self):
109 # Test random argument to shuffle.
110 shuffle = self.gen.shuffle
111 mock_random = unittest.mock.Mock(return_value=0.5)
112 seq = bytearray(b'abcdefghijk')
Raymond Hettinger190fac92020-05-02 16:45:32 -0700113 with self.assertWarns(DeprecationWarning):
114 shuffle(seq, mock_random)
csabellaf111fd22017-05-11 11:19:35 -0400115 mock_random.assert_called_with()
Antoine Pitrou5e394332012-11-04 02:10:33 +0100116
Raymond Hettingerdc4872e2010-09-07 10:06:56 +0000117 def test_choice(self):
118 choice = self.gen.choice
119 with self.assertRaises(IndexError):
120 choice([])
121 self.assertEqual(choice([50]), 50)
122 self.assertIn(choice([25, 75]), [25, 75])
123
Raymond Hettinger40f62172002-12-29 23:03:38 +0000124 def test_sample(self):
125 # For the entire allowable range of 0 <= k <= N, validate that
126 # the sample is of the correct length and contains only unique items
127 N = 100
Guido van Rossum805365e2007-05-07 22:24:25 +0000128 population = range(N)
129 for k in range(N+1):
Raymond Hettinger40f62172002-12-29 23:03:38 +0000130 s = self.gen.sample(population, k)
131 self.assertEqual(len(s), k)
Raymond Hettingera690a992003-11-16 16:17:49 +0000132 uniq = set(s)
Raymond Hettinger40f62172002-12-29 23:03:38 +0000133 self.assertEqual(len(uniq), k)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000134 self.assertTrue(uniq <= set(population))
Raymond Hettinger8ec78812003-01-04 05:55:11 +0000135 self.assertEqual(self.gen.sample([], 0), []) # test edge case N==k==0
R David Murraye3e1c172013-04-02 12:47:23 -0400136 # Exception raised if size of sample exceeds that of population
137 self.assertRaises(ValueError, self.gen.sample, population, N+1)
Raymond Hettingerbf871262016-11-21 14:34:33 -0800138 self.assertRaises(ValueError, self.gen.sample, [], -1)
Raymond Hettinger40f62172002-12-29 23:03:38 +0000139
Raymond Hettinger7b0cf762003-01-17 17:23:23 +0000140 def test_sample_distribution(self):
141 # For the entire allowable range of 0 <= k <= N, validate that
142 # sample generates all possible permutations
143 n = 5
144 pop = range(n)
145 trials = 10000 # large num prevents false negatives without slowing normal case
Guido van Rossum805365e2007-05-07 22:24:25 +0000146 for k in range(n):
Raymond Hettingerffdb8bb2004-09-27 15:29:05 +0000147 expected = factorial(n) // factorial(n-k)
Raymond Hettinger7b0cf762003-01-17 17:23:23 +0000148 perms = {}
Guido van Rossum805365e2007-05-07 22:24:25 +0000149 for i in range(trials):
Raymond Hettinger7b0cf762003-01-17 17:23:23 +0000150 perms[tuple(self.gen.sample(pop, k))] = None
151 if len(perms) == expected:
152 break
153 else:
154 self.fail()
155
Raymond Hettinger66d09f12003-09-06 04:25:54 +0000156 def test_sample_inputs(self):
157 # SF bug #801342 -- population can be any iterable defining __len__()
Raymond Hettinger66d09f12003-09-06 04:25:54 +0000158 self.gen.sample(range(20), 2)
Guido van Rossum805365e2007-05-07 22:24:25 +0000159 self.gen.sample(range(20), 2)
Raymond Hettinger66d09f12003-09-06 04:25:54 +0000160 self.gen.sample(str('abcdefghijklmnopqrst'), 2)
161 self.gen.sample(tuple('abcdefghijklmnopqrst'), 2)
162
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000163 def test_sample_on_dicts(self):
Raymond Hettinger1acde192008-01-14 01:00:53 +0000164 self.assertRaises(TypeError, self.gen.sample, dict.fromkeys('abcdef'), 2)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000165
Raymond Hettinger4fe00202020-04-19 00:36:42 -0700166 def test_sample_on_sets(self):
167 with self.assertWarns(DeprecationWarning):
168 population = {10, 20, 30, 40, 50, 60, 70}
169 self.gen.sample(population, k=5)
170
masklinn1e27b572020-12-19 05:33:36 +0100171 def test_sample_on_seqsets(self):
172 class SeqSet(abc.Sequence, abc.Set):
173 def __init__(self, items):
174 self._items = items
175
176 def __len__(self):
177 return len(self._items)
178
179 def __getitem__(self, index):
180 return self._items[index]
181
182 population = SeqSet([2, 4, 1, 3])
183 with warnings.catch_warnings():
184 warnings.simplefilter("error", DeprecationWarning)
185 self.gen.sample(population, k=2)
186
Raymond Hettinger81a5fc32020-05-08 07:53:15 -0700187 def test_sample_with_counts(self):
188 sample = self.gen.sample
189
190 # General case
191 colors = ['red', 'green', 'blue', 'orange', 'black', 'brown', 'amber']
192 counts = [500, 200, 20, 10, 5, 0, 1 ]
193 k = 700
194 summary = Counter(sample(colors, counts=counts, k=k))
195 self.assertEqual(sum(summary.values()), k)
196 for color, weight in zip(colors, counts):
197 self.assertLessEqual(summary[color], weight)
198 self.assertNotIn('brown', summary)
199
200 # Case that exhausts the population
201 k = sum(counts)
202 summary = Counter(sample(colors, counts=counts, k=k))
203 self.assertEqual(sum(summary.values()), k)
204 for color, weight in zip(colors, counts):
205 self.assertLessEqual(summary[color], weight)
206 self.assertNotIn('brown', summary)
207
208 # Case with population size of 1
209 summary = Counter(sample(['x'], counts=[10], k=8))
210 self.assertEqual(summary, Counter(x=8))
211
212 # Case with all counts equal.
213 nc = len(colors)
214 summary = Counter(sample(colors, counts=[10]*nc, k=10*nc))
215 self.assertEqual(summary, Counter(10*colors))
216
217 # Test error handling
218 with self.assertRaises(TypeError):
219 sample(['red', 'green', 'blue'], counts=10, k=10) # counts not iterable
220 with self.assertRaises(ValueError):
221 sample(['red', 'green', 'blue'], counts=[-3, -7, -8], k=2) # counts are negative
222 with self.assertRaises(ValueError):
223 sample(['red', 'green', 'blue'], counts=[0, 0, 0], k=2) # counts are zero
224 with self.assertRaises(ValueError):
225 sample(['red', 'green'], counts=[10, 10], k=21) # population too small
226 with self.assertRaises(ValueError):
227 sample(['red', 'green', 'blue'], counts=[1, 2], k=2) # too few counts
228 with self.assertRaises(ValueError):
229 sample(['red', 'green', 'blue'], counts=[1, 2, 3, 4], k=2) # too many counts
230
Raymond Hettinger28aa4a02016-09-07 00:08:44 -0700231 def test_choices(self):
232 choices = self.gen.choices
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700233 data = ['red', 'green', 'blue', 'yellow']
234 str_data = 'abcd'
235 range_data = range(4)
236 set_data = set(range(4))
237
238 # basic functionality
239 for sample in [
Raymond Hettinger9016f282016-09-26 21:45:57 -0700240 choices(data, k=5),
241 choices(data, range(4), k=5),
Raymond Hettinger28aa4a02016-09-07 00:08:44 -0700242 choices(k=5, population=data, weights=range(4)),
243 choices(k=5, population=data, cum_weights=range(4)),
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700244 ]:
245 self.assertEqual(len(sample), 5)
246 self.assertEqual(type(sample), list)
247 self.assertTrue(set(sample) <= set(data))
248
249 # test argument handling
Raymond Hettinger28aa4a02016-09-07 00:08:44 -0700250 with self.assertRaises(TypeError): # missing arguments
251 choices(2)
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700252
Raymond Hettinger9016f282016-09-26 21:45:57 -0700253 self.assertEqual(choices(data, k=0), []) # k == 0
254 self.assertEqual(choices(data, k=-1), []) # negative k behaves like ``[0] * -1``
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700255 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700256 choices(data, k=2.5) # k is a float
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700257
Raymond Hettinger9016f282016-09-26 21:45:57 -0700258 self.assertTrue(set(choices(str_data, k=5)) <= set(str_data)) # population is a string sequence
259 self.assertTrue(set(choices(range_data, k=5)) <= set(range_data)) # population is a range
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700260 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700261 choices(set_data, k=2) # population is not a sequence
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700262
Raymond Hettinger9016f282016-09-26 21:45:57 -0700263 self.assertTrue(set(choices(data, None, k=5)) <= set(data)) # weights is None
264 self.assertTrue(set(choices(data, weights=None, k=5)) <= set(data))
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700265 with self.assertRaises(ValueError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700266 choices(data, [1,2], k=5) # len(weights) != len(population)
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700267 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700268 choices(data, 10, k=5) # non-iterable weights
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700269 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700270 choices(data, [None]*4, k=5) # non-numeric weights
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700271 for weights in [
272 [15, 10, 25, 30], # integer weights
273 [15.1, 10.2, 25.2, 30.3], # float weights
274 [Fraction(1, 3), Fraction(2, 6), Fraction(3, 6), Fraction(4, 6)], # fractional weights
275 [True, False, True, False] # booleans (include / exclude)
276 ]:
Raymond Hettinger9016f282016-09-26 21:45:57 -0700277 self.assertTrue(set(choices(data, weights, k=5)) <= set(data))
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700278
279 with self.assertRaises(ValueError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700280 choices(data, cum_weights=[1,2], k=5) # len(weights) != len(population)
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700281 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700282 choices(data, cum_weights=10, k=5) # non-iterable cum_weights
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700283 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700284 choices(data, cum_weights=[None]*4, k=5) # non-numeric cum_weights
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700285 with self.assertRaises(TypeError):
Raymond Hettinger9016f282016-09-26 21:45:57 -0700286 choices(data, range(4), cum_weights=range(4), k=5) # both weights and cum_weights
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700287 for weights in [
288 [15, 10, 25, 30], # integer cum_weights
289 [15.1, 10.2, 25.2, 30.3], # float cum_weights
290 [Fraction(1, 3), Fraction(2, 6), Fraction(3, 6), Fraction(4, 6)], # fractional cum_weights
291 ]:
Raymond Hettinger9016f282016-09-26 21:45:57 -0700292 self.assertTrue(set(choices(data, cum_weights=weights, k=5)) <= set(data))
Raymond Hettingere8f1e002016-09-06 17:15:29 -0700293
Raymond Hettinger7b166522016-10-14 01:19:38 -0400294 # Test weight focused on a single element of the population
295 self.assertEqual(choices('abcd', [1, 0, 0, 0]), ['a'])
296 self.assertEqual(choices('abcd', [0, 1, 0, 0]), ['b'])
297 self.assertEqual(choices('abcd', [0, 0, 1, 0]), ['c'])
298 self.assertEqual(choices('abcd', [0, 0, 0, 1]), ['d'])
299
300 # Test consistency with random.choice() for empty population
301 with self.assertRaises(IndexError):
302 choices([], k=1)
303 with self.assertRaises(IndexError):
304 choices([], weights=[], k=1)
305 with self.assertRaises(IndexError):
306 choices([], cum_weights=[], k=5)
307
Raymond Hettingerddf71712018-06-27 01:08:31 -0700308 def test_choices_subnormal(self):
Min ho Kim96e12d52019-07-22 06:12:33 +1000309 # Subnormal weights would occasionally trigger an IndexError
Raymond Hettingerddf71712018-06-27 01:08:31 -0700310 # in choices() when the value returned by random() was large
311 # enough to make `random() * total` round up to the total.
312 # See https://bugs.python.org/msg275594 for more detail.
313 choices = self.gen.choices
314 choices(population=[1, 2], weights=[1e-323, 1e-323], k=5000)
315
Raymond Hettinger041d8b42019-11-23 02:22:13 -0800316 def test_choices_with_all_zero_weights(self):
317 # See issue #38881
318 with self.assertRaises(ValueError):
319 self.gen.choices('AB', [0.0, 0.0])
320
Ram Rachumb0dfc752020-09-29 04:32:10 +0300321 def test_choices_negative_total(self):
322 with self.assertRaises(ValueError):
323 self.gen.choices('ABC', [3, -5, 1])
324
325 def test_choices_infinite_total(self):
326 with self.assertRaises(ValueError):
327 self.gen.choices('A', [float('inf')])
328 with self.assertRaises(ValueError):
329 self.gen.choices('AB', [0.0, float('inf')])
330 with self.assertRaises(ValueError):
331 self.gen.choices('AB', [-float('inf'), 123])
332 with self.assertRaises(ValueError):
333 self.gen.choices('AB', [0.0, float('nan')])
334 with self.assertRaises(ValueError):
335 self.gen.choices('AB', [float('-inf'), float('inf')])
336
Raymond Hettinger40f62172002-12-29 23:03:38 +0000337 def test_gauss(self):
338 # Ensure that the seed() method initializes all the hidden state. In
339 # particular, through 2.2.1 it failed to reset a piece of state used
340 # by (and only by) the .gauss() method.
341
342 for seed in 1, 12, 123, 1234, 12345, 123456, 654321:
343 self.gen.seed(seed)
344 x1 = self.gen.random()
345 y1 = self.gen.gauss(0, 1)
346
347 self.gen.seed(seed)
348 x2 = self.gen.random()
349 y2 = self.gen.gauss(0, 1)
350
351 self.assertEqual(x1, x2)
352 self.assertEqual(y1, y2)
353
Antoine Pitrou75a33782020-04-17 19:32:14 +0200354 def test_getrandbits(self):
355 # Verify ranges
356 for k in range(1, 1000):
357 self.assertTrue(0 <= self.gen.getrandbits(k) < 2**k)
358 self.assertEqual(self.gen.getrandbits(0), 0)
359
360 # Verify all bits active
361 getbits = self.gen.getrandbits
362 for span in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]:
363 all_bits = 2**span-1
364 cum = 0
365 cpl_cum = 0
366 for i in range(100):
367 v = getbits(span)
368 cum |= v
369 cpl_cum |= all_bits ^ v
370 self.assertEqual(cum, all_bits)
371 self.assertEqual(cpl_cum, all_bits)
372
373 # Verify argument checking
374 self.assertRaises(TypeError, self.gen.getrandbits)
375 self.assertRaises(TypeError, self.gen.getrandbits, 1, 2)
376 self.assertRaises(ValueError, self.gen.getrandbits, -1)
377 self.assertRaises(TypeError, self.gen.getrandbits, 10.1)
378
Raymond Hettinger5f078ff2003-06-24 20:29:04 +0000379 def test_pickling(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +0200380 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
381 state = pickle.dumps(self.gen, proto)
382 origseq = [self.gen.random() for i in range(10)]
383 newgen = pickle.loads(state)
384 restoredseq = [newgen.random() for i in range(10)]
385 self.assertEqual(origseq, restoredseq)
Raymond Hettinger40f62172002-12-29 23:03:38 +0000386
Dong-hee Na6989af02020-06-21 18:44:58 +0900387 @test.support.cpython_only
388 def test_bug_41052(self):
389 # _random.Random should not be allowed to serialization
390 import _random
391 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
392 r = _random.Random()
393 self.assertRaises(TypeError, pickle.dumps, r, proto)
394
AMIRb8fde8b2020-12-22 03:15:50 +0330395 @test.support.cpython_only
396 def test_bug_42008(self):
397 # _random.Random should call seed with first element of arg tuple
398 import _random
399 r1 = _random.Random()
400 r1.seed(8675309)
401 r2 = _random.Random(8675309)
402 self.assertEqual(r1.random(), r2.random())
403
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000404 def test_bug_1727780(self):
405 # verify that version-2-pickles can be loaded
406 # fine, whether they are created on 32-bit or 64-bit
407 # platforms, and that version-3-pickles load fine.
408 files = [("randv2_32.pck", 780),
409 ("randv2_64.pck", 866),
410 ("randv3.pck", 343)]
411 for file, value in files:
Serhiy Storchaka5b10b982019-03-05 10:06:26 +0200412 with open(support.findfile(file),"rb") as f:
413 r = pickle.load(f)
Raymond Hettinger05156612010-09-07 04:44:52 +0000414 self.assertEqual(int(r.random()*1000), value)
415
416 def test_bug_9025(self):
417 # Had problem with an uneven distribution in int(n*random())
418 # Verify the fix by checking that distributions fall within expectations.
419 n = 100000
420 randrange = self.gen.randrange
421 k = sum(randrange(6755399441055744) % 3 == 2 for i in range(n))
422 self.assertTrue(0.30 < k/n < .37, (k/n))
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000423
Victor Stinner9f5fe792020-04-17 19:05:35 +0200424 def test_randbytes(self):
425 # Verify ranges
426 for n in range(1, 10):
427 data = self.gen.randbytes(n)
428 self.assertEqual(type(data), bytes)
429 self.assertEqual(len(data), n)
430
431 self.assertEqual(self.gen.randbytes(0), b'')
432
433 # Verify argument checking
434 self.assertRaises(TypeError, self.gen.randbytes)
435 self.assertRaises(TypeError, self.gen.randbytes, 1, 2)
436 self.assertRaises(ValueError, self.gen.randbytes, -1)
437 self.assertRaises(TypeError, self.gen.randbytes, 1.0)
438
439
Ezio Melotti3e4a98b2013-04-19 05:45:27 +0300440try:
441 random.SystemRandom().random()
442except NotImplementedError:
443 SystemRandom_available = False
444else:
445 SystemRandom_available = True
446
447@unittest.skipUnless(SystemRandom_available, "random.SystemRandom not available")
448class SystemRandom_TestBasicOps(TestBasicOps, unittest.TestCase):
Raymond Hettinger23f12412004-09-13 22:23:21 +0000449 gen = random.SystemRandom()
Raymond Hettinger356a4592004-08-30 06:14:31 +0000450
451 def test_autoseed(self):
452 # Doesn't need to do anything except not fail
453 self.gen.seed()
454
455 def test_saverestore(self):
456 self.assertRaises(NotImplementedError, self.gen.getstate)
457 self.assertRaises(NotImplementedError, self.gen.setstate, None)
458
459 def test_seedargs(self):
460 # Doesn't need to do anything except not fail
461 self.gen.seed(100)
462
Raymond Hettinger356a4592004-08-30 06:14:31 +0000463 def test_gauss(self):
464 self.gen.gauss_next = None
465 self.gen.seed(100)
466 self.assertEqual(self.gen.gauss_next, None)
467
468 def test_pickling(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +0200469 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
470 self.assertRaises(NotImplementedError, pickle.dumps, self.gen, proto)
Raymond Hettinger356a4592004-08-30 06:14:31 +0000471
472 def test_53_bits_per_float(self):
473 # This should pass whenever a C double has 53 bit precision.
474 span = 2 ** 53
475 cum = 0
Guido van Rossum805365e2007-05-07 22:24:25 +0000476 for i in range(100):
Raymond Hettinger356a4592004-08-30 06:14:31 +0000477 cum |= int(self.gen.random() * span)
478 self.assertEqual(cum, span-1)
479
480 def test_bigrand(self):
481 # The randrange routine should build-up the required number of bits
482 # in stages so that all bit positions are active.
483 span = 2 ** 500
484 cum = 0
Guido van Rossum805365e2007-05-07 22:24:25 +0000485 for i in range(100):
Raymond Hettinger356a4592004-08-30 06:14:31 +0000486 r = self.gen.randrange(span)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000487 self.assertTrue(0 <= r < span)
Raymond Hettinger356a4592004-08-30 06:14:31 +0000488 cum |= r
489 self.assertEqual(cum, span-1)
490
491 def test_bigrand_ranges(self):
492 for i in [40,80, 160, 200, 211, 250, 375, 512, 550]:
Zachary Warea6edea52013-11-26 14:50:10 -0600493 start = self.gen.randrange(2 ** (i-2))
494 stop = self.gen.randrange(2 ** i)
Raymond Hettinger356a4592004-08-30 06:14:31 +0000495 if stop <= start:
Zachary Warea6edea52013-11-26 14:50:10 -0600496 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000497 self.assertTrue(start <= self.gen.randrange(start, stop) < stop)
Raymond Hettinger356a4592004-08-30 06:14:31 +0000498
499 def test_rangelimits(self):
500 for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
501 self.assertEqual(set(range(start,stop)),
Guido van Rossum805365e2007-05-07 22:24:25 +0000502 set([self.gen.randrange(start,stop) for i in range(100)]))
Raymond Hettinger356a4592004-08-30 06:14:31 +0000503
R David Murraye3e1c172013-04-02 12:47:23 -0400504 def test_randrange_nonunit_step(self):
505 rint = self.gen.randrange(0, 10, 2)
506 self.assertIn(rint, (0, 2, 4, 6, 8))
507 rint = self.gen.randrange(0, 2, 2)
508 self.assertEqual(rint, 0)
509
510 def test_randrange_errors(self):
511 raises = partial(self.assertRaises, ValueError, self.gen.randrange)
512 # Empty range
513 raises(3, 3)
514 raises(-721)
515 raises(0, 100, -12)
516 # Non-integer start/stop
Serhiy Storchakaf066bd92021-01-25 23:02:04 +0200517 self.assertWarns(DeprecationWarning, raises, 3.14159)
518 self.assertWarns(DeprecationWarning, self.gen.randrange, 3.0)
519 self.assertWarns(DeprecationWarning, self.gen.randrange, Fraction(3, 1))
520 self.assertWarns(DeprecationWarning, raises, '3')
521 self.assertWarns(DeprecationWarning, raises, 0, 2.71828)
522 self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 2.0)
523 self.assertWarns(DeprecationWarning, self.gen.randrange, 0, Fraction(2, 1))
524 self.assertWarns(DeprecationWarning, raises, 0, '2')
R David Murraye3e1c172013-04-02 12:47:23 -0400525 # Zero and non-integer step
526 raises(0, 42, 0)
Serhiy Storchakaf066bd92021-01-25 23:02:04 +0200527 self.assertWarns(DeprecationWarning, raises, 0, 42, 0.0)
528 self.assertWarns(DeprecationWarning, raises, 0, 0, 0.0)
529 self.assertWarns(DeprecationWarning, raises, 0, 42, 3.14159)
530 self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 3.0)
531 self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, Fraction(3, 1))
532 self.assertWarns(DeprecationWarning, raises, 0, 42, '3')
533 self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 1.0)
534 self.assertWarns(DeprecationWarning, raises, 0, 0, 1.0)
R David Murraye3e1c172013-04-02 12:47:23 -0400535
Raymond Hettingera9621bb2020-12-28 11:10:34 -0800536 def test_randrange_argument_handling(self):
537 randrange = self.gen.randrange
538 with self.assertWarns(DeprecationWarning):
539 randrange(10.0, 20, 2)
540 with self.assertWarns(DeprecationWarning):
541 randrange(10, 20.0, 2)
542 with self.assertWarns(DeprecationWarning):
543 randrange(10, 20, 1.0)
544 with self.assertWarns(DeprecationWarning):
545 randrange(10, 20, 2.0)
546 with self.assertWarns(DeprecationWarning):
547 with self.assertRaises(ValueError):
548 randrange(10.5)
549 with self.assertWarns(DeprecationWarning):
550 with self.assertRaises(ValueError):
551 randrange(10, 20.5)
552 with self.assertWarns(DeprecationWarning):
553 with self.assertRaises(ValueError):
554 randrange(10, 20, 1.5)
555
Raymond Hettinger768fa142021-01-02 10:24:51 -0800556 def test_randrange_step(self):
557 # bpo-42772: When stop is None, the step argument was being ignored.
558 randrange = self.gen.randrange
559 with self.assertRaises(TypeError):
560 randrange(1000, step=100)
561 with self.assertRaises(TypeError):
562 randrange(1000, None, step=100)
563
Raymond Hettinger356a4592004-08-30 06:14:31 +0000564 def test_randbelow_logic(self, _log=log, int=int):
565 # check bitcount transition points: 2**i and 2**(i+1)-1
566 # show that: k = int(1.001 + _log(n, 2))
567 # is equal to or one greater than the number of bits in n
Guido van Rossum805365e2007-05-07 22:24:25 +0000568 for i in range(1, 1000):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000569 n = 1 << i # check an exact power of two
Raymond Hettinger356a4592004-08-30 06:14:31 +0000570 numbits = i+1
571 k = int(1.00001 + _log(n, 2))
572 self.assertEqual(k, numbits)
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000573 self.assertEqual(n, 2**(k-1))
Raymond Hettinger356a4592004-08-30 06:14:31 +0000574
575 n += n - 1 # check 1 below the next power of two
576 k = int(1.00001 + _log(n, 2))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000577 self.assertIn(k, [numbits, numbits+1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000578 self.assertTrue(2**k > n > 2**(k-2))
Raymond Hettinger356a4592004-08-30 06:14:31 +0000579
580 n -= n >> 15 # check a little farther below the next power of two
581 k = int(1.00001 + _log(n, 2))
582 self.assertEqual(k, numbits) # note the stronger assertion
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000583 self.assertTrue(2**k > n > 2**(k-1)) # note the stronger assertion
Raymond Hettinger356a4592004-08-30 06:14:31 +0000584
585
Ezio Melotti3e4a98b2013-04-19 05:45:27 +0300586class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
Raymond Hettinger40f62172002-12-29 23:03:38 +0000587 gen = random.Random()
588
Raymond Hettingerf763a722010-09-07 00:38:15 +0000589 def test_guaranteed_stable(self):
590 # These sequences are guaranteed to stay the same across versions of python
591 self.gen.seed(3456147, version=1)
592 self.assertEqual([self.gen.random().hex() for i in range(4)],
593 ['0x1.ac362300d90d2p-1', '0x1.9d16f74365005p-1',
594 '0x1.1ebb4352e4c4dp-1', '0x1.1a7422abf9c11p-1'])
Raymond Hettingerf763a722010-09-07 00:38:15 +0000595 self.gen.seed("the quick brown fox", version=2)
596 self.assertEqual([self.gen.random().hex() for i in range(4)],
Raymond Hettinger3fcf0022010-12-08 01:13:53 +0000597 ['0x1.1239ddfb11b7cp-3', '0x1.b3cbb5c51b120p-4',
598 '0x1.8c4f55116b60fp-1', '0x1.63eb525174a27p-1'])
Raymond Hettingerf763a722010-09-07 00:38:15 +0000599
Raymond Hettingerc7bab7c2016-08-31 15:01:08 -0700600 def test_bug_27706(self):
601 # Verify that version 1 seeds are unaffected by hash randomization
602
603 self.gen.seed('nofar', version=1) # hash('nofar') == 5990528763808513177
604 self.assertEqual([self.gen.random().hex() for i in range(4)],
605 ['0x1.8645314505ad7p-1', '0x1.afb1f82e40a40p-5',
606 '0x1.2a59d2285e971p-1', '0x1.56977142a7880p-6'])
607
608 self.gen.seed('rachel', version=1) # hash('rachel') == -9091735575445484789
609 self.assertEqual([self.gen.random().hex() for i in range(4)],
610 ['0x1.0b294cc856fcdp-1', '0x1.2ad22d79e77b8p-3',
611 '0x1.3052b9c072678p-2', '0x1.578f332106574p-3'])
612
613 self.gen.seed('', version=1) # hash('') == 0
614 self.assertEqual([self.gen.random().hex() for i in range(4)],
615 ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1',
616 '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2'])
617
Oren Milmand780b2d2017-09-28 10:50:01 +0300618 def test_bug_31478(self):
619 # There shouldn't be an assertion failure in _random.Random.seed() in
620 # case the argument has a bad __abs__() method.
621 class BadInt(int):
622 def __abs__(self):
623 return None
624 try:
625 self.gen.seed(BadInt())
626 except TypeError:
627 pass
628
Raymond Hettinger132a7d72017-09-17 09:04:30 -0700629 def test_bug_31482(self):
630 # Verify that version 1 seeds are unaffected by hash randomization
631 # when the seeds are expressed as bytes rather than strings.
632 # The hash(b) values listed are the Python2.7 hash() values
633 # which were used for seeding.
634
635 self.gen.seed(b'nofar', version=1) # hash('nofar') == 5990528763808513177
636 self.assertEqual([self.gen.random().hex() for i in range(4)],
637 ['0x1.8645314505ad7p-1', '0x1.afb1f82e40a40p-5',
638 '0x1.2a59d2285e971p-1', '0x1.56977142a7880p-6'])
639
640 self.gen.seed(b'rachel', version=1) # hash('rachel') == -9091735575445484789
641 self.assertEqual([self.gen.random().hex() for i in range(4)],
642 ['0x1.0b294cc856fcdp-1', '0x1.2ad22d79e77b8p-3',
643 '0x1.3052b9c072678p-2', '0x1.578f332106574p-3'])
644
645 self.gen.seed(b'', version=1) # hash('') == 0
646 self.assertEqual([self.gen.random().hex() for i in range(4)],
647 ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1',
648 '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2'])
649
650 b = b'\x00\x20\x40\x60\x80\xA0\xC0\xE0\xF0'
651 self.gen.seed(b, version=1) # hash(b) == 5015594239749365497
652 self.assertEqual([self.gen.random().hex() for i in range(4)],
653 ['0x1.52c2fde444d23p-1', '0x1.875174f0daea4p-2',
654 '0x1.9e9b2c50e5cd2p-1', '0x1.fa57768bd321cp-2'])
655
Raymond Hettinger58335872004-07-09 14:26:18 +0000656 def test_setstate_first_arg(self):
657 self.assertRaises(ValueError, self.gen.setstate, (1, None, None))
658
659 def test_setstate_middle_arg(self):
bladebryan9616a822017-04-21 23:10:46 -0700660 start_state = self.gen.getstate()
Raymond Hettinger58335872004-07-09 14:26:18 +0000661 # Wrong type, s/b tuple
662 self.assertRaises(TypeError, self.gen.setstate, (2, None, None))
663 # Wrong length, s/b 625
664 self.assertRaises(ValueError, self.gen.setstate, (2, (1,2,3), None))
665 # Wrong type, s/b tuple of 625 ints
666 self.assertRaises(TypeError, self.gen.setstate, (2, ('a',)*625, None))
667 # Last element s/b an int also
668 self.assertRaises(TypeError, self.gen.setstate, (2, (0,)*624+('a',), None))
Serhiy Storchaka178f0b62015-07-24 09:02:53 +0300669 # Last element s/b between 0 and 624
670 with self.assertRaises((ValueError, OverflowError)):
671 self.gen.setstate((2, (1,)*624+(625,), None))
672 with self.assertRaises((ValueError, OverflowError)):
673 self.gen.setstate((2, (1,)*624+(-1,), None))
bladebryan9616a822017-04-21 23:10:46 -0700674 # Failed calls to setstate() should not have changed the state.
675 bits100 = self.gen.getrandbits(100)
676 self.gen.setstate(start_state)
677 self.assertEqual(self.gen.getrandbits(100), bits100)
Raymond Hettinger58335872004-07-09 14:26:18 +0000678
R David Murraye3e1c172013-04-02 12:47:23 -0400679 # Little trick to make "tuple(x % (2**32) for x in internalstate)"
680 # raise ValueError. I cannot think of a simple way to achieve this, so
681 # I am opting for using a generator as the middle argument of setstate
682 # which attempts to cast a NaN to integer.
683 state_values = self.gen.getstate()[1]
684 state_values = list(state_values)
685 state_values[-1] = float('nan')
686 state = (int(x) for x in state_values)
687 self.assertRaises(TypeError, self.gen.setstate, (2, state, None))
688
Raymond Hettinger40f62172002-12-29 23:03:38 +0000689 def test_referenceImplementation(self):
690 # Compare the python implementation with results from the original
691 # code. Create 2000 53-bit precision random floats. Compare only
692 # the last ten entries to show that the independent implementations
693 # are tracking. Here is the main() function needed to create the
694 # list of expected random numbers:
695 # void main(void){
696 # int i;
697 # unsigned long init[4]={61731, 24903, 614, 42143}, length=4;
698 # init_by_array(init, length);
699 # for (i=0; i<2000; i++) {
700 # printf("%.15f ", genrand_res53());
701 # if (i%5==4) printf("\n");
702 # }
703 # }
704 expected = [0.45839803073713259,
705 0.86057815201978782,
706 0.92848331726782152,
707 0.35932681119782461,
708 0.081823493762449573,
709 0.14332226470169329,
710 0.084297823823520024,
711 0.53814864671831453,
712 0.089215024911993401,
713 0.78486196105372907]
714
Guido van Rossume2a383d2007-01-15 16:59:06 +0000715 self.gen.seed(61731 + (24903<<32) + (614<<64) + (42143<<96))
Raymond Hettinger40f62172002-12-29 23:03:38 +0000716 actual = self.randomlist(2000)[-10:]
717 for a, e in zip(actual, expected):
718 self.assertAlmostEqual(a,e,places=14)
719
720 def test_strong_reference_implementation(self):
721 # Like test_referenceImplementation, but checks for exact bit-level
722 # equality. This should pass on any box where C double contains
723 # at least 53 bits of precision (the underlying algorithm suffers
724 # no rounding errors -- all results are exact).
725 from math import ldexp
726
Guido van Rossume2a383d2007-01-15 16:59:06 +0000727 expected = [0x0eab3258d2231f,
728 0x1b89db315277a5,
729 0x1db622a5518016,
730 0x0b7f9af0d575bf,
731 0x029e4c4db82240,
732 0x04961892f5d673,
733 0x02b291598e4589,
734 0x11388382c15694,
735 0x02dad977c9e1fe,
736 0x191d96d4d334c6]
737 self.gen.seed(61731 + (24903<<32) + (614<<64) + (42143<<96))
Raymond Hettinger40f62172002-12-29 23:03:38 +0000738 actual = self.randomlist(2000)[-10:]
739 for a, e in zip(actual, expected):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000740 self.assertEqual(int(ldexp(a, 53)), e)
Raymond Hettinger40f62172002-12-29 23:03:38 +0000741
742 def test_long_seed(self):
743 # This is most interesting to run in debug mode, just to make sure
744 # nothing blows up. Under the covers, a dynamically resized array
745 # is allocated, consuming space proportional to the number of bits
746 # in the seed. Unfortunately, that's a quadratic-time algorithm,
747 # so don't make this horribly big.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000748 seed = (1 << (10000 * 8)) - 1 # about 10K bytes
Raymond Hettinger40f62172002-12-29 23:03:38 +0000749 self.gen.seed(seed)
750
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000751 def test_53_bits_per_float(self):
752 # This should pass whenever a C double has 53 bit precision.
753 span = 2 ** 53
754 cum = 0
Guido van Rossum805365e2007-05-07 22:24:25 +0000755 for i in range(100):
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000756 cum |= int(self.gen.random() * span)
757 self.assertEqual(cum, span-1)
758
759 def test_bigrand(self):
760 # The randrange routine should build-up the required number of bits
761 # in stages so that all bit positions are active.
762 span = 2 ** 500
763 cum = 0
Guido van Rossum805365e2007-05-07 22:24:25 +0000764 for i in range(100):
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000765 r = self.gen.randrange(span)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000766 self.assertTrue(0 <= r < span)
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000767 cum |= r
768 self.assertEqual(cum, span-1)
769
770 def test_bigrand_ranges(self):
771 for i in [40,80, 160, 200, 211, 250, 375, 512, 550]:
Zachary Warea6edea52013-11-26 14:50:10 -0600772 start = self.gen.randrange(2 ** (i-2))
773 stop = self.gen.randrange(2 ** i)
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000774 if stop <= start:
Zachary Warea6edea52013-11-26 14:50:10 -0600775 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000776 self.assertTrue(start <= self.gen.randrange(start, stop) < stop)
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000777
778 def test_rangelimits(self):
779 for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
Raymond Hettingera690a992003-11-16 16:17:49 +0000780 self.assertEqual(set(range(start,stop)),
Guido van Rossum805365e2007-05-07 22:24:25 +0000781 set([self.gen.randrange(start,stop) for i in range(100)]))
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000782
Antoine Pitrou75a33782020-04-17 19:32:14 +0200783 def test_getrandbits(self):
784 super().test_getrandbits()
785
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000786 # Verify cross-platform repeatability
787 self.gen.seed(1234567)
788 self.assertEqual(self.gen.getrandbits(100),
Guido van Rossume2a383d2007-01-15 16:59:06 +0000789 97904845777343510404718956115)
Raymond Hettinger58335872004-07-09 14:26:18 +0000790
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200791 def test_randrange_uses_getrandbits(self):
792 # Verify use of getrandbits by randrange
793 # Use same seed as in the cross-platform repeatability test
Antoine Pitrou75a33782020-04-17 19:32:14 +0200794 # in test_getrandbits above.
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200795 self.gen.seed(1234567)
796 # If randrange uses getrandbits, it should pick getrandbits(100)
797 # when called with a 100-bits stop argument.
798 self.assertEqual(self.gen.randrange(2**99),
799 97904845777343510404718956115)
800
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000801 def test_randbelow_logic(self, _log=log, int=int):
802 # check bitcount transition points: 2**i and 2**(i+1)-1
803 # show that: k = int(1.001 + _log(n, 2))
804 # is equal to or one greater than the number of bits in n
Guido van Rossum805365e2007-05-07 22:24:25 +0000805 for i in range(1, 1000):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000806 n = 1 << i # check an exact power of two
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000807 numbits = i+1
808 k = int(1.00001 + _log(n, 2))
809 self.assertEqual(k, numbits)
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000810 self.assertEqual(n, 2**(k-1))
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000811
812 n += n - 1 # check 1 below the next power of two
813 k = int(1.00001 + _log(n, 2))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000814 self.assertIn(k, [numbits, numbits+1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000815 self.assertTrue(2**k > n > 2**(k-2))
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000816
817 n -= n >> 15 # check a little farther below the next power of two
818 k = int(1.00001 + _log(n, 2))
819 self.assertEqual(k, numbits) # note the stronger assertion
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000820 self.assertTrue(2**k > n > 2**(k-1)) # note the stronger assertion
Raymond Hettinger2f726e92003-10-05 09:09:15 +0000821
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200822 def test_randbelow_without_getrandbits(self):
R David Murraye3e1c172013-04-02 12:47:23 -0400823 # Random._randbelow() can only use random() when the built-in one
824 # has been overridden but no new getrandbits() method was supplied.
R David Murraye3e1c172013-04-02 12:47:23 -0400825 maxsize = 1<<random.BPF
826 with warnings.catch_warnings():
827 warnings.simplefilter("ignore", UserWarning)
828 # Population range too large (n >= maxsize)
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200829 self.gen._randbelow_without_getrandbits(
830 maxsize+1, maxsize=maxsize
831 )
832 self.gen._randbelow_without_getrandbits(5640, maxsize=maxsize)
Raymond Hettinger4168f1e2020-05-01 10:34:19 -0700833 # issue 33203: test that _randbelow returns zero on
Wolfgang Maier091e95e2018-04-05 17:19:44 +0200834 # n == 0 also in its getrandbits-independent branch.
Raymond Hettinger4168f1e2020-05-01 10:34:19 -0700835 x = self.gen._randbelow_without_getrandbits(0, maxsize=maxsize)
836 self.assertEqual(x, 0)
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200837
R David Murraye3e1c172013-04-02 12:47:23 -0400838 # This might be going too far to test a single line, but because of our
839 # noble aim of achieving 100% test coverage we need to write a case in
840 # which the following line in Random._randbelow() gets executed:
841 #
842 # rem = maxsize % n
843 # limit = (maxsize - rem) / maxsize
844 # r = random()
845 # while r >= limit:
846 # r = random() # <== *This line* <==<
847 #
848 # Therefore, to guarantee that the while loop is executed at least
849 # once, we need to mock random() so that it returns a number greater
850 # than 'limit' the first time it gets called.
851
852 n = 42
853 epsilon = 0.01
854 limit = (maxsize - (maxsize % n)) / maxsize
Wolfgang Maierba3a87a2018-04-17 17:16:17 +0200855 with unittest.mock.patch.object(random.Random, 'random') as random_mock:
856 random_mock.side_effect = [limit + epsilon, limit - epsilon]
857 self.gen._randbelow_without_getrandbits(n, maxsize=maxsize)
858 self.assertEqual(random_mock.call_count, 2)
R David Murraye3e1c172013-04-02 12:47:23 -0400859
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000860 def test_randrange_bug_1590891(self):
861 start = 1000000000000
862 stop = -100000000000000000000
863 step = -200
864 x = self.gen.randrange(start, stop, step)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000865 self.assertTrue(stop < x <= start)
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000866 self.assertEqual((x+stop)%step, 0)
867
Raymond Hettinger30d00e52016-10-29 16:55:36 -0700868 def test_choices_algorithms(self):
Raymond Hettinger24e42392016-11-13 00:42:56 -0500869 # The various ways of specifying weights should produce the same results
Raymond Hettinger30d00e52016-10-29 16:55:36 -0700870 choices = self.gen.choices
Raymond Hettinger6023d332016-11-21 15:32:08 -0800871 n = 104729
Raymond Hettinger30d00e52016-10-29 16:55:36 -0700872
873 self.gen.seed(8675309)
874 a = self.gen.choices(range(n), k=10000)
875
876 self.gen.seed(8675309)
877 b = self.gen.choices(range(n), [1]*n, k=10000)
878 self.assertEqual(a, b)
879
880 self.gen.seed(8675309)
881 c = self.gen.choices(range(n), cum_weights=range(1, n+1), k=10000)
882 self.assertEqual(a, c)
883
penguindustin96466302019-05-06 14:57:17 -0400884 # American Roulette
Raymond Hettinger77d574d2016-10-29 17:42:36 -0700885 population = ['Red', 'Black', 'Green']
886 weights = [18, 18, 2]
887 cum_weights = [18, 36, 38]
888 expanded_population = ['Red'] * 18 + ['Black'] * 18 + ['Green'] * 2
889
890 self.gen.seed(9035768)
891 a = self.gen.choices(expanded_population, k=10000)
892
893 self.gen.seed(9035768)
894 b = self.gen.choices(population, weights, k=10000)
895 self.assertEqual(a, b)
896
897 self.gen.seed(9035768)
898 c = self.gen.choices(population, cum_weights=cum_weights, k=10000)
899 self.assertEqual(a, c)
900
Victor Stinner9f5fe792020-04-17 19:05:35 +0200901 def test_randbytes(self):
902 super().test_randbytes()
903
904 # Mersenne Twister randbytes() is deterministic
905 # and does not depend on the endian and bitness.
906 seed = 8675309
Serhiy Storchaka223221b2020-04-17 23:51:28 +0300907 expected = b'3\xa8\xf9f\xf4\xa4\xd06\x19\x8f\x9f\x82\x02oe\xf0'
Victor Stinner9f5fe792020-04-17 19:05:35 +0200908
909 self.gen.seed(seed)
910 self.assertEqual(self.gen.randbytes(16), expected)
911
912 # randbytes(0) must not consume any entropy
913 self.gen.seed(seed)
914 self.assertEqual(self.gen.randbytes(0), b'')
915 self.assertEqual(self.gen.randbytes(16), expected)
916
917 # Four randbytes(4) calls give the same output than randbytes(16)
918 self.gen.seed(seed)
919 self.assertEqual(b''.join([self.gen.randbytes(4) for _ in range(4)]),
920 expected)
921
Serhiy Storchaka223221b2020-04-17 23:51:28 +0300922 # Each randbytes(1), randbytes(2) or randbytes(3) call consumes
923 # 4 bytes of entropy
Victor Stinner9f5fe792020-04-17 19:05:35 +0200924 self.gen.seed(seed)
Serhiy Storchaka223221b2020-04-17 23:51:28 +0300925 expected1 = expected[3::4]
926 self.assertEqual(b''.join(self.gen.randbytes(1) for _ in range(4)),
927 expected1)
928
929 self.gen.seed(seed)
930 expected2 = b''.join(expected[i + 2: i + 4]
Victor Stinner9f5fe792020-04-17 19:05:35 +0200931 for i in range(0, len(expected), 4))
932 self.assertEqual(b''.join(self.gen.randbytes(2) for _ in range(4)),
933 expected2)
934
935 self.gen.seed(seed)
Serhiy Storchaka223221b2020-04-17 23:51:28 +0300936 expected3 = b''.join(expected[i + 1: i + 4]
Victor Stinner9f5fe792020-04-17 19:05:35 +0200937 for i in range(0, len(expected), 4))
938 self.assertEqual(b''.join(self.gen.randbytes(3) for _ in range(4)),
939 expected3)
940
Serhiy Storchaka223221b2020-04-17 23:51:28 +0300941 def test_randbytes_getrandbits(self):
942 # There is a simple relation between randbytes() and getrandbits()
943 seed = 2849427419
944 gen2 = random.Random()
945 self.gen.seed(seed)
946 gen2.seed(seed)
947 for n in range(9):
948 self.assertEqual(self.gen.randbytes(n),
949 gen2.getrandbits(n * 8).to_bytes(n, 'little'))
950
jonanifrancof7b5bacd2021-01-18 19:04:29 +0100951 def test_sample_counts_equivalence(self):
952 # Test the documented strong equivalence to a sample with repeated elements.
953 # We run this test on random.Random() which makes deterministic selections
954 # for a given seed value.
955 sample = self.gen.sample
956 seed = self.gen.seed
957
958 colors = ['red', 'green', 'blue', 'orange', 'black', 'amber']
959 counts = [500, 200, 20, 10, 5, 1 ]
960 k = 700
961 seed(8675309)
962 s1 = sample(colors, counts=counts, k=k)
963 seed(8675309)
964 expanded = [color for (color, count) in zip(colors, counts) for i in range(count)]
965 self.assertEqual(len(expanded), sum(counts))
966 s2 = sample(expanded, k=k)
967 self.assertEqual(s1, s2)
968
969 pop = 'abcdefghi'
970 counts = [10, 9, 8, 7, 6, 5, 4, 3, 2]
971 seed(8675309)
972 s1 = ''.join(sample(pop, counts=counts, k=30))
973 expanded = ''.join([letter for (letter, count) in zip(pop, counts) for i in range(count)])
974 seed(8675309)
975 s2 = ''.join(sample(expanded, k=30))
976 self.assertEqual(s1, s2)
977
Victor Stinner9f5fe792020-04-17 19:05:35 +0200978
Raymond Hettinger2d0c2562009-02-19 09:53:18 +0000979def gamma(z, sqrt2pi=(2.0*pi)**0.5):
980 # Reflection to right half of complex plane
981 if z < 0.5:
982 return pi / sin(pi*z) / gamma(1.0-z)
983 # Lanczos approximation with g=7
984 az = z + (7.0 - 0.5)
985 return az ** (z-0.5) / exp(az) * sqrt2pi * fsum([
986 0.9999999999995183,
987 676.5203681218835 / z,
988 -1259.139216722289 / (z+1.0),
989 771.3234287757674 / (z+2.0),
990 -176.6150291498386 / (z+3.0),
991 12.50734324009056 / (z+4.0),
992 -0.1385710331296526 / (z+5.0),
993 0.9934937113930748e-05 / (z+6.0),
994 0.1659470187408462e-06 / (z+7.0),
995 ])
Raymond Hettinger3dd990c2003-01-05 09:20:06 +0000996
Raymond Hettinger15ec3732003-01-05 01:08:34 +0000997class TestDistributions(unittest.TestCase):
998 def test_zeroinputs(self):
999 # Verify that distributions can handle a series of zero inputs'
1000 g = random.Random()
Guido van Rossum805365e2007-05-07 22:24:25 +00001001 x = [g.random() for i in range(50)] + [0.0]*5
Raymond Hettinger15ec3732003-01-05 01:08:34 +00001002 g.random = x[:].pop; g.uniform(1,10)
1003 g.random = x[:].pop; g.paretovariate(1.0)
1004 g.random = x[:].pop; g.expovariate(1.0)
1005 g.random = x[:].pop; g.weibullvariate(1.0, 1.0)
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001006 g.random = x[:].pop; g.vonmisesvariate(1.0, 1.0)
Raymond Hettinger15ec3732003-01-05 01:08:34 +00001007 g.random = x[:].pop; g.normalvariate(0.0, 1.0)
1008 g.random = x[:].pop; g.gauss(0.0, 1.0)
1009 g.random = x[:].pop; g.lognormvariate(0.0, 1.0)
1010 g.random = x[:].pop; g.vonmisesvariate(0.0, 1.0)
1011 g.random = x[:].pop; g.gammavariate(0.01, 1.0)
1012 g.random = x[:].pop; g.gammavariate(1.0, 1.0)
1013 g.random = x[:].pop; g.gammavariate(200.0, 1.0)
1014 g.random = x[:].pop; g.betavariate(3.0, 3.0)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001015 g.random = x[:].pop; g.triangular(0.0, 1.0, 1.0/3.0)
Raymond Hettinger15ec3732003-01-05 01:08:34 +00001016
Raymond Hettinger3dd990c2003-01-05 09:20:06 +00001017 def test_avg_std(self):
1018 # Use integration to test distribution average and standard deviation.
1019 # Only works for distributions which do not consume variates in pairs
1020 g = random.Random()
1021 N = 5000
Guido van Rossum805365e2007-05-07 22:24:25 +00001022 x = [i/float(N) for i in range(1,N)]
Raymond Hettinger3dd990c2003-01-05 09:20:06 +00001023 for variate, args, mu, sigmasqrd in [
1024 (g.uniform, (1.0,10.0), (10.0+1.0)/2, (10.0-1.0)**2/12),
Christian Heimesfe337bf2008-03-23 21:54:12 +00001025 (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 +00001026 (g.expovariate, (1.5,), 1/1.5, 1/1.5**2),
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001027 (g.vonmisesvariate, (1.23, 0), pi, pi**2/3),
Raymond Hettinger3dd990c2003-01-05 09:20:06 +00001028 (g.paretovariate, (5.0,), 5.0/(5.0-1),
1029 5.0/((5.0-1)**2*(5.0-2))),
1030 (g.weibullvariate, (1.0, 3.0), gamma(1+1/3.0),
1031 gamma(1+2/3.0)-gamma(1+1/3.0)**2) ]:
1032 g.random = x[:].pop
1033 y = []
Guido van Rossum805365e2007-05-07 22:24:25 +00001034 for i in range(len(x)):
Raymond Hettinger3dd990c2003-01-05 09:20:06 +00001035 try:
1036 y.append(variate(*args))
1037 except IndexError:
1038 pass
1039 s1 = s2 = 0
1040 for e in y:
1041 s1 += e
1042 s2 += (e - mu) ** 2
1043 N = len(y)
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001044 self.assertAlmostEqual(s1/N, mu, places=2,
1045 msg='%s%r' % (variate.__name__, args))
1046 self.assertAlmostEqual(s2/(N-1), sigmasqrd, places=2,
1047 msg='%s%r' % (variate.__name__, args))
1048
1049 def test_constant(self):
1050 g = random.Random()
1051 N = 100
1052 for variate, args, expected in [
1053 (g.uniform, (10.0, 10.0), 10.0),
1054 (g.triangular, (10.0, 10.0), 10.0),
Raymond Hettinger978c6ab2014-05-25 17:25:27 -07001055 (g.triangular, (10.0, 10.0, 10.0), 10.0),
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001056 (g.expovariate, (float('inf'),), 0.0),
1057 (g.vonmisesvariate, (3.0, float('inf')), 3.0),
1058 (g.gauss, (10.0, 0.0), 10.0),
1059 (g.lognormvariate, (0.0, 0.0), 1.0),
1060 (g.lognormvariate, (-float('inf'), 0.0), 0.0),
1061 (g.normalvariate, (10.0, 0.0), 10.0),
1062 (g.paretovariate, (float('inf'),), 1.0),
1063 (g.weibullvariate, (10.0, float('inf')), 10.0),
1064 (g.weibullvariate, (0.0, 10.0), 0.0),
1065 ]:
1066 for i in range(N):
1067 self.assertEqual(variate(*args), expected)
Raymond Hettinger3dd990c2003-01-05 09:20:06 +00001068
Mark Dickinsonbe5f9192013-02-10 14:16:10 +00001069 def test_von_mises_range(self):
1070 # Issue 17149: von mises variates were not consistently in the
1071 # range [0, 2*PI].
1072 g = random.Random()
1073 N = 100
1074 for mu in 0.0, 0.1, 3.1, 6.2:
1075 for kappa in 0.0, 2.3, 500.0:
1076 for _ in range(N):
1077 sample = g.vonmisesvariate(mu, kappa)
1078 self.assertTrue(
1079 0 <= sample <= random.TWOPI,
1080 msg=("vonmisesvariate({}, {}) produced a result {} out"
1081 " of range [0, 2*pi]").format(mu, kappa, sample))
1082
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001083 def test_von_mises_large_kappa(self):
1084 # Issue #17141: vonmisesvariate() was hang for large kappas
1085 random.vonmisesvariate(0, 1e15)
1086 random.vonmisesvariate(0, 1e100)
1087
R David Murraye3e1c172013-04-02 12:47:23 -04001088 def test_gammavariate_errors(self):
1089 # Both alpha and beta must be > 0.0
1090 self.assertRaises(ValueError, random.gammavariate, -1, 3)
1091 self.assertRaises(ValueError, random.gammavariate, 0, 2)
1092 self.assertRaises(ValueError, random.gammavariate, 2, 0)
1093 self.assertRaises(ValueError, random.gammavariate, 1, -3)
1094
leodema63d15222018-12-24 07:54:25 +01001095 # There are three different possibilities in the current implementation
1096 # of random.gammavariate(), depending on the value of 'alpha'. What we
1097 # are going to do here is to fix the values returned by random() to
1098 # generate test cases that provide 100% line coverage of the method.
R David Murraye3e1c172013-04-02 12:47:23 -04001099 @unittest.mock.patch('random.Random.random')
leodema63d15222018-12-24 07:54:25 +01001100 def test_gammavariate_alpha_greater_one(self, random_mock):
R David Murraye3e1c172013-04-02 12:47:23 -04001101
leodema63d15222018-12-24 07:54:25 +01001102 # #1: alpha > 1.0.
1103 # We want the first random number to be outside the
R David Murraye3e1c172013-04-02 12:47:23 -04001104 # [1e-7, .9999999] range, so that the continue statement executes
1105 # once. The values of u1 and u2 will be 0.5 and 0.3, respectively.
1106 random_mock.side_effect = [1e-8, 0.5, 0.3]
1107 returned_value = random.gammavariate(1.1, 2.3)
1108 self.assertAlmostEqual(returned_value, 2.53)
1109
leodema63d15222018-12-24 07:54:25 +01001110 @unittest.mock.patch('random.Random.random')
1111 def test_gammavariate_alpha_equal_one(self, random_mock):
R David Murraye3e1c172013-04-02 12:47:23 -04001112
leodema63d15222018-12-24 07:54:25 +01001113 # #2.a: alpha == 1.
1114 # The execution body of the while loop executes once.
1115 # Then random.random() returns 0.45,
1116 # which causes while to stop looping and the algorithm to terminate.
1117 random_mock.side_effect = [0.45]
1118 returned_value = random.gammavariate(1.0, 3.14)
1119 self.assertAlmostEqual(returned_value, 1.877208182372648)
1120
1121 @unittest.mock.patch('random.Random.random')
1122 def test_gammavariate_alpha_equal_one_equals_expovariate(self, random_mock):
1123
1124 # #2.b: alpha == 1.
1125 # It must be equivalent of calling expovariate(1.0 / beta).
1126 beta = 3.14
1127 random_mock.side_effect = [1e-8, 1e-8]
1128 gammavariate_returned_value = random.gammavariate(1.0, beta)
1129 expovariate_returned_value = random.expovariate(1.0 / beta)
1130 self.assertAlmostEqual(gammavariate_returned_value, expovariate_returned_value)
1131
1132 @unittest.mock.patch('random.Random.random')
1133 def test_gammavariate_alpha_between_zero_and_one(self, random_mock):
1134
1135 # #3: 0 < alpha < 1.
1136 # This is the most complex region of code to cover,
R David Murraye3e1c172013-04-02 12:47:23 -04001137 # as there are multiple if-else statements. Let's take a look at the
1138 # source code, and determine the values that we need accordingly:
1139 #
1140 # while 1:
1141 # u = random()
1142 # b = (_e + alpha)/_e
1143 # p = b*u
1144 # if p <= 1.0: # <=== (A)
1145 # x = p ** (1.0/alpha)
1146 # else: # <=== (B)
1147 # x = -_log((b-p)/alpha)
1148 # u1 = random()
1149 # if p > 1.0: # <=== (C)
1150 # if u1 <= x ** (alpha - 1.0): # <=== (D)
1151 # break
1152 # elif u1 <= _exp(-x): # <=== (E)
1153 # break
1154 # return x * beta
1155 #
1156 # First, we want (A) to be True. For that we need that:
1157 # b*random() <= 1.0
1158 # r1 = random() <= 1.0 / b
1159 #
1160 # We now get to the second if-else branch, and here, since p <= 1.0,
1161 # (C) is False and we take the elif branch, (E). For it to be True,
1162 # so that the break is executed, we need that:
1163 # r2 = random() <= _exp(-x)
1164 # r2 <= _exp(-(p ** (1.0/alpha)))
1165 # r2 <= _exp(-((b*r1) ** (1.0/alpha)))
1166
1167 _e = random._e
1168 _exp = random._exp
1169 _log = random._log
1170 alpha = 0.35
1171 beta = 1.45
1172 b = (_e + alpha)/_e
1173 epsilon = 0.01
1174
1175 r1 = 0.8859296441566 # 1.0 / b
1176 r2 = 0.3678794411714 # _exp(-((b*r1) ** (1.0/alpha)))
1177
1178 # These four "random" values result in the following trace:
1179 # (A) True, (E) False --> [next iteration of while]
1180 # (A) True, (E) True --> [while loop breaks]
1181 random_mock.side_effect = [r1, r2 + epsilon, r1, r2]
1182 returned_value = random.gammavariate(alpha, beta)
1183 self.assertAlmostEqual(returned_value, 1.4499999999997544)
1184
1185 # Let's now make (A) be False. If this is the case, when we get to the
1186 # second if-else 'p' is greater than 1, so (C) evaluates to True. We
1187 # now encounter a second if statement, (D), which in order to execute
1188 # must satisfy the following condition:
1189 # r2 <= x ** (alpha - 1.0)
1190 # r2 <= (-_log((b-p)/alpha)) ** (alpha - 1.0)
1191 # r2 <= (-_log((b-(b*r1))/alpha)) ** (alpha - 1.0)
1192 r1 = 0.8959296441566 # (1.0 / b) + epsilon -- so that (A) is False
1193 r2 = 0.9445400408898141
1194
1195 # And these four values result in the following trace:
1196 # (B) and (C) True, (D) False --> [next iteration of while]
1197 # (B) and (C) True, (D) True [while loop breaks]
1198 random_mock.side_effect = [r1, r2 + epsilon, r1, r2]
1199 returned_value = random.gammavariate(alpha, beta)
1200 self.assertAlmostEqual(returned_value, 1.5830349561760781)
1201
1202 @unittest.mock.patch('random.Random.gammavariate')
1203 def test_betavariate_return_zero(self, gammavariate_mock):
1204 # betavariate() returns zero when the Gamma distribution
1205 # that it uses internally returns this same value.
1206 gammavariate_mock.return_value = 0.0
1207 self.assertEqual(0.0, random.betavariate(2.71828, 3.14159))
Serhiy Storchaka6c22b1d2013-02-10 19:28:56 +02001208
Serhiy Storchakaec1622d2018-05-08 15:45:15 +03001209
Wolfgang Maierba3a87a2018-04-17 17:16:17 +02001210class TestRandomSubclassing(unittest.TestCase):
1211 def test_random_subclass_with_kwargs(self):
1212 # SF bug #1486663 -- this used to erroneously raise a TypeError
1213 class Subclass(random.Random):
1214 def __init__(self, newarg=None):
1215 random.Random.__init__(self)
1216 Subclass(newarg=1)
1217
1218 def test_subclasses_overriding_methods(self):
1219 # Subclasses with an overridden random, but only the original
1220 # getrandbits method should not rely on getrandbits in for randrange,
1221 # but should use a getrandbits-independent implementation instead.
1222
1223 # subclass providing its own random **and** getrandbits methods
1224 # like random.SystemRandom does => keep relying on getrandbits for
1225 # randrange
1226 class SubClass1(random.Random):
1227 def random(self):
Serhiy Storchakaec1622d2018-05-08 15:45:15 +03001228 called.add('SubClass1.random')
1229 return random.Random.random(self)
Wolfgang Maierba3a87a2018-04-17 17:16:17 +02001230
1231 def getrandbits(self, n):
Serhiy Storchakaec1622d2018-05-08 15:45:15 +03001232 called.add('SubClass1.getrandbits')
1233 return random.Random.getrandbits(self, n)
1234 called = set()
1235 SubClass1().randrange(42)
1236 self.assertEqual(called, {'SubClass1.getrandbits'})
Wolfgang Maierba3a87a2018-04-17 17:16:17 +02001237
1238 # subclass providing only random => can only use random for randrange
1239 class SubClass2(random.Random):
1240 def random(self):
Serhiy Storchakaec1622d2018-05-08 15:45:15 +03001241 called.add('SubClass2.random')
1242 return random.Random.random(self)
1243 called = set()
1244 SubClass2().randrange(42)
1245 self.assertEqual(called, {'SubClass2.random'})
Wolfgang Maierba3a87a2018-04-17 17:16:17 +02001246
1247 # subclass defining getrandbits to complement its inherited random
1248 # => can now rely on getrandbits for randrange again
1249 class SubClass3(SubClass2):
1250 def getrandbits(self, n):
Serhiy Storchakaec1622d2018-05-08 15:45:15 +03001251 called.add('SubClass3.getrandbits')
1252 return random.Random.getrandbits(self, n)
1253 called = set()
1254 SubClass3().randrange(42)
1255 self.assertEqual(called, {'SubClass3.getrandbits'})
1256
1257 # subclass providing only random and inherited getrandbits
1258 # => random takes precedence
1259 class SubClass4(SubClass3):
1260 def random(self):
1261 called.add('SubClass4.random')
1262 return random.Random.random(self)
1263 called = set()
1264 SubClass4().randrange(42)
1265 self.assertEqual(called, {'SubClass4.random'})
1266
1267 # Following subclasses don't define random or getrandbits directly,
1268 # but inherit them from classes which are not subclasses of Random
1269 class Mixin1:
1270 def random(self):
1271 called.add('Mixin1.random')
1272 return random.Random.random(self)
1273 class Mixin2:
1274 def getrandbits(self, n):
1275 called.add('Mixin2.getrandbits')
1276 return random.Random.getrandbits(self, n)
1277
1278 class SubClass5(Mixin1, random.Random):
1279 pass
1280 called = set()
1281 SubClass5().randrange(42)
1282 self.assertEqual(called, {'Mixin1.random'})
1283
1284 class SubClass6(Mixin2, random.Random):
1285 pass
1286 called = set()
1287 SubClass6().randrange(42)
1288 self.assertEqual(called, {'Mixin2.getrandbits'})
1289
1290 class SubClass7(Mixin1, Mixin2, random.Random):
1291 pass
1292 called = set()
1293 SubClass7().randrange(42)
1294 self.assertEqual(called, {'Mixin1.random'})
1295
1296 class SubClass8(Mixin2, Mixin1, random.Random):
1297 pass
1298 called = set()
1299 SubClass8().randrange(42)
1300 self.assertEqual(called, {'Mixin2.getrandbits'})
1301
Wolfgang Maierba3a87a2018-04-17 17:16:17 +02001302
Raymond Hettinger40f62172002-12-29 23:03:38 +00001303class TestModule(unittest.TestCase):
1304 def testMagicConstants(self):
1305 self.assertAlmostEqual(random.NV_MAGICCONST, 1.71552776992141)
1306 self.assertAlmostEqual(random.TWOPI, 6.28318530718)
1307 self.assertAlmostEqual(random.LOG4, 1.38629436111989)
1308 self.assertAlmostEqual(random.SG_MAGICCONST, 2.50407739677627)
1309
1310 def test__all__(self):
1311 # tests validity but not completeness of the __all__ list
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001312 self.assertTrue(set(random.__all__) <= set(dir(random)))
Raymond Hettinger40f62172002-12-29 23:03:38 +00001313
Antoine Pitrou346cbd32017-05-27 17:50:54 +02001314 @unittest.skipUnless(hasattr(os, "fork"), "fork() required")
1315 def test_after_fork(self):
1316 # Test the global Random instance gets reseeded in child
1317 r, w = os.pipe()
Victor Stinnerda5e9302017-08-09 17:59:05 +02001318 pid = os.fork()
1319 if pid == 0:
1320 # child process
Antoine Pitrou346cbd32017-05-27 17:50:54 +02001321 try:
1322 val = random.getrandbits(128)
1323 with open(w, "w") as f:
1324 f.write(str(val))
1325 finally:
1326 os._exit(0)
1327 else:
Victor Stinnerda5e9302017-08-09 17:59:05 +02001328 # parent process
Antoine Pitrou346cbd32017-05-27 17:50:54 +02001329 os.close(w)
1330 val = random.getrandbits(128)
1331 with open(r, "r") as f:
1332 child_val = eval(f.read())
1333 self.assertNotEqual(val, child_val)
1334
Victor Stinner278c1e12020-03-31 20:08:12 +02001335 support.wait_process(pid, exitcode=0)
Victor Stinnerda5e9302017-08-09 17:59:05 +02001336
Thomas Woutersb2137042007-02-01 18:02:27 +00001337
Raymond Hettinger40f62172002-12-29 23:03:38 +00001338if __name__ == "__main__":
Ezio Melotti3e4a98b2013-04-19 05:45:27 +03001339 unittest.main()