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
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
54 d = self.empty.children()
55 d.addCallback(self.assertEquals, [])
56 return d
57
67 d.addCallback(cb)
68 return d
69
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
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
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
128
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
136 d = self.empty.subtree()
137 def cb(entries):
138 self.assertEquals(len(entries), 1)
139 d.addCallback(cb)
140 return d
141
143 d = self.oneChild.subtree()
144 d.addCallback(self.assertEquals, [
145 self.oneChild,
146 self.theChild,
147 ])
148 return d
149
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
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
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
205 d.addCallbacks(testutil.mustRaise, eb)
206 return d
207
214 d.addCallbacks(testutil.mustRaise, eb)
215 return d
216
222
229 d.addCallbacks(testutil.mustRaise, eb)
230 return d
231
236 d.addCallbacks(testutil.mustRaise, eb)
237 return d
238
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
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
257 d.addCallbacks(testutil.mustRaise, eb)
258 return d
259
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
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
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
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
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
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
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
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
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
402 d.addCallback(cb1)
403 d.addCallback(self.assertEquals, [])
404 return d
405
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
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
469
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
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
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
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
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
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