| OLD | NEW |
| (Empty) |
| 1 # -*- test-case-name: twisted.test.test_util -*- | |
| 2 # Copyright (c) 2001-2008 Twisted Matrix Laboratories. | |
| 3 # See LICENSE for details. | |
| 4 | |
| 5 import os.path, sys | |
| 6 import shutil, errno | |
| 7 try: | |
| 8 import pwd, grp | |
| 9 except ImportError: | |
| 10 pwd = grp = None | |
| 11 | |
| 12 from twisted.trial import unittest | |
| 13 | |
| 14 from twisted.python import util | |
| 15 from twisted.internet import reactor | |
| 16 from twisted.internet.interfaces import IReactorProcess | |
| 17 from twisted.internet.protocol import ProcessProtocol | |
| 18 from twisted.internet.defer import Deferred | |
| 19 from twisted.internet.error import ProcessDone | |
| 20 | |
| 21 | |
| 22 class UtilTestCase(unittest.TestCase): | |
| 23 | |
| 24 def testUniq(self): | |
| 25 l = ["a", 1, "ab", "a", 3, 4, 1, 2, 2, 4, 6] | |
| 26 self.assertEquals(util.uniquify(l), ["a", 1, "ab", 3, 4, 2, 6]) | |
| 27 | |
| 28 def testRaises(self): | |
| 29 self.failUnless(util.raises(ZeroDivisionError, divmod, 1, 0)) | |
| 30 self.failIf(util.raises(ZeroDivisionError, divmod, 0, 1)) | |
| 31 | |
| 32 try: | |
| 33 util.raises(TypeError, divmod, 1, 0) | |
| 34 except ZeroDivisionError: | |
| 35 pass | |
| 36 else: | |
| 37 raise unittest.FailTest, "util.raises didn't raise when it should ha
ve" | |
| 38 | |
| 39 def testUninterruptably(self): | |
| 40 def f(a, b): | |
| 41 self.calls += 1 | |
| 42 exc = self.exceptions.pop() | |
| 43 if exc is not None: | |
| 44 raise exc(errno.EINTR, "Interrupted system call!") | |
| 45 return a + b | |
| 46 | |
| 47 self.exceptions = [None] | |
| 48 self.calls = 0 | |
| 49 self.assertEquals(util.untilConcludes(f, 1, 2), 3) | |
| 50 self.assertEquals(self.calls, 1) | |
| 51 | |
| 52 self.exceptions = [None, OSError, IOError] | |
| 53 self.calls = 0 | |
| 54 self.assertEquals(util.untilConcludes(f, 2, 3), 5) | |
| 55 self.assertEquals(self.calls, 3) | |
| 56 | |
| 57 def testUnsignedID(self): | |
| 58 util.id = lambda x: x | |
| 59 try: | |
| 60 for i in range(1, 100): | |
| 61 self.assertEquals(util.unsignedID(i), i) | |
| 62 top = (sys.maxint + 1L) * 2L | |
| 63 for i in range(-100, -1): | |
| 64 self.assertEquals(util.unsignedID(i), top + i) | |
| 65 finally: | |
| 66 del util.id | |
| 67 | |
| 68 def testNameToLabel(self): | |
| 69 """ | |
| 70 Test the various kinds of inputs L{nameToLabel} supports. | |
| 71 """ | |
| 72 nameData = [ | |
| 73 ('f', 'F'), | |
| 74 ('fo', 'Fo'), | |
| 75 ('foo', 'Foo'), | |
| 76 ('fooBar', 'Foo Bar'), | |
| 77 ('fooBarBaz', 'Foo Bar Baz'), | |
| 78 ] | |
| 79 for inp, out in nameData: | |
| 80 got = util.nameToLabel(inp) | |
| 81 self.assertEquals( | |
| 82 got, out, | |
| 83 "nameToLabel(%r) == %r != %r" % (inp, got, out)) | |
| 84 | |
| 85 | |
| 86 def test_uidFromNumericString(self): | |
| 87 """ | |
| 88 When L{uidFromString} is called with a base-ten string representation | |
| 89 of an integer, it returns the integer. | |
| 90 """ | |
| 91 self.assertEqual(util.uidFromString("100"), 100) | |
| 92 | |
| 93 | |
| 94 def test_uidFromUsernameString(self): | |
| 95 """ | |
| 96 When L{uidFromString} is called with a base-ten string representation | |
| 97 of an integer, it returns the integer. | |
| 98 """ | |
| 99 pwent = pwd.getpwuid(os.getuid()) | |
| 100 self.assertEqual(util.uidFromString(pwent.pw_name), pwent.pw_uid) | |
| 101 if pwd is None: | |
| 102 test_uidFromUsernameString.skip = ( | |
| 103 "Username/UID conversion requires the pwd module.") | |
| 104 | |
| 105 | |
| 106 def test_gidFromNumericString(self): | |
| 107 """ | |
| 108 When L{gidFromString} is called with a base-ten string representation | |
| 109 of an integer, it returns the integer. | |
| 110 """ | |
| 111 self.assertEqual(util.gidFromString("100"), 100) | |
| 112 | |
| 113 | |
| 114 def test_gidFromGroupnameString(self): | |
| 115 """ | |
| 116 When L{gidFromString} is called with a base-ten string representation | |
| 117 of an integer, it returns the integer. | |
| 118 """ | |
| 119 grent = grp.getgrgid(os.getgid()) | |
| 120 self.assertEqual(util.gidFromString(grent.gr_name), grent.gr_gid) | |
| 121 if grp is None: | |
| 122 test_gidFromGroupnameString.skip = ( | |
| 123 "Group Name/GID conversion requires the grp module.") | |
| 124 | |
| 125 | |
| 126 | |
| 127 class TestMergeFunctionMetadata(unittest.TestCase): | |
| 128 """ | |
| 129 Tests for L{mergeFunctionMetadata}. | |
| 130 """ | |
| 131 | |
| 132 def test_mergedFunctionBehavesLikeMergeTarget(self): | |
| 133 """ | |
| 134 After merging C{foo}'s data into C{bar}, the returned function behaves | |
| 135 as if it is C{bar}. | |
| 136 """ | |
| 137 foo_object = object() | |
| 138 bar_object = object() | |
| 139 | |
| 140 def foo(): | |
| 141 return foo_object | |
| 142 | |
| 143 def bar(x, y, (a, b), c=10, *d, **e): | |
| 144 return bar_object | |
| 145 | |
| 146 baz = util.mergeFunctionMetadata(foo, bar) | |
| 147 self.assertIdentical(baz(1, 2, (3, 4), quux=10), bar_object) | |
| 148 | |
| 149 | |
| 150 def test_moduleIsMerged(self): | |
| 151 """ | |
| 152 Merging C{foo} into C{bar} returns a function with C{foo}'s | |
| 153 C{__module__}. | |
| 154 """ | |
| 155 def foo(): | |
| 156 pass | |
| 157 | |
| 158 def bar(): | |
| 159 pass | |
| 160 bar.__module__ = 'somewhere.else' | |
| 161 | |
| 162 baz = util.mergeFunctionMetadata(foo, bar) | |
| 163 self.assertEqual(baz.__module__, foo.__module__) | |
| 164 | |
| 165 | |
| 166 def test_docstringIsMerged(self): | |
| 167 """ | |
| 168 Merging C{foo} into C{bar} returns a function with C{foo}'s docstring. | |
| 169 """ | |
| 170 | |
| 171 def foo(): | |
| 172 """ | |
| 173 This is foo. | |
| 174 """ | |
| 175 | |
| 176 def bar(): | |
| 177 """ | |
| 178 This is bar. | |
| 179 """ | |
| 180 | |
| 181 baz = util.mergeFunctionMetadata(foo, bar) | |
| 182 self.assertEqual(baz.__doc__, foo.__doc__) | |
| 183 | |
| 184 | |
| 185 def test_nameIsMerged(self): | |
| 186 """ | |
| 187 Merging C{foo} into C{bar} returns a function with C{foo}'s name. | |
| 188 """ | |
| 189 | |
| 190 def foo(): | |
| 191 pass | |
| 192 | |
| 193 def bar(): | |
| 194 pass | |
| 195 | |
| 196 baz = util.mergeFunctionMetadata(foo, bar) | |
| 197 self.assertEqual(baz.__name__, foo.__name__) | |
| 198 | |
| 199 | |
| 200 def test_instanceDictionaryIsMerged(self): | |
| 201 """ | |
| 202 Merging C{foo} into C{bar} returns a function with C{bar}'s | |
| 203 dictionary, updated by C{foo}'s. | |
| 204 """ | |
| 205 | |
| 206 def foo(): | |
| 207 pass | |
| 208 foo.a = 1 | |
| 209 foo.b = 2 | |
| 210 | |
| 211 def bar(): | |
| 212 pass | |
| 213 bar.b = 3 | |
| 214 bar.c = 4 | |
| 215 | |
| 216 baz = util.mergeFunctionMetadata(foo, bar) | |
| 217 self.assertEqual(foo.a, baz.a) | |
| 218 self.assertEqual(foo.b, baz.b) | |
| 219 self.assertEqual(bar.c, baz.c) | |
| 220 | |
| 221 | |
| 222 | |
| 223 class OrderedDictTest(unittest.TestCase): | |
| 224 def testOrderedDict(self): | |
| 225 d = util.OrderedDict() | |
| 226 d['a'] = 'b' | |
| 227 d['b'] = 'a' | |
| 228 d[3] = 12 | |
| 229 d[1234] = 4321 | |
| 230 self.assertEquals(repr(d), "{'a': 'b', 'b': 'a', 3: 12, 1234: 4321}") | |
| 231 self.assertEquals(d.values(), ['b', 'a', 12, 4321]) | |
| 232 del d[3] | |
| 233 self.assertEquals(repr(d), "{'a': 'b', 'b': 'a', 1234: 4321}") | |
| 234 self.assertEquals(d, {'a': 'b', 'b': 'a', 1234:4321}) | |
| 235 self.assertEquals(d.keys(), ['a', 'b', 1234]) | |
| 236 self.assertEquals(list(d.iteritems()), | |
| 237 [('a', 'b'), ('b','a'), (1234, 4321)]) | |
| 238 item = d.popitem() | |
| 239 self.assertEquals(item, (1234, 4321)) | |
| 240 | |
| 241 def testInitialization(self): | |
| 242 d = util.OrderedDict({'monkey': 'ook', | |
| 243 'apple': 'red'}) | |
| 244 self.failUnless(d._order) | |
| 245 | |
| 246 d = util.OrderedDict(((1,1),(3,3),(2,2),(0,0))) | |
| 247 self.assertEquals(repr(d), "{1: 1, 3: 3, 2: 2, 0: 0}") | |
| 248 | |
| 249 class InsensitiveDictTest(unittest.TestCase): | |
| 250 def testPreserve(self): | |
| 251 InsensitiveDict=util.InsensitiveDict | |
| 252 dct=InsensitiveDict({'Foo':'bar', 1:2, 'fnz':{1:2}}, preserve=1) | |
| 253 self.assertEquals(dct['fnz'], {1:2}) | |
| 254 self.assertEquals(dct['foo'], 'bar') | |
| 255 self.assertEquals(dct.copy(), dct) | |
| 256 self.assertEquals(dct['foo'], dct.get('Foo')) | |
| 257 assert 1 in dct and 'foo' in dct | |
| 258 self.assertEquals(eval(repr(dct)), dct) | |
| 259 keys=['Foo', 'fnz', 1] | |
| 260 for x in keys: | |
| 261 assert x in dct.keys() | |
| 262 assert (x, dct[x]) in dct.items() | |
| 263 self.assertEquals(len(keys), len(dct)) | |
| 264 del dct[1] | |
| 265 del dct['foo'] | |
| 266 | |
| 267 def testNoPreserve(self): | |
| 268 InsensitiveDict=util.InsensitiveDict | |
| 269 dct=InsensitiveDict({'Foo':'bar', 1:2, 'fnz':{1:2}}, preserve=0) | |
| 270 keys=['foo', 'fnz', 1] | |
| 271 for x in keys: | |
| 272 assert x in dct.keys() | |
| 273 assert (x, dct[x]) in dct.items() | |
| 274 self.assertEquals(len(keys), len(dct)) | |
| 275 del dct[1] | |
| 276 del dct['foo'] | |
| 277 | |
| 278 | |
| 279 | |
| 280 | |
| 281 class PasswordTestingProcessProtocol(ProcessProtocol): | |
| 282 """ | |
| 283 Write the string C{"secret\n"} to a subprocess and then collect all of | |
| 284 its output and fire a Deferred with it when the process ends. | |
| 285 """ | |
| 286 def connectionMade(self): | |
| 287 self.output = [] | |
| 288 self.transport.write('secret\n') | |
| 289 | |
| 290 def childDataReceived(self, fd, output): | |
| 291 self.output.append((fd, output)) | |
| 292 | |
| 293 def processEnded(self, reason): | |
| 294 self.finished.callback((reason, self.output)) | |
| 295 | |
| 296 | |
| 297 class GetPasswordTest(unittest.TestCase): | |
| 298 if not IReactorProcess.providedBy(reactor): | |
| 299 skip = "Process support required to test getPassword" | |
| 300 | |
| 301 def test_stdin(self): | |
| 302 """ | |
| 303 Making sure getPassword accepts a password from standard input by | |
| 304 running a child process which uses getPassword to read in a string | |
| 305 which it then writes it out again. Write a string to the child | |
| 306 process and then read one and make sure it is the right string. | |
| 307 """ | |
| 308 p = PasswordTestingProcessProtocol() | |
| 309 p.finished = Deferred() | |
| 310 reactor.spawnProcess( | |
| 311 p, | |
| 312 sys.executable, | |
| 313 [sys.executable, | |
| 314 '-c', | |
| 315 ('import sys\n' | |
| 316 'from twisted.python.util import getPassword\n' | |
| 317 'sys.stdout.write(getPassword())\n' | |
| 318 'sys.stdout.flush()\n')], | |
| 319 env={'PYTHONPATH': os.pathsep.join(sys.path)}) | |
| 320 | |
| 321 def processFinished((reason, output)): | |
| 322 reason.trap(ProcessDone) | |
| 323 self.assertIn((1, 'secret'), output) | |
| 324 | |
| 325 return p.finished.addCallback(processFinished) | |
| 326 | |
| 327 | |
| 328 | |
| 329 class SearchUpwardsTest(unittest.TestCase): | |
| 330 def testSearchupwards(self): | |
| 331 os.makedirs('searchupwards/a/b/c') | |
| 332 file('searchupwards/foo.txt', 'w').close() | |
| 333 file('searchupwards/a/foo.txt', 'w').close() | |
| 334 file('searchupwards/a/b/c/foo.txt', 'w').close() | |
| 335 os.mkdir('searchupwards/bar') | |
| 336 os.mkdir('searchupwards/bam') | |
| 337 os.mkdir('searchupwards/a/bar') | |
| 338 os.mkdir('searchupwards/a/b/bam') | |
| 339 actual=util.searchupwards('searchupwards/a/b/c', | |
| 340 files=['foo.txt'], | |
| 341 dirs=['bar', 'bam']) | |
| 342 expected=os.path.abspath('searchupwards') + os.sep | |
| 343 self.assertEqual(actual, expected) | |
| 344 shutil.rmtree('searchupwards') | |
| 345 actual=util.searchupwards('searchupwards/a/b/c', | |
| 346 files=['foo.txt'], | |
| 347 dirs=['bar', 'bam']) | |
| 348 expected=None | |
| 349 self.assertEqual(actual, expected) | |
| 350 | |
| 351 class Foo: | |
| 352 def __init__(self, x): | |
| 353 self.x = x | |
| 354 | |
| 355 class DSU(unittest.TestCase): | |
| 356 def testDSU(self): | |
| 357 L = [Foo(x) for x in range(20, 9, -1)] | |
| 358 L2 = util.dsu(L, lambda o: o.x) | |
| 359 self.assertEquals(range(10, 21), [o.x for o in L2]) | |
| 360 | |
| 361 class IntervalDifferentialTestCase(unittest.TestCase): | |
| 362 def testDefault(self): | |
| 363 d = iter(util.IntervalDifferential([], 10)) | |
| 364 for i in range(100): | |
| 365 self.assertEquals(d.next(), (10, None)) | |
| 366 | |
| 367 def testSingle(self): | |
| 368 d = iter(util.IntervalDifferential([5], 10)) | |
| 369 for i in range(100): | |
| 370 self.assertEquals(d.next(), (5, 0)) | |
| 371 | |
| 372 def testPair(self): | |
| 373 d = iter(util.IntervalDifferential([5, 7], 10)) | |
| 374 for i in range(100): | |
| 375 self.assertEquals(d.next(), (5, 0)) | |
| 376 self.assertEquals(d.next(), (2, 1)) | |
| 377 self.assertEquals(d.next(), (3, 0)) | |
| 378 self.assertEquals(d.next(), (4, 1)) | |
| 379 self.assertEquals(d.next(), (1, 0)) | |
| 380 self.assertEquals(d.next(), (5, 0)) | |
| 381 self.assertEquals(d.next(), (1, 1)) | |
| 382 self.assertEquals(d.next(), (4, 0)) | |
| 383 self.assertEquals(d.next(), (3, 1)) | |
| 384 self.assertEquals(d.next(), (2, 0)) | |
| 385 self.assertEquals(d.next(), (5, 0)) | |
| 386 self.assertEquals(d.next(), (0, 1)) | |
| 387 | |
| 388 def testTriple(self): | |
| 389 d = iter(util.IntervalDifferential([2, 4, 5], 10)) | |
| 390 for i in range(100): | |
| 391 self.assertEquals(d.next(), (2, 0)) | |
| 392 self.assertEquals(d.next(), (2, 0)) | |
| 393 self.assertEquals(d.next(), (0, 1)) | |
| 394 self.assertEquals(d.next(), (1, 2)) | |
| 395 self.assertEquals(d.next(), (1, 0)) | |
| 396 self.assertEquals(d.next(), (2, 0)) | |
| 397 self.assertEquals(d.next(), (0, 1)) | |
| 398 self.assertEquals(d.next(), (2, 0)) | |
| 399 self.assertEquals(d.next(), (0, 2)) | |
| 400 self.assertEquals(d.next(), (2, 0)) | |
| 401 self.assertEquals(d.next(), (0, 1)) | |
| 402 self.assertEquals(d.next(), (2, 0)) | |
| 403 self.assertEquals(d.next(), (1, 2)) | |
| 404 self.assertEquals(d.next(), (1, 0)) | |
| 405 self.assertEquals(d.next(), (0, 1)) | |
| 406 self.assertEquals(d.next(), (2, 0)) | |
| 407 self.assertEquals(d.next(), (2, 0)) | |
| 408 self.assertEquals(d.next(), (0, 1)) | |
| 409 self.assertEquals(d.next(), (0, 2)) | |
| 410 | |
| 411 def testInsert(self): | |
| 412 d = iter(util.IntervalDifferential([], 10)) | |
| 413 self.assertEquals(d.next(), (10, None)) | |
| 414 d.addInterval(3) | |
| 415 self.assertEquals(d.next(), (3, 0)) | |
| 416 self.assertEquals(d.next(), (3, 0)) | |
| 417 d.addInterval(6) | |
| 418 self.assertEquals(d.next(), (3, 0)) | |
| 419 self.assertEquals(d.next(), (3, 0)) | |
| 420 self.assertEquals(d.next(), (0, 1)) | |
| 421 self.assertEquals(d.next(), (3, 0)) | |
| 422 self.assertEquals(d.next(), (3, 0)) | |
| 423 self.assertEquals(d.next(), (0, 1)) | |
| 424 | |
| 425 def testRemove(self): | |
| 426 d = iter(util.IntervalDifferential([3, 5], 10)) | |
| 427 self.assertEquals(d.next(), (3, 0)) | |
| 428 self.assertEquals(d.next(), (2, 1)) | |
| 429 self.assertEquals(d.next(), (1, 0)) | |
| 430 d.removeInterval(3) | |
| 431 self.assertEquals(d.next(), (4, 0)) | |
| 432 self.assertEquals(d.next(), (5, 0)) | |
| 433 d.removeInterval(5) | |
| 434 self.assertEquals(d.next(), (10, None)) | |
| 435 self.assertRaises(ValueError, d.removeInterval, 10) | |
| 436 | |
| 437 | |
| 438 | |
| 439 class Record(util.FancyEqMixin): | |
| 440 """ | |
| 441 Trivial user of L{FancyEqMixin} used by tests. | |
| 442 """ | |
| 443 compareAttributes = ('a', 'b') | |
| 444 | |
| 445 def __init__(self, a, b): | |
| 446 self.a = a | |
| 447 self.b = b | |
| 448 | |
| 449 | |
| 450 | |
| 451 class DifferentRecord(util.FancyEqMixin): | |
| 452 """ | |
| 453 Trivial user of L{FancyEqMixin} which is not related to L{Record}. | |
| 454 """ | |
| 455 compareAttributes = ('a', 'b') | |
| 456 | |
| 457 def __init__(self, a, b): | |
| 458 self.a = a | |
| 459 self.b = b | |
| 460 | |
| 461 | |
| 462 | |
| 463 class DerivedRecord(Record): | |
| 464 """ | |
| 465 A class with an inheritance relationship to L{Record}. | |
| 466 """ | |
| 467 | |
| 468 | |
| 469 | |
| 470 class EqualToEverything(object): | |
| 471 """ | |
| 472 A class the instances of which consider themselves equal to everything. | |
| 473 """ | |
| 474 def __eq__(self, other): | |
| 475 return True | |
| 476 | |
| 477 | |
| 478 def __ne__(self, other): | |
| 479 return False | |
| 480 | |
| 481 | |
| 482 | |
| 483 class EqualToNothing(object): | |
| 484 """ | |
| 485 A class the instances of which consider themselves equal to nothing. | |
| 486 """ | |
| 487 def __eq__(self, other): | |
| 488 return False | |
| 489 | |
| 490 | |
| 491 def __ne__(self, other): | |
| 492 return True | |
| 493 | |
| 494 | |
| 495 | |
| 496 class EqualityTests(unittest.TestCase): | |
| 497 """ | |
| 498 Tests for L{FancyEqMixin}. | |
| 499 """ | |
| 500 def test_identity(self): | |
| 501 """ | |
| 502 Instances of a class which mixes in L{FancyEqMixin} but which | |
| 503 defines no comparison attributes compare by identity. | |
| 504 """ | |
| 505 class Empty(util.FancyEqMixin): | |
| 506 pass | |
| 507 | |
| 508 self.assertFalse(Empty() == Empty()) | |
| 509 self.assertTrue(Empty() != Empty()) | |
| 510 empty = Empty() | |
| 511 self.assertTrue(empty == empty) | |
| 512 self.assertFalse(empty != empty) | |
| 513 | |
| 514 | |
| 515 def test_equality(self): | |
| 516 """ | |
| 517 Instances of a class which mixes in L{FancyEqMixin} should compare | |
| 518 equal if all of their attributes compare equal. They should not | |
| 519 compare equal if any of their attributes do not compare equal. | |
| 520 """ | |
| 521 self.assertTrue(Record(1, 2) == Record(1, 2)) | |
| 522 self.assertFalse(Record(1, 2) == Record(1, 3)) | |
| 523 self.assertFalse(Record(1, 2) == Record(2, 2)) | |
| 524 self.assertFalse(Record(1, 2) == Record(3, 4)) | |
| 525 | |
| 526 | |
| 527 def test_unequality(self): | |
| 528 """ | |
| 529 Unequality between instances of a particular L{record} should be | |
| 530 defined as the negation of equality. | |
| 531 """ | |
| 532 self.assertFalse(Record(1, 2) != Record(1, 2)) | |
| 533 self.assertTrue(Record(1, 2) != Record(1, 3)) | |
| 534 self.assertTrue(Record(1, 2) != Record(2, 2)) | |
| 535 self.assertTrue(Record(1, 2) != Record(3, 4)) | |
| 536 | |
| 537 | |
| 538 def test_differentClassesEquality(self): | |
| 539 """ | |
| 540 Instances of different classes which mix in L{FancyEqMixin} should not | |
| 541 compare equal. | |
| 542 """ | |
| 543 self.assertFalse(Record(1, 2) == DifferentRecord(1, 2)) | |
| 544 | |
| 545 | |
| 546 def test_differentClassesInequality(self): | |
| 547 """ | |
| 548 Instances of different classes which mix in L{FancyEqMixin} should | |
| 549 compare unequal. | |
| 550 """ | |
| 551 self.assertTrue(Record(1, 2) != DifferentRecord(1, 2)) | |
| 552 | |
| 553 | |
| 554 def test_inheritedClassesEquality(self): | |
| 555 """ | |
| 556 An instance of a class which derives from a class which mixes in | |
| 557 L{FancyEqMixin} should compare equal to an instance of the base class | |
| 558 if and only if all of their attributes compare equal. | |
| 559 """ | |
| 560 self.assertTrue(Record(1, 2) == DerivedRecord(1, 2)) | |
| 561 self.assertFalse(Record(1, 2) == DerivedRecord(1, 3)) | |
| 562 self.assertFalse(Record(1, 2) == DerivedRecord(2, 2)) | |
| 563 self.assertFalse(Record(1, 2) == DerivedRecord(3, 4)) | |
| 564 | |
| 565 | |
| 566 def test_inheritedClassesInequality(self): | |
| 567 """ | |
| 568 An instance of a class which derives from a class which mixes in | |
| 569 L{FancyEqMixin} should compare unequal to an instance of the base | |
| 570 class if any of their attributes compare unequal. | |
| 571 """ | |
| 572 self.assertFalse(Record(1, 2) != DerivedRecord(1, 2)) | |
| 573 self.assertTrue(Record(1, 2) != DerivedRecord(1, 3)) | |
| 574 self.assertTrue(Record(1, 2) != DerivedRecord(2, 2)) | |
| 575 self.assertTrue(Record(1, 2) != DerivedRecord(3, 4)) | |
| 576 | |
| 577 | |
| 578 def test_rightHandArgumentImplementsEquality(self): | |
| 579 """ | |
| 580 The right-hand argument to the equality operator is given a chance | |
| 581 to determine the result of the operation if it is of a type | |
| 582 unrelated to the L{FancyEqMixin}-based instance on the left-hand | |
| 583 side. | |
| 584 """ | |
| 585 self.assertTrue(Record(1, 2) == EqualToEverything()) | |
| 586 self.assertFalse(Record(1, 2) == EqualToNothing()) | |
| 587 | |
| 588 | |
| 589 def test_rightHandArgumentImplementsUnequality(self): | |
| 590 """ | |
| 591 The right-hand argument to the non-equality operator is given a | |
| 592 chance to determine the result of the operation if it is of a type | |
| 593 unrelated to the L{FancyEqMixin}-based instance on the left-hand | |
| 594 side. | |
| 595 """ | |
| 596 self.assertFalse(Record(1, 2) != EqualToEverything()) | |
| 597 self.assertTrue(Record(1, 2) != EqualToNothing()) | |
| OLD | NEW |