Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-test
[kai/samba.git] / source / lib / ldb / tests / python / ldap.py
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 # This is a port of the original in testprogs/ejs/ldap.js
4
5 import getopt
6 import optparse
7 import sys
8
9 sys.path.append("bin/python")
10
11 import samba.getopt as options
12
13 from samba.auth import system_session
14 from ldb import (SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError,
15                  LDB_ERR_NO_SUCH_OBJECT, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS,
16                  LDB_ERR_ENTRY_ALREADY_EXISTS, LDB_ERR_UNWILLING_TO_PERFORM,
17                  LDB_ERR_NOT_ALLOWED_ON_NON_LEAF, LDB_ERR_OTHER, LDB_ERR_INVALID_DN_SYNTAX)
18 from samba import Ldb
19 from subunit import SubunitTestRunner
20 from samba import param
21 import unittest
22
23 parser = optparse.OptionParser("ldap [options] <host>")
24 sambaopts = options.SambaOptions(parser)
25 parser.add_option_group(sambaopts)
26 parser.add_option_group(options.VersionOptions(parser))
27 # use command line creds if available
28 credopts = options.CredentialsOptions(parser)
29 parser.add_option_group(credopts)
30 opts, args = parser.parse_args()
31
32 if len(args) < 1:
33     parser.print_usage()
34     sys.exit(1)
35
36 host = args[0]
37
38 lp = sambaopts.get_loadparm()
39 creds = credopts.get_credentials(lp)
40
41 class BasicTests(unittest.TestCase):
42     def delete_force(self, ldb, dn):
43         try:
44             ldb.delete(dn)
45         except LdbError, (num, _): 
46             self.assertEquals(num, LDB_ERR_NO_SUCH_OBJECT)
47
48     def find_basedn(self, ldb):
49         res = ldb.search(base="", expression="", scope=SCOPE_BASE, 
50                          attrs=["defaultNamingContext"])
51         self.assertEquals(len(res), 1)
52         return res[0]["defaultNamingContext"][0]
53
54     def find_configurationdn(self, ldb):
55         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["configurationNamingContext"])
56         self.assertEquals(len(res), 1)
57         return res[0]["configurationNamingContext"][0]
58
59     def find_schemadn(self, ldb):
60         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
61         self.assertEquals(len(res), 1)
62         return res[0]["schemaNamingContext"][0]
63
64     def setUp(self):
65         self.ldb = ldb
66         self.gc_ldb = gc_ldb
67         self.base_dn = self.find_basedn(ldb)
68         self.configuration_dn = self.find_configurationdn(ldb)
69         self.schema_dn = self.find_schemadn(ldb)
70
71         print "baseDN: %s\n" % self.base_dn
72
73         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
74         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
75
76     def test_group_add_invalid_member(self):
77         """Testing group add with invalid member"""
78         try:
79             self.ldb.add({
80                 "dn": "cn=ldaptestgroup,cn=uSers," + self.base_dn,
81                 "objectclass": "group",
82                 "member": "cn=ldaptestuser,cn=useRs," + self.base_dn})
83             self.fail()
84         except LdbError, (num, _): 
85             self.assertEquals(num, LDB_ERR_NO_SUCH_OBJECT)
86
87     def test_all(self):
88         """Basic tests"""
89
90         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
91
92         print "Testing user add"
93         ldb.add({
94         "dn": "cn=ldaptestuser,cn=uSers," + self.base_dn,
95         "objectclass": ["user", "person"],
96         "cN": "LDAPtestUSER",
97         "givenname": "ldap",
98         "sn": "testy"})
99
100         ldb.add({
101             "dn": "cn=ldaptestgroup,cn=uSers," + self.base_dn,
102             "objectclass": "group",
103             "member": "cn=ldaptestuser,cn=useRs," + self.base_dn})
104
105         self.delete_force(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
106         ldb.add({
107             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
108             "objectclass": "computer",
109             "cN": "LDAPtestCOMPUTER"})
110
111         self.delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
112         ldb.add({"dn": "cn=ldaptest2computer,cn=computers," + self.base_dn,
113             "objectClass": "computer",
114             "cn": "LDAPtest2COMPUTER",
115             "userAccountControl": "4096",
116             "displayname": "ldap testy"})
117
118         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
119         try:
120             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
121                      "objectClass": "computer",
122                      "cn": "LDAPtest2COMPUTER"
123                      })
124             self.fail()
125         except LdbError, (num, _): 
126             self.assertEquals(num, LDB_ERR_INVALID_DN_SYNTAX)
127             
128         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
129         try:
130             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
131                      "objectClass": "computer",
132                      "cn": "ldaptestcomputer3",
133                      "sAMAccountType": "805306368"
134                 })
135             self.fail()
136         except LdbError, (num, _): 
137             self.assertEquals(num, LDB_ERR_UNWILLING_TO_PERFORM)
138             
139         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
140         try:
141             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
142                      "objectClass": "computer",
143                      "cn": "ldaptestcomputer3",
144                      "userAccountControl": "0"
145                 })
146             self.fail()
147         except LdbError, (num, _): 
148             self.assertEquals(num, LDB_ERR_UNWILLING_TO_PERFORM)
149             
150         self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn)
151         try:
152             ldb.add({"dn": "cn=ldaptestuser7,cn=users," + self.base_dn,
153                      "objectClass": "user",
154                      "cn": "LDAPtestuser7",
155                      "userAccountControl": "0"
156                 })
157             self.fail()
158         except LdbError, (num, _): 
159             self.assertEquals(num, LDB_ERR_UNWILLING_TO_PERFORM)
160             
161         self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn)
162
163         ldb.add({"dn": "cn=ldaptestuser7,cn=users," + self.base_dn,
164                  "objectClass": "user",
165                  "cn": "LDAPtestuser7",
166                  "userAccountControl": "2"
167                  })
168             
169         self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn)
170
171         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
172         ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
173                  "objectClass": "computer",
174                  "cn": "LDAPtestCOMPUTER3"
175                  })
176             
177         print "Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))";
178         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))");
179         self.assertEquals(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res))
180
181         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer3,CN=Computers," + self.base_dn));
182         self.assertEquals(res[0]["cn"][0], "ldaptestcomputer3");
183         self.assertEquals(res[0]["name"][0], "ldaptestcomputer3");
184         self.assertEquals(res[0]["objectClass"][0], "top");
185         self.assertEquals(res[0]["objectClass"][1], "person");
186         self.assertEquals(res[0]["objectClass"][2], "organizationalPerson");
187         self.assertEquals(res[0]["objectClass"][3], "user");
188         self.assertEquals(res[0]["objectClass"][4], "computer");
189         self.assertTrue("objectGUID" in res[0])
190         self.assertTrue("whenCreated" in res[0])
191         self.assertEquals(res[0]["objectCategory"][0], ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn));
192         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513);
193         self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306368);
194         self.assertEquals(int(res[0]["userAccountControl"][0]), 546);
195
196         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
197
198         print "Testing attribute or value exists behaviour"
199         try:
200             ldb.modify_ldif("""
201 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
202 changetype: modify
203 replace: servicePrincipalName
204 servicePrincipalName: host/ldaptest2computer
205 servicePrincipalName: host/ldaptest2computer
206 servicePrincipalName: cifs/ldaptest2computer
207 """)
208             self.fail()
209         except LdbError, (num, msg):
210             self.assertEquals(num, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS)
211
212         ldb.modify_ldif("""
213 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
214 changetype: modify
215 replace: servicePrincipalName
216 servicePrincipalName: host/ldaptest2computer
217 servicePrincipalName: cifs/ldaptest2computer
218 """)
219         try:
220             ldb.modify_ldif("""
221 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
222 changetype: modify
223 add: servicePrincipalName
224 servicePrincipalName: host/ldaptest2computer
225 """)
226             self.fail()
227         except LdbError, (num, msg):
228             self.assertEquals(num, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS)
229
230         print "Testing ranged results"
231         ldb.modify_ldif("""
232 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
233 changetype: modify
234 replace: servicePrincipalName
235 """)
236             
237         ldb.modify_ldif("""
238 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
239 changetype: modify
240 add: servicePrincipalName
241 servicePrincipalName: host/ldaptest2computer0
242 servicePrincipalName: host/ldaptest2computer1
243 servicePrincipalName: host/ldaptest2computer2
244 servicePrincipalName: host/ldaptest2computer3
245 servicePrincipalName: host/ldaptest2computer4
246 servicePrincipalName: host/ldaptest2computer5
247 servicePrincipalName: host/ldaptest2computer6
248 servicePrincipalName: host/ldaptest2computer7
249 servicePrincipalName: host/ldaptest2computer8
250 servicePrincipalName: host/ldaptest2computer9
251 servicePrincipalName: host/ldaptest2computer10
252 servicePrincipalName: host/ldaptest2computer11
253 servicePrincipalName: host/ldaptest2computer12
254 servicePrincipalName: host/ldaptest2computer13
255 servicePrincipalName: host/ldaptest2computer14
256 servicePrincipalName: host/ldaptest2computer15
257 servicePrincipalName: host/ldaptest2computer16
258 servicePrincipalName: host/ldaptest2computer17
259 servicePrincipalName: host/ldaptest2computer18
260 servicePrincipalName: host/ldaptest2computer19
261 servicePrincipalName: host/ldaptest2computer20
262 servicePrincipalName: host/ldaptest2computer21
263 servicePrincipalName: host/ldaptest2computer22
264 servicePrincipalName: host/ldaptest2computer23
265 servicePrincipalName: host/ldaptest2computer24
266 servicePrincipalName: host/ldaptest2computer25
267 servicePrincipalName: host/ldaptest2computer26
268 servicePrincipalName: host/ldaptest2computer27
269 servicePrincipalName: host/ldaptest2computer28
270 servicePrincipalName: host/ldaptest2computer29
271 """)
272
273         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, 
274                          attrs=["servicePrincipalName;range=0-*"])
275         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
276         #print len(res[0]["servicePrincipalName;range=0-*"])
277         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
278
279         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"])
280         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
281             # print res[0]["servicePrincipalName;range=0-19"].length
282         self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20)
283
284             
285         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"])
286         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
287         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
288
289         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-40"])
290         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
291         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
292
293         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=30-40"])
294         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
295         self.assertEquals(len(res[0]["servicePrincipalName;range=30-*"]), 0)
296
297             
298         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"])
299         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
300         self.assertEquals(len(res[0]["servicePrincipalName;range=10-*"]), 20)
301         # pos_11 = res[0]["servicePrincipalName;range=10-*"][18]
302
303         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"])
304         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
305         self.assertEquals(len(res[0]["servicePrincipalName;range=11-*"]), 19)
306             # print res[0]["servicePrincipalName;range=11-*"][18]
307             # print pos_11
308             # self.assertEquals((res[0]["servicePrincipalName;range=11-*"][18]), pos_11)
309
310         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"])
311         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
312         self.assertEquals(len(res[0]["servicePrincipalName;range=11-15"]), 5)
313             # self.assertEquals(res[0]["servicePrincipalName;range=11-15"][4], pos_11)
314
315         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"])
316         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
317             # print res[0]["servicePrincipalName"][18]
318             # print pos_11
319         self.assertEquals(len(res[0]["servicePrincipalName"]), 30)
320             # self.assertEquals(res[0]["servicePrincipalName"][18], pos_11)
321
322         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
323         ldb.add({
324             "dn": "cn=ldaptestuser2,cn=useRs," + self.base_dn,
325             "objectClass": ["person", "user"],
326             "cn": "LDAPtestUSER2",
327             "givenname": "testy",
328             "sn": "ldap user2"})
329
330         print "Testing Ambigious Name Resolution"
331         # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
332         res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))")
333         self.assertEquals(len(res), 3, "Could not find (&(anr=ldap testy)(objectClass=user))")
334
335         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
336         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
337         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
338
339         # Testing ldb.search for (&(anr=ldap)(objectClass=user))
340         res = ldb.search(expression="(&(anr=ldap)(objectClass=user))")
341         self.assertEquals(len(res), 4, "Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
342
343         # Testing ldb.search for (&(anr==ldap)(objectClass=user))
344         res = ldb.search(expression="(&(anr==ldap)(objectClass=user))")
345         self.assertEquals(len(res), 1, "Could not find (&(anr==ldap)(objectClass=user)). Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
346
347         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
348         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
349         self.assertEquals(res[0]["name"], "ldaptestuser")
350
351         # Testing ldb.search for (&(anr=testy)(objectClass=user))
352         res = ldb.search(expression="(&(anr=testy)(objectClass=user))")
353         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res))
354
355         # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
356         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
357         self.assertEquals(len(res), 2, "Found only %d for (&(anr=ldap testy)(objectClass=user))" % len(res))
358
359         # Testing ldb.search for (&(anr==ldap testy)(objectClass=user))
360         res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
361         self.assertEquals(len(res), 1, "Found only %d for (&(anr==ldap testy)(objectClass=user))" % len(res))
362
363         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
364         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
365         self.assertEquals(res[0]["name"][0], "ldaptestuser")
366
367         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
368         res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
369         self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))")
370
371         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
372         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
373         self.assertEquals(res[0]["name"][0], "ldaptestuser")
374
375         # Testing ldb.search for (&(anr=testy ldap user)(objectClass=user))
376         res = ldb.search(expression="(&(anr=testy ldap user)(objectClass=user))")
377         self.assertEquals(len(res), 1, "Could not find (&(anr=testy ldap user)(objectClass=user))")
378
379         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
380         self.assertEquals(res[0]["cn"], "ldaptestuser2")
381         self.assertEquals(res[0]["name"], "ldaptestuser2")
382
383         # Testing ldb.search for (&(anr==testy ldap user2)(objectClass=user))
384         res = ldb.search(expression="(&(anr==testy ldap user2)(objectClass=user))")
385         self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))")
386
387         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
388         self.assertEquals(res[0]["cn"], "ldaptestuser2")
389         self.assertEquals(res[0]["name"], "ldaptestuser2")
390
391         # Testing ldb.search for (&(anr==ldap user2)(objectClass=user))
392         res = ldb.search(expression="(&(anr==ldap user2)(objectClass=user))")
393         self.assertEquals(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))")
394
395         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
396         self.assertEquals(res[0]["cn"], "ldaptestuser2")
397         self.assertEquals(res[0]["name"], "ldaptestuser2")
398
399         # Testing ldb.search for (&(anr==not ldap user2)(objectClass=user))
400         res = ldb.search(expression="(&(anr==not ldap user2)(objectClass=user))")
401         self.assertEquals(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))")
402
403         # Testing ldb.search for (&(anr=not ldap user2)(objectClass=user))
404         res = ldb.search(expression="(&(anr=not ldap user2)(objectClass=user))")
405         self.assertEquals(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))")
406
407         # Testing ldb.search for (&(anr="testy ldap")(objectClass=user)) (ie, with quotes)
408         res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))")
409         self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))")
410
411         print "Testing Group Modifies"
412         ldb.modify_ldif("""
413 dn: cn=ldaptestgroup,cn=users,""" + self.base_dn + """
414 changetype: modify
415 add: member
416 member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
417 member: cn=ldaptestcomputer,cn=computers,""" + self.base_dn + """
418 """)
419
420         self.delete_force(ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
421
422         print "Testing adding non-existent user to a group"
423         try:
424             ldb.modify_ldif("""
425 dn: cn=ldaptestgroup,cn=users,""" + self.base_dn + """
426 changetype: modify
427 add: member
428 member: cn=ldaptestuser3,cn=users,""" + self.base_dn + """
429 """)
430             self.fail()
431         except LdbError, (num, _):
432             self.assertEquals(num, LDB_ERR_NO_SUCH_OBJECT)
433
434         print "Testing Renames"
435
436         ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
437
438         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
439
440         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestUSER3,cn=users," + self.base_dn)
441
442         print "Testing ldb.search for (&(cn=ldaptestuser3)(objectClass=user))"
443         res = ldb.search(expression="(&(cn=ldaptestuser3)(objectClass=user))")
444         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser3)(objectClass=user))")
445
446         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
447         self.assertEquals(res[0]["cn"], "ldaptestUSER3")
448         self.assertEquals(res[0]["name"], "ldaptestUSER3")
449
450         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))"
451         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
452         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
453
454         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
455         self.assertEquals(res[0]["cn"], "ldaptestUSER3")
456         self.assertEquals(res[0]["name"], "ldaptestUSER3")
457
458         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))"
459         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
460         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
461
462         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
463         self.assertEquals(res[0]["cn"], "ldaptestUSER3")
464         self.assertEquals(res[0]["name"], "ldaptestUSER3")
465
466         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))"
467         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
468         self.assertEquals(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
469
470         # This is a Samba special, and does not exist in real AD
471         #    print "Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
472         #    res = ldb.search("(dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
473         #    if (res.error != 0 || len(res) != 1) {
474         #        print "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
475         #        self.assertEquals(len(res), 1)
476         #    }
477         #    self.assertEquals(res[0].dn, ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
478         #    self.assertEquals(res[0].cn, "ldaptestUSER3")
479         #    self.assertEquals(res[0].name, "ldaptestUSER3")
480
481         print "Testing ldb.search for (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
482         res = ldb.search(expression="(distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
483         self.assertEquals(len(res), 1, "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
484         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
485         self.assertEquals(res[0]["cn"], "ldaptestUSER3")
486         self.assertEquals(res[0]["name"], "ldaptestUSER3")
487
488         # ensure we cannot add it again
489         try:
490             ldb.add({"dn": "cn=ldaptestuser3,cn=userS," + self.base_dn,
491                       "objectClass": ["person", "user"],
492                       "cn": "LDAPtestUSER3"})
493             self.fail()
494         except LdbError, (num, _):
495             self.assertEquals(num, LDB_ERR_ENTRY_ALREADY_EXISTS)
496
497         # rename back
498         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
499
500         # ensure we cannnot rename it twice
501         try:
502             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, 
503                        "cn=ldaptestuser2,cn=users," + self.base_dn)
504             self.fail()
505         except LdbError, (num, _): 
506             self.assertEquals(num, LDB_ERR_NO_SUCH_OBJECT)
507
508         # ensure can now use that name
509         ldb.add({"dn": "cn=ldaptestuser3,cn=users," + self.base_dn,
510                       "objectClass": ["person", "user"],
511                       "cn": "LDAPtestUSER3"})
512         
513         # ensure we now cannnot rename
514         try:
515             ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
516             self.fail()
517         except LdbError, (num, _):
518             self.assertEquals(num, LDB_ERR_ENTRY_ALREADY_EXISTS)
519         try:
520             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=configuration," + self.base_dn)
521             self.fail()
522         except LdbError, (num, _):
523             self.assertTrue(num in (71, 64))
524
525         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser5,cn=users," + self.base_dn)
526
527         ldb.delete("cn=ldaptestuser5,cn=users," + self.base_dn)
528
529         self.delete_force(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
530
531         ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn, "cn=ldaptestgroup2,cn=users," + self.base_dn)
532
533         print "Testing subtree Renames"
534
535         ldb.add({"dn": "cn=ldaptestcontainer," + self.base_dn, 
536                  "objectClass": "container"})
537         
538         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer," + self.base_dn)
539         ldb.add({"dn": "CN=ldaptestuser4,CN=ldaptestcontainer," + self.base_dn, 
540                  "objectClass": ["person", "user"],
541                  "cn": "LDAPtestUSER4"})
542
543         ldb.modify_ldif("""
544 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
545 changetype: modify
546 add: member
547 member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
548 """)
549         
550         print "Testing ldb.rename of cn=ldaptestcontainer," + self.base_dn + " to cn=ldaptestcontainer2," + self.base_dn
551         ldb.rename("CN=ldaptestcontainer," + self.base_dn, "CN=ldaptestcontainer2," + self.base_dn)
552
553         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user))"
554         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))")
555         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user))")
556
557         print "Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
558         try:
559             ldb.search("cn=ldaptestcontainer," + self.base_dn, 
560                     expression="(&(cn=ldaptestuser4)(objectClass=user))", 
561                     scope=SCOPE_SUBTREE)
562             self.fail()
563         except LdbError, (num, _):
564             self.assertEquals(num, LDB_ERR_NO_SUCH_OBJECT)
565
566         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
567         try:
568             res = ldb.search("cn=ldaptestcontainer," + self.base_dn, 
569                     expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_ONELEVEL)
570             self.fail()
571         except LdbError, (num, _):
572             self.assertEquals(num, LDB_ERR_NO_SUCH_OBJECT)
573
574         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container"
575         res = ldb.search("cn=ldaptestcontainer2," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_SUBTREE)
576         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user)) under cn=ldaptestcontainer2," + self.base_dn)
577
578         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
579         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
580
581         print "Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes"
582         res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE)
583         self.assertEquals(len(res), 1, "Could not find (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)), perhaps linked attributes are not conistant with subtree renames?")
584
585         print "Testing ldb.rename (into itself) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn
586         try:
587             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn)
588             self.fail()
589         except LdbError, (num, _):
590             self.assertEquals(num, LDB_ERR_UNWILLING_TO_PERFORM)
591
592         print "Testing ldb.rename (into non-existent container) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn
593         try:
594             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn)
595             self.fail()
596         except LdbError, (num, _):
597             self.assertTrue(num in (LDB_ERR_UNWILLING_TO_PERFORM, LDB_ERR_OTHER))
598
599         print "Testing delete (should fail, not a leaf node) of renamed cn=ldaptestcontainer2," + self.base_dn
600         try:
601             ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
602             self.fail()
603         except LdbError, (num, _):
604             self.assertEquals(num, LDB_ERR_NOT_ALLOWED_ON_NON_LEAF)
605
606         print "Testing base ldb.search for CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn
607         res = ldb.search(expression="(objectclass=*)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
608         self.assertEquals(len(res), 1)
609         res = ldb.search(expression="(cn=ldaptestuser40)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
610         self.assertEquals(len(res), 0)
611
612         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
613         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_ONELEVEL)
614         # FIXME: self.assertEquals(len(res), 0)
615
616         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
617         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_SUBTREE)
618         # FIXME: self.assertEquals(len(res), 0)
619
620         print "Testing delete of subtree renamed "+("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)
621         ldb.delete(("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
622         print "Testing delete of renamed cn=ldaptestcontainer2," + self.base_dn
623         ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
624         
625         self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà ,cn=users," + self.base_dn)
626         ldb.add({"dn": "cn=ldaptestutf8user èùéìòà ,cn=users," + self.base_dn, "objectClass": "user"})
627
628         self.delete_force(self.ldb, "cn=ldaptestutf8user2  èùéìòà ,cn=users," + self.base_dn)
629         ldb.add({"dn": "cn=ldaptestutf8user2  èùéìòà ,cn=users," + self.base_dn, "objectClass": "user"})
630
631         print "Testing ldb.search for (&(cn=ldaptestuser)(objectClass=user))"
632         res = ldb.search(expression="(&(cn=ldaptestuser)(objectClass=user))")
633         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
634
635         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
636         self.assertEquals(res[0]["cn"], "ldaptestuser")
637         self.assertEquals(res[0]["name"], "ldaptestuser")
638         self.assertEquals(res[0]["objectClass"], ["top", "person", "organizationalPerson", "user"])
639         self.assertTrue("objectGUID" in res[0])
640         self.assertTrue("whenCreated" in res[0])
641         self.assertEquals(res[0]["objectCategory"], ("CN=Person,CN=Schema,CN=Configuration," + self.base_dn))
642         self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306368)
643         self.assertEquals(int(res[0]["userAccountControl"][0]), 546)
644         self.assertEquals(res[0]["memberOf"][0], ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
645         self.assertEquals(len(res[0]["memberOf"]), 1)
646      
647         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))"
648         res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
649         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
650
651         self.assertEquals(res[0].dn, res2[0].dn)
652
653         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))"
654         res3 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
655         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)): matched %d" % len(res3))
656
657         self.assertEquals(res[0].dn, res3[0].dn)
658
659         if gc_ldb is not None:
660             print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog"
661             res3gc = gc_ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
662             self.assertEquals(len(res3gc), 1)
663         
664             self.assertEquals(res[0].dn, res3gc[0].dn)
665
666         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control"
667         
668         res3control = gc_ldb.search(self.base_dn, expression="(&(cn=ldaptestuser)(objectCategory=PerSon))", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
669         self.assertEquals(len(res3control), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog")
670         
671         self.assertEquals(res[0].dn, res3control[0].dn)
672
673         ldb.delete(res[0].dn)
674
675         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))"
676         res = ldb.search(expression="(&(cn=ldaptestcomputer)(objectClass=user))")
677         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
678
679         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer,CN=Computers," + self.base_dn))
680         self.assertEquals(res[0]["cn"], "ldaptestcomputer")
681         self.assertEquals(res[0]["name"], "ldaptestcomputer")
682         self.assertEquals(res[0]["objectClass"], ["top", "person", "organizationalPerson", "user", "computer"])
683         self.assertTrue("objectGUID" in res[0])
684         self.assertTrue("whenCreated" in res[0])
685         self.assertEquals(res[0]["objectCategory"], ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn))
686         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513)
687         self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306368)
688         self.assertEquals(int(res[0]["userAccountControl"][0]), 546)
689         self.assertEquals(res[0]["memberOf"][0], "CN=ldaptestgroup2,CN=Users," + self.base_dn)
690         self.assertEquals(len(res[0]["memberOf"]), 1)
691
692         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))"
693         res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
694         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
695
696         self.assertEquals(res[0].dn, res2[0].dn)
697
698         if gc_ldb is not None:
699             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog"
700             res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
701             self.assertEquals(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog")
702
703             self.assertEquals(res[0].dn, res2gc[0].dn)
704
705         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))"
706         res3 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
707         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))")
708
709         self.assertEquals(res[0].dn, res3[0].dn)
710
711         if gc_ldb is not None:
712             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog"
713             res3gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
714             self.assertEquals(len(res3gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog")
715
716             self.assertEquals(res[0].dn, res3gc[0].dn)
717
718         print "Testing ldb.search for (&(cn=ldaptestcomp*r)(objectCategory=compuTER))"
719         res4 = ldb.search(expression="(&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
720         self.assertEquals(len(res4), 1, "Could not find (&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
721
722         self.assertEquals(res[0].dn, res4[0].dn)
723
724         print "Testing ldb.search for (&(cn=ldaptestcomput*)(objectCategory=compuTER))"
725         res5 = ldb.search(expression="(&(cn=ldaptestcomput*)(objectCategory=compuTER))")
726         self.assertEquals(len(res5), 1, "Could not find (&(cn=ldaptestcomput*)(objectCategory=compuTER))")
727
728         self.assertEquals(res[0].dn, res5[0].dn)
729
730         print "Testing ldb.search for (&(cn=*daptestcomputer)(objectCategory=compuTER))"
731         res6 = ldb.search(expression="(&(cn=*daptestcomputer)(objectCategory=compuTER))")
732         self.assertEquals(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))")
733
734         self.assertEquals(res[0].dn, res6[0].dn)
735
736         ldb.delete(res[0].dn)
737
738         print "Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))"
739         res = ldb.search(expression="(&(cn=ldaptest2computer)(objectClass=user))")
740         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptest2computer)(objectClass=user))")
741
742         self.assertEquals(res[0].dn, ("CN=ldaptest2computer,CN=Computers," + self.base_dn))
743         self.assertEquals(res[0]["cn"], "ldaptest2computer")
744         self.assertEquals(res[0]["name"], "ldaptest2computer")
745         self.assertEquals(res[0]["objectClass"], ["top", "person", "organizationalPerson", "user", "computer"])
746         self.assertTrue("objectGUID" in res[0])
747         self.assertTrue("whenCreated" in res[0])
748         self.assertEquals(res[0]["objectCategory"][0], "CN=Computer,CN=Schema,CN=Configuration," + self.base_dn)
749         self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306369)
750         self.assertEquals(int(res[0]["userAccountControl"][0]), 4096)
751
752         ldb.delete(res[0].dn)
753
754         attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "memberOf"]
755         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
756         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
757         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
758
759         self.assertEquals(res[0].dn, ("CN=ldaptestuser2,CN=Users," + self.base_dn))
760         self.assertEquals(res[0]["cn"], "ldaptestuser2")
761         self.assertEquals(res[0]["name"], "ldaptestuser2")
762         self.assertEquals(res[0]["objectClass"], ["top", "person", "organizationalPerson", "user"])
763         self.assertTrue("objectGUID" in res[0])
764         self.assertTrue("whenCreated" in res[0])
765         self.assertTrue("nTSecurityDescriptor" in res[0])
766         self.assertEquals(res[0]["memberOf"][0], ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
767
768         attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"]
769         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))"
770         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
771         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
772
773         self.assertEquals(res[0].dn, ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
774         self.assertEquals(res[0]["cn"], "ldaptestgroup2")
775         self.assertEquals(res[0]["name"], "ldaptestgroup2")
776         self.assertEquals(res[0]["objectClass"], ["top", "group"])
777         self.assertTrue("objectGuid" not in res[0])
778         self.assertTrue("whenCreated" in res[0])
779         self.assertTrue("nTSecurityDescriptor" in res[0])
780         self.assertEquals(res[0]["member"], ["CN=ldaptestuser2,CN=Users," + self.base_dn])
781
782         ldb.modify_ldif("""
783 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
784 changetype: modify
785 replace: member
786 member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
787 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
788 """)
789         
790         print "Testing Linked attribute behaviours"
791         ldb.modify_ldif("""
792 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
793 changetype: modify
794 delete: member
795 """)
796
797         ldb.modify_ldif("""
798 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
799 changetype: modify
800 add: member
801 member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
802 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
803 """)
804         
805         ldb.modify_ldif("""
806 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
807 changetype: modify
808 replace: member
809 """)
810         
811         ldb.modify_ldif("""
812 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
813 changetype: modify
814 add: member
815 member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
816 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
817 """)
818         
819         ldb.modify_ldif("""
820 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
821 changetype: modify
822 delete: member
823 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
824 """)
825         
826         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
827         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
828
829         self.assertEquals(res[0].dn, ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
830         self.assertEquals(res[0]["member"][0], ("CN=ldaptestuser2,CN=Users," + self.base_dn))
831         self.assertEquals(len(res[0]["member"]), 1)
832
833         ldb.delete(("CN=ldaptestuser2,CN=Users," + self.base_dn))
834
835         attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"]
836         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete"
837         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
838         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete")
839
840         self.assertEquals(res[0].dn, ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
841         self.assertTrue("member" not in res[0])
842
843         print "Testing ldb.search for (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))"
844         res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
845         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
846
847         self.assertEquals(res[0].dn, ("CN=ldaptestutf8user èùéìòà,CN=Users," + self.base_dn))
848         self.assertEquals(res[0]["cn"], "ldaptestutf8user èùéìòà")
849         self.assertEquals(res[0]["name"], "ldaptestutf8user èùéìòà")
850         self.assertEquals(res[0]["objectClass"], ["top", "person", "organizationalPerson", "user"])
851         self.assertTrue("objectGUID" in res[0])
852         self.assertTrue("whenCreated" in res[0])
853
854         ldb.delete(res[0].dn)
855
856         print "Testing ldb.search for (&(cn=ldaptestutf8user2*)(objectClass=user))"
857         res = ldb.search(expression="(&(cn=ldaptestutf8user2*)(objectClass=user))")
858         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user2*)(objectClass=user))")
859
860         ldb.delete(res[0].dn)
861
862         ldb.delete(("CN=ldaptestgroup2,CN=Users," + self.base_dn))
863
864         print "Testing ldb.search for (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))"
865         res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
866
867         #FIXME: self.assert len(res) == 1, "Could not find (expect space collapse, win2k3 fails) (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))"
868
869         print "Testing that we can't get at the configuration DN from the main search base"
870         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
871         self.assertEquals(len(res), 0)
872
873         print "Testing that we can get at the configuration DN from the main search base on the LDAP port with the 'phantom root' search_options control"
874         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
875         self.assertTrue(len(res) > 0)
876
877         if gc_ldb is not None:
878             print "Testing that we can get at the configuration DN from the main search base on the GC port with the search_options control == 0"
879             
880             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:0"])
881             self.assertTrue(len(res) > 0)
882
883             print "Testing that we do find configuration elements in the global catlog"
884             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
885             self.assertTrue(len(res) > 0)
886         
887             print "Testing that we do find configuration elements and user elements at the same time"
888             res = gc_ldb.search(self.base_dn, expression="(|(objectClass=crossRef)(objectClass=person))", scope=SCOPE_SUBTREE, attrs=["cn"])
889             self.assertTrue(len(res) > 0)
890
891             print "Testing that we do find configuration elements in the global catlog, with the configuration basedn"
892             res = gc_ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
893             self.assertTrue(len(res) > 0)
894
895         print "Testing that we can get at the configuration DN on the main LDAP port"
896         res = ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
897         self.assertTrue(len(res) > 0)
898
899         print "Testing objectCategory canonacolisation"
900         res = ldb.search(self.configuration_dn, expression="objectCategory=ntDsDSA", scope=SCOPE_SUBTREE, attrs=["cn"])
901         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=ntDsDSA")
902         self.assertTrue(len(res) != 0)
903         
904         res = ldb.search(self.configuration_dn, expression="objectCategory=CN=ntDs-DSA," + self.schema_dn, scope=SCOPE_SUBTREE, attrs=["cn"])
905         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=CN=ntDs-DSA," + self.schema_dn)
906         self.assertTrue(len(res) != 0)
907         
908         print "Testing objectClass attribute order on "+ self.base_dn
909         res = ldb.search(expression="objectClass=domain", base=self.base_dn, 
910                          scope=SCOPE_BASE, attrs=["objectClass"])
911         self.assertEquals(len(res), 1)
912
913         self.assertEquals(res[0]["objectClass"], ["top", "domain", "domainDNS"])
914
915     #  check enumeration
916
917         print "Testing ldb.search for objectCategory=person"
918         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"])
919         self.assertTrue(len(res) > 0)
920
921         print "Testing ldb.search for objectCategory=person with domain scope control"
922         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
923         self.assertTrue(len(res) > 0)
924      
925         print "Testing ldb.search for objectCategory=user"
926         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"])
927         self.assertTrue(len(res) > 0)
928         
929         print "Testing ldb.search for objectCategory=user with domain scope control"
930         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
931         self.assertTrue(len(res) > 0)
932         
933         print "Testing ldb.search for objectCategory=group"
934         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"])
935         self.assertTrue(len(res) > 0)
936
937         print "Testing ldb.search for objectCategory=group with domain scope control"
938         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
939         self.assertTrue(len(res) > 0)
940
941
942 class BaseDnTests(unittest.TestCase):
943     def setUp(self):
944         self.ldb = ldb
945
946     def test_rootdse_attrs(self):
947         """Testing for all rootDSE attributes"""
948         res = self.ldb.search(scope=SCOPE_BASE, attrs=[])
949         self.assertEquals(len(res), 1)
950
951     def test_highestcommittedusn(self):
952         """Testing for highestCommittedUSN"""
953         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["highestCommittedUSN"])
954         self.assertEquals(len(res), 1)
955         self.assertTrue(int(res[0]["highestCommittedUSN"][0]) != 0)
956
957     def test_netlogon(self):
958         """Testing for netlogon via LDAP"""
959         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["netlogon"])
960         self.assertEquals(len(res), 0)
961
962     def test_netlogon_highestcommitted_usn(self):
963         """Testing for netlogon and highestCommittedUSN via LDAP"""
964         res = self.ldb.search("", scope=SCOPE_BASE, 
965                 attrs=["netlogon", "highestCommittedUSN"])
966         self.assertEquals(len(res), 0)
967
968
969 if not "://" in host:
970     host = "ldap://%s" % host
971
972 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
973 gc_ldb = Ldb("%s:3268" % host, credentials=creds, 
974              session_info=system_session(), lp=lp)
975
976 runner = SubunitTestRunner()
977 runner.run(unittest.makeSuite(BaseDnTests))
978 runner.run(unittest.makeSuite(BasicTests))