2 def foo(): pass # keep the line number constant
5 from StringIO import StringIO
6 from twisted.trial import unittest
7 from twisted.internet import defer, reactor
8 from twisted.python.failure import Failure
10 from allmydata.util import base32, idlib, humanreadable, mathutil, hashutil
11 from allmydata.util import assertutil, fileutil, deferredutil, abbreviate
12 from allmydata.util import limiter, time_format, pollmixin, cachedir
13 from allmydata.util import statistics, dictutil, rrefutil
14 from allmydata.util.rrefutil import ServerFailure
16 class Base32(unittest.TestCase):
17 def test_b2a_matches_Pythons(self):
19 y = "\x12\x34\x45\x67\x89\x0a\xbc\xde\xf0"
20 x = base64.b32encode(y)
21 while x and x[-1] == '=':
24 self.failUnlessEqual(base32.b2a(y), x)
26 self.failUnlessEqual(base32.b2a("\x12\x34"), "ci2a")
27 def test_b2a_or_none(self):
28 self.failUnlessEqual(base32.b2a_or_none(None), None)
29 self.failUnlessEqual(base32.b2a_or_none("\x12\x34"), "ci2a")
31 self.failUnlessEqual(base32.a2b("ci2a"), "\x12\x34")
32 self.failUnlessRaises(AssertionError, base32.a2b, "b0gus")
34 class IDLib(unittest.TestCase):
35 def test_nodeid_b2a(self):
36 self.failUnlessEqual(idlib.nodeid_b2a("\x00"*20), "a"*32)
38 class NoArgumentException(Exception):
42 class HumanReadable(unittest.TestCase):
45 self.failUnlessEqual(hr(foo), "<foo() at test_util.py:2>")
46 self.failUnlessEqual(hr(self.test_repr),
47 "<bound method HumanReadable.test_repr of <allmydata.test.test_util.HumanReadable testMethod=test_repr>>")
48 self.failUnlessEqual(hr(1L), "1")
49 self.failUnlessEqual(hr(10**40),
50 "100000000000000000...000000000000000000")
51 self.failUnlessEqual(hr(self), "<allmydata.test.test_util.HumanReadable testMethod=test_repr>")
52 self.failUnlessEqual(hr([1,2]), "[1, 2]")
53 self.failUnlessEqual(hr({1:2}), "{1:2}")
58 hr(e) == "<ValueError: ()>" # python-2.4
59 or hr(e) == "ValueError()") # python-2.5
61 raise ValueError("oops")
64 hr(e) == "<ValueError: 'oops'>" # python-2.4
65 or hr(e) == "ValueError('oops',)") # python-2.5
67 raise NoArgumentException
70 hr(e) == "<NoArgumentException>" # python-2.4
71 or hr(e) == "NoArgumentException()") # python-2.5
77 class Math(unittest.TestCase):
78 def test_div_ceil(self):
80 self.failUnlessEqual(f(0, 1), 0)
81 self.failUnlessEqual(f(0, 2), 0)
82 self.failUnlessEqual(f(0, 3), 0)
83 self.failUnlessEqual(f(1, 3), 1)
84 self.failUnlessEqual(f(2, 3), 1)
85 self.failUnlessEqual(f(3, 3), 1)
86 self.failUnlessEqual(f(4, 3), 2)
87 self.failUnlessEqual(f(5, 3), 2)
88 self.failUnlessEqual(f(6, 3), 2)
89 self.failUnlessEqual(f(7, 3), 3)
91 def test_next_multiple(self):
92 f = mathutil.next_multiple
93 self.failUnlessEqual(f(5, 1), 5)
94 self.failUnlessEqual(f(5, 2), 6)
95 self.failUnlessEqual(f(5, 3), 6)
96 self.failUnlessEqual(f(5, 4), 8)
97 self.failUnlessEqual(f(5, 5), 5)
98 self.failUnlessEqual(f(5, 6), 6)
99 self.failUnlessEqual(f(32, 1), 32)
100 self.failUnlessEqual(f(32, 2), 32)
101 self.failUnlessEqual(f(32, 3), 33)
102 self.failUnlessEqual(f(32, 4), 32)
103 self.failUnlessEqual(f(32, 5), 35)
104 self.failUnlessEqual(f(32, 6), 36)
105 self.failUnlessEqual(f(32, 7), 35)
106 self.failUnlessEqual(f(32, 8), 32)
107 self.failUnlessEqual(f(32, 9), 36)
108 self.failUnlessEqual(f(32, 10), 40)
109 self.failUnlessEqual(f(32, 11), 33)
110 self.failUnlessEqual(f(32, 12), 36)
111 self.failUnlessEqual(f(32, 13), 39)
112 self.failUnlessEqual(f(32, 14), 42)
113 self.failUnlessEqual(f(32, 15), 45)
114 self.failUnlessEqual(f(32, 16), 32)
115 self.failUnlessEqual(f(32, 17), 34)
116 self.failUnlessEqual(f(32, 18), 36)
117 self.failUnlessEqual(f(32, 589), 589)
119 def test_pad_size(self):
120 f = mathutil.pad_size
121 self.failUnlessEqual(f(0, 4), 0)
122 self.failUnlessEqual(f(1, 4), 3)
123 self.failUnlessEqual(f(2, 4), 2)
124 self.failUnlessEqual(f(3, 4), 1)
125 self.failUnlessEqual(f(4, 4), 0)
126 self.failUnlessEqual(f(5, 4), 3)
128 def test_is_power_of_k(self):
129 f = mathutil.is_power_of_k
130 for i in range(1, 100):
131 if i in (1, 2, 4, 8, 16, 32, 64):
132 self.failUnless(f(i, 2), "but %d *is* a power of 2" % i)
134 self.failIf(f(i, 2), "but %d is *not* a power of 2" % i)
135 for i in range(1, 100):
136 if i in (1, 3, 9, 27, 81):
137 self.failUnless(f(i, 3), "but %d *is* a power of 3" % i)
139 self.failIf(f(i, 3), "but %d is *not* a power of 3" % i)
141 def test_next_power_of_k(self):
142 f = mathutil.next_power_of_k
143 self.failUnlessEqual(f(0,2), 1)
144 self.failUnlessEqual(f(1,2), 1)
145 self.failUnlessEqual(f(2,2), 2)
146 self.failUnlessEqual(f(3,2), 4)
147 self.failUnlessEqual(f(4,2), 4)
148 for i in range(5, 8): self.failUnlessEqual(f(i,2), 8, "%d" % i)
149 for i in range(9, 16): self.failUnlessEqual(f(i,2), 16, "%d" % i)
150 for i in range(17, 32): self.failUnlessEqual(f(i,2), 32, "%d" % i)
151 for i in range(33, 64): self.failUnlessEqual(f(i,2), 64, "%d" % i)
152 for i in range(65, 100): self.failUnlessEqual(f(i,2), 128, "%d" % i)
154 self.failUnlessEqual(f(0,3), 1)
155 self.failUnlessEqual(f(1,3), 1)
156 self.failUnlessEqual(f(2,3), 3)
157 self.failUnlessEqual(f(3,3), 3)
158 for i in range(4, 9): self.failUnlessEqual(f(i,3), 9, "%d" % i)
159 for i in range(10, 27): self.failUnlessEqual(f(i,3), 27, "%d" % i)
160 for i in range(28, 81): self.failUnlessEqual(f(i,3), 81, "%d" % i)
161 for i in range(82, 200): self.failUnlessEqual(f(i,3), 243, "%d" % i)
165 self.failUnlessEqual(f([1,2,3]), 2)
166 self.failUnlessEqual(f([0,0,0,4]), 1)
167 self.failUnlessAlmostEqual(f([0.0, 1.0, 1.0]), .666666666666)
169 def test_round_sigfigs(self):
170 f = mathutil.round_sigfigs
171 self.failUnlessEqual(f(22.0/3, 4), 7.3330000000000002)
173 class Statistics(unittest.TestCase):
174 def should_assert(self, msg, func, *args, **kwargs):
176 func(*args, **kwargs)
178 except AssertionError, e:
181 def failUnlessListEqual(self, a, b, msg = None):
182 self.failUnlessEqual(len(a), len(b))
183 for i in range(len(a)):
184 self.failUnlessEqual(a[i], b[i], msg)
186 def failUnlessListAlmostEqual(self, a, b, places = 7, msg = None):
187 self.failUnlessEqual(len(a), len(b))
188 for i in range(len(a)):
189 self.failUnlessAlmostEqual(a[i], b[i], places, msg)
191 def test_binomial_coeff(self):
192 f = statistics.binomial_coeff
193 self.failUnlessEqual(f(20, 0), 1)
194 self.failUnlessEqual(f(20, 1), 20)
195 self.failUnlessEqual(f(20, 2), 190)
196 self.failUnlessEqual(f(20, 8), f(20, 12))
197 self.should_assert("Should assert if n < k", f, 2, 3)
199 def test_binomial_distribution_pmf(self):
200 f = statistics.binomial_distribution_pmf
203 pmf_stat = [0.81, 0.18, 0.01]
204 self.failUnlessListAlmostEqual(pmf_comp, pmf_stat)
206 # Summing across a PMF should give the total probability 1
207 self.failUnlessAlmostEqual(sum(pmf_comp), 1)
208 self.should_assert("Should assert if not 0<=p<=1", f, 1, -1)
209 self.should_assert("Should assert if n < 1", f, 0, .1)
212 statistics.print_pmf(pmf_comp, out=out)
213 lines = out.getvalue().splitlines()
214 self.failUnlessEqual(lines[0], "i=0: 0.81")
215 self.failUnlessEqual(lines[1], "i=1: 0.18")
216 self.failUnlessEqual(lines[2], "i=2: 0.01")
218 def test_survival_pmf(self):
219 f = statistics.survival_pmf
220 # Cross-check binomial-distribution method against convolution
222 p_list = [.9999] * 100 + [.99] * 50 + [.8] * 20
223 pmf1 = statistics.survival_pmf_via_conv(p_list)
224 pmf2 = statistics.survival_pmf_via_bd(p_list)
225 self.failUnlessListAlmostEqual(pmf1, pmf2)
226 self.failUnlessTrue(statistics.valid_pmf(pmf1))
227 self.should_assert("Should assert if p_i > 1", f, [1.1]);
228 self.should_assert("Should assert if p_i < 0", f, [-.1]);
230 def test_repair_count_pmf(self):
231 survival_pmf = statistics.binomial_distribution_pmf(5, .9)
232 repair_pmf = statistics.repair_count_pmf(survival_pmf, 3)
233 # repair_pmf[0] == sum(survival_pmf[0,1,2,5])
234 # repair_pmf[1] == survival_pmf[4]
235 # repair_pmf[2] = survival_pmf[3]
236 self.failUnlessListAlmostEqual(repair_pmf,
237 [0.00001 + 0.00045 + 0.0081 + 0.59049,
242 def test_repair_cost(self):
243 survival_pmf = statistics.binomial_distribution_pmf(5, .9)
244 bwcost = statistics.bandwidth_cost_function
245 cost = statistics.mean_repair_cost(bwcost, 1000,
246 survival_pmf, 3, ul_dl_ratio=1.0)
247 self.failUnlessAlmostEqual(cost, 558.90)
248 cost = statistics.mean_repair_cost(bwcost, 1000,
249 survival_pmf, 3, ul_dl_ratio=8.0)
250 self.failUnlessAlmostEqual(cost, 1664.55)
252 # I haven't manually checked the math beyond here -warner
253 cost = statistics.eternal_repair_cost(bwcost, 1000,
255 discount_rate=0, ul_dl_ratio=1.0)
256 self.failUnlessAlmostEqual(cost, 65292.056074766246)
257 cost = statistics.eternal_repair_cost(bwcost, 1000,
261 self.failUnlessAlmostEqual(cost, 9133.6097158191551)
263 def test_convolve(self):
264 f = statistics.convolve
268 v1v2result = [ 4, 13, 28, 27, 18 ]
269 # Convolution is commutative
272 self.failUnlessListEqual(r1, r2, "Convolution should be commutative")
273 self.failUnlessListEqual(r1, v1v2result, "Didn't match known result")
274 # Convolution is associative
275 r1 = f(f(v1, v2), v3)
276 r2 = f(v1, f(v2, v3))
277 self.failUnlessListEqual(r1, r2, "Convolution should be associative")
278 # Convolution is distributive
279 r1 = f(v3, [ a + b for a, b in zip(v1, v2) ])
282 r2 = [ a + b for a, b in zip(tmp1, tmp2) ]
283 self.failUnlessListEqual(r1, r2, "Convolution should be distributive")
284 # Convolution is scalar multiplication associative
286 r1 = [ a * 4 for a in tmp1 ]
287 tmp2 = [ a * 4 for a in v1 ]
289 self.failUnlessListEqual(r1, r2, "Convolution should be scalar multiplication associative")
291 def test_find_k(self):
292 f = statistics.find_k
293 g = statistics.pr_file_loss
294 plist = [.9] * 10 + [.8] * 10 # N=20
297 self.failUnlessEqual(k, 10)
298 self.failUnless(g(plist, k) < t)
300 def test_pr_file_loss(self):
301 f = statistics.pr_file_loss
303 self.failUnlessEqual(f(plist, 3), .0546875)
305 def test_pr_backup_file_loss(self):
306 f = statistics.pr_backup_file_loss
308 self.failUnlessEqual(f(plist, .5, 3), .02734375)
311 class Asserts(unittest.TestCase):
312 def should_assert(self, func, *args, **kwargs):
314 func(*args, **kwargs)
315 except AssertionError, e:
318 self.fail("assert failed with non-AssertionError: %s" % e)
319 self.fail("assert was not caught")
321 def should_not_assert(self, func, *args, **kwargs):
323 regexp = kwargs["re"]
326 func(*args, **kwargs)
327 except AssertionError, e:
328 self.fail("assertion fired when it should not have: %s" % e)
330 self.fail("assertion (which shouldn't have failed) failed with non-AssertionError: %s" % e)
334 def test_assert(self):
335 f = assertutil._assert
336 self.should_assert(f)
337 self.should_assert(f, False)
338 self.should_not_assert(f, True)
340 m = self.should_assert(f, False, "message")
341 self.failUnlessEqual(m, "'message' <type 'str'>", m)
342 m = self.should_assert(f, False, "message1", othermsg=12)
343 self.failUnlessEqual("'message1' <type 'str'>, othermsg: 12 <type 'int'>", m)
344 m = self.should_assert(f, False, othermsg="message2")
345 self.failUnlessEqual("othermsg: 'message2' <type 'str'>", m)
347 def test_precondition(self):
348 f = assertutil.precondition
349 self.should_assert(f)
350 self.should_assert(f, False)
351 self.should_not_assert(f, True)
353 m = self.should_assert(f, False, "message")
354 self.failUnlessEqual("precondition: 'message' <type 'str'>", m)
355 m = self.should_assert(f, False, "message1", othermsg=12)
356 self.failUnlessEqual("precondition: 'message1' <type 'str'>, othermsg: 12 <type 'int'>", m)
357 m = self.should_assert(f, False, othermsg="message2")
358 self.failUnlessEqual("precondition: othermsg: 'message2' <type 'str'>", m)
360 def test_postcondition(self):
361 f = assertutil.postcondition
362 self.should_assert(f)
363 self.should_assert(f, False)
364 self.should_not_assert(f, True)
366 m = self.should_assert(f, False, "message")
367 self.failUnlessEqual("postcondition: 'message' <type 'str'>", m)
368 m = self.should_assert(f, False, "message1", othermsg=12)
369 self.failUnlessEqual("postcondition: 'message1' <type 'str'>, othermsg: 12 <type 'int'>", m)
370 m = self.should_assert(f, False, othermsg="message2")
371 self.failUnlessEqual("postcondition: othermsg: 'message2' <type 'str'>", m)
373 class FileUtil(unittest.TestCase):
374 def mkdir(self, basedir, path, mode=0777):
375 fn = os.path.join(basedir, path)
376 fileutil.make_dirs(fn, mode)
378 def touch(self, basedir, path, mode=None, data="touch\n"):
379 fn = os.path.join(basedir, path)
386 def test_rm_dir(self):
387 basedir = "util/FileUtil/test_rm_dir"
388 fileutil.make_dirs(basedir)
389 # create it again to test idempotency
390 fileutil.make_dirs(basedir)
391 d = os.path.join(basedir, "doomed")
393 self.touch(d, "a/b/1.txt")
394 self.touch(d, "a/b/2.txt", 0444)
395 self.touch(d, "a/b/3.txt", 0)
397 self.touch(d, "a/c/1.txt")
398 self.touch(d, "a/c/2.txt", 0444)
399 self.touch(d, "a/c/3.txt", 0)
400 os.chmod(os.path.join(d, "a/c"), 0444)
402 self.touch(d, "a/d/1.txt")
403 self.touch(d, "a/d/2.txt", 0444)
404 self.touch(d, "a/d/3.txt", 0)
405 os.chmod(os.path.join(d, "a/d"), 0)
408 self.failIf(os.path.exists(d))
409 # remove it again to test idempotency
412 def test_remove_if_possible(self):
413 basedir = "util/FileUtil/test_remove_if_possible"
414 fileutil.make_dirs(basedir)
415 self.touch(basedir, "here")
416 fn = os.path.join(basedir, "here")
417 fileutil.remove_if_possible(fn)
418 self.failIf(os.path.exists(fn))
419 fileutil.remove_if_possible(fn) # should be idempotent
420 fileutil.rm_dir(basedir)
421 fileutil.remove_if_possible(fn) # should survive errors
423 def test_open_or_create(self):
424 basedir = "util/FileUtil/test_open_or_create"
425 fileutil.make_dirs(basedir)
426 fn = os.path.join(basedir, "here")
427 f = fileutil.open_or_create(fn)
430 f = fileutil.open_or_create(fn)
437 self.failUnlessEqual(data, "stuff.more.")
439 def test_NamedTemporaryDirectory(self):
440 basedir = "util/FileUtil/test_NamedTemporaryDirectory"
441 fileutil.make_dirs(basedir)
442 td = fileutil.NamedTemporaryDirectory(dir=basedir)
444 self.failUnless(basedir in name)
445 self.failUnless(basedir in repr(td))
446 self.failUnless(os.path.isdir(name))
448 # it is conceivable that we need to force gc here, but I'm not sure
449 self.failIf(os.path.isdir(name))
451 def test_rename(self):
452 basedir = "util/FileUtil/test_rename"
453 fileutil.make_dirs(basedir)
454 self.touch(basedir, "here")
455 fn = os.path.join(basedir, "here")
456 fn2 = os.path.join(basedir, "there")
457 fileutil.rename(fn, fn2)
458 self.failIf(os.path.exists(fn))
459 self.failUnless(os.path.exists(fn2))
462 basedir = "util/FileUtil/test_du"
463 fileutil.make_dirs(basedir)
464 d = os.path.join(basedir, "space-consuming")
466 self.touch(d, "a/b/1.txt", data="a"*10)
467 self.touch(d, "a/b/2.txt", data="b"*11)
469 self.touch(d, "a/c/1.txt", data="c"*12)
470 self.touch(d, "a/c/2.txt", data="d"*13)
472 used = fileutil.du(basedir)
473 self.failUnlessEqual(10+11+12+13, used)
475 class PollMixinTests(unittest.TestCase):
477 self.pm = pollmixin.PollMixin()
479 def test_PollMixin_True(self):
480 d = self.pm.poll(check_f=lambda : True,
484 def test_PollMixin_False_then_True(self):
485 i = iter([False, True])
486 d = self.pm.poll(check_f=i.next,
490 def test_timeout(self):
491 d = self.pm.poll(check_f=lambda: False,
495 self.fail("poll should have failed, not returned %s" % (res,))
497 f.trap(pollmixin.TimeoutError)
498 return None # success
499 d.addCallbacks(_suc, _err)
502 class DeferredUtilTests(unittest.TestCase):
503 def test_gather_results(self):
504 d1 = defer.Deferred()
505 d2 = defer.Deferred()
506 res = deferredutil.gatherResults([d1, d2])
507 d1.errback(ValueError("BAD"))
509 self.fail("Should have errbacked, not resulted in %s" % (res,))
511 thef.trap(ValueError)
512 res.addCallbacks(_callb, _errb)
515 def test_success(self):
516 d1, d2 = defer.Deferred(), defer.Deferred()
519 dlss = deferredutil.DeferredListShouldSucceed([d1,d2])
520 dlss.addCallbacks(good.append, bad.append)
523 self.failUnlessEqual(good, [[1,2]])
524 self.failUnlessEqual(bad, [])
526 def test_failure(self):
527 d1, d2 = defer.Deferred(), defer.Deferred()
530 dlss = deferredutil.DeferredListShouldSucceed([d1,d2])
531 dlss.addCallbacks(good.append, bad.append)
532 d1.addErrback(lambda _ignore: None)
533 d2.addErrback(lambda _ignore: None)
535 d2.errback(ValueError())
536 self.failUnlessEqual(good, [])
537 self.failUnlessEqual(len(bad), 1)
539 self.failUnless(isinstance(f, Failure))
540 self.failUnless(f.check(ValueError))
542 class HashUtilTests(unittest.TestCase):
544 def test_random_key(self):
545 k = hashutil.random_key()
546 self.failUnlessEqual(len(k), hashutil.KEYLEN)
548 def test_sha256d(self):
549 h1 = hashutil.tagged_hash("tag1", "value")
550 h2 = hashutil.tagged_hasher("tag1")
554 self.failUnlessEqual(h1, h2a)
555 self.failUnlessEqual(h2a, h2b)
557 def test_sha256d_truncated(self):
558 h1 = hashutil.tagged_hash("tag1", "value", 16)
559 h2 = hashutil.tagged_hasher("tag1", 16)
562 self.failUnlessEqual(len(h1), 16)
563 self.failUnlessEqual(len(h2), 16)
564 self.failUnlessEqual(h1, h2)
567 h1 = hashutil.convergence_hash(3, 10, 1000, "data", "secret")
568 h2 = hashutil.convergence_hasher(3, 10, 1000, "secret")
571 self.failUnlessEqual(h1, h2)
573 def test_hashers(self):
574 h1 = hashutil.block_hash("foo")
575 h2 = hashutil.block_hasher()
577 self.failUnlessEqual(h1, h2.digest())
579 h1 = hashutil.uri_extension_hash("foo")
580 h2 = hashutil.uri_extension_hasher()
582 self.failUnlessEqual(h1, h2.digest())
584 h1 = hashutil.plaintext_hash("foo")
585 h2 = hashutil.plaintext_hasher()
587 self.failUnlessEqual(h1, h2.digest())
589 h1 = hashutil.crypttext_hash("foo")
590 h2 = hashutil.crypttext_hasher()
592 self.failUnlessEqual(h1, h2.digest())
594 h1 = hashutil.crypttext_segment_hash("foo")
595 h2 = hashutil.crypttext_segment_hasher()
597 self.failUnlessEqual(h1, h2.digest())
599 h1 = hashutil.plaintext_segment_hash("foo")
600 h2 = hashutil.plaintext_segment_hasher()
602 self.failUnlessEqual(h1, h2.digest())
604 class Abbreviate(unittest.TestCase):
606 a = abbreviate.abbreviate_time
607 self.failUnlessEqual(a(None), "unknown")
608 self.failUnlessEqual(a(0), "0 seconds")
609 self.failUnlessEqual(a(1), "1 second")
610 self.failUnlessEqual(a(2), "2 seconds")
611 self.failUnlessEqual(a(119), "119 seconds")
613 self.failUnlessEqual(a(2*MIN), "2 minutes")
614 self.failUnlessEqual(a(60*MIN), "60 minutes")
615 self.failUnlessEqual(a(179*MIN), "179 minutes")
617 self.failUnlessEqual(a(180*MIN), "3 hours")
618 self.failUnlessEqual(a(4*HOUR), "4 hours")
621 self.failUnlessEqual(a(2*DAY), "2 days")
622 self.failUnlessEqual(a(2*MONTH), "2 months")
624 self.failUnlessEqual(a(5*YEAR), "5 years")
626 def test_space(self):
627 tests_si = [(None, "unknown"),
634 (20*1000, "20.00 kB"),
635 (1024*1024, "1.05 MB"),
636 (1000*1000, "1.00 MB"),
637 (1000*1000*1000, "1.00 GB"),
638 (1000*1000*1000*1000, "1.00 TB"),
639 (1000*1000*1000*1000*1000, "1.00 PB"),
640 (1234567890123456, "1.23 PB"),
642 for (x, expected) in tests_si:
643 got = abbreviate.abbreviate_space(x, SI=True)
644 self.failUnlessEqual(got, expected)
646 tests_base1024 = [(None, "unknown"),
653 (20*1024, "20.00 kiB"),
654 (1000*1000, "976.56 kiB"),
655 (1024*1024, "1.00 MiB"),
656 (1024*1024*1024, "1.00 GiB"),
657 (1024*1024*1024*1024, "1.00 TiB"),
658 (1000*1000*1000*1000*1000, "909.49 TiB"),
659 (1024*1024*1024*1024*1024, "1.00 PiB"),
660 (1234567890123456, "1.10 PiB"),
662 for (x, expected) in tests_base1024:
663 got = abbreviate.abbreviate_space(x, SI=False)
664 self.failUnlessEqual(got, expected)
666 self.failUnlessEqual(abbreviate.abbreviate_space_both(1234567),
667 "(1.23 MB, 1.18 MiB)")
669 def test_parse_space(self):
670 p = abbreviate.parse_abbreviated_size
671 self.failUnlessEqual(p(""), None)
672 self.failUnlessEqual(p(None), None)
673 self.failUnlessEqual(p("123"), 123)
674 self.failUnlessEqual(p("123B"), 123)
675 self.failUnlessEqual(p("2K"), 2000)
676 self.failUnlessEqual(p("2kb"), 2000)
677 self.failUnlessEqual(p("2KiB"), 2048)
678 self.failUnlessEqual(p("10MB"), 10*1000*1000)
679 self.failUnlessEqual(p("10MiB"), 10*1024*1024)
680 self.failUnlessEqual(p("5G"), 5*1000*1000*1000)
681 self.failUnlessEqual(p("4GiB"), 4*1024*1024*1024)
682 e = self.failUnlessRaises(ValueError, p, "12 cubits")
683 self.failUnless("12 cubits" in str(e))
685 class Limiter(unittest.TestCase):
686 def job(self, i, foo):
687 self.calls.append( (i, foo) )
688 self.simultaneous += 1
689 self.peak_simultaneous = max(self.simultaneous, self.peak_simultaneous)
692 self.simultaneous -= 1
693 d.callback("done %d" % i)
694 reactor.callLater(1.0, _done)
697 def bad_job(self, i, foo):
698 raise ValueError("bad_job %d" % i)
700 def test_limiter(self):
702 self.simultaneous = 0
703 self.peak_simultaneous = 0
704 l = limiter.ConcurrencyLimiter()
707 dl.append(l.add(self.job, i, foo=str(i)))
708 d = defer.DeferredList(dl, fireOnOneErrback=True)
710 self.failUnlessEqual(self.simultaneous, 0)
711 self.failUnless(self.peak_simultaneous <= 10)
712 self.failUnlessEqual(len(self.calls), 20)
714 self.failUnless( (i, str(i)) in self.calls)
718 def test_errors(self):
720 self.simultaneous = 0
721 self.peak_simultaneous = 0
722 l = limiter.ConcurrencyLimiter()
725 dl.append(l.add(self.job, i, foo=str(i)))
726 d2 = l.add(self.bad_job, 21, "21")
727 d = defer.DeferredList(dl, fireOnOneErrback=True)
730 for (success, result) in res:
731 self.failUnlessEqual(success, True)
732 results.append(result)
734 expected_results = ["done %d" % i for i in range(20)]
735 expected_results.sort()
736 self.failUnlessEqual(results, expected_results)
737 self.failUnless(self.peak_simultaneous <= 10)
738 self.failUnlessEqual(len(self.calls), 20)
740 self.failUnless( (i, str(i)) in self.calls)
742 self.fail("should have failed, not got %s" % (res,))
745 self.failUnless("bad_job 21" in str(f))
746 d2.addCallbacks(_good, _err)
748 d.addCallback(_most_done)
750 self.failUnlessEqual(self.simultaneous, 0)
751 self.failUnless(self.peak_simultaneous <= 10)
752 self.failUnlessEqual(len(self.calls), 20)
754 self.failUnless( (i, str(i)) in self.calls)
755 d.addCallback(_all_done)
758 class TimeFormat(unittest.TestCase):
759 def test_epoch(self):
760 s = time_format.iso_utc_time_to_localseconds("1970-01-01T00:00:01")
761 self.failUnlessEqual(s, 1.0)
762 s = time_format.iso_utc_time_to_localseconds("1970-01-01_00:00:01")
763 self.failUnlessEqual(s, 1.0)
764 s = time_format.iso_utc_time_to_localseconds("1970-01-01 00:00:01")
765 self.failUnlessEqual(s, 1.0)
767 self.failUnlessEqual(time_format.iso_utc(1.0), "1970-01-01_00:00:01")
768 self.failUnlessEqual(time_format.iso_utc(1.0, sep=" "),
769 "1970-01-01 00:00:01")
773 self.failUnlessEqual(time_format.iso_utc(t=my_time),
774 "1970-01-01_00:00:01")
775 e = self.failUnlessRaises(ValueError,
776 time_format.iso_utc_time_to_localseconds,
777 "invalid timestring")
778 self.failUnless("not a complete ISO8601 timestamp" in str(e))
779 s = time_format.iso_utc_time_to_localseconds("1970-01-01_00:00:01.500")
780 self.failUnlessEqual(s, 1.5)
782 class CacheDir(unittest.TestCase):
783 def test_basic(self):
784 basedir = "test_util/CacheDir/test_basic"
786 def _failIfExists(name):
787 absfn = os.path.join(basedir, name)
788 self.failIf(os.path.exists(absfn),
789 "%s exists but it shouldn't" % absfn)
791 def _failUnlessExists(name):
792 absfn = os.path.join(basedir, name)
793 self.failUnless(os.path.exists(absfn),
794 "%s doesn't exist but it should" % absfn)
796 cdm = cachedir.CacheDirectoryManager(basedir)
797 a = cdm.get_file("a")
798 b = cdm.get_file("b")
799 c = cdm.get_file("c")
800 f = open(a.get_filename(), "wb"); f.write("hi"); f.close(); del f
801 f = open(b.get_filename(), "wb"); f.write("hi"); f.close(); del f
802 f = open(c.get_filename(), "wb"); f.write("hi"); f.close(); del f
804 _failUnlessExists("a")
805 _failUnlessExists("b")
806 _failUnlessExists("c")
810 _failUnlessExists("a")
811 _failUnlessExists("b")
812 _failUnlessExists("c")
815 # this file won't be deleted yet, because it isn't old enough
817 _failUnlessExists("a")
818 _failUnlessExists("b")
819 _failUnlessExists("c")
821 # we change the definition of "old" to make everything old
826 _failUnlessExists("b")
827 _failUnlessExists("c")
835 _failUnlessExists("b")
836 _failUnlessExists("c")
838 b2 = cdm.get_file("b")
842 _failUnlessExists("b")
843 _failUnlessExists("c")
847 def __init__(self, x):
852 return "<%s %s>" % (self.__class__.__name__, self.x,)
855 def __le__(self, other):
856 return self.x <= other
857 def __lt__(self, other):
858 return self.x < other
859 def __ge__(self, other):
860 return self.x >= other
861 def __gt__(self, other):
862 return self.x > other
863 def __ne__(self, other):
864 return self.x != other
865 def __eq__(self, other):
866 return self.x == other
868 class DictUtil(unittest.TestCase):
869 def _help_test_empty_dict(self, klass):
873 self.failUnless(d1 == d2, "d1: %r, d2: %r" % (d1, d2,))
874 self.failUnless(len(d1) == 0)
875 self.failUnless(len(d2) == 0)
877 def _help_test_nonempty_dict(self, klass):
878 d1 = klass({'a': 1, 'b': "eggs", 3: "spam",})
879 d2 = klass({'a': 1, 'b': "eggs", 3: "spam",})
881 self.failUnless(d1 == d2)
882 self.failUnless(len(d1) == 3, "%s, %s" % (len(d1), d1,))
883 self.failUnless(len(d2) == 3)
885 def _help_test_eq_but_notis(self, klass):
886 d = klass({'a': 3, 'b': EqButNotIs(3), 'c': 3})
891 d['b'] = EqButNotIs(3)
896 d['b'] = EqButNotIs(3)
902 d['a'] = EqButNotIs(3)
907 fake3 = EqButNotIs(3)
908 fake7 = EqButNotIs(7)
912 self.failUnless(filter(lambda x: x is 8, d.itervalues()))
913 self.failUnless(filter(lambda x: x is fake7, d.itervalues()))
914 # The real 7 should have been ejected by the d[3] = 8.
915 self.failUnless(not filter(lambda x: x is 7, d.itervalues()))
916 self.failUnless(filter(lambda x: x is fake3, d.iterkeys()))
917 self.failUnless(filter(lambda x: x is 3, d.iterkeys()))
922 fake3 = EqButNotIs(3)
923 fake7 = EqButNotIs(7)
926 self.failUnless(filter(lambda x: x is 8, d.itervalues()))
927 self.failUnless(filter(lambda x: x is fake7, d.itervalues()))
928 # The real 7 should have been ejected by the d[3] = 8.
929 self.failUnless(not filter(lambda x: x is 7, d.itervalues()))
930 self.failUnless(filter(lambda x: x is fake3, d.iterkeys()))
931 self.failUnless(filter(lambda x: x is 3, d.iterkeys()))
935 self._help_test_eq_but_notis(dictutil.UtilDict)
936 self._help_test_eq_but_notis(dictutil.NumDict)
937 self._help_test_eq_but_notis(dictutil.ValueOrderedDict)
938 self._help_test_nonempty_dict(dictutil.UtilDict)
939 self._help_test_nonempty_dict(dictutil.NumDict)
940 self._help_test_nonempty_dict(dictutil.ValueOrderedDict)
941 self._help_test_eq_but_notis(dictutil.UtilDict)
942 self._help_test_eq_but_notis(dictutil.NumDict)
943 self._help_test_eq_but_notis(dictutil.ValueOrderedDict)
945 def test_dict_of_sets(self):
946 ds = dictutil.DictOfSets()
951 self.failUnlessEqual(ds[1], set(["a"]))
952 self.failUnlessEqual(ds[2], set(["b", "c"]))
953 ds.discard(3, "d") # should not raise an exception
955 self.failUnlessEqual(ds[2], set(["c"]))
959 ds.union(1, ["a", "e"])
961 self.failUnlessEqual(ds[1], set(["a","e"]))
962 self.failUnlessEqual(ds[3], set(["f"]))
963 ds2 = dictutil.DictOfSets()
968 self.failUnlessEqual(ds[1], set(["a","e"]))
969 self.failUnlessEqual(ds[3], set(["f", "g"]))
970 self.failUnlessEqual(ds[4], set(["h"]))
973 d1 = {1: "a", 2: "b"}
974 d2 = {2: "c", 3: "d"}
975 dictutil.move(1, d1, d2)
976 self.failUnlessEqual(d1, {2: "b"})
977 self.failUnlessEqual(d2, {1: "a", 2: "c", 3: "d"})
979 d1 = {1: "a", 2: "b"}
980 d2 = {2: "c", 3: "d"}
981 dictutil.move(2, d1, d2)
982 self.failUnlessEqual(d1, {1: "a"})
983 self.failUnlessEqual(d2, {2: "b", 3: "d"})
985 d1 = {1: "a", 2: "b"}
986 d2 = {2: "c", 3: "d"}
987 self.failUnlessRaises(KeyError, dictutil.move, 5, d1, d2, strict=True)
989 def test_subtract(self):
990 d1 = {1: "a", 2: "b"}
991 d2 = {2: "c", 3: "d"}
992 d3 = dictutil.subtract(d1, d2)
993 self.failUnlessEqual(d3, {1: "a"})
995 d1 = {1: "a", 2: "b"}
997 d3 = dictutil.subtract(d1, d2)
998 self.failUnlessEqual(d3, {1: "a"})
1000 def test_utildict(self):
1001 d = dictutil.UtilDict({1: "a", 2: "b"})
1004 self.failUnlessEqual(d, {2: "b"})
1007 self.failUnlessRaises(TypeError, eq, d, "not a dict")
1009 d = dictutil.UtilDict({1: "b", 2: "a"})
1010 self.failUnlessEqual(d.items_sorted_by_value(),
1011 [(2, "a"), (1, "b")])
1012 self.failUnlessEqual(d.items_sorted_by_key(),
1013 [(1, "b"), (2, "a")])
1014 self.failUnlessEqual(repr(d), "{1: 'b', 2: 'a'}")
1015 self.failUnless(1 in d)
1017 d2 = dictutil.UtilDict({3: "c", 4: "d"})
1018 self.failUnless(d != d2)
1019 self.failUnless(d2 > d)
1020 self.failUnless(d2 >= d)
1021 self.failUnless(d <= d2)
1022 self.failUnless(d < d2)
1023 self.failUnlessEqual(d[1], "b")
1024 self.failUnlessEqual(sorted(list([k for k in d])), [1,2])
1027 self.failUnlessEqual(d, d3)
1028 self.failUnless(isinstance(d3, dictutil.UtilDict))
1030 d4 = d.fromkeys([3,4], "e")
1031 self.failUnlessEqual(d4, {3: "e", 4: "e"})
1033 self.failUnlessEqual(d.get(1), "b")
1034 self.failUnlessEqual(d.get(3), None)
1035 self.failUnlessEqual(d.get(3, "default"), "default")
1036 self.failUnlessEqual(sorted(list(d.items())),
1037 [(1, "b"), (2, "a")])
1038 self.failUnlessEqual(sorted(list(d.iteritems())),
1039 [(1, "b"), (2, "a")])
1040 self.failUnlessEqual(sorted(d.keys()), [1, 2])
1041 self.failUnlessEqual(sorted(d.values()), ["a", "b"])
1042 x = d.setdefault(1, "new")
1043 self.failUnlessEqual(x, "b")
1044 self.failUnlessEqual(d[1], "b")
1045 x = d.setdefault(3, "new")
1046 self.failUnlessEqual(x, "new")
1047 self.failUnlessEqual(d[3], "new")
1051 self.failUnless(x in [(1, "b"), (2, "a")])
1053 self.failUnless(x in [(1, "b"), (2, "a")])
1054 self.failUnlessRaises(KeyError, d.popitem)
1056 def test_numdict(self):
1057 d = dictutil.NumDict({"a": 1, "b": 2})
1059 d.add_num("a", 10, 5)
1060 d.add_num("c", 20, 5)
1062 self.failUnlessEqual(d, {"a": 11, "b": 2, "c": 25, "d": 30})
1064 d.subtract_num("a", 10)
1065 d.subtract_num("e", 10)
1066 d.subtract_num("f", 10, 15)
1067 self.failUnlessEqual(d, {"a": 1, "b": 2, "c": 25, "d": 30,
1070 self.failUnlessEqual(d.sum(), sum([1, 2, 25, 30, -10, 5]))
1072 d = dictutil.NumDict()
1076 self.failUnlessEqual(d, {"a": 2, "b": 6})
1080 self.failUnlessEqual(d, {"a": 1, "b": 6, "c": -1, "d": 4})
1081 self.failUnlessEqual(d.items_sorted_by_key(),
1082 [("a", 1), ("b", 6), ("c", -1), ("d", 4)])
1083 self.failUnlessEqual(d.items_sorted_by_value(),
1084 [("c", -1), ("a", 1), ("d", 4), ("b", 6)])
1085 self.failUnlessEqual(d.item_with_largest_value(), ("b", 6))
1087 d = dictutil.NumDict({"a": 1, "b": 2})
1088 self.failUnlessEqual(repr(d), "{'a': 1, 'b': 2}")
1089 self.failUnless("a" in d)
1091 d2 = dictutil.NumDict({"c": 3, "d": 4})
1092 self.failUnless(d != d2)
1093 self.failUnless(d2 > d)
1094 self.failUnless(d2 >= d)
1095 self.failUnless(d <= d2)
1096 self.failUnless(d < d2)
1097 self.failUnlessEqual(d["a"], 1)
1098 self.failUnlessEqual(sorted(list([k for k in d])), ["a","b"])
1101 self.failUnlessRaises(TypeError, eq, d, "not a dict")
1104 self.failUnlessEqual(d, d3)
1105 self.failUnless(isinstance(d3, dictutil.NumDict))
1107 d4 = d.fromkeys(["a","b"], 5)
1108 self.failUnlessEqual(d4, {"a": 5, "b": 5})
1110 self.failUnlessEqual(d.get("a"), 1)
1111 self.failUnlessEqual(d.get("c"), 0)
1112 self.failUnlessEqual(d.get("c", 5), 5)
1113 self.failUnlessEqual(sorted(list(d.items())),
1114 [("a", 1), ("b", 2)])
1115 self.failUnlessEqual(sorted(list(d.iteritems())),
1116 [("a", 1), ("b", 2)])
1117 self.failUnlessEqual(sorted(d.keys()), ["a", "b"])
1118 self.failUnlessEqual(sorted(d.values()), [1, 2])
1119 self.failUnless(d.has_key("a"))
1120 self.failIf(d.has_key("c"))
1122 x = d.setdefault("c", 3)
1123 self.failUnlessEqual(x, 3)
1124 self.failUnlessEqual(d["c"], 3)
1125 x = d.setdefault("c", 5)
1126 self.failUnlessEqual(x, 3)
1127 self.failUnlessEqual(d["c"], 3)
1131 self.failUnless(x in [("a", 1), ("b", 2)])
1133 self.failUnless(x in [("a", 1), ("b", 2)])
1134 self.failUnlessRaises(KeyError, d.popitem)
1137 d.update({"c": 4, "d": 5})
1138 self.failUnlessEqual(d, {"c": 4, "d": 5})
1140 def test_del_if_present(self):
1141 d = {1: "a", 2: "b"}
1142 dictutil.del_if_present(d, 1)
1143 dictutil.del_if_present(d, 3)
1144 self.failUnlessEqual(d, {2: "b"})
1146 def test_valueordereddict(self):
1147 d = dictutil.ValueOrderedDict()
1152 self.failUnlessEqual(d, {"a": 3, "b": 2, "c": 1})
1153 self.failUnlessEqual(d.items(), [("c", 1), ("b", 2), ("a", 3)])
1154 self.failUnlessEqual(d.values(), [1, 2, 3])
1155 self.failUnlessEqual(d.keys(), ["c", "b", "a"])
1156 self.failUnlessEqual(repr(d), "<ValueOrderedDict {c: 1, b: 2, a: 3}>")
1159 self.failIf(d == {"a": 4})
1160 self.failUnless(d != {"a": 4})
1162 x = d.setdefault("d", 0)
1163 self.failUnlessEqual(x, 0)
1164 self.failUnlessEqual(d["d"], 0)
1165 x = d.setdefault("d", -1)
1166 self.failUnlessEqual(x, 0)
1167 self.failUnlessEqual(d["d"], 0)
1169 x = d.remove("e", "default", False)
1170 self.failUnlessEqual(x, "default")
1171 self.failUnlessRaises(KeyError, d.remove, "e", "default", True)
1172 x = d.remove("d", 5)
1173 self.failUnlessEqual(x, 0)
1175 x = d.__getitem__("c")
1176 self.failUnlessEqual(x, 1)
1177 x = d.__getitem__("e", "default", False)
1178 self.failUnlessEqual(x, "default")
1179 self.failUnlessRaises(KeyError, d.__getitem__, "e", "default", True)
1181 self.failUnlessEqual(d.popitem(), ("c", 1))
1182 self.failUnlessEqual(d.popitem(), ("b", 2))
1183 self.failUnlessEqual(d.popitem(), ("a", 3))
1184 self.failUnlessRaises(KeyError, d.popitem)
1186 d = dictutil.ValueOrderedDict({"a": 3, "b": 2, "c": 1})
1187 x = d.pop("d", "default", False)
1188 self.failUnlessEqual(x, "default")
1189 self.failUnlessRaises(KeyError, d.pop, "d", "default", True)
1191 self.failUnlessEqual(x, 2)
1192 self.failUnlessEqual(d.items(), [("c", 1), ("a", 3)])
1194 d = dictutil.ValueOrderedDict({"a": 3, "b": 2, "c": 1})
1195 x = d.pop_from_list(1) # pop the second item, b/2
1196 self.failUnlessEqual(x, "b")
1197 self.failUnlessEqual(d.items(), [("c", 1), ("a", 3)])
1199 class FakeRemoteReference:
1200 def callRemote(self, methname, *args, **kwargs):
1201 return defer.maybeDeferred(self.oops)
1203 raise IndexError("remote missing key")
1205 class RemoteFailures(unittest.TestCase):
1206 def test_check(self):
1208 raise IndexError("local missing key")
1211 self.failUnlessEqual(localf.check(IndexError, KeyError), IndexError)
1212 self.failUnlessEqual(localf.check(ValueError, KeyError), None)
1213 self.failUnlessEqual(localf.check(ServerFailure), None)
1215 frr = FakeRemoteReference()
1216 wrr = rrefutil.WrappedRemoteReference(frr)
1217 d = wrr.callRemote("oops")
1219 self.failUnlessEqual(f.check(IndexError, KeyError), None)
1220 self.failUnlessEqual(f.check(ServerFailure, KeyError),
1222 d.addErrback(_check)
1225 def test_is_remote(self):
1227 raise IndexError("local missing key")
1230 self.failIf(rrefutil.is_remote(localf))
1231 self.failUnless(rrefutil.is_local(localf))
1233 frr = FakeRemoteReference()
1234 wrr = rrefutil.WrappedRemoteReference(frr)
1235 d = wrr.callRemote("oops")
1237 self.failUnless(rrefutil.is_remote(f))
1238 self.failIf(rrefutil.is_local(f))
1239 d.addErrback(_check)
1242 def test_trap(self):
1244 raise IndexError("local missing key")
1248 self.failUnlessRaises(Failure, localf.trap, ValueError, KeyError)
1249 self.failUnlessRaises(Failure, localf.trap, ServerFailure)
1250 self.failUnlessEqual(localf.trap(IndexError, KeyError), IndexError)
1251 self.failUnlessEqual(rrefutil.trap_local(localf, IndexError, KeyError),
1253 self.failUnlessRaises(Failure,
1254 rrefutil.trap_remote, localf, ValueError, KeyError)
1256 frr = FakeRemoteReference()
1257 wrr = rrefutil.WrappedRemoteReference(frr)
1258 d = wrr.callRemote("oops")
1260 self.failUnlessRaises(Failure,
1261 f.trap, ValueError, KeyError)
1262 self.failUnlessRaises(Failure,
1264 self.failUnlessEqual(f.trap(ServerFailure), ServerFailure)
1265 self.failUnlessRaises(Failure,
1266 rrefutil.trap_remote, f, ValueError, KeyError)
1267 self.failUnlessEqual(rrefutil.trap_remote(f, IndexError, KeyError),
1269 self.failUnlessRaises(Failure,
1270 rrefutil.trap_local, f, ValueError, KeyError)
1271 self.failUnlessRaises(Failure,
1272 rrefutil.trap_local, f, IndexError)
1273 d.addErrback(_check)