Home | History | Annotate | Download | only in test
      1 import unittest
      2 import unittest.mock
      3 import random
      4 import os
      5 import time
      6 import pickle
      7 import warnings
      8 from functools import partial
      9 from math import log, exp, pi, fsum, sin, factorial
     10 from test import support
     11 from fractions import Fraction
     12 
     13 
     14 class 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 occassionally 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             f = open(support.findfile(file),"rb")
    272             r = pickle.load(f)
    273             f.close()
    274             self.assertEqual(int(r.random()*1000), value)
    275 
    276     def test_bug_9025(self):
    277         # Had problem with an uneven distribution in int(n*random())
    278         # Verify the fix by checking that distributions fall within expectations.
    279         n = 100000
    280         randrange = self.gen.randrange
    281         k = sum(randrange(6755399441055744) % 3 == 2 for i in range(n))
    282         self.assertTrue(0.30 < k/n < .37, (k/n))
    283 
    284 try:
    285     random.SystemRandom().random()
    286 except NotImplementedError:
    287     SystemRandom_available = False
    288 else:
    289     SystemRandom_available = True
    290 
    291 @unittest.skipUnless(SystemRandom_available, "random.SystemRandom not available")
    292 class SystemRandom_TestBasicOps(TestBasicOps, unittest.TestCase):
    293     gen = random.SystemRandom()
    294 
    295     def test_autoseed(self):
    296         # Doesn't need to do anything except not fail
    297         self.gen.seed()
    298 
    299     def test_saverestore(self):
    300         self.assertRaises(NotImplementedError, self.gen.getstate)
    301         self.assertRaises(NotImplementedError, self.gen.setstate, None)
    302 
    303     def test_seedargs(self):
    304         # Doesn't need to do anything except not fail
    305         self.gen.seed(100)
    306 
    307     def test_gauss(self):
    308         self.gen.gauss_next = None
    309         self.gen.seed(100)
    310         self.assertEqual(self.gen.gauss_next, None)
    311 
    312     def test_pickling(self):
    313         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
    314             self.assertRaises(NotImplementedError, pickle.dumps, self.gen, proto)
    315 
    316     def test_53_bits_per_float(self):
    317         # This should pass whenever a C double has 53 bit precision.
    318         span = 2 ** 53
    319         cum = 0
    320         for i in range(100):
    321             cum |= int(self.gen.random() * span)
    322         self.assertEqual(cum, span-1)
    323 
    324     def test_bigrand(self):
    325         # The randrange routine should build-up the required number of bits
    326         # in stages so that all bit positions are active.
    327         span = 2 ** 500
    328         cum = 0
    329         for i in range(100):
    330             r = self.gen.randrange(span)
    331             self.assertTrue(0 <= r < span)
    332             cum |= r
    333         self.assertEqual(cum, span-1)
    334 
    335     def test_bigrand_ranges(self):
    336         for i in [40,80, 160, 200, 211, 250, 375, 512, 550]:
    337             start = self.gen.randrange(2 ** (i-2))
    338             stop = self.gen.randrange(2 ** i)
    339             if stop <= start:
    340                 continue
    341             self.assertTrue(start <= self.gen.randrange(start, stop) < stop)
    342 
    343     def test_rangelimits(self):
    344         for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
    345             self.assertEqual(set(range(start,stop)),
    346                 set([self.gen.randrange(start,stop) for i in range(100)]))
    347 
    348     def test_randrange_nonunit_step(self):
    349         rint = self.gen.randrange(0, 10, 2)
    350         self.assertIn(rint, (0, 2, 4, 6, 8))
    351         rint = self.gen.randrange(0, 2, 2)
    352         self.assertEqual(rint, 0)
    353 
    354     def test_randrange_errors(self):
    355         raises = partial(self.assertRaises, ValueError, self.gen.randrange)
    356         # Empty range
    357         raises(3, 3)
    358         raises(-721)
    359         raises(0, 100, -12)
    360         # Non-integer start/stop
    361         raises(3.14159)
    362         raises(0, 2.71828)
    363         # Zero and non-integer step
    364         raises(0, 42, 0)
    365         raises(0, 42, 3.14159)
    366 
    367     def test_genrandbits(self):
    368         # Verify ranges
    369         for k in range(1, 1000):
    370             self.assertTrue(0 <= self.gen.getrandbits(k) < 2**k)
    371 
    372         # Verify all bits active
    373         getbits = self.gen.getrandbits
    374         for span in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]:
    375             cum = 0
    376             for i in range(100):
    377                 cum |= getbits(span)
    378             self.assertEqual(cum, 2**span-1)
    379 
    380         # Verify argument checking
    381         self.assertRaises(TypeError, self.gen.getrandbits)
    382         self.assertRaises(TypeError, self.gen.getrandbits, 1, 2)
    383         self.assertRaises(ValueError, self.gen.getrandbits, 0)
    384         self.assertRaises(ValueError, self.gen.getrandbits, -1)
    385         self.assertRaises(TypeError, self.gen.getrandbits, 10.1)
    386 
    387     def test_randbelow_logic(self, _log=log, int=int):
    388         # check bitcount transition points:  2**i and 2**(i+1)-1
    389         # show that: k = int(1.001 + _log(n, 2))
    390         # is equal to or one greater than the number of bits in n
    391         for i in range(1, 1000):
    392             n = 1 << i # check an exact power of two
    393             numbits = i+1
    394             k = int(1.00001 + _log(n, 2))
    395             self.assertEqual(k, numbits)
    396             self.assertEqual(n, 2**(k-1))
    397 
    398             n += n - 1      # check 1 below the next power of two
    399             k = int(1.00001 + _log(n, 2))
    400             self.assertIn(k, [numbits, numbits+1])
    401             self.assertTrue(2**k > n > 2**(k-2))
    402 
    403             n -= n >> 15     # check a little farther below the next power of two
    404             k = int(1.00001 + _log(n, 2))
    405             self.assertEqual(k, numbits)        # note the stronger assertion
    406             self.assertTrue(2**k > n > 2**(k-1))   # note the stronger assertion
    407 
    408 
    409 class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
    410     gen = random.Random()
    411 
    412     def test_guaranteed_stable(self):
    413         # These sequences are guaranteed to stay the same across versions of python
    414         self.gen.seed(3456147, version=1)
    415         self.assertEqual([self.gen.random().hex() for i in range(4)],
    416             ['0x1.ac362300d90d2p-1', '0x1.9d16f74365005p-1',
    417              '0x1.1ebb4352e4c4dp-1', '0x1.1a7422abf9c11p-1'])
    418         self.gen.seed("the quick brown fox", version=2)
    419         self.assertEqual([self.gen.random().hex() for i in range(4)],
    420             ['0x1.1239ddfb11b7cp-3', '0x1.b3cbb5c51b120p-4',
    421              '0x1.8c4f55116b60fp-1', '0x1.63eb525174a27p-1'])
    422 
    423     def test_bug_27706(self):
    424         # Verify that version 1 seeds are unaffected by hash randomization
    425 
    426         self.gen.seed('nofar', version=1)   # hash('nofar') == 5990528763808513177
    427         self.assertEqual([self.gen.random().hex() for i in range(4)],
    428             ['0x1.8645314505ad7p-1', '0x1.afb1f82e40a40p-5',
    429              '0x1.2a59d2285e971p-1', '0x1.56977142a7880p-6'])
    430 
    431         self.gen.seed('rachel', version=1)  # hash('rachel') == -9091735575445484789
    432         self.assertEqual([self.gen.random().hex() for i in range(4)],
    433             ['0x1.0b294cc856fcdp-1', '0x1.2ad22d79e77b8p-3',
    434              '0x1.3052b9c072678p-2', '0x1.578f332106574p-3'])
    435 
    436         self.gen.seed('', version=1)        # hash('') == 0
    437         self.assertEqual([self.gen.random().hex() for i in range(4)],
    438             ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1',
    439              '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2'])
    440 
    441     def test_bug_31478(self):
    442         # There shouldn't be an assertion failure in _random.Random.seed() in
    443         # case the argument has a bad __abs__() method.
    444         class BadInt(int):
    445             def __abs__(self):
    446                 return None
    447         try:
    448             self.gen.seed(BadInt())
    449         except TypeError:
    450             pass
    451 
    452     def test_bug_31482(self):
    453         # Verify that version 1 seeds are unaffected by hash randomization
    454         # when the seeds are expressed as bytes rather than strings.
    455         # The hash(b) values listed are the Python2.7 hash() values
    456         # which were used for seeding.
    457 
    458         self.gen.seed(b'nofar', version=1)   # hash('nofar') == 5990528763808513177
    459         self.assertEqual([self.gen.random().hex() for i in range(4)],
    460             ['0x1.8645314505ad7p-1', '0x1.afb1f82e40a40p-5',
    461              '0x1.2a59d2285e971p-1', '0x1.56977142a7880p-6'])
    462 
    463         self.gen.seed(b'rachel', version=1)  # hash('rachel') == -9091735575445484789
    464         self.assertEqual([self.gen.random().hex() for i in range(4)],
    465             ['0x1.0b294cc856fcdp-1', '0x1.2ad22d79e77b8p-3',
    466              '0x1.3052b9c072678p-2', '0x1.578f332106574p-3'])
    467 
    468         self.gen.seed(b'', version=1)        # hash('') == 0
    469         self.assertEqual([self.gen.random().hex() for i in range(4)],
    470             ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1',
    471              '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2'])
    472 
    473         b = b'\x00\x20\x40\x60\x80\xA0\xC0\xE0\xF0'
    474         self.gen.seed(b, version=1)         # hash(b) == 5015594239749365497
    475         self.assertEqual([self.gen.random().hex() for i in range(4)],
    476             ['0x1.52c2fde444d23p-1', '0x1.875174f0daea4p-2',
    477              '0x1.9e9b2c50e5cd2p-1', '0x1.fa57768bd321cp-2'])
    478 
    479     def test_setstate_first_arg(self):
    480         self.assertRaises(ValueError, self.gen.setstate, (1, None, None))
    481 
    482     def test_setstate_middle_arg(self):
    483         start_state = self.gen.getstate()
    484         # Wrong type, s/b tuple
    485         self.assertRaises(TypeError, self.gen.setstate, (2, None, None))
    486         # Wrong length, s/b 625
    487         self.assertRaises(ValueError, self.gen.setstate, (2, (1,2,3), None))
    488         # Wrong type, s/b tuple of 625 ints
    489         self.assertRaises(TypeError, self.gen.setstate, (2, ('a',)*625, None))
    490         # Last element s/b an int also
    491         self.assertRaises(TypeError, self.gen.setstate, (2, (0,)*624+('a',), None))
    492         # Last element s/b between 0 and 624
    493         with self.assertRaises((ValueError, OverflowError)):
    494             self.gen.setstate((2, (1,)*624+(625,), None))
    495         with self.assertRaises((ValueError, OverflowError)):
    496             self.gen.setstate((2, (1,)*624+(-1,), None))
    497         # Failed calls to setstate() should not have changed the state.
    498         bits100 = self.gen.getrandbits(100)
    499         self.gen.setstate(start_state)
    500         self.assertEqual(self.gen.getrandbits(100), bits100)
    501 
    502         # Little trick to make "tuple(x % (2**32) for x in internalstate)"
    503         # raise ValueError. I cannot think of a simple way to achieve this, so
    504         # I am opting for using a generator as the middle argument of setstate
    505         # which attempts to cast a NaN to integer.
    506         state_values = self.gen.getstate()[1]
    507         state_values = list(state_values)
    508         state_values[-1] = float('nan')
    509         state = (int(x) for x in state_values)
    510         self.assertRaises(TypeError, self.gen.setstate, (2, state, None))
    511 
    512     def test_referenceImplementation(self):
    513         # Compare the python implementation with results from the original
    514         # code.  Create 2000 53-bit precision random floats.  Compare only
    515         # the last ten entries to show that the independent implementations
    516         # are tracking.  Here is the main() function needed to create the
    517         # list of expected random numbers:
    518         #    void main(void){
    519         #         int i;
    520         #         unsigned long init[4]={61731, 24903, 614, 42143}, length=4;
    521         #         init_by_array(init, length);
    522         #         for (i=0; i<2000; i++) {
    523         #           printf("%.15f ", genrand_res53());
    524         #           if (i%5==4) printf("\n");
    525         #         }
    526         #     }
    527         expected = [0.45839803073713259,
    528                     0.86057815201978782,
    529                     0.92848331726782152,
    530                     0.35932681119782461,
    531                     0.081823493762449573,
    532                     0.14332226470169329,
    533                     0.084297823823520024,
    534                     0.53814864671831453,
    535                     0.089215024911993401,
    536                     0.78486196105372907]
    537 
    538         self.gen.seed(61731 + (24903<<32) + (614<<64) + (42143<<96))
    539         actual = self.randomlist(2000)[-10:]
    540         for a, e in zip(actual, expected):
    541             self.assertAlmostEqual(a,e,places=14)
    542 
    543     def test_strong_reference_implementation(self):
    544         # Like test_referenceImplementation, but checks for exact bit-level
    545         # equality.  This should pass on any box where C double contains
    546         # at least 53 bits of precision (the underlying algorithm suffers
    547         # no rounding errors -- all results are exact).
    548         from math import ldexp
    549 
    550         expected = [0x0eab3258d2231f,
    551                     0x1b89db315277a5,
    552                     0x1db622a5518016,
    553                     0x0b7f9af0d575bf,
    554                     0x029e4c4db82240,
    555                     0x04961892f5d673,
    556                     0x02b291598e4589,
    557                     0x11388382c15694,
    558                     0x02dad977c9e1fe,
    559                     0x191d96d4d334c6]
    560         self.gen.seed(61731 + (24903<<32) + (614<<64) + (42143<<96))
    561         actual = self.randomlist(2000)[-10:]
    562         for a, e in zip(actual, expected):
    563             self.assertEqual(int(ldexp(a, 53)), e)
    564 
    565     def test_long_seed(self):
    566         # This is most interesting to run in debug mode, just to make sure
    567         # nothing blows up.  Under the covers, a dynamically resized array
    568         # is allocated, consuming space proportional to the number of bits
    569         # in the seed.  Unfortunately, that's a quadratic-time algorithm,
    570         # so don't make this horribly big.
    571         seed = (1 << (10000 * 8)) - 1  # about 10K bytes
    572         self.gen.seed(seed)
    573 
    574     def test_53_bits_per_float(self):
    575         # This should pass whenever a C double has 53 bit precision.
    576         span = 2 ** 53
    577         cum = 0
    578         for i in range(100):
    579             cum |= int(self.gen.random() * span)
    580         self.assertEqual(cum, span-1)
    581 
    582     def test_bigrand(self):
    583         # The randrange routine should build-up the required number of bits
    584         # in stages so that all bit positions are active.
    585         span = 2 ** 500
    586         cum = 0
    587         for i in range(100):
    588             r = self.gen.randrange(span)
    589             self.assertTrue(0 <= r < span)
    590             cum |= r
    591         self.assertEqual(cum, span-1)
    592 
    593     def test_bigrand_ranges(self):
    594         for i in [40,80, 160, 200, 211, 250, 375, 512, 550]:
    595             start = self.gen.randrange(2 ** (i-2))
    596             stop = self.gen.randrange(2 ** i)
    597             if stop <= start:
    598                 continue
    599             self.assertTrue(start <= self.gen.randrange(start, stop) < stop)
    600 
    601     def test_rangelimits(self):
    602         for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
    603             self.assertEqual(set(range(start,stop)),
    604                 set([self.gen.randrange(start,stop) for i in range(100)]))
    605 
    606     def test_genrandbits(self):
    607         # Verify cross-platform repeatability
    608         self.gen.seed(1234567)
    609         self.assertEqual(self.gen.getrandbits(100),
    610                          97904845777343510404718956115)
    611         # Verify ranges
    612         for k in range(1, 1000):
    613             self.assertTrue(0 <= self.gen.getrandbits(k) < 2**k)
    614 
    615         # Verify all bits active
    616         getbits = self.gen.getrandbits
    617         for span in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]:
    618             cum = 0
    619             for i in range(100):
    620                 cum |= getbits(span)
    621             self.assertEqual(cum, 2**span-1)
    622 
    623         # Verify argument checking
    624         self.assertRaises(TypeError, self.gen.getrandbits)
    625         self.assertRaises(TypeError, self.gen.getrandbits, 'a')
    626         self.assertRaises(TypeError, self.gen.getrandbits, 1, 2)
    627         self.assertRaises(ValueError, self.gen.getrandbits, 0)
    628         self.assertRaises(ValueError, self.gen.getrandbits, -1)
    629 
    630     def test_randbelow_logic(self, _log=log, int=int):
    631         # check bitcount transition points:  2**i and 2**(i+1)-1
    632         # show that: k = int(1.001 + _log(n, 2))
    633         # is equal to or one greater than the number of bits in n
    634         for i in range(1, 1000):
    635             n = 1 << i # check an exact power of two
    636             numbits = i+1
    637             k = int(1.00001 + _log(n, 2))
    638             self.assertEqual(k, numbits)
    639             self.assertEqual(n, 2**(k-1))
    640 
    641             n += n - 1      # check 1 below the next power of two
    642             k = int(1.00001 + _log(n, 2))
    643             self.assertIn(k, [numbits, numbits+1])
    644             self.assertTrue(2**k > n > 2**(k-2))
    645 
    646             n -= n >> 15     # check a little farther below the next power of two
    647             k = int(1.00001 + _log(n, 2))
    648             self.assertEqual(k, numbits)        # note the stronger assertion
    649             self.assertTrue(2**k > n > 2**(k-1))   # note the stronger assertion
    650 
    651     @unittest.mock.patch('random.Random.random')
    652     def test_randbelow_overridden_random(self, random_mock):
    653         # Random._randbelow() can only use random() when the built-in one
    654         # has been overridden but no new getrandbits() method was supplied.
    655         random_mock.side_effect = random.SystemRandom().random
    656         maxsize = 1<<random.BPF
    657         with warnings.catch_warnings():
    658             warnings.simplefilter("ignore", UserWarning)
    659             # Population range too large (n >= maxsize)
    660             self.gen._randbelow(maxsize+1, maxsize = maxsize)
    661         self.gen._randbelow(5640, maxsize = maxsize)
    662         # issue 33203: test that _randbelow raises ValueError on
    663         # n == 0 also in its getrandbits-independent branch.
    664         with self.assertRaises(ValueError):
    665             self.gen._randbelow(0, maxsize=maxsize)
    666         # This might be going too far to test a single line, but because of our
    667         # noble aim of achieving 100% test coverage we need to write a case in
    668         # which the following line in Random._randbelow() gets executed:
    669         #
    670         # rem = maxsize % n
    671         # limit = (maxsize - rem) / maxsize
    672         # r = random()
    673         # while r >= limit:
    674         #     r = random() # <== *This line* <==<
    675         #
    676         # Therefore, to guarantee that the while loop is executed at least
    677         # once, we need to mock random() so that it returns a number greater
    678         # than 'limit' the first time it gets called.
    679 
    680         n = 42
    681         epsilon = 0.01
    682         limit = (maxsize - (maxsize % n)) / maxsize
    683         random_mock.side_effect = [limit + epsilon, limit - epsilon]
    684         self.gen._randbelow(n, maxsize = maxsize)
    685 
    686     def test_randrange_bug_1590891(self):
    687         start = 1000000000000
    688         stop = -100000000000000000000
    689         step = -200
    690         x = self.gen.randrange(start, stop, step)
    691         self.assertTrue(stop < x <= start)
    692         self.assertEqual((x+stop)%step, 0)
    693 
    694     def test_choices_algorithms(self):
    695         # The various ways of specifying weights should produce the same results
    696         choices = self.gen.choices
    697         n = 104729
    698 
    699         self.gen.seed(8675309)
    700         a = self.gen.choices(range(n), k=10000)
    701 
    702         self.gen.seed(8675309)
    703         b = self.gen.choices(range(n), [1]*n, k=10000)
    704         self.assertEqual(a, b)
    705 
    706         self.gen.seed(8675309)
    707         c = self.gen.choices(range(n), cum_weights=range(1, n+1), k=10000)
    708         self.assertEqual(a, c)
    709 
    710         # Amerian Roulette
    711         population = ['Red', 'Black', 'Green']
    712         weights = [18, 18, 2]
    713         cum_weights = [18, 36, 38]
    714         expanded_population = ['Red'] * 18 + ['Black'] * 18 + ['Green'] * 2
    715 
    716         self.gen.seed(9035768)
    717         a = self.gen.choices(expanded_population, k=10000)
    718 
    719         self.gen.seed(9035768)
    720         b = self.gen.choices(population, weights, k=10000)
    721         self.assertEqual(a, b)
    722 
    723         self.gen.seed(9035768)
    724         c = self.gen.choices(population, cum_weights=cum_weights, k=10000)
    725         self.assertEqual(a, c)
    726 
    727 def gamma(z, sqrt2pi=(2.0*pi)**0.5):
    728     # Reflection to right half of complex plane
    729     if z < 0.5:
    730         return pi / sin(pi*z) / gamma(1.0-z)
    731     # Lanczos approximation with g=7
    732     az = z + (7.0 - 0.5)
    733     return az ** (z-0.5) / exp(az) * sqrt2pi * fsum([
    734         0.9999999999995183,
    735         676.5203681218835 / z,
    736         -1259.139216722289 / (z+1.0),
    737         771.3234287757674 / (z+2.0),
    738         -176.6150291498386 / (z+3.0),
    739         12.50734324009056 / (z+4.0),
    740         -0.1385710331296526 / (z+5.0),
    741         0.9934937113930748e-05 / (z+6.0),
    742         0.1659470187408462e-06 / (z+7.0),
    743     ])
    744 
    745 class TestDistributions(unittest.TestCase):
    746     def test_zeroinputs(self):
    747         # Verify that distributions can handle a series of zero inputs'
    748         g = random.Random()
    749         x = [g.random() for i in range(50)] + [0.0]*5
    750         g.random = x[:].pop; g.uniform(1,10)
    751         g.random = x[:].pop; g.paretovariate(1.0)
    752         g.random = x[:].pop; g.expovariate(1.0)
    753         g.random = x[:].pop; g.weibullvariate(1.0, 1.0)
    754         g.random = x[:].pop; g.vonmisesvariate(1.0, 1.0)
    755         g.random = x[:].pop; g.normalvariate(0.0, 1.0)
    756         g.random = x[:].pop; g.gauss(0.0, 1.0)
    757         g.random = x[:].pop; g.lognormvariate(0.0, 1.0)
    758         g.random = x[:].pop; g.vonmisesvariate(0.0, 1.0)
    759         g.random = x[:].pop; g.gammavariate(0.01, 1.0)
    760         g.random = x[:].pop; g.gammavariate(1.0, 1.0)
    761         g.random = x[:].pop; g.gammavariate(200.0, 1.0)
    762         g.random = x[:].pop; g.betavariate(3.0, 3.0)
    763         g.random = x[:].pop; g.triangular(0.0, 1.0, 1.0/3.0)
    764 
    765     def test_avg_std(self):
    766         # Use integration to test distribution average and standard deviation.
    767         # Only works for distributions which do not consume variates in pairs
    768         g = random.Random()
    769         N = 5000
    770         x = [i/float(N) for i in range(1,N)]
    771         for variate, args, mu, sigmasqrd in [
    772                 (g.uniform, (1.0,10.0), (10.0+1.0)/2, (10.0-1.0)**2/12),
    773                 (g.triangular, (0.0, 1.0, 1.0/3.0), 4.0/9.0, 7.0/9.0/18.0),
    774                 (g.expovariate, (1.5,), 1/1.5, 1/1.5**2),
    775                 (g.vonmisesvariate, (1.23, 0), pi, pi**2/3),
    776                 (g.paretovariate, (5.0,), 5.0/(5.0-1),
    777                                   5.0/((5.0-1)**2*(5.0-2))),
    778                 (g.weibullvariate, (1.0, 3.0), gamma(1+1/3.0),
    779                                   gamma(1+2/3.0)-gamma(1+1/3.0)**2) ]:
    780             g.random = x[:].pop
    781             y = []
    782             for i in range(len(x)):
    783                 try:
    784                     y.append(variate(*args))
    785                 except IndexError:
    786                     pass
    787             s1 = s2 = 0
    788             for e in y:
    789                 s1 += e
    790                 s2 += (e - mu) ** 2
    791             N = len(y)
    792             self.assertAlmostEqual(s1/N, mu, places=2,
    793                                    msg='%s%r' % (variate.__name__, args))
    794             self.assertAlmostEqual(s2/(N-1), sigmasqrd, places=2,
    795                                    msg='%s%r' % (variate.__name__, args))
    796 
    797     def test_constant(self):
    798         g = random.Random()
    799         N = 100
    800         for variate, args, expected in [
    801                 (g.uniform, (10.0, 10.0), 10.0),
    802                 (g.triangular, (10.0, 10.0), 10.0),
    803                 (g.triangular, (10.0, 10.0, 10.0), 10.0),
    804                 (g.expovariate, (float('inf'),), 0.0),
    805                 (g.vonmisesvariate, (3.0, float('inf')), 3.0),
    806                 (g.gauss, (10.0, 0.0), 10.0),
    807                 (g.lognormvariate, (0.0, 0.0), 1.0),
    808                 (g.lognormvariate, (-float('inf'), 0.0), 0.0),
    809                 (g.normalvariate, (10.0, 0.0), 10.0),
    810                 (g.paretovariate, (float('inf'),), 1.0),
    811                 (g.weibullvariate, (10.0, float('inf')), 10.0),
    812                 (g.weibullvariate, (0.0, 10.0), 0.0),
    813             ]:
    814             for i in range(N):
    815                 self.assertEqual(variate(*args), expected)
    816 
    817     def test_von_mises_range(self):
    818         # Issue 17149: von mises variates were not consistently in the
    819         # range [0, 2*PI].
    820         g = random.Random()
    821         N = 100
    822         for mu in 0.0, 0.1, 3.1, 6.2:
    823             for kappa in 0.0, 2.3, 500.0:
    824                 for _ in range(N):
    825                     sample = g.vonmisesvariate(mu, kappa)
    826                     self.assertTrue(
    827                         0 <= sample <= random.TWOPI,
    828                         msg=("vonmisesvariate({}, {}) produced a result {} out"
    829                              " of range [0, 2*pi]").format(mu, kappa, sample))
    830 
    831     def test_von_mises_large_kappa(self):
    832         # Issue #17141: vonmisesvariate() was hang for large kappas
    833         random.vonmisesvariate(0, 1e15)
    834         random.vonmisesvariate(0, 1e100)
    835 
    836     def test_gammavariate_errors(self):
    837         # Both alpha and beta must be > 0.0
    838         self.assertRaises(ValueError, random.gammavariate, -1, 3)
    839         self.assertRaises(ValueError, random.gammavariate, 0, 2)
    840         self.assertRaises(ValueError, random.gammavariate, 2, 0)
    841         self.assertRaises(ValueError, random.gammavariate, 1, -3)
    842 
    843     @unittest.mock.patch('random.Random.random')
    844     def test_gammavariate_full_code_coverage(self, random_mock):
    845         # There are three different possibilities in the current implementation
    846         # of random.gammavariate(), depending on the value of 'alpha'. What we
    847         # are going to do here is to fix the values returned by random() to
    848         # generate test cases that provide 100% line coverage of the method.
    849 
    850         # #1: alpha > 1.0: we want the first random number to be outside the
    851         # [1e-7, .9999999] range, so that the continue statement executes
    852         # once. The values of u1 and u2 will be 0.5 and 0.3, respectively.
    853         random_mock.side_effect = [1e-8, 0.5, 0.3]
    854         returned_value = random.gammavariate(1.1, 2.3)
    855         self.assertAlmostEqual(returned_value, 2.53)
    856 
    857         # #2: alpha == 1: first random number less than 1e-7 to that the body
    858         # of the while loop executes once. Then random.random() returns 0.45,
    859         # which causes while to stop looping and the algorithm to terminate.
    860         random_mock.side_effect = [1e-8, 0.45]
    861         returned_value = random.gammavariate(1.0, 3.14)
    862         self.assertAlmostEqual(returned_value, 2.507314166123803)
    863 
    864         # #3: 0 < alpha < 1. This is the most complex region of code to cover,
    865         # as there are multiple if-else statements. Let's take a look at the
    866         # source code, and determine the values that we need accordingly:
    867         #
    868         # while 1:
    869         #     u = random()
    870         #     b = (_e + alpha)/_e
    871         #     p = b*u
    872         #     if p <= 1.0: # <=== (A)
    873         #         x = p ** (1.0/alpha)
    874         #     else: # <=== (B)
    875         #         x = -_log((b-p)/alpha)
    876         #     u1 = random()
    877         #     if p > 1.0: # <=== (C)
    878         #         if u1 <= x ** (alpha - 1.0): # <=== (D)
    879         #             break
    880         #     elif u1 <= _exp(-x): # <=== (E)
    881         #         break
    882         # return x * beta
    883         #
    884         # First, we want (A) to be True. For that we need that:
    885         # b*random() <= 1.0
    886         # r1 = random() <= 1.0 / b
    887         #
    888         # We now get to the second if-else branch, and here, since p <= 1.0,
    889         # (C) is False and we take the elif branch, (E). For it to be True,
    890         # so that the break is executed, we need that:
    891         # r2 = random() <= _exp(-x)
    892         # r2 <= _exp(-(p ** (1.0/alpha)))
    893         # r2 <= _exp(-((b*r1) ** (1.0/alpha)))
    894 
    895         _e = random._e
    896         _exp = random._exp
    897         _log = random._log
    898         alpha = 0.35
    899         beta = 1.45
    900         b = (_e + alpha)/_e
    901         epsilon = 0.01
    902 
    903         r1 = 0.8859296441566 # 1.0 / b
    904         r2 = 0.3678794411714 # _exp(-((b*r1) ** (1.0/alpha)))
    905 
    906         # These four "random" values result in the following trace:
    907         # (A) True, (E) False --> [next iteration of while]
    908         # (A) True, (E) True --> [while loop breaks]
    909         random_mock.side_effect = [r1, r2 + epsilon, r1, r2]
    910         returned_value = random.gammavariate(alpha, beta)
    911         self.assertAlmostEqual(returned_value, 1.4499999999997544)
    912 
    913         # Let's now make (A) be False. If this is the case, when we get to the
    914         # second if-else 'p' is greater than 1, so (C) evaluates to True. We
    915         # now encounter a second if statement, (D), which in order to execute
    916         # must satisfy the following condition:
    917         # r2 <= x ** (alpha - 1.0)
    918         # r2 <= (-_log((b-p)/alpha)) ** (alpha - 1.0)
    919         # r2 <= (-_log((b-(b*r1))/alpha)) ** (alpha - 1.0)
    920         r1 = 0.8959296441566 # (1.0 / b) + epsilon -- so that (A) is False
    921         r2 = 0.9445400408898141
    922 
    923         # And these four values result in the following trace:
    924         # (B) and (C) True, (D) False --> [next iteration of while]
    925         # (B) and (C) True, (D) True [while loop breaks]
    926         random_mock.side_effect = [r1, r2 + epsilon, r1, r2]
    927         returned_value = random.gammavariate(alpha, beta)
    928         self.assertAlmostEqual(returned_value, 1.5830349561760781)
    929 
    930     @unittest.mock.patch('random.Random.gammavariate')
    931     def test_betavariate_return_zero(self, gammavariate_mock):
    932         # betavariate() returns zero when the Gamma distribution
    933         # that it uses internally returns this same value.
    934         gammavariate_mock.return_value = 0.0
    935         self.assertEqual(0.0, random.betavariate(2.71828, 3.14159))
    936 
    937 class TestModule(unittest.TestCase):
    938     def testMagicConstants(self):
    939         self.assertAlmostEqual(random.NV_MAGICCONST, 1.71552776992141)
    940         self.assertAlmostEqual(random.TWOPI, 6.28318530718)
    941         self.assertAlmostEqual(random.LOG4, 1.38629436111989)
    942         self.assertAlmostEqual(random.SG_MAGICCONST, 2.50407739677627)
    943 
    944     def test__all__(self):
    945         # tests validity but not completeness of the __all__ list
    946         self.assertTrue(set(random.__all__) <= set(dir(random)))
    947 
    948     def test_random_subclass_with_kwargs(self):
    949         # SF bug #1486663 -- this used to erroneously raise a TypeError
    950         class Subclass(random.Random):
    951             def __init__(self, newarg=None):
    952                 random.Random.__init__(self)
    953         Subclass(newarg=1)
    954 
    955     @unittest.skipUnless(hasattr(os, "fork"), "fork() required")
    956     def test_after_fork(self):
    957         # Test the global Random instance gets reseeded in child
    958         r, w = os.pipe()
    959         pid = os.fork()
    960         if pid == 0:
    961             # child process
    962             try:
    963                 val = random.getrandbits(128)
    964                 with open(w, "w") as f:
    965                     f.write(str(val))
    966             finally:
    967                 os._exit(0)
    968         else:
    969             # parent process
    970             os.close(w)
    971             val = random.getrandbits(128)
    972             with open(r, "r") as f:
    973                 child_val = eval(f.read())
    974             self.assertNotEqual(val, child_val)
    975 
    976             pid, status = os.waitpid(pid, 0)
    977             self.assertEqual(status, 0)
    978 
    979 
    980 if __name__ == "__main__":
    981     unittest.main()
    982