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
9 from twisted.python import log
11 from allmydata.util import base32, idlib, humanreadable, mathutil, hashutil
12 from allmydata.util import assertutil, fileutil, deferredutil, abbreviate
13 from allmydata.util import limiter, time_format, pollmixin, cachedir
14 from allmydata.util import statistics, dictutil, pipeline
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 def test_constant_time_compare(self):
605 self.failUnless(hashutil.constant_time_compare("a", "a"))
606 self.failUnless(hashutil.constant_time_compare("ab", "ab"))
607 self.failIf(hashutil.constant_time_compare("a", "b"))
608 self.failIf(hashutil.constant_time_compare("a", "aa"))
610 class Abbreviate(unittest.TestCase):
612 a = abbreviate.abbreviate_time
613 self.failUnlessEqual(a(None), "unknown")
614 self.failUnlessEqual(a(0), "0 seconds")
615 self.failUnlessEqual(a(1), "1 second")
616 self.failUnlessEqual(a(2), "2 seconds")
617 self.failUnlessEqual(a(119), "119 seconds")
619 self.failUnlessEqual(a(2*MIN), "2 minutes")
620 self.failUnlessEqual(a(60*MIN), "60 minutes")
621 self.failUnlessEqual(a(179*MIN), "179 minutes")
623 self.failUnlessEqual(a(180*MIN), "3 hours")
624 self.failUnlessEqual(a(4*HOUR), "4 hours")
627 self.failUnlessEqual(a(2*DAY), "2 days")
628 self.failUnlessEqual(a(2*MONTH), "2 months")
630 self.failUnlessEqual(a(5*YEAR), "5 years")
632 def test_space(self):
633 tests_si = [(None, "unknown"),
640 (20*1000, "20.00 kB"),
641 (1024*1024, "1.05 MB"),
642 (1000*1000, "1.00 MB"),
643 (1000*1000*1000, "1.00 GB"),
644 (1000*1000*1000*1000, "1.00 TB"),
645 (1000*1000*1000*1000*1000, "1.00 PB"),
646 (1234567890123456, "1.23 PB"),
648 for (x, expected) in tests_si:
649 got = abbreviate.abbreviate_space(x, SI=True)
650 self.failUnlessEqual(got, expected)
652 tests_base1024 = [(None, "unknown"),
659 (20*1024, "20.00 kiB"),
660 (1000*1000, "976.56 kiB"),
661 (1024*1024, "1.00 MiB"),
662 (1024*1024*1024, "1.00 GiB"),
663 (1024*1024*1024*1024, "1.00 TiB"),
664 (1000*1000*1000*1000*1000, "909.49 TiB"),
665 (1024*1024*1024*1024*1024, "1.00 PiB"),
666 (1234567890123456, "1.10 PiB"),
668 for (x, expected) in tests_base1024:
669 got = abbreviate.abbreviate_space(x, SI=False)
670 self.failUnlessEqual(got, expected)
672 self.failUnlessEqual(abbreviate.abbreviate_space_both(1234567),
673 "(1.23 MB, 1.18 MiB)")
675 def test_parse_space(self):
676 p = abbreviate.parse_abbreviated_size
677 self.failUnlessEqual(p(""), None)
678 self.failUnlessEqual(p(None), None)
679 self.failUnlessEqual(p("123"), 123)
680 self.failUnlessEqual(p("123B"), 123)
681 self.failUnlessEqual(p("2K"), 2000)
682 self.failUnlessEqual(p("2kb"), 2000)
683 self.failUnlessEqual(p("2KiB"), 2048)
684 self.failUnlessEqual(p("10MB"), 10*1000*1000)
685 self.failUnlessEqual(p("10MiB"), 10*1024*1024)
686 self.failUnlessEqual(p("5G"), 5*1000*1000*1000)
687 self.failUnlessEqual(p("4GiB"), 4*1024*1024*1024)
688 e = self.failUnlessRaises(ValueError, p, "12 cubits")
689 self.failUnless("12 cubits" in str(e))
691 class Limiter(unittest.TestCase):
692 timeout = 480 # This takes longer than 240 seconds on Francois's arm box.
694 def job(self, i, foo):
695 self.calls.append( (i, foo) )
696 self.simultaneous += 1
697 self.peak_simultaneous = max(self.simultaneous, self.peak_simultaneous)
700 self.simultaneous -= 1
701 d.callback("done %d" % i)
702 reactor.callLater(1.0, _done)
705 def bad_job(self, i, foo):
706 raise ValueError("bad_job %d" % i)
708 def test_limiter(self):
710 self.simultaneous = 0
711 self.peak_simultaneous = 0
712 l = limiter.ConcurrencyLimiter()
715 dl.append(l.add(self.job, i, foo=str(i)))
716 d = defer.DeferredList(dl, fireOnOneErrback=True)
718 self.failUnlessEqual(self.simultaneous, 0)
719 self.failUnless(self.peak_simultaneous <= 10)
720 self.failUnlessEqual(len(self.calls), 20)
722 self.failUnless( (i, str(i)) in self.calls)
726 def test_errors(self):
728 self.simultaneous = 0
729 self.peak_simultaneous = 0
730 l = limiter.ConcurrencyLimiter()
733 dl.append(l.add(self.job, i, foo=str(i)))
734 d2 = l.add(self.bad_job, 21, "21")
735 d = defer.DeferredList(dl, fireOnOneErrback=True)
738 for (success, result) in res:
739 self.failUnlessEqual(success, True)
740 results.append(result)
742 expected_results = ["done %d" % i for i in range(20)]
743 expected_results.sort()
744 self.failUnlessEqual(results, expected_results)
745 self.failUnless(self.peak_simultaneous <= 10)
746 self.failUnlessEqual(len(self.calls), 20)
748 self.failUnless( (i, str(i)) in self.calls)
750 self.fail("should have failed, not got %s" % (res,))
753 self.failUnless("bad_job 21" in str(f))
754 d2.addCallbacks(_good, _err)
756 d.addCallback(_most_done)
758 self.failUnlessEqual(self.simultaneous, 0)
759 self.failUnless(self.peak_simultaneous <= 10)
760 self.failUnlessEqual(len(self.calls), 20)
762 self.failUnless( (i, str(i)) in self.calls)
763 d.addCallback(_all_done)
766 class TimeFormat(unittest.TestCase):
767 def test_epoch(self):
768 return self._help_test_epoch()
770 def test_epoch_in_London(self):
771 # Europe/London is a particularly troublesome timezone. Nowadays, its
772 # offset from GMT is 0. But in 1970, its offset from GMT was 1.
773 # (Apparently in 1970 Britain had redefined standard time to be GMT+1
774 # and stayed in standard time all year round, whereas today
775 # Europe/London standard time is GMT and Europe/London Daylight
776 # Savings Time is GMT+1.) The current implementation of
777 # time_format.iso_utc_time_to_localseconds() breaks if the timezone is
778 # Europe/London. (As soon as this unit test is done then I'll change
779 # that implementation to something that works even in this case...)
780 origtz = os.environ.get('TZ')
781 os.environ['TZ'] = "Europe/London"
782 if hasattr(time, 'tzset'):
785 return self._help_test_epoch()
790 os.environ['TZ'] = origtz
791 if hasattr(time, 'tzset'):
794 def _help_test_epoch(self):
795 origtzname = time.tzname
796 s = time_format.iso_utc_time_to_seconds("1970-01-01T00:00:01")
797 self.failUnlessEqual(s, 1.0)
798 s = time_format.iso_utc_time_to_seconds("1970-01-01_00:00:01")
799 self.failUnlessEqual(s, 1.0)
800 s = time_format.iso_utc_time_to_seconds("1970-01-01 00:00:01")
801 self.failUnlessEqual(s, 1.0)
803 self.failUnlessEqual(time_format.iso_utc(1.0), "1970-01-01_00:00:01")
804 self.failUnlessEqual(time_format.iso_utc(1.0, sep=" "),
805 "1970-01-01 00:00:01")
808 isostr = time_format.iso_utc(now)
809 timestamp = time_format.iso_utc_time_to_seconds(isostr)
810 self.failUnlessEqual(int(timestamp), int(now))
814 self.failUnlessEqual(time_format.iso_utc(t=my_time),
815 "1970-01-01_00:00:01")
816 e = self.failUnlessRaises(ValueError,
817 time_format.iso_utc_time_to_seconds,
818 "invalid timestring")
819 self.failUnless("not a complete ISO8601 timestamp" in str(e))
820 s = time_format.iso_utc_time_to_seconds("1970-01-01_00:00:01.500")
821 self.failUnlessEqual(s, 1.5)
823 # Look for daylight-savings-related errors.
824 thatmomentinmarch = time_format.iso_utc_time_to_seconds("2009-03-20 21:49:02.226536")
825 self.failUnlessEqual(thatmomentinmarch, 1237585742.226536)
826 self.failUnlessEqual(origtzname, time.tzname)
828 class CacheDir(unittest.TestCase):
829 def test_basic(self):
830 basedir = "test_util/CacheDir/test_basic"
832 def _failIfExists(name):
833 absfn = os.path.join(basedir, name)
834 self.failIf(os.path.exists(absfn),
835 "%s exists but it shouldn't" % absfn)
837 def _failUnlessExists(name):
838 absfn = os.path.join(basedir, name)
839 self.failUnless(os.path.exists(absfn),
840 "%s doesn't exist but it should" % absfn)
842 cdm = cachedir.CacheDirectoryManager(basedir)
843 a = cdm.get_file("a")
844 b = cdm.get_file("b")
845 c = cdm.get_file("c")
846 f = open(a.get_filename(), "wb"); f.write("hi"); f.close(); del f
847 f = open(b.get_filename(), "wb"); f.write("hi"); f.close(); del f
848 f = open(c.get_filename(), "wb"); f.write("hi"); f.close(); del f
850 _failUnlessExists("a")
851 _failUnlessExists("b")
852 _failUnlessExists("c")
856 _failUnlessExists("a")
857 _failUnlessExists("b")
858 _failUnlessExists("c")
861 # this file won't be deleted yet, because it isn't old enough
863 _failUnlessExists("a")
864 _failUnlessExists("b")
865 _failUnlessExists("c")
867 # we change the definition of "old" to make everything old
872 _failUnlessExists("b")
873 _failUnlessExists("c")
881 _failUnlessExists("b")
882 _failUnlessExists("c")
884 b2 = cdm.get_file("b")
888 _failUnlessExists("b")
889 _failUnlessExists("c")
893 def __init__(self, x):
898 return "<%s %s>" % (self.__class__.__name__, self.x,)
901 def __le__(self, other):
902 return self.x <= other
903 def __lt__(self, other):
904 return self.x < other
905 def __ge__(self, other):
906 return self.x >= other
907 def __gt__(self, other):
908 return self.x > other
909 def __ne__(self, other):
910 return self.x != other
911 def __eq__(self, other):
912 return self.x == other
914 class DictUtil(unittest.TestCase):
915 def _help_test_empty_dict(self, klass):
919 self.failUnless(d1 == d2, "d1: %r, d2: %r" % (d1, d2,))
920 self.failUnless(len(d1) == 0)
921 self.failUnless(len(d2) == 0)
923 def _help_test_nonempty_dict(self, klass):
924 d1 = klass({'a': 1, 'b': "eggs", 3: "spam",})
925 d2 = klass({'a': 1, 'b': "eggs", 3: "spam",})
927 self.failUnless(d1 == d2)
928 self.failUnless(len(d1) == 3, "%s, %s" % (len(d1), d1,))
929 self.failUnless(len(d2) == 3)
931 def _help_test_eq_but_notis(self, klass):
932 d = klass({'a': 3, 'b': EqButNotIs(3), 'c': 3})
937 d['b'] = EqButNotIs(3)
942 d['b'] = EqButNotIs(3)
948 d['a'] = EqButNotIs(3)
953 fake3 = EqButNotIs(3)
954 fake7 = EqButNotIs(7)
958 self.failUnless(filter(lambda x: x is 8, d.itervalues()))
959 self.failUnless(filter(lambda x: x is fake7, d.itervalues()))
960 # The real 7 should have been ejected by the d[3] = 8.
961 self.failUnless(not filter(lambda x: x is 7, d.itervalues()))
962 self.failUnless(filter(lambda x: x is fake3, d.iterkeys()))
963 self.failUnless(filter(lambda x: x is 3, d.iterkeys()))
968 fake3 = EqButNotIs(3)
969 fake7 = EqButNotIs(7)
972 self.failUnless(filter(lambda x: x is 8, d.itervalues()))
973 self.failUnless(filter(lambda x: x is fake7, d.itervalues()))
974 # The real 7 should have been ejected by the d[3] = 8.
975 self.failUnless(not filter(lambda x: x is 7, d.itervalues()))
976 self.failUnless(filter(lambda x: x is fake3, d.iterkeys()))
977 self.failUnless(filter(lambda x: x is 3, d.iterkeys()))
981 self._help_test_eq_but_notis(dictutil.UtilDict)
982 self._help_test_eq_but_notis(dictutil.NumDict)
983 self._help_test_eq_but_notis(dictutil.ValueOrderedDict)
984 self._help_test_nonempty_dict(dictutil.UtilDict)
985 self._help_test_nonempty_dict(dictutil.NumDict)
986 self._help_test_nonempty_dict(dictutil.ValueOrderedDict)
987 self._help_test_eq_but_notis(dictutil.UtilDict)
988 self._help_test_eq_but_notis(dictutil.NumDict)
989 self._help_test_eq_but_notis(dictutil.ValueOrderedDict)
991 def test_dict_of_sets(self):
992 ds = dictutil.DictOfSets()
997 self.failUnlessEqual(ds[1], set(["a"]))
998 self.failUnlessEqual(ds[2], set(["b", "c"]))
999 ds.discard(3, "d") # should not raise an exception
1001 self.failUnlessEqual(ds[2], set(["c"]))
1003 self.failIf(2 in ds)
1005 ds.union(1, ["a", "e"])
1007 self.failUnlessEqual(ds[1], set(["a","e"]))
1008 self.failUnlessEqual(ds[3], set(["f"]))
1009 ds2 = dictutil.DictOfSets()
1014 self.failUnlessEqual(ds[1], set(["a","e"]))
1015 self.failUnlessEqual(ds[3], set(["f", "g"]))
1016 self.failUnlessEqual(ds[4], set(["h"]))
1018 def test_move(self):
1019 d1 = {1: "a", 2: "b"}
1020 d2 = {2: "c", 3: "d"}
1021 dictutil.move(1, d1, d2)
1022 self.failUnlessEqual(d1, {2: "b"})
1023 self.failUnlessEqual(d2, {1: "a", 2: "c", 3: "d"})
1025 d1 = {1: "a", 2: "b"}
1026 d2 = {2: "c", 3: "d"}
1027 dictutil.move(2, d1, d2)
1028 self.failUnlessEqual(d1, {1: "a"})
1029 self.failUnlessEqual(d2, {2: "b", 3: "d"})
1031 d1 = {1: "a", 2: "b"}
1032 d2 = {2: "c", 3: "d"}
1033 self.failUnlessRaises(KeyError, dictutil.move, 5, d1, d2, strict=True)
1035 def test_subtract(self):
1036 d1 = {1: "a", 2: "b"}
1037 d2 = {2: "c", 3: "d"}
1038 d3 = dictutil.subtract(d1, d2)
1039 self.failUnlessEqual(d3, {1: "a"})
1041 d1 = {1: "a", 2: "b"}
1043 d3 = dictutil.subtract(d1, d2)
1044 self.failUnlessEqual(d3, {1: "a"})
1046 def test_utildict(self):
1047 d = dictutil.UtilDict({1: "a", 2: "b"})
1050 self.failUnlessEqual(d, {2: "b"})
1053 self.failUnlessRaises(TypeError, eq, d, "not a dict")
1055 d = dictutil.UtilDict({1: "b", 2: "a"})
1056 self.failUnlessEqual(d.items_sorted_by_value(),
1057 [(2, "a"), (1, "b")])
1058 self.failUnlessEqual(d.items_sorted_by_key(),
1059 [(1, "b"), (2, "a")])
1060 self.failUnlessEqual(repr(d), "{1: 'b', 2: 'a'}")
1061 self.failUnless(1 in d)
1063 d2 = dictutil.UtilDict({3: "c", 4: "d"})
1064 self.failUnless(d != d2)
1065 self.failUnless(d2 > d)
1066 self.failUnless(d2 >= d)
1067 self.failUnless(d <= d2)
1068 self.failUnless(d < d2)
1069 self.failUnlessEqual(d[1], "b")
1070 self.failUnlessEqual(sorted(list([k for k in d])), [1,2])
1073 self.failUnlessEqual(d, d3)
1074 self.failUnless(isinstance(d3, dictutil.UtilDict))
1076 d4 = d.fromkeys([3,4], "e")
1077 self.failUnlessEqual(d4, {3: "e", 4: "e"})
1079 self.failUnlessEqual(d.get(1), "b")
1080 self.failUnlessEqual(d.get(3), None)
1081 self.failUnlessEqual(d.get(3, "default"), "default")
1082 self.failUnlessEqual(sorted(list(d.items())),
1083 [(1, "b"), (2, "a")])
1084 self.failUnlessEqual(sorted(list(d.iteritems())),
1085 [(1, "b"), (2, "a")])
1086 self.failUnlessEqual(sorted(d.keys()), [1, 2])
1087 self.failUnlessEqual(sorted(d.values()), ["a", "b"])
1088 x = d.setdefault(1, "new")
1089 self.failUnlessEqual(x, "b")
1090 self.failUnlessEqual(d[1], "b")
1091 x = d.setdefault(3, "new")
1092 self.failUnlessEqual(x, "new")
1093 self.failUnlessEqual(d[3], "new")
1097 self.failUnless(x in [(1, "b"), (2, "a")])
1099 self.failUnless(x in [(1, "b"), (2, "a")])
1100 self.failUnlessRaises(KeyError, d.popitem)
1102 def test_numdict(self):
1103 d = dictutil.NumDict({"a": 1, "b": 2})
1105 d.add_num("a", 10, 5)
1106 d.add_num("c", 20, 5)
1108 self.failUnlessEqual(d, {"a": 11, "b": 2, "c": 25, "d": 30})
1110 d.subtract_num("a", 10)
1111 d.subtract_num("e", 10)
1112 d.subtract_num("f", 10, 15)
1113 self.failUnlessEqual(d, {"a": 1, "b": 2, "c": 25, "d": 30,
1116 self.failUnlessEqual(d.sum(), sum([1, 2, 25, 30, -10, 5]))
1118 d = dictutil.NumDict()
1122 self.failUnlessEqual(d, {"a": 2, "b": 6})
1126 self.failUnlessEqual(d, {"a": 1, "b": 6, "c": -1, "d": 4})
1127 self.failUnlessEqual(d.items_sorted_by_key(),
1128 [("a", 1), ("b", 6), ("c", -1), ("d", 4)])
1129 self.failUnlessEqual(d.items_sorted_by_value(),
1130 [("c", -1), ("a", 1), ("d", 4), ("b", 6)])
1131 self.failUnlessEqual(d.item_with_largest_value(), ("b", 6))
1133 d = dictutil.NumDict({"a": 1, "b": 2})
1134 self.failUnlessEqual(repr(d), "{'a': 1, 'b': 2}")
1135 self.failUnless("a" in d)
1137 d2 = dictutil.NumDict({"c": 3, "d": 4})
1138 self.failUnless(d != d2)
1139 self.failUnless(d2 > d)
1140 self.failUnless(d2 >= d)
1141 self.failUnless(d <= d2)
1142 self.failUnless(d < d2)
1143 self.failUnlessEqual(d["a"], 1)
1144 self.failUnlessEqual(sorted(list([k for k in d])), ["a","b"])
1147 self.failUnlessRaises(TypeError, eq, d, "not a dict")
1150 self.failUnlessEqual(d, d3)
1151 self.failUnless(isinstance(d3, dictutil.NumDict))
1153 d4 = d.fromkeys(["a","b"], 5)
1154 self.failUnlessEqual(d4, {"a": 5, "b": 5})
1156 self.failUnlessEqual(d.get("a"), 1)
1157 self.failUnlessEqual(d.get("c"), 0)
1158 self.failUnlessEqual(d.get("c", 5), 5)
1159 self.failUnlessEqual(sorted(list(d.items())),
1160 [("a", 1), ("b", 2)])
1161 self.failUnlessEqual(sorted(list(d.iteritems())),
1162 [("a", 1), ("b", 2)])
1163 self.failUnlessEqual(sorted(d.keys()), ["a", "b"])
1164 self.failUnlessEqual(sorted(d.values()), [1, 2])
1165 self.failUnless(d.has_key("a"))
1166 self.failIf(d.has_key("c"))
1168 x = d.setdefault("c", 3)
1169 self.failUnlessEqual(x, 3)
1170 self.failUnlessEqual(d["c"], 3)
1171 x = d.setdefault("c", 5)
1172 self.failUnlessEqual(x, 3)
1173 self.failUnlessEqual(d["c"], 3)
1177 self.failUnless(x in [("a", 1), ("b", 2)])
1179 self.failUnless(x in [("a", 1), ("b", 2)])
1180 self.failUnlessRaises(KeyError, d.popitem)
1183 d.update({"c": 4, "d": 5})
1184 self.failUnlessEqual(d, {"c": 4, "d": 5})
1186 def test_del_if_present(self):
1187 d = {1: "a", 2: "b"}
1188 dictutil.del_if_present(d, 1)
1189 dictutil.del_if_present(d, 3)
1190 self.failUnlessEqual(d, {2: "b"})
1192 def test_valueordereddict(self):
1193 d = dictutil.ValueOrderedDict()
1198 self.failUnlessEqual(d, {"a": 3, "b": 2, "c": 1})
1199 self.failUnlessEqual(d.items(), [("c", 1), ("b", 2), ("a", 3)])
1200 self.failUnlessEqual(d.values(), [1, 2, 3])
1201 self.failUnlessEqual(d.keys(), ["c", "b", "a"])
1202 self.failUnlessEqual(repr(d), "<ValueOrderedDict {c: 1, b: 2, a: 3}>")
1205 self.failIf(d == {"a": 4})
1206 self.failUnless(d != {"a": 4})
1208 x = d.setdefault("d", 0)
1209 self.failUnlessEqual(x, 0)
1210 self.failUnlessEqual(d["d"], 0)
1211 x = d.setdefault("d", -1)
1212 self.failUnlessEqual(x, 0)
1213 self.failUnlessEqual(d["d"], 0)
1215 x = d.remove("e", "default", False)
1216 self.failUnlessEqual(x, "default")
1217 self.failUnlessRaises(KeyError, d.remove, "e", "default", True)
1218 x = d.remove("d", 5)
1219 self.failUnlessEqual(x, 0)
1221 x = d.__getitem__("c")
1222 self.failUnlessEqual(x, 1)
1223 x = d.__getitem__("e", "default", False)
1224 self.failUnlessEqual(x, "default")
1225 self.failUnlessRaises(KeyError, d.__getitem__, "e", "default", True)
1227 self.failUnlessEqual(d.popitem(), ("c", 1))
1228 self.failUnlessEqual(d.popitem(), ("b", 2))
1229 self.failUnlessEqual(d.popitem(), ("a", 3))
1230 self.failUnlessRaises(KeyError, d.popitem)
1232 d = dictutil.ValueOrderedDict({"a": 3, "b": 2, "c": 1})
1233 x = d.pop("d", "default", False)
1234 self.failUnlessEqual(x, "default")
1235 self.failUnlessRaises(KeyError, d.pop, "d", "default", True)
1237 self.failUnlessEqual(x, 2)
1238 self.failUnlessEqual(d.items(), [("c", 1), ("a", 3)])
1240 d = dictutil.ValueOrderedDict({"a": 3, "b": 2, "c": 1})
1241 x = d.pop_from_list(1) # pop the second item, b/2
1242 self.failUnlessEqual(x, "b")
1243 self.failUnlessEqual(d.items(), [("c", 1), ("a", 3)])
1245 class Pipeline(unittest.TestCase):
1246 def pause(self, *args, **kwargs):
1247 d = defer.Deferred()
1248 self.calls.append( (d, args, kwargs) )
1251 def failUnlessCallsAre(self, expected):
1254 self.failUnlessEqual(len(self.calls), len(expected), self.calls)
1255 for i,c in enumerate(self.calls):
1256 self.failUnlessEqual(c[1:], expected[i], str(i))
1258 def test_basic(self):
1261 p = pipeline.Pipeline(100)
1263 d = p.flush() # fires immediately
1264 d.addCallbacks(finished.append, log.err)
1265 self.failUnlessEqual(len(finished), 1)
1268 d = p.add(10, self.pause, "one")
1269 # the call should start right away, and our return Deferred should
1271 d.addCallbacks(finished.append, log.err)
1272 self.failUnlessEqual(len(finished), 1)
1273 self.failUnlessEqual(finished[0], None)
1274 self.failUnlessCallsAre([ ( ("one",) , {} ) ])
1275 self.failUnlessEqual(p.gauge, 10)
1280 d = p.add(20, self.pause, "two", kw=2)
1281 # pipeline: [one, two]
1283 # the call and the Deferred should fire right away
1284 d.addCallbacks(finished.append, log.err)
1285 self.failUnlessEqual(len(finished), 1)
1286 self.failUnlessEqual(finished[0], None)
1287 self.failUnlessCallsAre([ ( ("one",) , {} ),
1288 ( ("two",) , {"kw": 2} ),
1290 self.failUnlessEqual(p.gauge, 30)
1292 self.calls[0][0].callback("one-result")
1294 self.failUnlessEqual(p.gauge, 20)
1297 d = p.add(90, self.pause, "three", "posarg1")
1298 # pipeline: [two, three]
1301 fd.addCallbacks(flushed.append, log.err)
1302 self.failUnlessEqual(flushed, [])
1304 # the call will be made right away, but the return Deferred will not,
1305 # because the pipeline is now full.
1306 d.addCallbacks(finished.append, log.err)
1307 self.failUnlessEqual(len(finished), 0)
1308 self.failUnlessCallsAre([ ( ("one",) , {} ),
1309 ( ("two",) , {"kw": 2} ),
1310 ( ("three", "posarg1"), {} ),
1312 self.failUnlessEqual(p.gauge, 110)
1314 self.failUnlessRaises(pipeline.SingleFileError, p.add, 10, self.pause)
1316 # retiring either call will unblock the pipeline, causing the #3
1318 self.calls[2][0].callback("three-result")
1321 self.failUnlessEqual(len(finished), 1)
1322 self.failUnlessEqual(finished[0], None)
1323 self.failUnlessEqual(flushed, [])
1325 # retiring call#2 will finally allow the flush() Deferred to fire
1326 self.calls[1][0].callback("two-result")
1327 self.failUnlessEqual(len(flushed), 1)
1329 def test_errors(self):
1331 p = pipeline.Pipeline(100)
1333 d1 = p.add(200, self.pause, "one")
1337 d1.addBoth(finished.append)
1338 self.failUnlessEqual(finished, [])
1341 d2.addBoth(flushed.append)
1342 self.failUnlessEqual(flushed, [])
1344 self.calls[0][0].errback(ValueError("oops"))
1346 self.failUnlessEqual(len(finished), 1)
1348 self.failUnless(isinstance(f, Failure))
1349 self.failUnless(f.check(pipeline.PipelineError))
1351 self.failUnless("ValueError" in r, r)
1353 self.failUnless(f2.check(ValueError))
1355 self.failUnlessEqual(len(flushed), 1)
1357 self.failUnless(isinstance(f, Failure))
1358 self.failUnless(f.check(pipeline.PipelineError))
1360 self.failUnless(f2.check(ValueError))
1362 # now that the pipeline is in the failed state, any new calls will
1365 d3 = p.add(20, self.pause, "two")
1368 d3.addBoth(finished.append)
1369 self.failUnlessEqual(len(finished), 1)
1371 self.failUnless(isinstance(f, Failure))
1372 self.failUnless(f.check(pipeline.PipelineError))
1374 self.failUnless("ValueError" in r, r)
1376 self.failUnless(f2.check(ValueError))
1380 d4.addBoth(flushed.append)
1381 self.failUnlessEqual(len(flushed), 1)
1383 self.failUnless(isinstance(f, Failure))
1384 self.failUnless(f.check(pipeline.PipelineError))
1386 self.failUnless(f2.check(ValueError))
1388 def test_errors2(self):
1390 p = pipeline.Pipeline(100)
1392 d1 = p.add(10, self.pause, "one")
1393 d2 = p.add(20, self.pause, "two")
1394 d3 = p.add(30, self.pause, "three")
1397 # one call fails, then the second one succeeds: make sure
1398 # ExpandableDeferredList tolerates the second one
1401 d4.addBoth(flushed.append)
1402 self.failUnlessEqual(flushed, [])
1404 self.calls[0][0].errback(ValueError("oops"))
1405 self.failUnlessEqual(len(flushed), 1)
1407 self.failUnless(isinstance(f, Failure))
1408 self.failUnless(f.check(pipeline.PipelineError))
1410 self.failUnless(f2.check(ValueError))
1412 self.calls[1][0].callback("two-result")
1413 self.calls[2][0].errback(ValueError("three-error"))