1import unittest
2import unittest.mock
3import random
4import os
5import time
6import pickle
7import warnings
8from functools import partial
9from math import log, exp, pi, fsum, sin, factorial
10from test import support
11from fractions import Fraction
12
13
14class TestBasicOps:
15    # Superclass with tests common to all generators.
16    # Subclasses must arrange for self.gen to retrieve the Random instance
17    # to be tested.
18
19    def randomlist(self, n):
20        """Helper function to make a list of random numbers"""
21        return [self.gen.random() for i in range(n)]
22
23    def test_autoseed(self):
24        self.gen.seed()
25        state1 = self.gen.getstate()
26        time.sleep(0.1)
27        self.gen.seed()      # different seeds at different times
28        state2 = self.gen.getstate()
29        self.assertNotEqual(state1, state2)
30
31    def test_saverestore(self):
32        N = 1000
33        self.gen.seed()
34        state = self.gen.getstate()
35        randseq = self.randomlist(N)
36        self.gen.setstate(state)    # should regenerate the same sequence
37        self.assertEqual(randseq, self.randomlist(N))
38
39    def test_seedargs(self):
40        # Seed value with a negative hash.
41        class MySeed(object):
42            def __hash__(self):
43                return -1729
44        for arg in [None, 0, 0, 1, 1, -1, -1, 10**20, -(10**20),
45                    3.14, 1+2j, 'a', tuple('abc'), MySeed()]:
46            self.gen.seed(arg)
47        for arg in [list(range(3)), dict(one=1)]:
48            self.assertRaises(TypeError, self.gen.seed, arg)
49        self.assertRaises(TypeError, self.gen.seed, 1, 2, 3, 4)
50        self.assertRaises(TypeError, type(self.gen), [])
51
52    @unittest.mock.patch('random._urandom') # os.urandom
53    def test_seed_when_randomness_source_not_found(self, urandom_mock):
54        # Random.seed() uses time.time() when an operating system specific
55        # randomness source is not found. To test this on machines where it
56        # exists, run the above test, test_seedargs(), again after mocking
57        # os.urandom() so that it raises the exception expected when the
58        # randomness source is not available.
59        urandom_mock.side_effect = NotImplementedError
60        self.test_seedargs()
61
62    def test_shuffle(self):
63        shuffle = self.gen.shuffle
64        lst = []
65        shuffle(lst)
66        self.assertEqual(lst, [])
67        lst = [37]
68        shuffle(lst)
69        self.assertEqual(lst, [37])
70        seqs = [list(range(n)) for n in range(10)]
71        shuffled_seqs = [list(range(n)) for n in range(10)]
72        for shuffled_seq in shuffled_seqs:
73            shuffle(shuffled_seq)
74        for (seq, shuffled_seq) in zip(seqs, shuffled_seqs):
75            self.assertEqual(len(seq), len(shuffled_seq))
76            self.assertEqual(set(seq), set(shuffled_seq))
77        # The above tests all would pass if the shuffle was a
78        # no-op. The following non-deterministic test covers that.  It
79        # asserts that the shuffled sequence of 1000 distinct elements
80        # must be different from the original one. Although there is
81        # mathematically a non-zero probability that this could
82        # actually happen in a genuinely random shuffle, it is
83        # completely negligible, given that the number of possible
84        # permutations of 1000 objects is 1000! (factorial of 1000),
85        # which is considerably larger than the number of atoms in the
86        # universe...
87        lst = list(range(1000))
88        shuffled_lst = list(range(1000))
89        shuffle(shuffled_lst)
90        self.assertTrue(lst != shuffled_lst)
91        shuffle(lst)
92        self.assertTrue(lst != shuffled_lst)
93        self.assertRaises(TypeError, shuffle, (1, 2, 3))
94
95    def test_shuffle_random_argument(self):
96        # Test random argument to shuffle.
97        shuffle = self.gen.shuffle
98        mock_random = unittest.mock.Mock(return_value=0.5)
99        seq = bytearray(b'abcdefghijk')
100        shuffle(seq, mock_random)
101        mock_random.assert_called_with()
102
103    def test_choice(self):
104        choice = self.gen.choice
105        with self.assertRaises(IndexError):
106            choice([])
107        self.assertEqual(choice([50]), 50)
108        self.assertIn(choice([25, 75]), [25, 75])
109
110    def test_sample(self):
111        # For the entire allowable range of 0 <= k <= N, validate that
112        # the sample is of the correct length and contains only unique items
113        N = 100
114        population = range(N)
115        for k in range(N+1):
116            s = self.gen.sample(population, k)
117            self.assertEqual(len(s), k)
118            uniq = set(s)
119            self.assertEqual(len(uniq), k)
120            self.assertTrue(uniq <= set(population))
121        self.assertEqual(self.gen.sample([], 0), [])  # test edge case N==k==0
122        # Exception raised if size of sample exceeds that of population
123        self.assertRaises(ValueError, self.gen.sample, population, N+1)
124        self.assertRaises(ValueError, self.gen.sample, [], -1)
125
126    def test_sample_distribution(self):
127        # For the entire allowable range of 0 <= k <= N, validate that
128        # sample generates all possible permutations
129        n = 5
130        pop = range(n)
131        trials = 10000  # large num prevents false negatives without slowing normal case
132        for k in range(n):
133            expected = factorial(n) // factorial(n-k)
134            perms = {}
135            for i in range(trials):
136                perms[tuple(self.gen.sample(pop, k))] = None
137                if len(perms) == expected:
138                    break
139            else:
140                self.fail()
141
142    def test_sample_inputs(self):
143        # SF bug #801342 -- population can be any iterable defining __len__()
144        self.gen.sample(set(range(20)), 2)
145        self.gen.sample(range(20), 2)
146        self.gen.sample(range(20), 2)
147        self.gen.sample(str('abcdefghijklmnopqrst'), 2)
148        self.gen.sample(tuple('abcdefghijklmnopqrst'), 2)
149
150    def test_sample_on_dicts(self):
151        self.assertRaises(TypeError, self.gen.sample, dict.fromkeys('abcdef'), 2)
152
153    def test_choices(self):
154        choices = self.gen.choices
155        data = ['red', 'green', 'blue', 'yellow']
156        str_data = 'abcd'
157        range_data = range(4)
158        set_data = set(range(4))
159
160        # basic functionality
161        for sample in [
162            choices(data, k=5),
163            choices(data, range(4), k=5),
164            choices(k=5, population=data, weights=range(4)),
165            choices(k=5, population=data, cum_weights=range(4)),
166        ]:
167            self.assertEqual(len(sample), 5)
168            self.assertEqual(type(sample), list)
169            self.assertTrue(set(sample) <= set(data))
170
171        # test argument handling
172        with self.assertRaises(TypeError):                               # missing arguments
173            choices(2)
174
175        self.assertEqual(choices(data, k=0), [])                         # k == 0
176        self.assertEqual(choices(data, k=-1), [])                        # negative k behaves like ``[0] * -1``
177        with self.assertRaises(TypeError):
178            choices(data, k=2.5)                                         # k is a float
179
180        self.assertTrue(set(choices(str_data, k=5)) <= set(str_data))    # population is a string sequence
181        self.assertTrue(set(choices(range_data, k=5)) <= set(range_data))  # population is a range
182        with self.assertRaises(TypeError):
183            choices(set_data, k=2)                                       # population is not a sequence
184
185        self.assertTrue(set(choices(data, None, k=5)) <= set(data))      # weights is None
186        self.assertTrue(set(choices(data, weights=None, k=5)) <= set(data))
187        with self.assertRaises(ValueError):
188            choices(data, [1,2], k=5)                                    # len(weights) != len(population)
189        with self.assertRaises(TypeError):
190            choices(data, 10, k=5)                                       # non-iterable weights
191        with self.assertRaises(TypeError):
192            choices(data, [None]*4, k=5)                                 # non-numeric weights
193        for weights in [
194                [15, 10, 25, 30],                                                 # integer weights
195                [15.1, 10.2, 25.2, 30.3],                                         # float weights
196                [Fraction(1, 3), Fraction(2, 6), Fraction(3, 6), Fraction(4, 6)], # fractional weights
197                [True, False, True, False]                                        # booleans (include / exclude)
198        ]:
199            self.assertTrue(set(choices(data, weights, k=5)) <= set(data))
200
201        with self.assertRaises(ValueError):
202            choices(data, cum_weights=[1,2], k=5)                        # len(weights) != len(population)
203        with self.assertRaises(TypeError):
204            choices(data, cum_weights=10, k=5)                           # non-iterable cum_weights
205        with self.assertRaises(TypeError):
206            choices(data, cum_weights=[None]*4, k=5)                     # non-numeric cum_weights
207        with self.assertRaises(TypeError):
208            choices(data, range(4), cum_weights=range(4), k=5)           # both weights and cum_weights
209        for weights in [
210                [15, 10, 25, 30],                                                 # integer cum_weights
211                [15.1, 10.2, 25.2, 30.3],                                         # float cum_weights
212                [Fraction(1, 3), Fraction(2, 6), Fraction(3, 6), Fraction(4, 6)], # fractional cum_weights
213        ]:
214            self.assertTrue(set(choices(data, cum_weights=weights, k=5)) <= set(data))
215
216        # Test weight focused on a single element of the population
217        self.assertEqual(choices('abcd', [1, 0, 0, 0]), ['a'])
218        self.assertEqual(choices('abcd', [0, 1, 0, 0]), ['b'])
219        self.assertEqual(choices('abcd', [0, 0, 1, 0]), ['c'])
220        self.assertEqual(choices('abcd', [0, 0, 0, 1]), ['d'])
221
222        # Test consistency with random.choice() for empty population
223        with self.assertRaises(IndexError):
224            choices([], k=1)
225        with self.assertRaises(IndexError):
226            choices([], weights=[], k=1)
227        with self.assertRaises(IndexError):
228            choices([], cum_weights=[], k=5)
229
230    def test_choices_subnormal(self):
231        # Subnormal weights would occasionally trigger an IndexError
232        # in choices() when the value returned by random() was large
233        # enough to make `random() * total` round up to the total.
234        # See https://bugs.python.org/msg275594 for more detail.
235        choices = self.gen.choices
236        choices(population=[1, 2], weights=[1e-323, 1e-323], k=5000)
237
238    def test_gauss(self):
239        # Ensure that the seed() method initializes all the hidden state.  In
240        # particular, through 2.2.1 it failed to reset a piece of state used
241        # by (and only by) the .gauss() method.
242
243        for seed in 1, 12, 123, 1234, 12345, 123456, 654321:
244            self.gen.seed(seed)
245            x1 = self.gen.random()
246            y1 = self.gen.gauss(0, 1)
247
248            self.gen.seed(seed)
249            x2 = self.gen.random()
250            y2 = self.gen.gauss(0, 1)
251
252            self.assertEqual(x1, x2)
253            self.assertEqual(y1, y2)
254
255    def test_pickling(self):
256        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
257            state = pickle.dumps(self.gen, proto)
258            origseq = [self.gen.random() for i in range(10)]
259            newgen = pickle.loads(state)
260            restoredseq = [newgen.random() for i in range(10)]
261            self.assertEqual(origseq, restoredseq)
262
263    def test_bug_1727780(self):
264        # verify that version-2-pickles can be loaded
265        # fine, whether they are created on 32-bit or 64-bit
266        # platforms, and that version-3-pickles load fine.
267        files = [("randv2_32.pck", 780),
268                 ("randv2_64.pck", 866),
269                 ("randv3.pck", 343)]
270        for file, value in files:
271            with open(support.findfile(file),"rb") as f:
272                r = pickle.load(f)
273            self.assertEqual(int(r.random()*1000), value)
274
275    def test_bug_9025(self):
276        # Had problem with an uneven distribution in int(n*random())
277        # Verify the fix by checking that distributions fall within expectations.
278        n = 100000
279        randrange = self.gen.randrange
280        k = sum(randrange(6755399441055744) % 3 == 2 for i in range(n))
281        self.assertTrue(0.30 < k/n < .37, (k/n))
282
283try:
284    random.SystemRandom().random()
285except NotImplementedError:
286    SystemRandom_available = False
287else:
288    SystemRandom_available = True
289
290@unittest.skipUnless(SystemRandom_available, "random.SystemRandom not available")
291class SystemRandom_TestBasicOps(TestBasicOps, unittest.TestCase):
292    gen = random.SystemRandom()
293
294    def test_autoseed(self):
295        # Doesn't need to do anything except not fail
296        self.gen.seed()
297
298    def test_saverestore(self):
299        self.assertRaises(NotImplementedError, self.gen.getstate)
300        self.assertRaises(NotImplementedError, self.gen.setstate, None)
301
302    def test_seedargs(self):
303        # Doesn't need to do anything except not fail
304        self.gen.seed(100)
305
306    def test_gauss(self):
307        self.gen.gauss_next = None
308        self.gen.seed(100)
309        self.assertEqual(self.gen.gauss_next, None)
310
311    def test_pickling(self):
312        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
313            self.assertRaises(NotImplementedError, pickle.dumps, self.gen, proto)
314
315    def test_53_bits_per_float(self):
316        # This should pass whenever a C double has 53 bit precision.
317        span = 2 ** 53
318        cum = 0
319        for i in range(100):
320            cum |= int(self.gen.random() * span)
321        self.assertEqual(cum, span-1)
322
323    def test_bigrand(self):
324        # The randrange routine should build-up the required number of bits
325        # in stages so that all bit positions are active.
326        span = 2 ** 500
327        cum = 0
328        for i in range(100):
329            r = self.gen.randrange(span)
330            self.assertTrue(0 <= r < span)
331            cum |= r
332        self.assertEqual(cum, span-1)
333
334    def test_bigrand_ranges(self):
335        for i in [40,80, 160, 200, 211, 250, 375, 512, 550]:
336            start = self.gen.randrange(2 ** (i-2))
337            stop = self.gen.randrange(2 ** i)
338            if stop <= start:
339                continue
340            self.assertTrue(start <= self.gen.randrange(start, stop) < stop)
341
342    def test_rangelimits(self):
343        for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
344            self.assertEqual(set(range(start,stop)),
345                set([self.gen.randrange(start,stop) for i in range(100)]))
346
347    def test_randrange_nonunit_step(self):
348        rint = self.gen.randrange(0, 10, 2)
349        self.assertIn(rint, (0, 2, 4, 6, 8))
350        rint = self.gen.randrange(0, 2, 2)
351        self.assertEqual(rint, 0)
352
353    def test_randrange_errors(self):
354        raises = partial(self.assertRaises, ValueError, self.gen.randrange)
355        # Empty range
356        raises(3, 3)
357        raises(-721)
358        raises(0, 100, -12)
359        # Non-integer start/stop
360        raises(3.14159)
361        raises(0, 2.71828)
362        # Zero and non-integer step
363        raises(0, 42, 0)
364        raises(0, 42, 3.14159)
365
366    def test_genrandbits(self):
367        # Verify ranges
368        for k in range(1, 1000):
369            self.assertTrue(0 <= self.gen.getrandbits(k) < 2**k)
370
371        # Verify all bits active
372        getbits = self.gen.getrandbits
373        for span in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]:
374            cum = 0
375            for i in range(100):
376                cum |= getbits(span)
377            self.assertEqual(cum, 2**span-1)
378
379        # Verify argument checking
380        self.assertRaises(TypeError, self.gen.getrandbits)
381        self.assertRaises(TypeError, self.gen.getrandbits, 1, 2)
382        self.assertRaises(ValueError, self.gen.getrandbits, 0)
383        self.assertRaises(ValueError, self.gen.getrandbits, -1)
384        self.assertRaises(TypeError, self.gen.getrandbits, 10.1)
385
386    def test_randbelow_logic(self, _log=log, int=int):
387        # check bitcount transition points:  2**i and 2**(i+1)-1
388        # show that: k = int(1.001 + _log(n, 2))
389        # is equal to or one greater than the number of bits in n
390        for i in range(1, 1000):
391            n = 1 << i # check an exact power of two
392            numbits = i+1
393            k = int(1.00001 + _log(n, 2))
394            self.assertEqual(k, numbits)
395            self.assertEqual(n, 2**(k-1))
396
397            n += n - 1      # check 1 below the next power of two
398            k = int(1.00001 + _log(n, 2))
399            self.assertIn(k, [numbits, numbits+1])
400            self.assertTrue(2**k > n > 2**(k-2))
401
402            n -= n >> 15     # check a little farther below the next power of two
403            k = int(1.00001 + _log(n, 2))
404            self.assertEqual(k, numbits)        # note the stronger assertion
405            self.assertTrue(2**k > n > 2**(k-1))   # note the stronger assertion
406
407
408class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
409    gen = random.Random()
410
411    def test_guaranteed_stable(self):
412        # These sequences are guaranteed to stay the same across versions of python
413        self.gen.seed(3456147, version=1)
414        self.assertEqual([self.gen.random().hex() for i in range(4)],
415            ['0x1.ac362300d90d2p-1', '0x1.9d16f74365005p-1',
416             '0x1.1ebb4352e4c4dp-1', '0x1.1a7422abf9c11p-1'])
417        self.gen.seed("the quick brown fox", version=2)
418        self.assertEqual([self.gen.random().hex() for i in range(4)],
419            ['0x1.1239ddfb11b7cp-3', '0x1.b3cbb5c51b120p-4',
420             '0x1.8c4f55116b60fp-1', '0x1.63eb525174a27p-1'])
421
422    def test_bug_27706(self):
423        # Verify that version 1 seeds are unaffected by hash randomization
424
425        self.gen.seed('nofar', version=1)   # hash('nofar') == 5990528763808513177
426        self.assertEqual([self.gen.random().hex() for i in range(4)],
427            ['0x1.8645314505ad7p-1', '0x1.afb1f82e40a40p-5',
428             '0x1.2a59d2285e971p-1', '0x1.56977142a7880p-6'])
429
430        self.gen.seed('rachel', version=1)  # hash('rachel') == -9091735575445484789
431        self.assertEqual([self.gen.random().hex() for i in range(4)],
432            ['0x1.0b294cc856fcdp-1', '0x1.2ad22d79e77b8p-3',
433             '0x1.3052b9c072678p-2', '0x1.578f332106574p-3'])
434
435        self.gen.seed('', version=1)        # hash('') == 0
436        self.assertEqual([self.gen.random().hex() for i in range(4)],
437            ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1',
438             '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2'])
439
440    def test_bug_31478(self):
441        # There shouldn't be an assertion failure in _random.Random.seed() in
442        # case the argument has a bad __abs__() method.
443        class BadInt(int):
444            def __abs__(self):
445                return None
446        try:
447            self.gen.seed(BadInt())
448        except TypeError:
449            pass
450
451    def test_bug_31482(self):
452        # Verify that version 1 seeds are unaffected by hash randomization
453        # when the seeds are expressed as bytes rather than strings.
454        # The hash(b) values listed are the Python2.7 hash() values
455        # which were used for seeding.
456
457        self.gen.seed(b'nofar', version=1)   # hash('nofar') == 5990528763808513177
458        self.assertEqual([self.gen.random().hex() for i in range(4)],
459            ['0x1.8645314505ad7p-1', '0x1.afb1f82e40a40p-5',
460             '0x1.2a59d2285e971p-1', '0x1.56977142a7880p-6'])
461
462        self.gen.seed(b'rachel', version=1)  # hash('rachel') == -9091735575445484789
463        self.assertEqual([self.gen.random().hex() for i in range(4)],
464            ['0x1.0b294cc856fcdp-1', '0x1.2ad22d79e77b8p-3',
465             '0x1.3052b9c072678p-2', '0x1.578f332106574p-3'])
466
467        self.gen.seed(b'', version=1)        # hash('') == 0
468        self.assertEqual([self.gen.random().hex() for i in range(4)],
469            ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1',
470             '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2'])
471
472        b = b'\x00\x20\x40\x60\x80\xA0\xC0\xE0\xF0'
473        self.gen.seed(b, version=1)         # hash(b) == 5015594239749365497
474        self.assertEqual([self.gen.random().hex() for i in range(4)],
475            ['0x1.52c2fde444d23p-1', '0x1.875174f0daea4p-2',
476             '0x1.9e9b2c50e5cd2p-1', '0x1.fa57768bd321cp-2'])
477
478    def test_setstate_first_arg(self):
479        self.assertRaises(ValueError, self.gen.setstate, (1, None, None))
480
481    def test_setstate_middle_arg(self):
482        start_state = self.gen.getstate()
483        # Wrong type, s/b tuple
484        self.assertRaises(TypeError, self.gen.setstate, (2, None, None))
485        # Wrong length, s/b 625
486        self.assertRaises(ValueError, self.gen.setstate, (2, (1,2,3), None))
487        # Wrong type, s/b tuple of 625 ints
488        self.assertRaises(TypeError, self.gen.setstate, (2, ('a',)*625, None))
489        # Last element s/b an int also
490        self.assertRaises(TypeError, self.gen.setstate, (2, (0,)*624+('a',), None))
491        # Last element s/b between 0 and 624
492        with self.assertRaises((ValueError, OverflowError)):
493            self.gen.setstate((2, (1,)*624+(625,), None))
494        with self.assertRaises((ValueError, OverflowError)):
495            self.gen.setstate((2, (1,)*624+(-1,), None))
496        # Failed calls to setstate() should not have changed the state.
497        bits100 = self.gen.getrandbits(100)
498        self.gen.setstate(start_state)
499        self.assertEqual(self.gen.getrandbits(100), bits100)
500
501        # Little trick to make "tuple(x % (2**32) for x in internalstate)"
502        # raise ValueError. I cannot think of a simple way to achieve this, so
503        # I am opting for using a generator as the middle argument of setstate
504        # which attempts to cast a NaN to integer.
505        state_values = self.gen.getstate()[1]
506        state_values = list(state_values)
507        state_values[-1] = float('nan')
508        state = (int(x) for x in state_values)
509        self.assertRaises(TypeError, self.gen.setstate, (2, state, None))
510
511    def test_referenceImplementation(self):
512        # Compare the python implementation with results from the original
513        # code.  Create 2000 53-bit precision random floats.  Compare only
514        # the last ten entries to show that the independent implementations
515        # are tracking.  Here is the main() function needed to create the
516        # list of expected random numbers:
517        #    void main(void){
518        #         int i;
519        #         unsigned long init[4]={61731, 24903, 614, 42143}, length=4;
520        #         init_by_array(init, length);
521        #         for (i=0; i<2000; i++) {
522        #           printf("%.15f ", genrand_res53());
523        #           if (i%5==4) printf("\n");
524        #         }
525        #     }
526        expected = [0.45839803073713259,
527                    0.86057815201978782,
528                    0.92848331726782152,
529                    0.35932681119782461,
530                    0.081823493762449573,
531                    0.14332226470169329,
532                    0.084297823823520024,
533                    0.53814864671831453,
534                    0.089215024911993401,
535                    0.78486196105372907]
536
537        self.gen.seed(61731 + (24903<<32) + (614<<64) + (42143<<96))
538        actual = self.randomlist(2000)[-10:]
539        for a, e in zip(actual, expected):
540            self.assertAlmostEqual(a,e,places=14)
541
542    def test_strong_reference_implementation(self):
543        # Like test_referenceImplementation, but checks for exact bit-level
544        # equality.  This should pass on any box where C double contains
545        # at least 53 bits of precision (the underlying algorithm suffers
546        # no rounding errors -- all results are exact).
547        from math import ldexp
548
549        expected = [0x0eab3258d2231f,
550                    0x1b89db315277a5,
551                    0x1db622a5518016,
552                    0x0b7f9af0d575bf,
553                    0x029e4c4db82240,
554                    0x04961892f5d673,
555                    0x02b291598e4589,
556                    0x11388382c15694,
557                    0x02dad977c9e1fe,
558                    0x191d96d4d334c6]
559        self.gen.seed(61731 + (24903<<32) + (614<<64) + (42143<<96))
560        actual = self.randomlist(2000)[-10:]
561        for a, e in zip(actual, expected):
562            self.assertEqual(int(ldexp(a, 53)), e)
563
564    def test_long_seed(self):
565        # This is most interesting to run in debug mode, just to make sure
566        # nothing blows up.  Under the covers, a dynamically resized array
567        # is allocated, consuming space proportional to the number of bits
568        # in the seed.  Unfortunately, that's a quadratic-time algorithm,
569        # so don't make this horribly big.
570        seed = (1 << (10000 * 8)) - 1  # about 10K bytes
571        self.gen.seed(seed)
572
573    def test_53_bits_per_float(self):
574        # This should pass whenever a C double has 53 bit precision.
575        span = 2 ** 53
576        cum = 0
577        for i in range(100):
578            cum |= int(self.gen.random() * span)
579        self.assertEqual(cum, span-1)
580
581    def test_bigrand(self):
582        # The randrange routine should build-up the required number of bits
583        # in stages so that all bit positions are active.
584        span = 2 ** 500
585        cum = 0
586        for i in range(100):
587            r = self.gen.randrange(span)
588            self.assertTrue(0 <= r < span)
589            cum |= r
590        self.assertEqual(cum, span-1)
591
592    def test_bigrand_ranges(self):
593        for i in [40,80, 160, 200, 211, 250, 375, 512, 550]:
594            start = self.gen.randrange(2 ** (i-2))
595            stop = self.gen.randrange(2 ** i)
596            if stop <= start:
597                continue
598            self.assertTrue(start <= self.gen.randrange(start, stop) < stop)
599
600    def test_rangelimits(self):
601        for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
602            self.assertEqual(set(range(start,stop)),
603                set([self.gen.randrange(start,stop) for i in range(100)]))
604
605    def test_genrandbits(self):
606        # Verify cross-platform repeatability
607        self.gen.seed(1234567)
608        self.assertEqual(self.gen.getrandbits(100),
609                         97904845777343510404718956115)
610        # Verify ranges
611        for k in range(1, 1000):
612            self.assertTrue(0 <= self.gen.getrandbits(k) < 2**k)
613
614        # Verify all bits active
615        getbits = self.gen.getrandbits
616        for span in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]:
617            cum = 0
618            for i in range(100):
619                cum |= getbits(span)
620            self.assertEqual(cum, 2**span-1)
621
622        # Verify argument checking
623        self.assertRaises(TypeError, self.gen.getrandbits)
624        self.assertRaises(TypeError, self.gen.getrandbits, 'a')
625        self.assertRaises(TypeError, self.gen.getrandbits, 1, 2)
626        self.assertRaises(ValueError, self.gen.getrandbits, 0)
627        self.assertRaises(ValueError, self.gen.getrandbits, -1)
628
629    def test_randrange_uses_getrandbits(self):
630        # Verify use of getrandbits by randrange
631        # Use same seed as in the cross-platform repeatability test
632        # in test_genrandbits above.
633        self.gen.seed(1234567)
634        # If randrange uses getrandbits, it should pick getrandbits(100)
635        # when called with a 100-bits stop argument.
636        self.assertEqual(self.gen.randrange(2**99),
637                         97904845777343510404718956115)
638
639    def test_randbelow_logic(self, _log=log, int=int):
640        # check bitcount transition points:  2**i and 2**(i+1)-1
641        # show that: k = int(1.001 + _log(n, 2))
642        # is equal to or one greater than the number of bits in n
643        for i in range(1, 1000):
644            n = 1 << i # check an exact power of two
645            numbits = i+1
646            k = int(1.00001 + _log(n, 2))
647            self.assertEqual(k, numbits)
648            self.assertEqual(n, 2**(k-1))
649
650            n += n - 1      # check 1 below the next power of two
651            k = int(1.00001 + _log(n, 2))
652            self.assertIn(k, [numbits, numbits+1])
653            self.assertTrue(2**k > n > 2**(k-2))
654
655            n -= n >> 15     # check a little farther below the next power of two
656            k = int(1.00001 + _log(n, 2))
657            self.assertEqual(k, numbits)        # note the stronger assertion
658            self.assertTrue(2**k > n > 2**(k-1))   # note the stronger assertion
659
660    def test_randbelow_without_getrandbits(self):
661        # Random._randbelow() can only use random() when the built-in one
662        # has been overridden but no new getrandbits() method was supplied.
663        maxsize = 1<<random.BPF
664        with warnings.catch_warnings():
665            warnings.simplefilter("ignore", UserWarning)
666            # Population range too large (n >= maxsize)
667            self.gen._randbelow_without_getrandbits(
668                maxsize+1, maxsize=maxsize
669            )
670        self.gen._randbelow_without_getrandbits(5640, maxsize=maxsize)
671        # issue 33203: test that _randbelow raises ValueError on
672        # n == 0 also in its getrandbits-independent branch.
673        with self.assertRaises(ValueError):
674            self.gen._randbelow_without_getrandbits(0, maxsize=maxsize)
675
676        # This might be going too far to test a single line, but because of our
677        # noble aim of achieving 100% test coverage we need to write a case in
678        # which the following line in Random._randbelow() gets executed:
679        #
680        # rem = maxsize % n
681        # limit = (maxsize - rem) / maxsize
682        # r = random()
683        # while r >= limit:
684        #     r = random() # <== *This line* <==<
685        #
686        # Therefore, to guarantee that the while loop is executed at least
687        # once, we need to mock random() so that it returns a number greater
688        # than 'limit' the first time it gets called.
689
690        n = 42
691        epsilon = 0.01
692        limit = (maxsize - (maxsize % n)) / maxsize
693        with unittest.mock.patch.object(random.Random, 'random') as random_mock:
694            random_mock.side_effect = [limit + epsilon, limit - epsilon]
695            self.gen._randbelow_without_getrandbits(n, maxsize=maxsize)
696            self.assertEqual(random_mock.call_count, 2)
697
698    def test_randrange_bug_1590891(self):
699        start = 1000000000000
700        stop = -100000000000000000000
701        step = -200
702        x = self.gen.randrange(start, stop, step)
703        self.assertTrue(stop < x <= start)
704        self.assertEqual((x+stop)%step, 0)
705
706    def test_choices_algorithms(self):
707        # The various ways of specifying weights should produce the same results
708        choices = self.gen.choices
709        n = 104729
710
711        self.gen.seed(8675309)
712        a = self.gen.choices(range(n), k=10000)
713
714        self.gen.seed(8675309)
715        b = self.gen.choices(range(n), [1]*n, k=10000)
716        self.assertEqual(a, b)
717
718        self.gen.seed(8675309)
719        c = self.gen.choices(range(n), cum_weights=range(1, n+1), k=10000)
720        self.assertEqual(a, c)
721
722        # American Roulette
723        population = ['Red', 'Black', 'Green']
724        weights = [18, 18, 2]
725        cum_weights = [18, 36, 38]
726        expanded_population = ['Red'] * 18 + ['Black'] * 18 + ['Green'] * 2
727
728        self.gen.seed(9035768)
729        a = self.gen.choices(expanded_population, k=10000)
730
731        self.gen.seed(9035768)
732        b = self.gen.choices(population, weights, k=10000)
733        self.assertEqual(a, b)
734
735        self.gen.seed(9035768)
736        c = self.gen.choices(population, cum_weights=cum_weights, k=10000)
737        self.assertEqual(a, c)
738
739def gamma(z, sqrt2pi=(2.0*pi)**0.5):
740    # Reflection to right half of complex plane
741    if z < 0.5:
742        return pi / sin(pi*z) / gamma(1.0-z)
743    # Lanczos approximation with g=7
744    az = z + (7.0 - 0.5)
745    return az ** (z-0.5) / exp(az) * sqrt2pi * fsum([
746        0.9999999999995183,
747        676.5203681218835 / z,
748        -1259.139216722289 / (z+1.0),
749        771.3234287757674 / (z+2.0),
750        -176.6150291498386 / (z+3.0),
751        12.50734324009056 / (z+4.0),
752        -0.1385710331296526 / (z+5.0),
753        0.9934937113930748e-05 / (z+6.0),
754        0.1659470187408462e-06 / (z+7.0),
755    ])
756
757class TestDistributions(unittest.TestCase):
758    def test_zeroinputs(self):
759        # Verify that distributions can handle a series of zero inputs'
760        g = random.Random()
761        x = [g.random() for i in range(50)] + [0.0]*5
762        g.random = x[:].pop; g.uniform(1,10)
763        g.random = x[:].pop; g.paretovariate(1.0)
764        g.random = x[:].pop; g.expovariate(1.0)
765        g.random = x[:].pop; g.weibullvariate(1.0, 1.0)
766        g.random = x[:].pop; g.vonmisesvariate(1.0, 1.0)
767        g.random = x[:].pop; g.normalvariate(0.0, 1.0)
768        g.random = x[:].pop; g.gauss(0.0, 1.0)
769        g.random = x[:].pop; g.lognormvariate(0.0, 1.0)
770        g.random = x[:].pop; g.vonmisesvariate(0.0, 1.0)
771        g.random = x[:].pop; g.gammavariate(0.01, 1.0)
772        g.random = x[:].pop; g.gammavariate(1.0, 1.0)
773        g.random = x[:].pop; g.gammavariate(200.0, 1.0)
774        g.random = x[:].pop; g.betavariate(3.0, 3.0)
775        g.random = x[:].pop; g.triangular(0.0, 1.0, 1.0/3.0)
776
777    def test_avg_std(self):
778        # Use integration to test distribution average and standard deviation.
779        # Only works for distributions which do not consume variates in pairs
780        g = random.Random()
781        N = 5000
782        x = [i/float(N) for i in range(1,N)]
783        for variate, args, mu, sigmasqrd in [
784                (g.uniform, (1.0,10.0), (10.0+1.0)/2, (10.0-1.0)**2/12),
785                (g.triangular, (0.0, 1.0, 1.0/3.0), 4.0/9.0, 7.0/9.0/18.0),
786                (g.expovariate, (1.5,), 1/1.5, 1/1.5**2),
787                (g.vonmisesvariate, (1.23, 0), pi, pi**2/3),
788                (g.paretovariate, (5.0,), 5.0/(5.0-1),
789                                  5.0/((5.0-1)**2*(5.0-2))),
790                (g.weibullvariate, (1.0, 3.0), gamma(1+1/3.0),
791                                  gamma(1+2/3.0)-gamma(1+1/3.0)**2) ]:
792            g.random = x[:].pop
793            y = []
794            for i in range(len(x)):
795                try:
796                    y.append(variate(*args))
797                except IndexError:
798                    pass
799            s1 = s2 = 0
800            for e in y:
801                s1 += e
802                s2 += (e - mu) ** 2
803            N = len(y)
804            self.assertAlmostEqual(s1/N, mu, places=2,
805                                   msg='%s%r' % (variate.__name__, args))
806            self.assertAlmostEqual(s2/(N-1), sigmasqrd, places=2,
807                                   msg='%s%r' % (variate.__name__, args))
808
809    def test_constant(self):
810        g = random.Random()
811        N = 100
812        for variate, args, expected in [
813                (g.uniform, (10.0, 10.0), 10.0),
814                (g.triangular, (10.0, 10.0), 10.0),
815                (g.triangular, (10.0, 10.0, 10.0), 10.0),
816                (g.expovariate, (float('inf'),), 0.0),
817                (g.vonmisesvariate, (3.0, float('inf')), 3.0),
818                (g.gauss, (10.0, 0.0), 10.0),
819                (g.lognormvariate, (0.0, 0.0), 1.0),
820                (g.lognormvariate, (-float('inf'), 0.0), 0.0),
821                (g.normalvariate, (10.0, 0.0), 10.0),
822                (g.paretovariate, (float('inf'),), 1.0),
823                (g.weibullvariate, (10.0, float('inf')), 10.0),
824                (g.weibullvariate, (0.0, 10.0), 0.0),
825            ]:
826            for i in range(N):
827                self.assertEqual(variate(*args), expected)
828
829    def test_von_mises_range(self):
830        # Issue 17149: von mises variates were not consistently in the
831        # range [0, 2*PI].
832        g = random.Random()
833        N = 100
834        for mu in 0.0, 0.1, 3.1, 6.2:
835            for kappa in 0.0, 2.3, 500.0:
836                for _ in range(N):
837                    sample = g.vonmisesvariate(mu, kappa)
838                    self.assertTrue(
839                        0 <= sample <= random.TWOPI,
840                        msg=("vonmisesvariate({}, {}) produced a result {} out"
841                             " of range [0, 2*pi]").format(mu, kappa, sample))
842
843    def test_von_mises_large_kappa(self):
844        # Issue #17141: vonmisesvariate() was hang for large kappas
845        random.vonmisesvariate(0, 1e15)
846        random.vonmisesvariate(0, 1e100)
847
848    def test_gammavariate_errors(self):
849        # Both alpha and beta must be > 0.0
850        self.assertRaises(ValueError, random.gammavariate, -1, 3)
851        self.assertRaises(ValueError, random.gammavariate, 0, 2)
852        self.assertRaises(ValueError, random.gammavariate, 2, 0)
853        self.assertRaises(ValueError, random.gammavariate, 1, -3)
854
855    # There are three different possibilities in the current implementation
856    # of random.gammavariate(), depending on the value of 'alpha'. What we
857    # are going to do here is to fix the values returned by random() to
858    # generate test cases that provide 100% line coverage of the method.
859    @unittest.mock.patch('random.Random.random')
860    def test_gammavariate_alpha_greater_one(self, random_mock):
861
862        # #1: alpha > 1.0.
863        # We want the first random number to be outside the
864        # [1e-7, .9999999] range, so that the continue statement executes
865        # once. The values of u1 and u2 will be 0.5 and 0.3, respectively.
866        random_mock.side_effect = [1e-8, 0.5, 0.3]
867        returned_value = random.gammavariate(1.1, 2.3)
868        self.assertAlmostEqual(returned_value, 2.53)
869
870    @unittest.mock.patch('random.Random.random')
871    def test_gammavariate_alpha_equal_one(self, random_mock):
872
873        # #2.a: alpha == 1.
874        # The execution body of the while loop executes once.
875        # Then random.random() returns 0.45,
876        # which causes while to stop looping and the algorithm to terminate.
877        random_mock.side_effect = [0.45]
878        returned_value = random.gammavariate(1.0, 3.14)
879        self.assertAlmostEqual(returned_value, 1.877208182372648)
880
881    @unittest.mock.patch('random.Random.random')
882    def test_gammavariate_alpha_equal_one_equals_expovariate(self, random_mock):
883
884        # #2.b: alpha == 1.
885        # It must be equivalent of calling expovariate(1.0 / beta).
886        beta = 3.14
887        random_mock.side_effect = [1e-8, 1e-8]
888        gammavariate_returned_value = random.gammavariate(1.0, beta)
889        expovariate_returned_value = random.expovariate(1.0 / beta)
890        self.assertAlmostEqual(gammavariate_returned_value, expovariate_returned_value)
891
892    @unittest.mock.patch('random.Random.random')
893    def test_gammavariate_alpha_between_zero_and_one(self, random_mock):
894
895        # #3: 0 < alpha < 1.
896        # This is the most complex region of code to cover,
897        # as there are multiple if-else statements. Let's take a look at the
898        # source code, and determine the values that we need accordingly:
899        #
900        # while 1:
901        #     u = random()
902        #     b = (_e + alpha)/_e
903        #     p = b*u
904        #     if p <= 1.0: # <=== (A)
905        #         x = p ** (1.0/alpha)
906        #     else: # <=== (B)
907        #         x = -_log((b-p)/alpha)
908        #     u1 = random()
909        #     if p > 1.0: # <=== (C)
910        #         if u1 <= x ** (alpha - 1.0): # <=== (D)
911        #             break
912        #     elif u1 <= _exp(-x): # <=== (E)
913        #         break
914        # return x * beta
915        #
916        # First, we want (A) to be True. For that we need that:
917        # b*random() <= 1.0
918        # r1 = random() <= 1.0 / b
919        #
920        # We now get to the second if-else branch, and here, since p <= 1.0,
921        # (C) is False and we take the elif branch, (E). For it to be True,
922        # so that the break is executed, we need that:
923        # r2 = random() <= _exp(-x)
924        # r2 <= _exp(-(p ** (1.0/alpha)))
925        # r2 <= _exp(-((b*r1) ** (1.0/alpha)))
926
927        _e = random._e
928        _exp = random._exp
929        _log = random._log
930        alpha = 0.35
931        beta = 1.45
932        b = (_e + alpha)/_e
933        epsilon = 0.01
934
935        r1 = 0.8859296441566 # 1.0 / b
936        r2 = 0.3678794411714 # _exp(-((b*r1) ** (1.0/alpha)))
937
938        # These four "random" values result in the following trace:
939        # (A) True, (E) False --> [next iteration of while]
940        # (A) True, (E) True --> [while loop breaks]
941        random_mock.side_effect = [r1, r2 + epsilon, r1, r2]
942        returned_value = random.gammavariate(alpha, beta)
943        self.assertAlmostEqual(returned_value, 1.4499999999997544)
944
945        # Let's now make (A) be False. If this is the case, when we get to the
946        # second if-else 'p' is greater than 1, so (C) evaluates to True. We
947        # now encounter a second if statement, (D), which in order to execute
948        # must satisfy the following condition:
949        # r2 <= x ** (alpha - 1.0)
950        # r2 <= (-_log((b-p)/alpha)) ** (alpha - 1.0)
951        # r2 <= (-_log((b-(b*r1))/alpha)) ** (alpha - 1.0)
952        r1 = 0.8959296441566 # (1.0 / b) + epsilon -- so that (A) is False
953        r2 = 0.9445400408898141
954
955        # And these four values result in the following trace:
956        # (B) and (C) True, (D) False --> [next iteration of while]
957        # (B) and (C) True, (D) True [while loop breaks]
958        random_mock.side_effect = [r1, r2 + epsilon, r1, r2]
959        returned_value = random.gammavariate(alpha, beta)
960        self.assertAlmostEqual(returned_value, 1.5830349561760781)
961
962    @unittest.mock.patch('random.Random.gammavariate')
963    def test_betavariate_return_zero(self, gammavariate_mock):
964        # betavariate() returns zero when the Gamma distribution
965        # that it uses internally returns this same value.
966        gammavariate_mock.return_value = 0.0
967        self.assertEqual(0.0, random.betavariate(2.71828, 3.14159))
968
969
970class TestRandomSubclassing(unittest.TestCase):
971    def test_random_subclass_with_kwargs(self):
972        # SF bug #1486663 -- this used to erroneously raise a TypeError
973        class Subclass(random.Random):
974            def __init__(self, newarg=None):
975                random.Random.__init__(self)
976        Subclass(newarg=1)
977
978    def test_subclasses_overriding_methods(self):
979        # Subclasses with an overridden random, but only the original
980        # getrandbits method should not rely on getrandbits in for randrange,
981        # but should use a getrandbits-independent implementation instead.
982
983        # subclass providing its own random **and** getrandbits methods
984        # like random.SystemRandom does => keep relying on getrandbits for
985        # randrange
986        class SubClass1(random.Random):
987            def random(self):
988                called.add('SubClass1.random')
989                return random.Random.random(self)
990
991            def getrandbits(self, n):
992                called.add('SubClass1.getrandbits')
993                return random.Random.getrandbits(self, n)
994        called = set()
995        SubClass1().randrange(42)
996        self.assertEqual(called, {'SubClass1.getrandbits'})
997
998        # subclass providing only random => can only use random for randrange
999        class SubClass2(random.Random):
1000            def random(self):
1001                called.add('SubClass2.random')
1002                return random.Random.random(self)
1003        called = set()
1004        SubClass2().randrange(42)
1005        self.assertEqual(called, {'SubClass2.random'})
1006
1007        # subclass defining getrandbits to complement its inherited random
1008        # => can now rely on getrandbits for randrange again
1009        class SubClass3(SubClass2):
1010            def getrandbits(self, n):
1011                called.add('SubClass3.getrandbits')
1012                return random.Random.getrandbits(self, n)
1013        called = set()
1014        SubClass3().randrange(42)
1015        self.assertEqual(called, {'SubClass3.getrandbits'})
1016
1017        # subclass providing only random and inherited getrandbits
1018        # => random takes precedence
1019        class SubClass4(SubClass3):
1020            def random(self):
1021                called.add('SubClass4.random')
1022                return random.Random.random(self)
1023        called = set()
1024        SubClass4().randrange(42)
1025        self.assertEqual(called, {'SubClass4.random'})
1026
1027        # Following subclasses don't define random or getrandbits directly,
1028        # but inherit them from classes which are not subclasses of Random
1029        class Mixin1:
1030            def random(self):
1031                called.add('Mixin1.random')
1032                return random.Random.random(self)
1033        class Mixin2:
1034            def getrandbits(self, n):
1035                called.add('Mixin2.getrandbits')
1036                return random.Random.getrandbits(self, n)
1037
1038        class SubClass5(Mixin1, random.Random):
1039            pass
1040        called = set()
1041        SubClass5().randrange(42)
1042        self.assertEqual(called, {'Mixin1.random'})
1043
1044        class SubClass6(Mixin2, random.Random):
1045            pass
1046        called = set()
1047        SubClass6().randrange(42)
1048        self.assertEqual(called, {'Mixin2.getrandbits'})
1049
1050        class SubClass7(Mixin1, Mixin2, random.Random):
1051            pass
1052        called = set()
1053        SubClass7().randrange(42)
1054        self.assertEqual(called, {'Mixin1.random'})
1055
1056        class SubClass8(Mixin2, Mixin1, random.Random):
1057            pass
1058        called = set()
1059        SubClass8().randrange(42)
1060        self.assertEqual(called, {'Mixin2.getrandbits'})
1061
1062
1063class TestModule(unittest.TestCase):
1064    def testMagicConstants(self):
1065        self.assertAlmostEqual(random.NV_MAGICCONST, 1.71552776992141)
1066        self.assertAlmostEqual(random.TWOPI, 6.28318530718)
1067        self.assertAlmostEqual(random.LOG4, 1.38629436111989)
1068        self.assertAlmostEqual(random.SG_MAGICCONST, 2.50407739677627)
1069
1070    def test__all__(self):
1071        # tests validity but not completeness of the __all__ list
1072        self.assertTrue(set(random.__all__) <= set(dir(random)))
1073
1074    @unittest.skipUnless(hasattr(os, "fork"), "fork() required")
1075    def test_after_fork(self):
1076        # Test the global Random instance gets reseeded in child
1077        r, w = os.pipe()
1078        pid = os.fork()
1079        if pid == 0:
1080            # child process
1081            try:
1082                val = random.getrandbits(128)
1083                with open(w, "w") as f:
1084                    f.write(str(val))
1085            finally:
1086                os._exit(0)
1087        else:
1088            # parent process
1089            os.close(w)
1090            val = random.getrandbits(128)
1091            with open(r, "r") as f:
1092                child_val = eval(f.read())
1093            self.assertNotEqual(val, child_val)
1094
1095            pid, status = os.waitpid(pid, 0)
1096            self.assertEqual(status, 0)
1097
1098
1099if __name__ == "__main__":
1100    unittest.main()
1101