r17598: Patch from Martin Kühl <mkhl@samba.org> to update the samba3sam test
[gd/samba-autobuild/.git] / testprogs / ejs / samba3sam.js
1 #!/usr/bin/env smbscript
2 /*
3   (C) Jelmer Vernooij <jelmer@samba.org> 2005
4   (C) Martin Kuehl <mkhl@samba.org> 2006
5   Published under the GNU GPL
6   Sponsored by Google Summer of Code
7  */
8
9 var sys;
10 var ldb = ldb_init();
11 var options = GetOptions(ARGV, "POPT_AUTOHELP", "POPT_COMMON_SAMBA");
12 if (options == undefined) {
13         println("Failed to parse options");
14         return -1;
15 }
16
17 libinclude("base.js");
18
19 if (options.ARGV.length != 2) {
20         println("Usage: samba3sam.js <TESTDIR> <DATADIR>");
21         return -1;
22 }
23
24 var prefix = options.ARGV[0];
25 var datadir = options.ARGV[1];
26
27 function setup_data(obj, ldif)
28 {
29         assert(ldif != undefined);
30         ldif = substitute_var(ldif, obj);
31         assert(ldif != undefined);
32         var ok = obj.db.add(ldif);
33         assert(ok);
34 }
35
36 function setup_modules(ldb, s3, s4, ldif)
37 {
38         assert(ldif != undefined);
39         ldif = substitute_var(ldif, s4);
40         assert(ldif != undefined);
41         var ok = ldb.add(ldif);
42         assert(ok);
43
44         var ldif = "
45 dn: @MAP=samba3sam
46 @FROM: " + s4.BASEDN + "
47 @TO: " + s3.BASEDN + "
48
49 dn: @MODULES
50 @LIST: rootdse,paged_results,server_sort,extended_dn,asq,samldb,objectclass,password_hash,operational,objectguid,rdn_name,samba3sam,partition
51
52 dn: @PARTITION
53 partition: " + s4.BASEDN + ":" + s4.url + "
54 partition: " + s3.BASEDN + ":" + s3.url + "
55 replicateEntries: @SUBCLASSES
56 replicateEntries: @ATTRIBUTES
57 replicateEntries: @INDEXLIST
58 ";
59         var ok = ldb.add(ldif);
60         assert(ok);
61 }
62
63 function test_s3sam_search(ldb)
64 {
65         println("Looking up by non-mapped attribute");
66         var msg = ldb.search("(cn=Administrator)");
67         assert(msg.length == 1);
68         assert(msg[0].cn == "Administrator");
69
70         println("Looking up by mapped attribute");
71         var msg = ldb.search("(name=Backup Operators)");
72         assert(msg.length == 1);
73         assert(msg[0].name == "Backup Operators");
74
75         println("Looking up by old name of renamed attribute");
76         var msg = ldb.search("(displayName=Backup Operators)");
77         assert(msg.length == 0);
78
79         println("Looking up mapped entry containing SID");
80         var msg = ldb.search("(cn=Replicator)");
81         assert(msg.length == 1);
82         println(msg[0].dn);
83         assert(msg[0].dn == "cn=Replicator,ou=Groups,sambaDomainName=TESTS,dc=vernstok,dc=nl");
84         assert(msg[0].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
85
86         println("Checking mapping of objectClass");
87         var oc = msg[0].objectClass;
88         assert(oc != undefined);
89         for (var i in oc) {
90                 assert(oc[i] == "posixGroup" || oc[i] == "group");
91         }
92
93         println("Looking up by objectClass");
94         var msg = ldb.search("(|(objectClass=user)(cn=Administrator))");
95         assert(msg != undefined);
96         assert(msg.length == 2);
97         for (var i = 0; i < msg.length; i++) {
98                 assert((msg[i].dn == "unixName=Administrator,ou=Users,sambaDomainName=TESTS,dc=vernstok,dc=nl") ||
99                        (msg[i].dn == "unixName=nobody,ou=Users,sambaDomainName=TESTS,dc=vernstok,dc=nl"));
100         }
101 }
102
103 function test_s3sam_modify(ldb, s3)
104 {
105         println("Adding a record that will be fallbacked");
106         ok = ldb.add("
107 dn: cn=Foo,dc=idealx,dc=org
108 foo: bar
109 blah: Blie
110 cn: Foo
111 showInAdvancedViewOnly: TRUE
112 ");
113         assert(ok);
114
115         println("Checking for existence of record (local)");
116         /* TODO: This record must be searched in the local database, which is currently only supported for base searches
117          * msg = ldb.search("(cn=Foo)", new Array('foo','blah','cn','showInAdvancedViewOnly'));
118          * TODO: Actually, this version should work as well but doesn't...
119          * msg = ldb.search("(cn=Foo)", "dc=idealx,dc=org", ldb.LDB_SCOPE_SUBTREE new Array('foo','blah','cn','showInAdvancedViewOnly'));
120          */
121         msg = ldb.search("", "cn=Foo,dc=idealx,dc=org", ldb.LDB_SCOPE_BASE new Array('foo','blah','cn','showInAdvancedViewOnly'));
122         assert(msg.length == 1);
123         assert(msg[0].showInAdvancedViewOnly == "TRUE");
124         assert(msg[0].foo == "bar");
125         assert(msg[0].blah == "Blie");
126
127         println("Adding record that will be mapped");
128         ok = ldb.add("
129 dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
130 objectClass: user
131 unixName: bin
132 unicodePwd: geheim
133 cn: Niemand
134 ");
135         assert(ok);
136
137         println("Checking for existence of record (remote)");
138         msg = ldb.search("(unixName=bin)", new Array('unixName','cn','dn', 'unicodePwd'));
139         assert(msg.length == 1);
140         assert(msg[0].cn == "Niemand"); 
141         assert(msg[0].unicodePwd == "geheim");
142
143         println("Checking for existence of record (local && remote)");
144         msg = ldb.search("(&(unixName=bin)(unicodePwd=geheim))", new Array('unixName','cn','dn', 'unicodePwd'));
145         assert(msg.length == 1);                // TODO: should check with more records
146         assert(msg[0].cn == "Niemand");
147         assert(msg[0].unixName == "bin");
148         assert(msg[0].unicodePwd == "geheim");
149
150         println("Checking for existence of record (local || remote)");
151         msg = ldb.search("(|(unixName=bin)(unicodePwd=geheim))", new Array('unixName','cn','dn', 'unicodePwd'));
152         assert(msg.length == 1);                // TODO: should check with more records
153         assert(msg[0].cn == "Niemand");
154         assert(msg[0].unixName == "bin" || msg[0].unicodePwd == "geheim");
155
156         println("Checking for data in destination database");
157         msg = s3.db.search("(cn=Niemand)");
158         assert(msg.length >= 1);
159         assert(msg[0].sambaSID == "S-1-5-21-4231626423-2410014848-2360679739-2001");
160         assert(msg[0].displayName == "Niemand");
161
162         println("Adding attribute...");
163         ok = ldb.modify("
164 dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
165 changetype: modify
166 add: description
167 description: Blah
168 ");
169         assert(ok);
170
171         println("Checking whether changes are still there...");
172         msg = ldb.search("(cn=Niemand)");
173         assert(msg.length >= 1);
174         assert(msg[0].cn == "Niemand");
175         assert(msg[0].description == "Blah");
176
177         println("Modifying attribute...");
178         ok = ldb.modify("
179 dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
180 changetype: modify
181 replace: description
182 description: Blie
183 ");
184         assert(ok);
185
186         println("Checking whether changes are still there...");
187         msg = ldb.search("(cn=Niemand)");
188         assert(msg.length >= 1);
189         assert(msg[0].description == "Blie");
190
191         println("Deleting attribute...");
192         ok = ldb.modify("
193 dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
194 changetype: modify
195 delete: description
196 ");
197         assert(ok);
198
199         println("Checking whether changes are no longer there...");
200         msg = ldb.search("(cn=Niemand)");
201         assert(msg.length >= 1);
202         assert(msg[0].description == undefined);
203
204         println("Renaming record...");
205         ok = ldb.rename("cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl", "cn=Niemand,dc=vernstok,dc=nl");
206
207         println("Checking whether DN has changed...");
208         msg = ldb.search("(cn=Niemand)");
209         assert(msg.length == 1);
210         assert(msg[0].dn == "cn=Niemand,dc=vernstok,dc=nl");
211
212         println("Deleting record...");
213         ok = ldb.del("cn=Niemand,dc=vernstok,dc=nl");
214         assert(ok);
215
216         println("Checking whether record is gone...");
217         msg = ldb.search("(cn=Niemand)");
218         assert(msg.length == 0);
219 }
220
221 function test_map_search(ldb, s3, s4)
222 {
223         println("Running search tests on mapped data");
224         var res;
225         var dn;
226         var attrs;
227
228         /* Add a set of split records */
229         var ldif = "
230 dn: cn=X,sambaDomainName=TESTS,${BASEDN}
231 objectClass: user
232 cn: X
233 codePage: x
234 revision: x
235 objectCategory: x
236 nextRid: y
237 lastLogon: x
238 description: x
239 objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
240 primaryGroupID: 1-5-21-4231626423-2410014848-2360679739-512
241
242 dn: cn=Y,sambaDomainName=TESTS,${BASEDN}
243 objectClass: top
244 cn: Y
245 codePage: x
246 revision: x
247 objectCategory: y
248 nextRid: y
249 lastLogon: y
250 description: x
251
252 dn: cn=Z,sambaDomainName=TESTS,${BASEDN}
253 objectClass: top
254 cn: Z
255 codePage: x
256 revision: y
257 objectCategory: z
258 nextRid: y
259 lastLogon: z
260 description: y
261 ";
262         ldif = substitute_var(ldif, s4);
263         assert(ldif != undefined);
264         var ok = ldb.add(ldif);
265         assert(ok);
266
267         /* Add a set of remote records */
268         var ldif = "
269 dn: cn=A,sambaDomainName=TESTS,${BASEDN}
270 objectClass: posixAccount
271 cn: A
272 sambaNextRid: x
273 sambaBadPasswordCount: x
274 sambaLogonTime: x
275 description: x
276 sambaSID: S-1-5-21-4231626423-2410014848-2360679739-552
277 sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-512
278
279 dn: cn=B,sambaDomainName=TESTS,${BASEDN}
280 objectClass: top
281 cn:B
282 sambaNextRid: x
283 sambaBadPasswordCount: x
284 sambaLogonTime: y
285 description: x
286
287 dn: cn=C,sambaDomainName=TESTS,${BASEDN}
288 objectClass: top
289 cn: C
290 sambaNextRid: x
291 sambaBadPasswordCount: y
292 sambaLogonTime: z
293 description: y
294 ";
295         ldif = substitute_var(ldif, s3);
296         assert(ldif != undefined);
297         var ok = s3.db.add(ldif);
298         assert(ok);
299
300         println("Testing search by DN");
301
302         /* Search remote record by local DN */
303         dn = "cn=A,sambaDomainName=TESTS," + s4.BASEDN;
304         attrs = new Array("objectCategory", "lastLogon");
305         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
306         assert(res != undefined);
307         assert(res.length == 1);
308         assert(res[0].dn == dn);
309         assert(res[0].objectCategory == undefined);
310         assert(res[0].lastLogon == "x");
311
312         /* Search remote record by remote DN */
313         dn = "cn=A,sambaDomainName=TESTS," + s3.BASEDN;
314         attrs = new Array("objectCategory", "lastLogon", "sambaLogonTime");
315         res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs);
316         assert(res != undefined);
317         assert(res.length == 1);
318         assert(res[0].dn == dn);
319         assert(res[0].objectCategory == undefined);
320         assert(res[0].lastLogon == undefined);
321         assert(res[0].sambaLogonTime == "x");
322
323         /* Search split record by local DN */
324         dn = "cn=X,sambaDomainName=TESTS," + s4.BASEDN;
325         attrs = new Array("objectCategory", "lastLogon");
326         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
327         assert(res != undefined);
328         assert(res.length == 1);
329         assert(res[0].dn == dn);
330         assert(res[0].objectCategory == "x");
331         assert(res[0].lastLogon == "x");
332
333         /* Search split record by remote DN */
334         dn = "cn=X,sambaDomainName=TESTS," + s3.BASEDN;
335         attrs = new Array("objectCategory", "lastLogon", "sambaLogonTime");
336         res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs);
337         assert(res != undefined);
338         assert(res.length == 1);
339         assert(res[0].dn == dn);
340         assert(res[0].objectCategory == undefined);
341         assert(res[0].lastLogon == undefined);
342         assert(res[0].sambaLogonTime == "x");
343
344         println("Testing search by attribute");
345
346         /* Search by ignored attribute */
347         attrs = new Array("objectCategory", "lastLogon");
348         res = ldb.search("(revision=x)", NULL, ldb. SCOPE_DEFAULT, attrs);
349         assert(res != undefined);
350         assert(res.length == 2);
351         assert(res[0].dn == ("cn=Y,sambaDomainName=TESTS," + s4.BASEDN));
352         assert(res[0].objectCategory == "y");
353         assert(res[0].lastLogon == "y");
354         assert(res[1].dn == ("cn=X,sambaDomainName=TESTS," + s4.BASEDN));
355         assert(res[1].objectCategory == "x");
356         assert(res[1].lastLogon == "x");
357
358         /* Search by kept attribute */
359         attrs = new Array("objectCategory", "lastLogon");
360         res = ldb.search("(description=y)", NULL, ldb. SCOPE_DEFAULT, attrs);
361         assert(res != undefined);
362         assert(res.length == 2);
363         assert(res[0].dn == ("cn=Z,sambaDomainName=TESTS," + s4.BASEDN));
364         assert(res[0].objectCategory == "z");
365         assert(res[0].lastLogon == "z");
366         assert(res[1].dn == ("cn=C,sambaDomainName=TESTS," + s4.BASEDN));
367         assert(res[1].objectCategory == undefined);
368         assert(res[1].lastLogon == "z");
369
370         /* Search by renamed attribute */
371         attrs = new Array("objectCategory", "lastLogon");
372         res = ldb.search("(badPwdCount=x)", NULL, ldb. SCOPE_DEFAULT, attrs);
373         assert(res != undefined);
374         assert(res.length == 2);
375         assert(res[0].dn == ("cn=B,sambaDomainName=TESTS," + s4.BASEDN));
376         assert(res[0].objectCategory == undefined);
377         assert(res[0].lastLogon == "y");
378         assert(res[1].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
379         assert(res[1].objectCategory == undefined);
380         assert(res[1].lastLogon == "x");
381
382         /* Search by converted attribute */
383         attrs = new Array("objectCategory", "lastLogon", "objectSid");
384         /* TODO:
385            Using the SID directly in the parse tree leads to conversion
386            errors, letting the search fail with no results.
387         res = ldb.search("(objectSid=S-1-5-21-4231626423-2410014848-2360679739-552)", NULL, ldb. SCOPE_DEFAULT, attrs);
388         */
389         res = ldb.search("(objectSid=*)", NULL, ldb. SCOPE_DEFAULT, attrs);
390         assert(res != undefined);
391         assert(res.length == 2);
392         assert(res[0].dn == ("cn=X,sambaDomainName=TESTS," + s4.BASEDN));
393         assert(res[0].objectCategory == "x");
394         assert(res[0].lastLogon == "x");
395         assert(res[0].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
396         assert(res[1].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
397         assert(res[1].objectCategory == undefined);
398         assert(res[1].lastLogon == "x");
399         assert(res[1].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
400
401         /* Search by generated attribute */
402         /* In most cases, this even works when the mapping is missing
403          * a `convert_operator' by enumerating the remote db. */
404         attrs = new Array("objectCategory", "lastLogon", "primaryGroupID");
405         res = ldb.search("(primaryGroupID=1-5-21-4231626423-2410014848-2360679739-512)", NULL, ldb. SCOPE_DEFAULT, attrs);
406         assert(res != undefined);
407         assert(res.length == 1);
408         assert(res[0].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
409         assert(res[0].objectCategory == undefined);
410         assert(res[0].lastLogon == "x");
411         assert(res[0].primaryGroupID == "1-5-21-4231626423-2410014848-2360679739-512");
412
413         /* TODO: There should actually be two results, A and X.  The
414          * primaryGroupID of X seems to get corrupted somewhere, and the
415          * objectSid isn't available during the generation of remote (!) data,
416          * which can be observed with the following search.  Also note that Xs
417          * objectSid seems to be fine in the previous search for objectSid... */
418         /*
419         res = ldb.search("(primaryGroupID=*)", NULL, ldb. SCOPE_DEFAULT, attrs);
420         println(res.length + " results found");
421         for (i=0;i<res.length;i++) {
422                 for (obj in res[i]) {
423                         println(obj + ": " + res[i][obj]);
424                 }
425                 println("---");
426         }
427         */
428
429         /* Search by remote name of renamed attribute */
430         attrs = new Array("objectCategory", "lastLogon");
431         res = ldb.search("(sambaBadPasswordCount=*)", "", ldb. SCOPE_DEFAULT, attrs);
432         assert(res != undefined);
433         assert(res.length == 0);
434
435         /* Search by objectClass */
436         attrs = new Array("objectCategory", "lastLogon", "objectClass");
437         res = ldb.search("(objectClass=user)", NULL, ldb. SCOPE_DEFAULT, attrs);
438         assert(res != undefined);
439         assert(res.length == 2);
440         assert(res[0].dn == ("cn=X,sambaDomainName=TESTS," + s4.BASEDN));
441         assert(res[0].objectCategory == "x");
442         assert(res[0].lastLogon == "x");
443         assert(res[0].objectClass != undefined);
444         assert(res[0].objectClass[3] == "user");
445         assert(res[1].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
446         assert(res[1].objectCategory == undefined);
447         assert(res[1].lastLogon == "x");
448         assert(res[1].objectClass != undefined);
449         assert(res[1].objectClass[0] == "user");
450
451         /* Prove that the objectClass is actually used for the search */
452         res = ldb.search("(|(objectClass=user)(badPwdCount=x))", NULL, ldb. SCOPE_DEFAULT, attrs);
453         assert(res != undefined);
454         assert(res.length == 3);
455         assert(res[0].dn == ("cn=B,sambaDomainName=TESTS," + s4.BASEDN));
456         assert(res[0].objectCategory == undefined);
457         assert(res[0].lastLogon == "y");
458         assert(res[0].objectClass != undefined);
459         for (i=0;i<res[0].objectClass.length;i++) {
460                 assert(res[0].objectClass[i] != "user");
461         }
462         assert(res[1].dn == ("cn=X,sambaDomainName=TESTS," + s4.BASEDN));
463         assert(res[1].objectCategory == "x");
464         assert(res[1].lastLogon == "x");
465         assert(res[1].objectClass != undefined);
466         assert(res[1].objectClass[3] == "user");
467         assert(res[2].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
468         assert(res[2].objectCategory == undefined);
469         assert(res[2].lastLogon == "x");
470         assert(res[2].objectClass != undefined);
471         assert(res[2].objectClass[0] == "user");
472
473         println("Testing search by parse tree");
474
475         /* Search by conjunction of local attributes */
476         attrs = new Array("objectCategory", "lastLogon");
477         res = ldb.search("(&(codePage=x)(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
478         assert(res != undefined);
479         assert(res.length == 2);
480         assert(res[0].dn == ("cn=Y,sambaDomainName=TESTS," + s4.BASEDN));
481         assert(res[0].objectCategory == "y");
482         assert(res[0].lastLogon == "y");
483         assert(res[1].dn == ("cn=X,sambaDomainName=TESTS," + s4.BASEDN));
484         assert(res[1].objectCategory == "x");
485         assert(res[1].lastLogon == "x");
486
487         /* Search by conjunction of remote attributes */
488         attrs = new Array("objectCategory", "lastLogon");
489         res = ldb.search("(&(lastLogon=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
490         assert(res != undefined);
491         assert(res.length == 2);
492         assert(res[0].dn == ("cn=X,sambaDomainName=TESTS," + s4.BASEDN));
493         assert(res[0].objectCategory == "x");
494         assert(res[0].lastLogon == "x");
495         assert(res[1].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
496         assert(res[1].objectCategory == undefined);
497         assert(res[1].lastLogon == "x");
498         
499         /* Search by conjunction of local and remote attribute */
500         attrs = new Array("objectCategory", "lastLogon");
501         res = ldb.search("(&(codePage=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
502         assert(res != undefined);
503         assert(res.length == 2);
504         assert(res[0].dn == ("cn=Y,sambaDomainName=TESTS," + s4.BASEDN));
505         assert(res[0].objectCategory == "y");
506         assert(res[0].lastLogon == "y");
507         assert(res[1].dn == ("cn=X,sambaDomainName=TESTS," + s4.BASEDN));
508         assert(res[1].objectCategory == "x");
509         assert(res[1].lastLogon == "x");
510
511         /* Search by conjunction of local and remote attribute w/o match */
512         attrs = new Array("objectCategory", "lastLogon");
513         res = ldb.search("(&(codePage=x)(nextRid=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
514         assert(res != undefined);
515         assert(res.length == 0);
516         res = ldb.search("(&(revision=x)(lastLogon=z))", NULL, ldb.SCOPE_DEFAULT, attrs);
517         assert(res != undefined);
518         assert(res.length == 0);
519
520         /* Search by disjunction of local attributes */
521         attrs = new Array("objectCategory", "lastLogon");
522         res = ldb.search("(|(revision=x)(objectCategory=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
523         assert(res != undefined);
524         assert(res.length == 2);
525         assert(res[0].dn == ("cn=Y,sambaDomainName=TESTS," + s4.BASEDN));
526         assert(res[0].objectCategory == "y");
527         assert(res[0].lastLogon == "y");
528         assert(res[1].dn == ("cn=X,sambaDomainName=TESTS," + s4.BASEDN));
529         assert(res[1].objectCategory == "x");
530         assert(res[1].lastLogon == "x");
531
532         /* Search by disjunction of remote attributes */
533         attrs = new Array("objectCategory", "lastLogon");
534         res = ldb.search("(|(badPwdCount=x)(lastLogon=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
535         assert(res != undefined);
536         assert(res.length == 3);
537         assert(res[0].dn == ("cn=B,sambaDomainName=TESTS," + s4.BASEDN));
538         assert(res[0].objectCategory == undefined);
539         assert(res[0].lastLogon == "y");
540         assert(res[1].dn == ("cn=X,sambaDomainName=TESTS," + s4.BASEDN));
541         assert(res[1].objectCategory == "x");
542         assert(res[1].lastLogon == "x");
543         assert(res[2].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
544         assert(res[2].objectCategory == undefined);
545         assert(res[2].lastLogon == "x");
546
547         /* Search by disjunction of local and remote attribute */
548         attrs = new Array("objectCategory", "lastLogon");
549         res = ldb.search("(|(revision=x)(lastLogon=y))", NULL, ldb.SCOPE_DEFAULT, attrs);
550         assert(res != undefined);
551         assert(res.length == 3);
552         assert(res[0].dn == ("cn=Y,sambaDomainName=TESTS," + s4.BASEDN));
553         assert(res[0].objectCategory == "y");
554         assert(res[0].lastLogon == "y");
555         assert(res[1].dn == ("cn=B,sambaDomainName=TESTS," + s4.BASEDN));
556         assert(res[1].objectCategory == undefined);
557         assert(res[1].lastLogon == "y");
558         assert(res[2].dn == ("cn=X,sambaDomainName=TESTS," + s4.BASEDN));
559         assert(res[2].objectCategory == "x");
560         assert(res[2].lastLogon == "x");
561
562         /* Search by disjunction of local and remote attribute w/o match */
563         attrs = new Array("objectCategory", "lastLogon");
564         res = ldb.search("(|(codePage=y)(nextRid=z))", NULL, ldb.SCOPE_DEFAULT, attrs);
565         assert(res != undefined);
566         assert(res.length == 0);
567
568         /* Search by negated local attribute */
569         attrs = new Array("objectCategory", "lastLogon");
570         res = ldb.search("(!(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
571         assert(res != undefined);
572         assert(res.length == 4);
573         assert(res[0].dn == ("cn=B,sambaDomainName=TESTS," + s4.BASEDN));
574         assert(res[0].objectCategory == undefined);
575         assert(res[0].lastLogon == "y");
576         assert(res[1].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
577         assert(res[1].objectCategory == undefined);
578         assert(res[1].lastLogon == "x");
579         assert(res[2].dn == ("cn=Z,sambaDomainName=TESTS," + s4.BASEDN));
580         assert(res[2].objectCategory == "z");
581         assert(res[2].lastLogon == "z");
582         assert(res[3].dn == ("cn=C,sambaDomainName=TESTS," + s4.BASEDN));
583         assert(res[3].objectCategory == undefined);
584         assert(res[3].lastLogon == "z");
585
586         /* Search by negated remote attribute */
587         attrs = new Array("objectCategory", "lastLogon");
588         res = ldb.search("(!(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
589         assert(res != undefined);
590         assert(res.length == 2);
591         assert(res[0].dn == ("cn=Z,sambaDomainName=TESTS," + s4.BASEDN));
592         assert(res[0].objectCategory == "z");
593         assert(res[0].lastLogon == "z");
594         assert(res[1].dn == ("cn=C,sambaDomainName=TESTS," + s4.BASEDN));
595         assert(res[1].objectCategory == undefined);
596         assert(res[1].lastLogon == "z");
597
598         /* Search by negated conjunction of local attributes */
599         attrs = new Array("objectCategory", "lastLogon");
600         res = ldb.search("(!(&(codePage=x)(revision=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
601         assert(res != undefined);
602         assert(res.length == 4);
603         assert(res[0].dn == ("cn=B,sambaDomainName=TESTS," + s4.BASEDN));
604         assert(res[0].objectCategory == undefined);
605         assert(res[0].lastLogon == "y");
606         assert(res[1].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
607         assert(res[1].objectCategory == undefined);
608         assert(res[1].lastLogon == "x");
609         assert(res[2].dn == ("cn=Z,sambaDomainName=TESTS," + s4.BASEDN));
610         assert(res[2].objectCategory == "z");
611         assert(res[2].lastLogon == "z");
612         assert(res[3].dn == ("cn=C,sambaDomainName=TESTS," + s4.BASEDN));
613         assert(res[3].objectCategory == undefined);
614         assert(res[3].lastLogon == "z");
615
616         /* Search by negated conjunction of remote attributes */
617         attrs = new Array("objectCategory", "lastLogon");
618         res = ldb.search("(!(&(lastLogon=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
619         assert(res != undefined);
620         assert(res.length == 4);
621         assert(res[0].dn == ("cn=Y,sambaDomainName=TESTS," + s4.BASEDN));
622         assert(res[0].objectCategory == "y");
623         assert(res[0].lastLogon == "y");
624         assert(res[1].dn == ("cn=B,sambaDomainName=TESTS," + s4.BASEDN));
625         assert(res[1].objectCategory == undefined);
626         assert(res[1].lastLogon == "y");
627         assert(res[2].dn == ("cn=Z,sambaDomainName=TESTS," + s4.BASEDN));
628         assert(res[2].objectCategory == "z");
629         assert(res[2].lastLogon == "z");
630         assert(res[3].dn == ("cn=C,sambaDomainName=TESTS," + s4.BASEDN));
631         assert(res[3].objectCategory == undefined);
632         assert(res[3].lastLogon == "z");
633
634         /* Search by negated conjunction of local and remote attribute */
635         attrs = new Array("objectCategory", "lastLogon");
636         res = ldb.search("(!(&(codePage=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
637         assert(res != undefined);
638         assert(res.length == 4);
639         assert(res[0].dn == ("cn=B,sambaDomainName=TESTS," + s4.BASEDN));
640         assert(res[0].objectCategory == undefined);
641         assert(res[0].lastLogon == "y");
642         assert(res[1].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
643         assert(res[1].objectCategory == undefined);
644         assert(res[1].lastLogon == "x");
645         assert(res[2].dn == ("cn=Z,sambaDomainName=TESTS," + s4.BASEDN));
646         assert(res[2].objectCategory == "z");
647         assert(res[2].lastLogon == "z");
648         assert(res[3].dn == ("cn=C,sambaDomainName=TESTS," + s4.BASEDN));
649         assert(res[3].objectCategory == undefined);
650         assert(res[3].lastLogon == "z");
651
652         /* Search by negated disjunction of local attributes */
653         attrs = new Array("objectCategory", "lastLogon");
654         res = ldb.search("(!(|(revision=x)(objectCategory=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
655         assert(res != undefined);
656         assert(res[0].dn == ("cn=B,sambaDomainName=TESTS," + s4.BASEDN));
657         assert(res[0].objectCategory == undefined);
658         assert(res[0].lastLogon == "y");
659         assert(res[1].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
660         assert(res[1].objectCategory == undefined);
661         assert(res[1].lastLogon == "x");
662         assert(res[2].dn == ("cn=Z,sambaDomainName=TESTS," + s4.BASEDN));
663         assert(res[2].objectCategory == "z");
664         assert(res[2].lastLogon == "z");
665         assert(res[3].dn == ("cn=C,sambaDomainName=TESTS," + s4.BASEDN));
666         assert(res[3].objectCategory == undefined);
667         assert(res[3].lastLogon == "z");
668
669         /* Search by negated disjunction of remote attributes */
670         attrs = new Array("objectCategory", "lastLogon");
671         res = ldb.search("(!(|(badPwdCount=x)(lastLogon=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
672         assert(res != undefined);
673         assert(res.length == 3);
674         assert(res[0].dn == ("cn=Y,sambaDomainName=TESTS," + s4.BASEDN));
675         assert(res[0].objectCategory == "y");
676         assert(res[0].lastLogon == "y");
677         assert(res[1].dn == ("cn=Z,sambaDomainName=TESTS," + s4.BASEDN));
678         assert(res[1].objectCategory == "z");
679         assert(res[1].lastLogon == "z");
680         assert(res[2].dn == ("cn=C,sambaDomainName=TESTS," + s4.BASEDN));
681         assert(res[2].objectCategory == undefined);
682         assert(res[2].lastLogon == "z");
683
684         /* Search by negated disjunction of local and remote attribute */
685         attrs = new Array("objectCategory", "lastLogon");
686         res = ldb.search("(!(|(revision=x)(lastLogon=y)))", NULL, ldb.SCOPE_DEFAULT, attrs);
687         assert(res != undefined);
688         assert(res.length == 3);
689         assert(res[0].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
690         assert(res[0].objectCategory == undefined);
691         assert(res[0].lastLogon == "x");
692         assert(res[1].dn == ("cn=Z,sambaDomainName=TESTS," + s4.BASEDN));
693         assert(res[1].objectCategory == "z");
694         assert(res[1].lastLogon == "z");
695         assert(res[2].dn == ("cn=C,sambaDomainName=TESTS," + s4.BASEDN));
696         assert(res[2].objectCategory == undefined);
697         assert(res[2].lastLogon == "z");
698
699         /* Search by complex parse tree */
700         attrs = new Array("objectCategory", "lastLogon");
701         res = ldb.search("(|(&(revision=x)(objectCategory=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", NULL, ldb.SCOPE_DEFAULT, attrs);
702         assert(res != undefined);
703         assert(res.length == 5);
704         assert(res[0].dn == ("cn=B,sambaDomainName=TESTS," + s4.BASEDN));
705         assert(res[0].objectCategory == undefined);
706         assert(res[0].lastLogon == "y");
707         assert(res[1].dn == ("cn=X,sambaDomainName=TESTS," + s4.BASEDN));
708         assert(res[1].objectCategory == "x");
709         assert(res[1].lastLogon == "x");
710         assert(res[2].dn == ("cn=A,sambaDomainName=TESTS," + s4.BASEDN));
711         assert(res[2].objectCategory == undefined);
712         assert(res[2].lastLogon == "x");
713         assert(res[3].dn == ("cn=Z,sambaDomainName=TESTS," + s4.BASEDN));
714         assert(res[3].objectCategory == "z");
715         assert(res[3].lastLogon == "z");
716         assert(res[4].dn == ("cn=C,sambaDomainName=TESTS," + s4.BASEDN));
717         assert(res[4].objectCategory == undefined);
718         assert(res[4].lastLogon == "z");
719 }
720
721 sys = sys_init();
722 var ldbfile = prefix + "/" + "test.ldb";
723 var ldburl = "tdb://" + ldbfile;
724
725 var samba4 = new Object("samba4 partition info");
726 samba4.file = prefix + "/" + "samba4.ldb";
727 samba4.url = "tdb://" + samba4.file;
728 samba4.BASEDN = "dc=vernstok,dc=nl";
729 samba4.db = ldb_init();
730
731 var samba3 = new Object("samba3 partition info");
732 samba3.file = prefix + "/" + "samba3.ldb";
733 samba3.url = "tdb://" + samba3.file;
734 samba3.BASEDN = "cn=Samba3Sam," + samba4.BASEDN;
735 samba3.db = ldb_init();
736
737 sys.unlink(ldbfile);
738 sys.unlink(samba3.file);
739 sys.unlink(samba4.file);
740
741 var ok = ldb.connect(ldburl);
742 assert(ok);
743 var ok = samba3.db.connect(samba3.url);
744 assert(ok);
745 var ok = samba4.db.connect(samba4.url);
746 assert(ok);
747
748 setup_data(samba3, sys.file_load(datadir + "/" + "samba3.ldif"));
749 setup_modules(ldb, samba3, samba4, sys.file_load(datadir + "/" + "provision_samba3sam.ldif"));
750
751 ldb = ldb_init();
752 var ok = ldb.connect(ldburl);
753 assert(ok);
754
755 test_s3sam_search(ldb);
756 test_s3sam_modify(ldb, samba3);
757
758 sys.unlink(ldbfile);
759 sys.unlink(samba3.file);
760 sys.unlink(samba4.file);
761
762 ldb = ldb_init();
763 var ok = ldb.connect(ldburl);
764 assert(ok);
765 samba3.db = ldb_init();
766 var ok = samba3.db.connect(samba3.url);
767 assert(ok);
768 samba4.db = ldb_init();
769 var ok = samba4.db.connect(samba4.url);
770 assert(ok);
771
772 setup_modules(ldb, samba3, samba4, sys.file_load(datadir + "provision_samba3sam.ldif"));
773
774 ldb = ldb_init();
775 var ok = ldb.connect(ldburl);
776 assert(ok);
777
778 test_map_search(ldb, samba3, samba4);
779
780 sys.unlink(ldbfile);
781 sys.unlink(samba3.file);
782 sys.unlink(samba4.file);
783
784 return 0;