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