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