test the secrets module as most of the functions in secrets are thin wrappers around functions defined elsewhere we don t need to test them exhaustively unit tests test secrets comparedigest function def testequalself test comparedigest functionality with equal bytetext strings for s in a bcd xyz123 a s100 b s100 self asserttruesecrets comparedigesta b self asserttruesecrets comparedigesta encode utf8 b encode utf8 def testunequalself test comparedigest functionality with unequal bytetext strings self assertfalsesecrets comparedigestabc abcd self assertfalsesecrets comparedigestbabc babcd for s in x mn a1b2c3 a s100 q b s100 k self assertfalsesecrets comparedigesta b self assertfalsesecrets comparedigesta encode utf8 b encode utf8 def testbadtypesself test that comparedigest raises with mixed types a abcde b a encode utf8 assert isinstancea str assert isinstanceb bytes self assertraisestypeerror secrets comparedigest a b self assertraisestypeerror secrets comparedigest b a def testboolself test that comparedigest returns a bool self assertisinstancesecrets comparedigestabc abc bool self assertisinstancesecrets comparedigestabc xyz bool class randomtestsunittest testcase test randbits test choice test randbelow test token functions def testtokendefaultsself test that token functions handle default size correctly for func in secrets tokenbytes secrets tokenhex secrets tokenurlsafe with self subtestfuncfunc name func name try func except typeerror self fails cannot be called with no argument name try funcnone except typeerror self fails cannot be called with none name size secrets defaultentropy self assertequallensecrets tokenbytesnone size self assertequallensecrets tokenhexnone 2size def testtokenbytesself test tokenbytes for n in 1 8 17 100 with self subtestnn self assertisinstancesecrets tokenbytesn bytes self assertequallensecrets tokenbytesn n def testtokenhexself test tokenhex for n in 1 12 25 90 with self subtestnn s secrets tokenhexn self assertisinstances str self assertequallens 2n self asserttrueallc in string hexdigits for c in s def testtokenurlsafeself test tokenurlsafe legal string asciiletters string digits for n in 1 11 28 76 with self subtestnn s secrets tokenurlsafen self assertisinstances str self asserttrueallc in legal for c in s if name main unittest main unit tests test secrets compare_digest function test compare_digest functionality with equal byte text strings test compare_digest functionality with unequal byte text strings test that compare_digest raises with mixed types test that compare_digest returns a bool test wrappers around systemrandom methods test randbits test choice test randbelow test token functions test that token_ functions handle default size correctly test token_bytes test token_hex test token_urlsafe
import secrets
import unittest
import string




class Compare_Digest_Tests(unittest.TestCase):
    

    def test_equal(self):
        
        for s in ("a", "bcd", "xyz123"):
            a = s*100
            b = s*100
            self.assertTrue(secrets.compare_digest(a, b))
            self.assertTrue(secrets.compare_digest(a.encode('utf-8'), b.encode('utf-8')))

    def test_unequal(self):
        
        self.assertFalse(secrets.compare_digest("abc", "abcd"))
        self.assertFalse(secrets.compare_digest(b"abc", b"abcd"))
        for s in ("x", "mn", "a1b2c3"):
            a = s*100 + "q"
            b = s*100 + "k"
            self.assertFalse(secrets.compare_digest(a, b))
            self.assertFalse(secrets.compare_digest(a.encode('utf-8'), b.encode('utf-8')))

    def test_bad_types(self):
        
        a = 'abcde'
        b = a.encode('utf-8')
        assert isinstance(a, str)
        assert isinstance(b, bytes)
        self.assertRaises(TypeError, secrets.compare_digest, a, b)
        self.assertRaises(TypeError, secrets.compare_digest, b, a)

    def test_bool(self):
        
        self.assertIsInstance(secrets.compare_digest("abc", "abc"), bool)
        self.assertIsInstance(secrets.compare_digest("abc", "xyz"), bool)


class Random_Tests(unittest.TestCase):
    

    def test_randbits(self):
        
        errmsg = "randbits(%d) returned %d"
        for numbits in (3, 12, 30):
            for i in range(6):
                n = secrets.randbits(numbits)
                self.assertTrue(0 <= n < 2**numbits, errmsg % (numbits, n))

    def test_choice(self):
        
        items = [1, 2, 4, 8, 16, 32, 64]
        for i in range(10):
            self.assertTrue(secrets.choice(items) in items)

    def test_randbelow(self):
        
        for i in range(2, 10):
            self.assertIn(secrets.randbelow(i), range(i))
        self.assertRaises(ValueError, secrets.randbelow, 0)
        self.assertRaises(ValueError, secrets.randbelow, -1)


class Token_Tests(unittest.TestCase):
    

    def test_token_defaults(self):
        
        for func in (secrets.token_bytes, secrets.token_hex,
                     secrets.token_urlsafe):
            with self.subTest(func=func):
                name = func.__name__
                try:
                    func()
                except TypeError:
                    self.fail("%s cannot be called with no argument" % name)
                try:
                    func(None)
                except TypeError:
                    self.fail("%s cannot be called with None" % name)
        size = secrets.DEFAULT_ENTROPY
        self.assertEqual(len(secrets.token_bytes(None)), size)
        self.assertEqual(len(secrets.token_hex(None)), 2*size)

    def test_token_bytes(self):
        
        for n in (1, 8, 17, 100):
            with self.subTest(n=n):
                self.assertIsInstance(secrets.token_bytes(n), bytes)
                self.assertEqual(len(secrets.token_bytes(n)), n)

    def test_token_hex(self):
        
        for n in (1, 12, 25, 90):
            with self.subTest(n=n):
                s = secrets.token_hex(n)
                self.assertIsInstance(s, str)
                self.assertEqual(len(s), 2*n)
                self.assertTrue(all(c in string.hexdigits for c in s))

    def test_token_urlsafe(self):
        
        legal = string.ascii_letters + string.digits + '-_'
        for n in (1, 11, 28, 76):
            with self.subTest(n=n):
                s = secrets.token_urlsafe(n)
                self.assertIsInstance(s, str)
                self.assertTrue(all(c in legal for c in s))


if __name__ == '__main__':
    unittest.main()