1 ## Copyright 2002 Andrew Loewenstern, All Rights Reserved
4 from whrandom import randrange
6 ## takes a 20 bit hash, big-endian, and returns it expressed a long python integer
8 assert(len(hstr) == 20)
9 return eval('0x' + hstr.encode('hex') + 'L')
11 ## takes a long int and returns a 20-character string
16 str = str.decode('hex')
17 return (20 - len(str)) *'\x00' + str
19 ## returns the distance between two 160-bit hashes expressed as 20-character strings
21 return intify(a) ^ intify(b)
24 ## returns a new pseudorandom globally unique ID string
28 h.update(chr(randrange(0,256)))
31 def newIDInRange(min, max):
32 return stringify(randRange(min,max))
34 def randRange(min, max):
35 return min + intify(newID()) % (max - min)
39 class NewID(unittest.TestCase):
41 self.assertEqual(len(newID()), 20)
42 def testHundreds(self):
46 class Intify(unittest.TestCase):
47 known = [('\0' * 20, 0),
48 ('\xff' * 20, 2L**160 - 1),
51 for str, value in self.known:
52 self.assertEqual(intify(str), value)
53 def testEndianessOnce(self):
55 while h[-1] == '\xff':
57 k = h[:-1] + chr(ord(h[-1]) + 1)
58 self.assertEqual(intify(k) - intify(h), 1)
59 def testEndianessLots(self):
61 self.testEndianessOnce()
63 class Disantance(unittest.TestCase):
65 (("\0" * 20, "\xff" * 20), 2**160L -1),
66 ((sha("foo").digest(), sha("foo").digest()), 0),
67 ((sha("bar").digest(), sha("bar").digest()), 0)
70 for pair, dist in self.known:
71 self.assertEqual(distance(pair[0], pair[1]), dist)
72 def testCommutitive(self):
74 x, y, z = newID(), newID(), newID()
75 self.assertEqual(distance(x,y) ^ distance(y, z), distance(x, z))
77 class RandRange(unittest.TestCase):
83 self.assertEqual(a <= c < b, 1, "output out of range %d %d %d" % (b, c, a))
86 assert b <= c < a, "output out of range %d %d %d" % (b, c, a)
88 def testOneHundredTimes(self):
94 if __name__ == '__main__':