summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-04-17 17:05:35 (GMT)
committerGitHub <noreply@github.com>2020-04-17 17:05:35 (GMT)
commit9f5fe7910f4a1bf5a425837d4915e332b945eb7b (patch)
tree5f652699332e33a81cf6baa5ff5b6fecadea1903 /Lib/test
parent22386bb4ef740ee92d34c87b8cb90d681423a853 (diff)
downloadcpython-9f5fe7910f4a1bf5a425837d4915e332b945eb7b.zip
cpython-9f5fe7910f4a1bf5a425837d4915e332b945eb7b.tar.gz
cpython-9f5fe7910f4a1bf5a425837d4915e332b945eb7b.tar.bz2
bpo-40286: Add randbytes() method to random.Random (GH-19527)
Add random.randbytes() function and random.Random.randbytes() method to generate random bytes. Modify secrets.token_bytes() to use SystemRandom.randbytes() rather than calling directly os.urandom(). Rename also genrand_int32() to genrand_uint32(), since it returns an unsigned 32-bit integer, not a signed integer. The _random module is now built with Py_BUILD_CORE_MODULE defined.
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/test_random.py51
1 files changed, 51 insertions, 0 deletions
diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py
index 548af70..f709e52 100644
--- a/Lib/test/test_random.py
+++ b/Lib/test/test_random.py
@@ -291,6 +291,22 @@ class TestBasicOps:
k = sum(randrange(6755399441055744) % 3 == 2 for i in range(n))
self.assertTrue(0.30 < k/n < .37, (k/n))
+ def test_randbytes(self):
+ # Verify ranges
+ for n in range(1, 10):
+ data = self.gen.randbytes(n)
+ self.assertEqual(type(data), bytes)
+ self.assertEqual(len(data), n)
+
+ self.assertEqual(self.gen.randbytes(0), b'')
+
+ # Verify argument checking
+ self.assertRaises(TypeError, self.gen.randbytes)
+ self.assertRaises(TypeError, self.gen.randbytes, 1, 2)
+ self.assertRaises(ValueError, self.gen.randbytes, -1)
+ self.assertRaises(TypeError, self.gen.randbytes, 1.0)
+
+
try:
random.SystemRandom().random()
except NotImplementedError:
@@ -747,6 +763,41 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
c = self.gen.choices(population, cum_weights=cum_weights, k=10000)
self.assertEqual(a, c)
+ def test_randbytes(self):
+ super().test_randbytes()
+
+ # Mersenne Twister randbytes() is deterministic
+ # and does not depend on the endian and bitness.
+ seed = 8675309
+ expected = b'f\xf9\xa836\xd0\xa4\xf4\x82\x9f\x8f\x19\xf0eo\x02'
+
+ self.gen.seed(seed)
+ self.assertEqual(self.gen.randbytes(16), expected)
+
+ # randbytes(0) must not consume any entropy
+ self.gen.seed(seed)
+ self.assertEqual(self.gen.randbytes(0), b'')
+ self.assertEqual(self.gen.randbytes(16), expected)
+
+ # Four randbytes(4) calls give the same output than randbytes(16)
+ self.gen.seed(seed)
+ self.assertEqual(b''.join([self.gen.randbytes(4) for _ in range(4)]),
+ expected)
+
+ # Each randbytes(2) or randbytes(3) call consumes 4 bytes of entropy
+ self.gen.seed(seed)
+ expected2 = b''.join(expected[i:i + 2]
+ for i in range(0, len(expected), 4))
+ self.assertEqual(b''.join(self.gen.randbytes(2) for _ in range(4)),
+ expected2)
+
+ self.gen.seed(seed)
+ expected3 = b''.join(expected[i:i + 3]
+ for i in range(0, len(expected), 4))
+ self.assertEqual(b''.join(self.gen.randbytes(3) for _ in range(4)),
+ expected3)
+
+
def gamma(z, sqrt2pi=(2.0*pi)**0.5):
# Reflection to right half of complex plane
if z < 0.5: