Package ldaptor :: Package test :: Module test_inmemory
[hide private]
[frames] | no frames]

Source Code for Module ldaptor.test.test_inmemory

  1  """ 
  2  Test cases for ldaptor.inmemory module. 
  3  """ 
  4   
  5  from twisted.trial import unittest 
  6  from cStringIO import StringIO 
  7  from ldaptor import inmemory, delta, testutil 
  8  from ldaptor.protocols.ldap import distinguishedname, ldaperrors 
  9   
10 -class TestInMemoryDatabase(unittest.TestCase):
11 - def setUp(self):
12 self.root = inmemory.ReadOnlyInMemoryLDAPEntry( 13 dn=distinguishedname.DistinguishedName('dc=example,dc=com')) 14 self.meta=self.root.addChild( 15 rdn='ou=metasyntactic', 16 attributes={ 17 'objectClass': ['a', 'b'], 18 'ou': ['metasyntactic'], 19 }) 20 self.foo=self.meta.addChild( 21 rdn='cn=foo', 22 attributes={ 23 'objectClass': ['a', 'b'], 24 'cn': ['foo'], 25 }) 26 self.bar=self.meta.addChild( 27 rdn='cn=bar', 28 attributes={ 29 'objectClass': ['a', 'b'], 30 'cn': ['bar'], 31 }) 32 33 self.empty=self.root.addChild( 34 rdn='ou=empty', 35 attributes={ 36 'objectClass': ['a', 'b'], 37 'ou': ['empty'], 38 }) 39 40 self.oneChild=self.root.addChild( 41 rdn='ou=oneChild', 42 attributes={ 43 'objectClass': ['a', 'b'], 44 'ou': ['oneChild'], 45 }) 46 self.theChild=self.oneChild.addChild( 47 rdn='cn=theChild', 48 attributes={ 49 'objectClass': ['a', 'b'], 50 'cn': ['theChild'], 51 })
52
53 - def test_children_empty(self):
54 d = self.empty.children() 55 d.addCallback(self.assertEquals, []) 56 return d
57
58 - def test_children_oneChild(self):
59 d = self.oneChild.children() 60 def cb(children): 61 self.assertEquals(len(children), 1) 62 got = [e.dn for e in children] 63 want = [distinguishedname.DistinguishedName('cn=theChild,ou=oneChild,dc=example,dc=com')] 64 got.sort() 65 want.sort() 66 self.assertEquals(got, want)
67 d.addCallback(cb) 68 return d
69
70 - def test_children_repeat(self):
71 """Test that .children() returns a copy of the data so that modifying it does not affect behaviour.""" 72 d = self.oneChild.children() 73 def cb1(children1): 74 self.assertEquals(len(children1), 1) 75 76 children1.pop() 77 78 d = self.oneChild.children() 79 return d
80 d.addCallback(cb1) 81 82 def cb2(children2): 83 self.assertEquals(len(children2), 1) 84 d.addCallback(cb2) 85 return d 86
87 - def test_children_twoChildren(self):
88 d = self.meta.children() 89 def cb(children): 90 self.assertEquals(len(children), 2) 91 want = [ 92 distinguishedname.DistinguishedName('cn=foo,ou=metasyntactic,dc=example,dc=com'), 93 distinguishedname.DistinguishedName('cn=bar,ou=metasyntactic,dc=example,dc=com'), 94 ] 95 got = [e.dn for e in children] 96 self.assertEquals(got, want)
97 d.addCallback(cb) 98 return d 99
100 - def test_addChild(self):
101 self.empty.addChild( 102 rdn='a=b', 103 attributes={ 104 'objectClass': ['a', 'b'], 105 'a': 'b', 106 }) 107 d = self.empty.children() 108 def cb(children): 109 self.assertEquals(len(children), 1) 110 got = [e.dn for e in children] 111 want = [ 112 distinguishedname.DistinguishedName('a=b,ou=empty,dc=example,dc=com'), 113 ] 114 got.sort() 115 want.sort() 116 self.assertEquals(got, want)
117 d.addCallback(cb) 118 return d 119
120 - def test_addChild_Exists(self):
121 self.assertRaises(ldaperrors.LDAPEntryAlreadyExists, 122 self.meta.addChild, 123 rdn='cn=foo', 124 attributes={ 125 'objectClass': ['a'], 126 'cn': 'foo', 127 })
128
129 - def test_parent(self):
130 self.assertEquals(self.foo.parent(), self.meta) 131 self.assertEquals(self.meta.parent(), self.root) 132 self.assertEquals(self.root.parent(), None)
133 134
135 - def test_subtree_empty(self):
136 d = self.empty.subtree() 137 def cb(entries): 138 self.assertEquals(len(entries), 1)
139 d.addCallback(cb) 140 return d 141
142 - def test_subtree_oneChild(self):
143 d = self.oneChild.subtree() 144 d.addCallback(self.assertEquals, [ 145 self.oneChild, 146 self.theChild, 147 ]) 148 return d
149
150 - def test_subtree_oneChild_cb(self):
151 got = [] 152 d = self.oneChild.subtree(got.append) 153 d.addCallback(self.assertEquals, None) 154 def cb(dummy): 155 want = [ 156 self.oneChild, 157 self.theChild, 158 ] 159 self.assertEquals(got, want)
160 d.addCallback(cb) 161 return d 162
163 - def test_subtree_many(self):
164 d = self.root.subtree() 165 def cb(results): 166 got = results 167 want = [ 168 self.root, 169 self.oneChild, 170 self.theChild, 171 self.empty, 172 self.meta, 173 self.bar, 174 self.foo, 175 ] 176 self.assertEquals(got, want)
177 d.addCallback(cb) 178 return d 179
180 - def test_subtree_many_cb(self):
181 got = [] 182 d = self.root.subtree(callback=got.append) 183 def cb(r): 184 self.assertEquals(r, None) 185 186 want = [ 187 self.root, 188 self.oneChild, 189 self.theChild, 190 self.empty, 191 self.meta, 192 self.bar, 193 self.foo, 194 ] 195 self.assertEquals(got, want)
196 d.addCallback(cb) 197 return d 198
199 - def test_lookup_fail(self):
200 dn = distinguishedname.DistinguishedName('cn=thud,ou=metasyntactic,dc=example,dc=com') 201 d = self.root.lookup(dn) 202 def eb(fail): 203 fail.trap(ldaperrors.LDAPNoSuchObject) 204 self.assertEquals(fail.value.message, dn)
205 d.addCallbacks(testutil.mustRaise, eb) 206 return d 207
208 - def test_lookup_fail_outOfTree(self):
209 dn = distinguishedname.DistinguishedName('dc=invalid') 210 d = self.root.lookup(dn) 211 def eb(fail): 212 fail.trap(ldaperrors.LDAPNoSuchObject) 213 self.assertEquals(fail.value.message, dn)
214 d.addCallbacks(testutil.mustRaise, eb) 215 return d 216
217 - def test_lookup_deep(self):
218 dn = distinguishedname.DistinguishedName('cn=bar,ou=metasyntactic,dc=example,dc=com') 219 d = self.root.lookup(dn) 220 d.addCallback(self.assertEquals, self.bar) 221 return d
222
223 - def test_delete_root(self):
224 newRoot = inmemory.ReadOnlyInMemoryLDAPEntry( 225 dn=distinguishedname.DistinguishedName('dc=example,dc=com')) 226 d = newRoot.delete() 227 def eb(fail): 228 fail.trap(inmemory.LDAPCannotRemoveRootError)
229 d.addCallbacks(testutil.mustRaise, eb) 230 return d 231
232 - def test_delete_nonLeaf(self):
233 d = self.meta.delete() 234 def eb(fail): 235 fail.trap(ldaperrors.LDAPNotAllowedOnNonLeaf)
236 d.addCallbacks(testutil.mustRaise, eb) 237 return d 238
239 - def test_delete(self):
240 d = self.foo.delete() 241 d.addCallback(self.assertEquals, self.foo) 242 d.addCallback(lambda _: self.meta.children()) 243 d.addCallback(self.assertEquals, [self.bar]) 244 return d
245
246 - def test_deleteChild(self):
247 d = self.meta.deleteChild('cn=bar') 248 d.addCallback(self.assertEquals, self.bar) 249 d.addCallback(lambda _: self.meta.children()) 250 d.addCallback(self.assertEquals, [self.foo]) 251 return d
252
253 - def test_deleteChild_NonExisting(self):
254 d = self.root.deleteChild('cn=not-exist') 255 def eb(fail): 256 fail.trap(ldaperrors.LDAPNoSuchObject)
257 d.addCallbacks(testutil.mustRaise, eb) 258 return d 259
260 - def test_setPassword(self):
261 self.foo.setPassword('s3krit', salt='\xf2\x4a') 262 self.failUnless('userPassword' in self.foo) 263 self.assertEquals(self.foo['userPassword'], 264 ['{SSHA}0n/Iw1NhUOKyaI9gm9v5YsO3ZInySg=='])
265
266 - def test_setPassword_noSalt(self):
267 self.foo.setPassword('s3krit') 268 self.failUnless('userPassword' in self.foo) 269 d = self.foo.bind('s3krit') 270 d.addCallback(self.assertIdentical, self.foo) 271 d.addCallback(lambda _: self.foo.bind('s4krit')) 272 def eb(fail): 273 fail.trap(ldaperrors.LDAPInvalidCredentials)
274 d.addCallbacks(testutil.mustRaise, eb) 275 return d 276
277 - def testSearch_withCallback(self):
278 got = [] 279 d = self.root.search(filterText='(|(cn=foo)(cn=bar))', 280 callback=got.append) 281 def cb(r): 282 self.assertEquals(r, None) 283 284 want = [ 285 self.bar, 286 self.foo, 287 ] 288 self.assertEquals(got, want)
289 d.addCallback(cb) 290 return d 291
292 - def testSearch_withoutCallback(self):
293 d = self.root.search(filterText='(|(cn=foo)(cn=bar))') 294 d.addCallback(self.assertEquals, [ 295 self.bar, 296 self.foo, 297 ]) 298 return d
299
300 - def test_move_noChildren_sameSuperior(self):
301 d = self.empty.move('ou=moved,dc=example,dc=com') 302 def getChildren(dummy): 303 return self.root.children()
304 d.addCallback(getChildren) 305 d.addCallback(self.assertEquals, [ 306 self.meta, 307 inmemory.ReadOnlyInMemoryLDAPEntry( 308 dn='ou=moved,dc=example,dc=com', 309 attributes={ 'objectClass': ['a', 'b'], 310 'ou': ['moved'], 311 }), 312 self.oneChild, 313 ]) 314 return d 315
316 - def test_move_children_sameSuperior(self):
317 d = self.meta.move('ou=moved,dc=example,dc=com') 318 def getChildren(dummy): 319 return self.root.children()
320 d.addCallback(getChildren) 321 d.addCallback(self.assertEquals, [ 322 inmemory.ReadOnlyInMemoryLDAPEntry( 323 dn='ou=moved,dc=example,dc=com', 324 attributes={ 'objectClass': ['a', 'b'], 325 'ou': ['moved'], 326 }), 327 self.empty, 328 self.oneChild, 329 ]) 330 return d 331 332
333 - def test_move_noChildren_newSuperior(self):
334 d = self.empty.move('ou=moved,ou=oneChild,dc=example,dc=com') 335 def getChildren(dummy): 336 return self.root.children()
337 d.addCallback(getChildren) 338 d.addCallback(self.assertEquals, [ 339 self.meta, 340 self.oneChild, 341 ]) 342 def getChildren2(dummy): 343 return self.oneChild.children() 344 d.addCallback(getChildren2) 345 d.addCallback(self.assertEquals, [ 346 self.theChild, 347 inmemory.ReadOnlyInMemoryLDAPEntry( 348 dn='ou=moved,ou=oneChild,dc=example,dc=com', 349 attributes={ 'objectClass': ['a', 'b'], 350 'ou': ['moved'], 351 }), 352 ]) 353 return d 354
355 - def test_move_children_newSuperior(self):
356 d = self.meta.move('ou=moved,ou=oneChild,dc=example,dc=com') 357 def getChildren(dummy): 358 return self.root.children()
359 d.addCallback(getChildren) 360 d.addCallback(self.assertEquals, [ 361 self.empty, 362 self.oneChild, 363 ]) 364 def getChildren2(dummy): 365 return self.oneChild.children() 366 d.addCallback(getChildren2) 367 d.addCallback(self.assertEquals, [ 368 self.theChild, 369 inmemory.ReadOnlyInMemoryLDAPEntry( 370 dn='ou=moved,ou=oneChild,dc=example,dc=com', 371 attributes={ 'objectClass': ['a', 'b'], 372 'ou': ['moved'], 373 }), 374 ]) 375 return d 376
377 - def test_commit(self):
378 """ReadOnlyInMemoryLDAPEntry.commit() succeeds immediately.""" 379 self.meta['foo'] = ['bar'] 380 d = self.meta.commit() 381 self.failUnless(d.called) 382 d.addCallback(self.assertIdentical, self.meta) 383 return d
384
385 -class FromLDIF(unittest.TestCase):
386 - def test_single(self):
387 ldif = StringIO('''\ 388 dn: cn=foo,dc=example,dc=com 389 objectClass: a 390 objectClass: b 391 aValue: a 392 aValue: b 393 bValue: c 394 395 ''') 396 d = inmemory.fromLDIFFile(ldif) 397 def cb1(db): 398 self.assertEquals( 399 db.dn, 400 distinguishedname.DistinguishedName('cn=foo,dc=example,dc=com')) 401 return db.children()
402 d.addCallback(cb1) 403 d.addCallback(self.assertEquals, []) 404 return d
405
406 - def test_two(self):
407 ldif = StringIO('''\ 408 dn: dc=example,dc=com 409 objectClass: dcObject 410 dc: example 411 412 dn: cn=foo,dc=example,dc=com 413 objectClass: a 414 cn: foo 415 416 ''') 417 d = inmemory.fromLDIFFile(ldif) 418 def cb1(db): 419 self.assertEquals( 420 db.dn, 421 distinguishedname.DistinguishedName('dc=example,dc=com')) 422 return db.subtree()
423 d.addCallback(cb1) 424 def cb2(children): 425 self.assertEquals(len(children), 2) 426 want = [ 427 distinguishedname.DistinguishedName('dc=example,dc=com'), 428 distinguishedname.DistinguishedName('cn=foo,dc=example,dc=com'), 429 ] 430 got = [e.dn for e in children] 431 self.assertEquals(got, want) 432 d.addCallback(cb2) 433 return d 434
435 - def test_missingNode(self):
436 ldif = StringIO('''\ 437 dn: dc=example,dc=com 438 objectClass: dcObject 439 dc: example 440 441 dn: cn=foo,ou=nonexisting,dc=example,dc=com 442 objectClass: a 443 cn: foo 444 445 ''') 446 d = inmemory.fromLDIFFile(ldif) 447 def eb(fail): 448 fail.trap(ldaperrors.LDAPNoSuchObject) 449 self.failUnlessEqual( 450 str(fail.value), 451 'noSuchObject: ou=nonexisting,dc=example,dc=com')
452 d.addCallbacks(testutil.mustRaise, eb) 453 return d 454 455
456 -class TestDiff(unittest.TestCase):
457 - def testNoChange(self):
458 a = inmemory.ReadOnlyInMemoryLDAPEntry('dc=example,dc=com', 459 { 460 'dc': ['example'], 461 }) 462 b = inmemory.ReadOnlyInMemoryLDAPEntry('dc=example,dc=com', 463 { 464 'dc': ['example'], 465 }) 466 d = a.diffTree(b) 467 d.addCallback(self.assertEquals, []) 468 return d
469
470 - def testRootChange_Add(self):
471 a = inmemory.ReadOnlyInMemoryLDAPEntry('dc=example,dc=com', 472 { 473 'dc': ['example'], 474 }) 475 b = inmemory.ReadOnlyInMemoryLDAPEntry('dc=example,dc=com', 476 { 477 'dc': ['example'], 478 'foo': ['bar'], 479 }) 480 d = a.diffTree(b) 481 d.addCallback(self.assertEquals, 482 [ delta.ModifyOp('dc=example,dc=com', 483 [ 484 delta.Add('foo', ['bar']), 485 ]), 486 ]) 487 return d
488
489 - def testChildChange_Add(self):
490 a = inmemory.ReadOnlyInMemoryLDAPEntry('dc=example,dc=com', 491 { 492 'dc': ['example'], 493 }) 494 a.addChild('cn=foo', 495 { 'cn': ['foo'], 496 }) 497 b = inmemory.ReadOnlyInMemoryLDAPEntry('dc=example,dc=com', 498 { 499 'dc': ['example'], 500 }) 501 b.addChild('cn=foo', 502 { 'cn': ['foo'], 503 'foo': ['bar'], 504 }) 505 d = a.diffTree(b) 506 d.addCallback(self.assertEquals, 507 [ delta.ModifyOp('cn=foo,dc=example,dc=com', 508 [ 509 delta.Add('foo', ['bar']), 510 ]), 511 ]) 512 return d
513
514 - def testAddChild(self):
515 a = inmemory.ReadOnlyInMemoryLDAPEntry( 516 dn=distinguishedname.DistinguishedName('dc=example,dc=com')) 517 b = inmemory.ReadOnlyInMemoryLDAPEntry( 518 dn=distinguishedname.DistinguishedName('dc=example,dc=com')) 519 520 foo=b.addChild( 521 rdn='cn=foo', 522 attributes={ 523 'objectClass': ['a', 'b'], 524 'cn': ['foo'], 525 }) 526 bar=b.addChild( 527 rdn='cn=bar', 528 attributes={ 529 'objectClass': ['a', 'b'], 530 'cn': ['bar'], 531 }) 532 533 d = a.diffTree(b) 534 d.addCallback(self.assertEquals, [ 535 delta.AddOp(bar), 536 delta.AddOp(foo), 537 ]) 538 return d
539
540 - def testAddSubtree(self):
541 a = inmemory.ReadOnlyInMemoryLDAPEntry( 542 dn=distinguishedname.DistinguishedName('dc=example,dc=com')) 543 b = inmemory.ReadOnlyInMemoryLDAPEntry( 544 dn=distinguishedname.DistinguishedName('dc=example,dc=com')) 545 546 foo=b.addChild( 547 rdn='ou=foo', 548 attributes={ 549 'objectClass': ['a', 'b'], 550 'ou': ['foo'], 551 }) 552 baz=foo.addChild( 553 rdn='cn=baz', 554 attributes={ 555 'objectClass': ['a', 'b'], 556 'cn': ['baz'], 557 }) 558 bar=b.addChild( 559 rdn='cn=bar', 560 attributes={ 561 'objectClass': ['a', 'b'], 562 'cn': ['bar'], 563 }) 564 565 d = a.diffTree(b) 566 d.addCallback(self.assertEquals, [ 567 delta.AddOp(bar), 568 delta.AddOp(foo), 569 delta.AddOp(baz), 570 ]) 571 return d
572
573 - def testDeleteChild(self):
574 a = inmemory.ReadOnlyInMemoryLDAPEntry( 575 dn=distinguishedname.DistinguishedName('dc=example,dc=com')) 576 b = inmemory.ReadOnlyInMemoryLDAPEntry( 577 dn=distinguishedname.DistinguishedName('dc=example,dc=com')) 578 579 foo=a.addChild( 580 rdn='cn=foo', 581 attributes={ 582 'objectClass': ['a', 'b'], 583 'cn': ['foo'], 584 }) 585 bar=a.addChild( 586 rdn='cn=bar', 587 attributes={ 588 'objectClass': ['a', 'b'], 589 'cn': ['bar'], 590 }) 591 592 d = a.diffTree(b) 593 d.addCallback(self.assertEquals, [ 594 delta.DeleteOp(bar), 595 delta.DeleteOp(foo), 596 ]) 597 return d
598
599 - def testDeleteSubtree(self):
600 a = inmemory.ReadOnlyInMemoryLDAPEntry( 601 dn=distinguishedname.DistinguishedName('dc=example,dc=com')) 602 b = inmemory.ReadOnlyInMemoryLDAPEntry( 603 dn=distinguishedname.DistinguishedName('dc=example,dc=com')) 604 605 foo=a.addChild( 606 rdn='ou=foo', 607 attributes={ 608 'objectClass': ['a', 'b'], 609 'ou': ['foo'], 610 }) 611 baz=foo.addChild( 612 rdn='cn=baz', 613 attributes={ 614 'objectClass': ['a', 'b'], 615 'cn': ['baz'], 616 }) 617 bar=a.addChild( 618 rdn='cn=bar', 619 attributes={ 620 'objectClass': ['a', 'b'], 621 'cn': ['bar'], 622 }) 623 624 d = a.diffTree(b) 625 d.addCallback(self.assertEquals, [ 626 delta.DeleteOp(bar), 627 delta.DeleteOp(baz), 628 delta.DeleteOp(foo), 629 ]) 630 return d
631