• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import unittest
2import unittest.mock
3import random
4import os
5import time
6import pickle
7import warnings
8import test.support
9
10from functools import partial
11from math import log, exp, pi, fsum, sin, factorial
12from test import support
13from fractions import Fraction
14from collections import abc, Counter
15
16class TestBasicOps:
17    # Superclass with tests common to all generators.
18    # Subclasses must arrange for self.gen to retrieve the Random instance
19    # to be tested.
20
21    def randomlist(self, n):
22        """Helper function to make a list of random numbers"""
23        return [self.gen.random() for i in range(n)]
24
25    def test_autoseed(self):
26        self.gen.seed()
27        state1 = self.gen.getstate()
28        time.sleep(0.1)
29        self.gen.seed()      # different seeds at different times
30        state2 = self.gen.getstate()
31        self.assertNotEqual(state1, state2)
32
33    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):
42        # Seed value with a negative hash.
43        class MySeed(object):
44            def __hash__(self):
45                return -1729
46        for arg in [None, 0, 1, -1, 10**20, -(10**20),
47                    False, True, 3.14, 'a']:
48            self.gen.seed(arg)
49
50        for arg in [1+2j, tuple('abc'), MySeed()]:
51            with self.assertWarns(DeprecationWarning):
52                self.gen.seed(arg)
53
54        for arg in [list(range(3)), dict(one=1)]:
55            with self.assertWarns(DeprecationWarning):
56                self.assertRaises(TypeError, self.gen.seed, arg)
57        self.assertRaises(TypeError, self.gen.seed, 1, 2, 3, 4)
58        self.assertRaises(TypeError, type(self.gen), [])
59
60    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
65    @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
68        # randomness source is not found. To test this on machines where it
69        # 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
75    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))
90        # 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)
106        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')
113        with self.assertWarns(DeprecationWarning):
114            shuffle(seq, mock_random)
115        mock_random.assert_called_with()
116
117    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
124    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
128        population = range(N)
129        for k in range(N+1):
130            s = self.gen.sample(population, k)
131            self.assertEqual(len(s), k)
132            uniq = set(s)
133            self.assertEqual(len(uniq), k)
134            self.assertTrue(uniq <= set(population))
135        self.assertEqual(self.gen.sample([], 0), [])  # test edge case N==k==0
136        # Exception raised if size of sample exceeds that of population
137        self.assertRaises(ValueError, self.gen.sample, population, N+1)
138        self.assertRaises(ValueError, self.gen.sample, [], -1)
139
140    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
146        for k in range(n):
147            expected = factorial(n) // factorial(n-k)
148            perms = {}
149            for i in range(trials):
150                perms[tuple(self.gen.sample(pop, k))] = None
151                if len(perms) == expected:
152                    break
153            else:
154                self.fail()
155
156    def test_sample_inputs(self):
157        # SF bug #801342 -- population can be any iterable defining __len__()
158        self.gen.sample(range(20), 2)
159        self.gen.sample(range(20), 2)
160        self.gen.sample(str('abcdefghijklmnopqrst'), 2)
161        self.gen.sample(tuple('abcdefghijklmnopqrst'), 2)
162
163    def test_sample_on_dicts(self):
164        self.assertRaises(TypeError, self.gen.sample, dict.fromkeys('abcdef'), 2)
165
166    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
171    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
187    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
231    def test_choices(self):
232        choices = self.gen.choices
233        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 [
240            choices(data, k=5),
241            choices(data, range(4), k=5),
242            choices(k=5, population=data, weights=range(4)),
243            choices(k=5, population=data, cum_weights=range(4)),
244        ]:
245            self.assertEqual(len(sample), 5)
246            self.assertEqual(type(sample), list)
247            self.assertTrue(set(sample) <= set(data))
248
249        # test argument handling
250        with self.assertRaises(TypeError):                               # missing arguments
251            choices(2)
252
253        self.assertEqual(choices(data, k=0), [])                         # k == 0
254        self.assertEqual(choices(data, k=-1), [])                        # negative k behaves like ``[0] * -1``
255        with self.assertRaises(TypeError):
256            choices(data, k=2.5)                                         # k is a float
257
258        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
260        with self.assertRaises(TypeError):
261            choices(set_data, k=2)                                       # population is not a sequence
262
263        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))
265        with self.assertRaises(ValueError):
266            choices(data, [1,2], k=5)                                    # len(weights) != len(population)
267        with self.assertRaises(TypeError):
268            choices(data, 10, k=5)                                       # non-iterable weights
269        with self.assertRaises(TypeError):
270            choices(data, [None]*4, k=5)                                 # non-numeric weights
271        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        ]:
277            self.assertTrue(set(choices(data, weights, k=5)) <= set(data))
278
279        with self.assertRaises(ValueError):
280            choices(data, cum_weights=[1,2], k=5)                        # len(weights) != len(population)
281        with self.assertRaises(TypeError):
282            choices(data, cum_weights=10, k=5)                           # non-iterable cum_weights
283        with self.assertRaises(TypeError):
284            choices(data, cum_weights=[None]*4, k=5)                     # non-numeric cum_weights
285        with self.assertRaises(TypeError):
286            choices(data, range(4), cum_weights=range(4), k=5)           # both weights and cum_weights
287        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        ]:
292            self.assertTrue(set(choices(data, cum_weights=weights, k=5)) <= set(data))
293
294        # 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
308    def test_choices_subnormal(self):
309        # Subnormal weights would occasionally trigger an IndexError
310        # 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
316    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
321    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
337    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
354    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
379    def test_pickling(self):
380        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)
386
387    @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
395    @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
404    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:
412            with open(support.findfile(file),"rb") as f:
413                r = pickle.load(f)
414            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))
423
424    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
440try:
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):
449    gen = random.SystemRandom()
450
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
463    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):
469        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
470            self.assertRaises(NotImplementedError, pickle.dumps, self.gen, proto)
471
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
476        for i in range(100):
477            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
485        for i in range(100):
486            r = self.gen.randrange(span)
487            self.assertTrue(0 <= r < span)
488            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]:
493            start = self.gen.randrange(2 ** (i-2))
494            stop = self.gen.randrange(2 ** i)
495            if stop <= start:
496                continue
497            self.assertTrue(start <= self.gen.randrange(start, stop) < stop)
498
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)),
502                set([self.gen.randrange(start,stop) for i in range(100)]))
503
504    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
517        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')
525        # Zero and non-integer step
526        raises(0, 42, 0)
527        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)
535
536    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
556    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
564    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
568        for i in range(1, 1000):
569            n = 1 << i # check an exact power of two
570            numbits = i+1
571            k = int(1.00001 + _log(n, 2))
572            self.assertEqual(k, numbits)
573            self.assertEqual(n, 2**(k-1))
574
575            n += n - 1      # check 1 below the next power of two
576            k = int(1.00001 + _log(n, 2))
577            self.assertIn(k, [numbits, numbits+1])
578            self.assertTrue(2**k > n > 2**(k-2))
579
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
583            self.assertTrue(2**k > n > 2**(k-1))   # note the stronger assertion
584
585
586class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
587    gen = random.Random()
588
589    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'])
595        self.gen.seed("the quick brown fox", version=2)
596        self.assertEqual([self.gen.random().hex() for i in range(4)],
597            ['0x1.1239ddfb11b7cp-3', '0x1.b3cbb5c51b120p-4',
598             '0x1.8c4f55116b60fp-1', '0x1.63eb525174a27p-1'])
599
600    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
618    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
629    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
656    def test_setstate_first_arg(self):
657        self.assertRaises(ValueError, self.gen.setstate, (1, None, None))
658
659    def test_setstate_middle_arg(self):
660        start_state = self.gen.getstate()
661        # 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))
669        # 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))
674        # 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)
678
679        # 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
689    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
715        self.gen.seed(61731 + (24903<<32) + (614<<64) + (42143<<96))
716        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
727        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))
738        actual = self.randomlist(2000)[-10:]
739        for a, e in zip(actual, expected):
740            self.assertEqual(int(ldexp(a, 53)), e)
741
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.
748        seed = (1 << (10000 * 8)) - 1  # about 10K bytes
749        self.gen.seed(seed)
750
751    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
755        for i in range(100):
756            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
764        for i in range(100):
765            r = self.gen.randrange(span)
766            self.assertTrue(0 <= r < span)
767            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]:
772            start = self.gen.randrange(2 ** (i-2))
773            stop = self.gen.randrange(2 ** i)
774            if stop <= start:
775                continue
776            self.assertTrue(start <= self.gen.randrange(start, stop) < stop)
777
778    def test_rangelimits(self):
779        for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
780            self.assertEqual(set(range(start,stop)),
781                set([self.gen.randrange(start,stop) for i in range(100)]))
782
783    def test_getrandbits(self):
784        super().test_getrandbits()
785
786        # Verify cross-platform repeatability
787        self.gen.seed(1234567)
788        self.assertEqual(self.gen.getrandbits(100),
789                         97904845777343510404718956115)
790
791    def test_randrange_uses_getrandbits(self):
792        # Verify use of getrandbits by randrange
793        # Use same seed as in the cross-platform repeatability test
794        # in test_getrandbits above.
795        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
801    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
805        for i in range(1, 1000):
806            n = 1 << i # check an exact power of two
807            numbits = i+1
808            k = int(1.00001 + _log(n, 2))
809            self.assertEqual(k, numbits)
810            self.assertEqual(n, 2**(k-1))
811
812            n += n - 1      # check 1 below the next power of two
813            k = int(1.00001 + _log(n, 2))
814            self.assertIn(k, [numbits, numbits+1])
815            self.assertTrue(2**k > n > 2**(k-2))
816
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
820            self.assertTrue(2**k > n > 2**(k-1))   # note the stronger assertion
821
822    def test_randbelow_without_getrandbits(self):
823        # Random._randbelow() can only use random() when the built-in one
824        # has been overridden but no new getrandbits() method was supplied.
825        maxsize = 1<<random.BPF
826        with warnings.catch_warnings():
827            warnings.simplefilter("ignore", UserWarning)
828            # Population range too large (n >= maxsize)
829            self.gen._randbelow_without_getrandbits(
830                maxsize+1, maxsize=maxsize
831            )
832        self.gen._randbelow_without_getrandbits(5640, maxsize=maxsize)
833        # issue 33203: test that _randbelow returns zero on
834        # n == 0 also in its getrandbits-independent branch.
835        x = self.gen._randbelow_without_getrandbits(0, maxsize=maxsize)
836        self.assertEqual(x, 0)
837
838        # 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
855        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)
859
860    def test_randrange_bug_1590891(self):
861        start = 1000000000000
862        stop = -100000000000000000000
863        step = -200
864        x = self.gen.randrange(start, stop, step)
865        self.assertTrue(stop < x <= start)
866        self.assertEqual((x+stop)%step, 0)
867
868    def test_choices_algorithms(self):
869        # The various ways of specifying weights should produce the same results
870        choices = self.gen.choices
871        n = 104729
872
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
884        # American Roulette
885        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
901    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
907        expected = b'3\xa8\xf9f\xf4\xa4\xd06\x19\x8f\x9f\x82\x02oe\xf0'
908
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
922        # Each randbytes(1), randbytes(2) or randbytes(3) call consumes
923        # 4 bytes of entropy
924        self.gen.seed(seed)
925        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]
931                             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)
936        expected3 = b''.join(expected[i + 1: i + 4]
937                             for i in range(0, len(expected), 4))
938        self.assertEqual(b''.join(self.gen.randbytes(3) for _ in range(4)),
939                         expected3)
940
941    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
951    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
978
979def 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    ])
996
997class TestDistributions(unittest.TestCase):
998    def test_zeroinputs(self):
999        # Verify that distributions can handle a series of zero inputs'
1000        g = random.Random()
1001        x = [g.random() for i in range(50)] + [0.0]*5
1002        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)
1006        g.random = x[:].pop; g.vonmisesvariate(1.0, 1.0)
1007        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)
1015        g.random = x[:].pop; g.triangular(0.0, 1.0, 1.0/3.0)
1016
1017    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
1022        x = [i/float(N) for i in range(1,N)]
1023        for variate, args, mu, sigmasqrd in [
1024                (g.uniform, (1.0,10.0), (10.0+1.0)/2, (10.0-1.0)**2/12),
1025                (g.triangular, (0.0, 1.0, 1.0/3.0), 4.0/9.0, 7.0/9.0/18.0),
1026                (g.expovariate, (1.5,), 1/1.5, 1/1.5**2),
1027                (g.vonmisesvariate, (1.23, 0), pi, pi**2/3),
1028                (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 = []
1034            for i in range(len(x)):
1035                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)
1044            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),
1055                (g.triangular, (10.0, 10.0, 10.0), 10.0),
1056                (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)
1068
1069    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
1083    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
1088    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
1095    # 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.
1099    @unittest.mock.patch('random.Random.random')
1100    def test_gammavariate_alpha_greater_one(self, random_mock):
1101
1102        # #1: alpha > 1.0.
1103        # We want the first random number to be outside the
1104        # [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
1110    @unittest.mock.patch('random.Random.random')
1111    def test_gammavariate_alpha_equal_one(self, random_mock):
1112
1113        # #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,
1137        # 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))
1208
1209
1210class 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):
1228                called.add('SubClass1.random')
1229                return random.Random.random(self)
1230
1231            def getrandbits(self, n):
1232                called.add('SubClass1.getrandbits')
1233                return random.Random.getrandbits(self, n)
1234        called = set()
1235        SubClass1().randrange(42)
1236        self.assertEqual(called, {'SubClass1.getrandbits'})
1237
1238        # subclass providing only random => can only use random for randrange
1239        class SubClass2(random.Random):
1240            def random(self):
1241                called.add('SubClass2.random')
1242                return random.Random.random(self)
1243        called = set()
1244        SubClass2().randrange(42)
1245        self.assertEqual(called, {'SubClass2.random'})
1246
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):
1251                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
1302
1303class 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
1312        self.assertTrue(set(random.__all__) <= set(dir(random)))
1313
1314    @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()
1318        pid = os.fork()
1319        if pid == 0:
1320            # child process
1321            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:
1328            # parent process
1329            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
1335            support.wait_process(pid, exitcode=0)
1336
1337
1338if __name__ == "__main__":
1339    unittest.main()
1340