1 ## Copyright 2002-2003 Andrew Loewenstern, All Rights Reserved
2 # see LICENSE.txt for license information
7 #this is ugly, hopefully os.entropy will be in 2.4
9 from entropy import entropy
14 s += chr(whrandom.randint(0,255))
18 """20 bit hash, big-endian -> long python integer"""
19 assert len(hstr) == 20
20 return long(hstr.encode('hex'), 16)
23 """long int -> 20-character string"""
29 str = str.decode('hex')
30 return (20 - len(str)) *'\x00' + str
33 """distance between two 160-bit hashes expressed as 20-character strings"""
34 return intify(a) ^ intify(b)
38 """returns a new pseudorandom globally unique ID string"""
43 def newIDInRange(min, max):
44 return stringify(randRange(min,max))
46 def randRange(min, max):
47 return min + intify(newID()) % (max - min)
50 return randRange(-2**30, 2**30)
55 class NewID(unittest.TestCase):
57 self.assertEqual(len(newID()), 20)
58 def testHundreds(self):
62 class Intify(unittest.TestCase):
63 known = [('\0' * 20, 0),
64 ('\xff' * 20, 2L**160 - 1),
67 for str, value in self.known:
68 self.assertEqual(intify(str), value)
69 def testEndianessOnce(self):
71 while h[-1] == '\xff':
73 k = h[:-1] + chr(ord(h[-1]) + 1)
74 self.assertEqual(intify(k) - intify(h), 1)
75 def testEndianessLots(self):
77 self.testEndianessOnce()
79 class Disantance(unittest.TestCase):
81 (("\0" * 20, "\xff" * 20), 2**160L -1),
82 ((sha("foo").digest(), sha("foo").digest()), 0),
83 ((sha("bar").digest(), sha("bar").digest()), 0)
86 for pair, dist in self.known:
87 self.assertEqual(distance(pair[0], pair[1]), dist)
88 def testCommutitive(self):
90 x, y, z = newID(), newID(), newID()
91 self.assertEqual(distance(x,y) ^ distance(y, z), distance(x, z))
93 class RandRange(unittest.TestCase):
99 self.assertEqual(a <= c < b, 1, "output out of range %d %d %d" % (b, c, a))
102 assert b <= c < a, "output out of range %d %d %d" % (b, c, a)
104 def testOneHundredTimes(self):
105 for i in xrange(100):
110 if __name__ == '__main__':