r25948: Fix up the samba3sam test (which is very fragile) to work with the new
[nivanova/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 options = GetOptions(ARGV, "POPT_AUTOHELP", "POPT_COMMON_SAMBA");
11 if (options == undefined) {
12         println("Failed to parse options");
13         return -1;
14 }
15
16 libinclude("base.js");
17
18 if (options.ARGV.length != 2) {
19         println("Usage: samba3sam.js <TESTDIR> <DATADIR>");
20         return -1;
21 }
22
23 var prefix = options.ARGV[0];
24 var datadir = options.ARGV[1];
25
26 function setup_data(obj, ldif)
27 {
28         assert(ldif != undefined);
29         ldif = substitute_var(ldif, obj);
30         assert(ldif != undefined);
31         var ok = obj.db.add(ldif);
32         assert(ok.error == 0);
33 }
34
35 function setup_modules(ldb, s3, s4, ldif)
36 {
37         assert(ldif != undefined);
38         ldif = substitute_var(ldif, s4);
39         assert(ldif != undefined);
40         var ok = ldb.add(ldif);
41         assert(ok.error == 0);
42
43         var ldif = "
44 dn: @MAP=samba3sam
45 @FROM: " + s4.BASEDN + "
46 @TO: sambaDomainName=TESTS," + s3.BASEDN + "
47
48 dn: @MODULES
49 @LIST: rootdse,paged_results,server_sort,extended_dn,asq,samldb,password_hash,operational,objectguid,rdn_name,samba3sam,partition
50
51 dn: @PARTITION
52 partition: " + s4.BASEDN + ":" + s4.url + "
53 partition: " + s3.BASEDN + ":" + s3.url + "
54 replicateEntries: @SUBCLASSES
55 replicateEntries: @ATTRIBUTES
56 replicateEntries: @INDEXLIST
57 ";
58         var ok = ldb.add(ldif);
59         assert(ok.error == 0);
60 }
61
62 function test_s3sam_search(ldb)
63 {
64         println("Looking up by non-mapped attribute");
65         var msg = ldb.search("(cn=Administrator)");
66         assert(msg.error == 0);
67         assert(msg.msgs.length == 1);
68         assert(msg.msgs[0].cn == "Administrator");
69
70         println("Looking up by mapped attribute");
71         var msg = ldb.search("(name=Backup Operators)");
72         assert(msg.error == 0);
73         assert(msg.msgs.length == 1);
74         assert(msg.msgs[0].name == "Backup Operators");
75
76         println("Looking up by old name of renamed attribute");
77         var msg = ldb.search("(displayName=Backup Operators)");
78         assert(msg.msgs.length == 0);
79
80         println("Looking up mapped entry containing SID");
81         var msg = ldb.search("(cn=Replicator)");
82         assert(msg.error == 0);
83         assert(msg.msgs.length == 1);
84         println(msg.msgs[0].dn);
85         assert(msg.msgs[0].dn == "cn=Replicator,ou=Groups,dc=vernstok,dc=nl");
86         assert(msg.msgs[0].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
87
88         println("Checking mapping of objectClass");
89         var oc = msg.msgs[0].objectClass;
90         assert(oc != undefined);
91         for (var i in oc) {
92                 assert(oc[i] == "posixGroup" || oc[i] == "group");
93         }
94
95         println("Looking up by objectClass");
96         var msg = ldb.search("(|(objectClass=user)(cn=Administrator))");
97         assert(msg.error == 0);
98         assert(msg.msgs.length == 2);
99         for (var i = 0; i < msg.msgs.length; i++) {
100                 assert((msg.msgs[i].dn == "unixName=Administrator,ou=Users,dc=vernstok,dc=nl") ||
101                        (msg.msgs[i].dn == "unixName=nobody,ou=Users,dc=vernstok,dc=nl"));
102         }
103 }
104
105 function test_s3sam_modify(ldb, s3)
106 {
107         var msg, ok;
108         println("Adding a record that will be fallbacked");
109         ok = ldb.add("
110 dn: cn=Foo
111 foo: bar
112 blah: Blie
113 cn: Foo
114 showInAdvancedViewOnly: TRUE
115 ");
116         if (ok.error != 0) {
117                 println(ok.errstr);
118                 assert(ok.error == 0);
119         }
120
121         println("Checking for existence of record (local)");
122         /* TODO: This record must be searched in the local database, which is currently only supported for base searches
123          * msg = ldb.search("(cn=Foo)", new Array('foo','blah','cn','showInAdvancedViewOnly'));
124          * TODO: Actually, this version should work as well but doesn't...
125          * 
126          */
127         var attrs =  new Array('foo','blah','cn','showInAdvancedViewOnly');
128         msg = ldb.search("(cn=Foo)", "cn=Foo", ldb.LDB_SCOPE_BASE, attrs);
129         assert(msg.error == 0);
130         assert(msg.msgs.length == 1);
131         assert(msg.msgs[0].showInAdvancedViewOnly == "TRUE");
132         assert(msg.msgs[0].foo == "bar");
133         assert(msg.msgs[0].blah == "Blie");
134
135         println("Adding record that will be mapped");
136         ok = ldb.add("
137 dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
138 objectClass: user
139 unixName: bin
140 sambaUnicodePwd: geheim
141 cn: Niemand
142 ");
143         if (ok.error != 0) {
144                 println(ok.errstr);
145                 assert(ok.error == 0);
146         }
147         assert(ok.error == 0);
148
149         println("Checking for existence of record (remote)");
150         msg = ldb.search("(unixName=bin)", new Array('unixName','cn','dn', 'sambaUnicodePwd'));
151         assert(msg.error == 0);
152         assert(msg.msgs.length == 1);
153         assert(msg.msgs[0].cn == "Niemand"); 
154         assert(msg.msgs[0].sambaUnicodePwd == "geheim");
155
156         println("Checking for existence of record (local && remote)");
157         msg = ldb.search("(&(unixName=bin)(sambaUnicodePwd=geheim))", new Array('unixName','cn','dn', 'sambaUnicodePwd'));
158         assert(msg.error == 0);
159         assert(msg.msgs.length == 1);           // TODO: should check with more records
160         assert(msg.msgs[0].cn == "Niemand");
161         assert(msg.msgs[0].unixName == "bin");
162         assert(msg.msgs[0].sambaUnicodePwd == "geheim");
163
164         println("Checking for existence of record (local || remote)");
165         msg = ldb.search("(|(unixName=bin)(sambaUnicodePwd=geheim))", new Array('unixName','cn','dn', 'sambaUnicodePwd'));
166         println("got " + msg.msgs.length + " replies");
167         assert(msg.error == 0);
168         assert(msg.msgs.length == 1);           // TODO: should check with more records
169         assert(msg.msgs[0].cn == "Niemand");
170         assert(msg.msgs[0].unixName == "bin" || msg.msgs[0].sambaUnicodePwd == "geheim");
171
172         println("Checking for data in destination database");
173         msg = s3.db.search("(cn=Niemand)");
174         assert(msg.error == 0);
175         assert(msg.msgs.length >= 1);
176         assert(msg.msgs[0].sambaSID == "S-1-5-21-4231626423-2410014848-2360679739-2001");
177         assert(msg.msgs[0].displayName == "Niemand");
178
179         println("Adding attribute...");
180         ok = ldb.modify("
181 dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
182 changetype: modify
183 add: description
184 description: Blah
185 ");
186         if (ok.error != 0) {
187                 println(ok.errstr);
188                 assert(ok.error == 0);
189         }
190         assert(ok.error == 0);
191
192         println("Checking whether changes are still there...");
193         msg = ldb.search("(cn=Niemand)");
194         assert(msg.error == 0);
195         assert(msg.msgs.length >= 1);
196         assert(msg.msgs[0].cn == "Niemand");
197         assert(msg.msgs[0].description == "Blah");
198
199         println("Modifying attribute...");
200         ok = ldb.modify("
201 dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
202 changetype: modify
203 replace: description
204 description: Blie
205 ");
206                 if (ok.error != 0) {
207                         println(ok.errstr);
208                         assert(ok.error == 0);
209                 }
210         assert(ok.error == 0);
211
212         println("Checking whether changes are still there...");
213         msg = ldb.search("(cn=Niemand)");
214         assert(msg.error == 0);
215         assert(msg.msgs.length >= 1);
216         assert(msg.msgs[0].description == "Blie");
217
218         println("Deleting attribute...");
219         ok = ldb.modify("
220 dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
221 changetype: modify
222 delete: description
223 ");
224         if (ok.error != 0) {
225                 println(ok.errstr);
226                 assert(ok.error == 0);
227         }
228         assert(ok.error == 0);
229
230         println("Checking whether changes are no longer there...");
231         msg = ldb.search("(cn=Niemand)");
232         assert(msg.error == 0);
233         assert(msg.msgs.length >= 1);
234         assert(msg.msgs[0].description == undefined);
235
236         println("Renaming record...");
237         ok = ldb.rename("cn=Niemand,cn=Users,dc=vernstok,dc=nl", "cn=Niemand2,cn=Users,dc=vernstok,dc=nl");
238         assert(ok.error == 0);
239
240         println("Checking whether DN has changed...");
241         msg = ldb.search("(cn=Niemand2)");
242         assert(msg.error == 0);
243         assert(msg.msgs.length == 1);
244         assert(msg.msgs[0].dn == "cn=Niemand2,cn=Users,dc=vernstok,dc=nl");
245
246         println("Deleting record...");
247         ok = ldb.del("cn=Niemand2,cn=Users,dc=vernstok,dc=nl");
248         if (ok.error != 0) {
249                 println(ok.errstr);
250                 assert(ok.error == 0);
251         }
252
253         println("Checking whether record is gone...");
254         msg = ldb.search("(cn=Niemand2)");
255         assert(msg.error == 0);
256         assert(msg.msgs.length == 0);
257 }
258
259 function test_map_search(ldb, s3, s4)
260 {
261         println("Running search tests on mapped data");
262         var res;
263         var dn;
264         var attrs;
265
266
267         var ldif = "
268 dn: " + "sambaDomainName=TESTS," + s3.BASEDN + "
269 objectclass: sambaDomain
270 objectclass: top
271 sambaSID: S-1-5-21-4231626423-2410014848-2360679739
272 sambaNextRid: 2000
273 sambaDomainName: TESTS"
274         ldif = substitute_var(ldif, s3);
275         assert(ldif != undefined);
276         var ok = s3.db.add(ldif);
277         assert(ok.error == 0);
278
279         printf("Add a set of split records");
280         var ldif = "
281 dn: " + s4.dn("cn=X") + "
282 objectClass: user
283 cn: X
284 codePage: x
285 revision: x
286 dnsHostName: x
287 nextRid: y
288 lastLogon: x
289 description: x
290 objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
291 primaryGroupID: 1-5-21-4231626423-2410014848-2360679739-512
292
293 dn: " + s4.dn("cn=Y") + "
294 objectClass: top
295 cn: Y
296 codePage: x
297 revision: x
298 dnsHostName: y
299 nextRid: y
300 lastLogon: y
301 description: x
302
303 dn: " + s4.dn("cn=Z") + "
304 objectClass: top
305 cn: Z
306 codePage: x
307 revision: y
308 dnsHostName: z
309 nextRid: y
310 lastLogon: z
311 description: y
312 ";
313
314         ldif = substitute_var(ldif, s4);
315         assert(ldif != undefined);
316         var ok = ldb.add(ldif);
317         if (ok.error != 0) {
318                 println(ok.errstr);
319                 assert(ok.error == 0);
320         }
321
322         println("Add a set of remote records");
323
324         var ldif = "
325 dn: " + s3.dn("cn=A") + "
326 objectClass: posixAccount
327 cn: A
328 sambaNextRid: x
329 sambaBadPasswordCount: x
330 sambaLogonTime: x
331 description: x
332 sambaSID: S-1-5-21-4231626423-2410014848-2360679739-552
333 sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-512
334
335 dn: " + s3.dn("cn=B") + "
336 objectClass: top
337 cn:B
338 sambaNextRid: x
339 sambaBadPasswordCount: x
340 sambaLogonTime: y
341 description: x
342
343 dn: " + s3.dn("cn=C") + "
344 objectClass: top
345 cn: C
346 sambaNextRid: x
347 sambaBadPasswordCount: y
348 sambaLogonTime: z
349 description: y
350 ";
351         ldif = substitute_var(ldif, s3);
352         assert(ldif != undefined);
353         var ok = s3.db.add(ldif);
354         assert(ok.error == 0);
355
356         println("Testing search by DN");
357
358         /* Search remote record by local DN */
359         dn = s4.dn("cn=A");
360         attrs = new Array("dnsHostName", "lastLogon");
361         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
362         assert(res.error == 0);
363         assert(res.msgs.length == 1);
364         assert(res.msgs[0].dn == dn);
365         assert(res.msgs[0].dnsHostName == undefined);
366         assert(res.msgs[0].lastLogon == "x");
367
368         /* Search remote record by remote DN */
369         dn = s3.dn("cn=A");
370         attrs = new Array("dnsHostName", "lastLogon", "sambaLogonTime");
371         res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs);
372         assert(res.error == 0);
373         assert(res.msgs.length == 1);
374         assert(res.msgs[0].dn == dn);
375         assert(res.msgs[0].dnsHostName == undefined);
376         assert(res.msgs[0].lastLogon == undefined);
377         assert(res.msgs[0].sambaLogonTime == "x");
378
379         /* Search split record by local DN */
380         dn = s4.dn("cn=X");
381         attrs = new Array("dnsHostName", "lastLogon");
382         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
383         assert(res.error == 0);
384         assert(res.msgs.length == 1);
385         assert(res.msgs[0].dn == dn);
386         assert(res.msgs[0].dnsHostName == "x");
387         assert(res.msgs[0].lastLogon == "x");
388
389         /* Search split record by remote DN */
390         dn = s3.dn("cn=X");
391         attrs = new Array("dnsHostName", "lastLogon", "sambaLogonTime");
392         res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs);
393         assert(res.error == 0);
394         assert(res.msgs.length == 1);
395         assert(res.msgs[0].dn == dn);
396         assert(res.msgs[0].dnsHostName == undefined);
397         assert(res.msgs[0].lastLogon == undefined);
398         assert(res.msgs[0].sambaLogonTime == "x");
399
400         println("Testing search by attribute");
401
402         /* Search by ignored attribute */
403         attrs = new Array("dnsHostName", "lastLogon");
404         res = ldb.search("(revision=x)", NULL, ldb. SCOPE_DEFAULT, attrs);
405         assert(res.error == 0);
406         assert(res.msgs.length == 2);
407         assert(res.msgs[0].dn == s4.dn("cn=Y"));
408         assert(res.msgs[0].dnsHostName == "y");
409         assert(res.msgs[0].lastLogon == "y");
410         assert(res.msgs[1].dn == s4.dn("cn=X"));
411         assert(res.msgs[1].dnsHostName == "x");
412         assert(res.msgs[1].lastLogon == "x");
413
414         /* Search by kept attribute */
415         attrs = new Array("dnsHostName", "lastLogon");
416         res = ldb.search("(description=y)", NULL, ldb. SCOPE_DEFAULT, attrs);
417         assert(res.error == 0);
418         assert(res.msgs.length == 2);
419         assert(res.msgs[0].dn == s4.dn("cn=Z"));
420         assert(res.msgs[0].dnsHostName == "z");
421         assert(res.msgs[0].lastLogon == "z");
422         assert(res.msgs[1].dn == s4.dn("cn=C"));
423         assert(res.msgs[1].dnsHostName == undefined);
424         assert(res.msgs[1].lastLogon == "z");
425
426         /* Search by renamed attribute */
427         attrs = new Array("dnsHostName", "lastLogon");
428         res = ldb.search("(badPwdCount=x)", NULL, ldb. SCOPE_DEFAULT, attrs);
429         assert(res.error == 0);
430         assert(res.msgs.length == 2);
431         assert(res.msgs[0].dn == s4.dn("cn=B"));
432         assert(res.msgs[0].dnsHostName == undefined);
433         assert(res.msgs[0].lastLogon == "y");
434         assert(res.msgs[1].dn == s4.dn("cn=A"));
435         assert(res.msgs[1].dnsHostName == undefined);
436         assert(res.msgs[1].lastLogon == "x");
437
438         /* Search by converted attribute */
439         attrs = new Array("dnsHostName", "lastLogon", "objectSid");
440         /* TODO:
441            Using the SID directly in the parse tree leads to conversion
442            errors, letting the search fail with no results.
443         res = ldb.search("(objectSid=S-1-5-21-4231626423-2410014848-2360679739-552)", NULL, ldb. SCOPE_DEFAULT, attrs);
444         */
445         res = ldb.search("(objectSid=*)", NULL, ldb. SCOPE_DEFAULT, attrs);
446         assert(res.error == 0);
447         assert(res.msgs.length == 3);
448         assert(res.msgs[0].dn == s4.dn("cn=X"));
449         assert(res.msgs[0].dnsHostName == "x");
450         assert(res.msgs[0].lastLogon == "x");
451         assert(res.msgs[0].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
452         assert(res.msgs[1].dn == s4.dn("cn=A"));
453         assert(res.msgs[1].dnsHostName == undefined);
454         assert(res.msgs[1].lastLogon == "x");
455         assert(res.msgs[1].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
456
457         /* Search by generated attribute */
458         /* In most cases, this even works when the mapping is missing
459          * a `convert_operator' by enumerating the remote db. */
460         attrs = new Array("dnsHostName", "lastLogon", "primaryGroupID");
461         res = ldb.search("(primaryGroupID=512)", NULL, ldb. SCOPE_DEFAULT, attrs);
462         assert(res.error == 0);
463         assert(res.msgs.length == 1);
464         assert(res.msgs[0].dn == s4.dn("cn=A"));
465         assert(res.msgs[0].dnsHostName == undefined);
466         assert(res.msgs[0].lastLogon == "x");
467         assert(res.msgs[0].primaryGroupID == "512");
468
469         /* TODO: There should actually be two results, A and X.  The
470          * primaryGroupID of X seems to get corrupted somewhere, and the
471          * objectSid isn't available during the generation of remote (!) data,
472          * which can be observed with the following search.  Also note that Xs
473          * objectSid seems to be fine in the previous search for objectSid... */
474         /*
475         res = ldb.search("(primaryGroupID=*)", NULL, ldb. SCOPE_DEFAULT, attrs);
476         println(res.msgs.length + " results found");
477         for (i=0;i<res.msgs.length;i++) {
478                 for (obj in res.msgs[i]) {
479                         println(obj + ": " + res.msgs[i][obj]);
480                 }
481                 println("---");
482         }
483         */
484
485         /* Search by remote name of renamed attribute */
486         attrs = new Array("dnsHostName", "lastLogon");
487         res = ldb.search("(sambaBadPasswordCount=*)", "", ldb. SCOPE_DEFAULT, attrs);
488         assert(res.error == 0);
489         assert(res.msgs.length == 0);
490
491         /* Search by objectClass */
492         attrs = new Array("dnsHostName", "lastLogon", "objectClass");
493         res = ldb.search("(objectClass=user)", NULL, ldb. SCOPE_DEFAULT, attrs);
494         assert(res.error == 0);
495         assert(res.msgs.length == 2);
496         assert(res.msgs[0].dn == s4.dn("cn=X"));
497         assert(res.msgs[0].dnsHostName == "x");
498         assert(res.msgs[0].lastLogon == "x");
499         assert(res.msgs[0].objectClass != undefined);
500         assert(res.msgs[0].objectClass[0] == "user"); 
501         assert(res.msgs[1].dn == s4.dn("cn=A"));
502         assert(res.msgs[1].dnsHostName == undefined);
503         assert(res.msgs[1].lastLogon == "x");
504         assert(res.msgs[1].objectClass != undefined);
505         assert(res.msgs[1].objectClass[0] == "user");
506
507         /* Prove that the objectClass is actually used for the search */
508         res = ldb.search("(|(objectClass=user)(badPwdCount=x))", NULL, ldb. SCOPE_DEFAULT, attrs);
509         assert(res.error == 0);
510         assert(res.msgs.length == 3);
511         assert(res.msgs[0].dn == s4.dn("cn=B"));
512         assert(res.msgs[0].dnsHostName == undefined);
513         assert(res.msgs[0].lastLogon == "y");
514         assert(res.msgs[0].objectClass != undefined);
515         for (i=0;i<res.msgs[0].objectClass.length;i++) {
516                 assert(res.msgs[0].objectClass[i] != "user");
517         }
518         assert(res.msgs[1].dn == s4.dn("cn=X"));
519         assert(res.msgs[1].dnsHostName == "x");
520         assert(res.msgs[1].lastLogon == "x");
521         assert(res.msgs[1].objectClass != undefined);
522         assert(res.msgs[1].objectClass[0] == "user");
523         assert(res.msgs[2].dn == s4.dn("cn=A"));
524         assert(res.msgs[2].dnsHostName == undefined);
525         assert(res.msgs[2].lastLogon == "x");
526         assert(res.msgs[2].objectClass != undefined);
527         assert(res.msgs[2].objectClass[0] == "user");
528
529         println("Testing search by parse tree");
530
531         /* Search by conjunction of local attributes */
532         attrs = new Array("dnsHostName", "lastLogon");
533         res = ldb.search("(&(codePage=x)(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
534         assert(res.error == 0);
535         assert(res.msgs.length == 2);
536         assert(res.msgs[0].dn == s4.dn("cn=Y"));
537         assert(res.msgs[0].dnsHostName == "y");
538         assert(res.msgs[0].lastLogon == "y");
539         assert(res.msgs[1].dn == s4.dn("cn=X"));
540         assert(res.msgs[1].dnsHostName == "x");
541         assert(res.msgs[1].lastLogon == "x");
542
543         /* Search by conjunction of remote attributes */
544         attrs = new Array("dnsHostName", "lastLogon");
545         res = ldb.search("(&(lastLogon=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
546         assert(res.error == 0);
547         assert(res.msgs.length == 2);
548         assert(res.msgs[0].dn == s4.dn("cn=X"));
549         assert(res.msgs[0].dnsHostName == "x");
550         assert(res.msgs[0].lastLogon == "x");
551         assert(res.msgs[1].dn == s4.dn("cn=A"));
552         assert(res.msgs[1].dnsHostName == undefined);
553         assert(res.msgs[1].lastLogon == "x");
554         
555         /* Search by conjunction of local and remote attribute */
556         attrs = new Array("dnsHostName", "lastLogon");
557         res = ldb.search("(&(codePage=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
558         assert(res.error == 0);
559         assert(res.msgs.length == 2);
560         assert(res.msgs[0].dn == s4.dn("cn=Y"));
561         assert(res.msgs[0].dnsHostName == "y");
562         assert(res.msgs[0].lastLogon == "y");
563         assert(res.msgs[1].dn == s4.dn("cn=X"));
564         assert(res.msgs[1].dnsHostName == "x");
565         assert(res.msgs[1].lastLogon == "x");
566
567         /* Search by conjunction of local and remote attribute w/o match */
568         attrs = new Array("dnsHostName", "lastLogon");
569         res = ldb.search("(&(codePage=x)(nextRid=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
570         assert(res.error == 0);
571         assert(res.msgs.length == 0);
572         res = ldb.search("(&(revision=x)(lastLogon=z))", NULL, ldb.SCOPE_DEFAULT, attrs);
573         assert(res.error == 0);
574         assert(res.msgs.length == 0);
575
576         /* Search by disjunction of local attributes */
577         attrs = new Array("dnsHostName", "lastLogon");
578         res = ldb.search("(|(revision=x)(dnsHostName=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
579         assert(res.error == 0);
580         assert(res.msgs.length == 2);
581         assert(res.msgs[0].dn == s4.dn("cn=Y"));
582         assert(res.msgs[0].dnsHostName == "y");
583         assert(res.msgs[0].lastLogon == "y");
584         assert(res.msgs[1].dn == s4.dn("cn=X"));
585         assert(res.msgs[1].dnsHostName == "x");
586         assert(res.msgs[1].lastLogon == "x");
587
588         /* Search by disjunction of remote attributes */
589         attrs = new Array("dnsHostName", "lastLogon");
590         res = ldb.search("(|(badPwdCount=x)(lastLogon=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
591         assert(res.error == 0);
592         assert(res.msgs.length == 3);
593         assert(res.msgs[0].dn == s4.dn("cn=B"));
594         assert(res.msgs[0].dnsHostName == undefined);
595         assert(res.msgs[0].lastLogon == "y");
596         assert(res.msgs[1].dn == s4.dn("cn=X"));
597         assert(res.msgs[1].dnsHostName == "x");
598         assert(res.msgs[1].lastLogon == "x");
599         assert(res.msgs[2].dn == s4.dn("cn=A"));
600         assert(res.msgs[2].dnsHostName == undefined);
601         assert(res.msgs[2].lastLogon == "x");
602
603         /* Search by disjunction of local and remote attribute */
604         attrs = new Array("dnsHostName", "lastLogon");
605         res = ldb.search("(|(revision=x)(lastLogon=y))", NULL, ldb.SCOPE_DEFAULT, attrs);
606         assert(res.error == 0);
607         assert(res.msgs.length == 3);
608         assert(res.msgs[0].dn == s4.dn("cn=Y"));
609         assert(res.msgs[0].dnsHostName == "y");
610         assert(res.msgs[0].lastLogon == "y");
611         assert(res.msgs[1].dn == s4.dn("cn=B"));
612         assert(res.msgs[1].dnsHostName == undefined);
613         assert(res.msgs[1].lastLogon == "y");
614         assert(res.msgs[2].dn == s4.dn("cn=X"));
615         assert(res.msgs[2].dnsHostName == "x");
616         assert(res.msgs[2].lastLogon == "x");
617
618         /* Search by disjunction of local and remote attribute w/o match */
619         attrs = new Array("dnsHostName", "lastLogon");
620         res = ldb.search("(|(codePage=y)(nextRid=z))", NULL, ldb.SCOPE_DEFAULT, attrs);
621         assert(res.error == 0);
622         assert(res.msgs.length == 0);
623
624         /* Search by negated local attribute */
625         attrs = new Array("dnsHostName", "lastLogon");
626         res = ldb.search("(!(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
627         assert(res.error == 0);
628         assert(res.msgs.length == 5);
629         assert(res.msgs[0].dn == s4.dn("cn=B"));
630         assert(res.msgs[0].dnsHostName == undefined);
631         assert(res.msgs[0].lastLogon == "y");
632         assert(res.msgs[1].dn == s4.dn("cn=A"));
633         assert(res.msgs[1].dnsHostName == undefined);
634         assert(res.msgs[1].lastLogon == "x");
635         assert(res.msgs[2].dn == s4.dn("cn=Z"));
636         assert(res.msgs[2].dnsHostName == "z");
637         assert(res.msgs[2].lastLogon == "z");
638         assert(res.msgs[3].dn == s4.dn("cn=C"));
639         assert(res.msgs[3].dnsHostName == undefined);
640         assert(res.msgs[3].lastLogon == "z");
641
642         /* Search by negated remote attribute */
643         attrs = new Array("dnsHostName", "lastLogon");
644         res = ldb.search("(!(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
645         assert(res.error == 0);
646         assert(res.msgs.length == 3);
647         assert(res.msgs[0].dn == s4.dn("cn=Z"));
648         assert(res.msgs[0].dnsHostName == "z");
649         assert(res.msgs[0].lastLogon == "z");
650         assert(res.msgs[1].dn == s4.dn("cn=C"));
651         assert(res.msgs[1].dnsHostName == undefined);
652         assert(res.msgs[1].lastLogon == "z");
653
654         /* Search by negated conjunction of local attributes */
655         attrs = new Array("dnsHostName", "lastLogon");
656         res = ldb.search("(!(&(codePage=x)(revision=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
657         assert(res.error == 0);
658         assert(res.msgs.length == 5);
659         assert(res.msgs[0].dn == s4.dn("cn=B"));
660         assert(res.msgs[0].dnsHostName == undefined);
661         assert(res.msgs[0].lastLogon == "y");
662         assert(res.msgs[1].dn == s4.dn("cn=A"));
663         assert(res.msgs[1].dnsHostName == undefined);
664         assert(res.msgs[1].lastLogon == "x");
665         assert(res.msgs[2].dn == s4.dn("cn=Z"));
666         assert(res.msgs[2].dnsHostName == "z");
667         assert(res.msgs[2].lastLogon == "z");
668         assert(res.msgs[3].dn == s4.dn("cn=C"));
669         assert(res.msgs[3].dnsHostName == undefined);
670         assert(res.msgs[3].lastLogon == "z");
671
672         /* Search by negated conjunction of remote attributes */
673         attrs = new Array("dnsHostName", "lastLogon");
674         res = ldb.search("(!(&(lastLogon=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
675         assert(res.error == 0);
676         assert(res.msgs.length == 5);
677         assert(res.msgs[0].dn == s4.dn("cn=Y"));
678         assert(res.msgs[0].dnsHostName == "y");
679         assert(res.msgs[0].lastLogon == "y");
680         assert(res.msgs[1].dn == s4.dn("cn=B"));
681         assert(res.msgs[1].dnsHostName == undefined);
682         assert(res.msgs[1].lastLogon == "y");
683         assert(res.msgs[2].dn == s4.dn("cn=Z"));
684         assert(res.msgs[2].dnsHostName == "z");
685         assert(res.msgs[2].lastLogon == "z");
686         assert(res.msgs[3].dn == s4.dn("cn=C"));
687         assert(res.msgs[3].dnsHostName == undefined);
688         assert(res.msgs[3].lastLogon == "z");
689
690         /* Search by negated conjunction of local and remote attribute */
691         attrs = new Array("dnsHostName", "lastLogon");
692         res = ldb.search("(!(&(codePage=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
693         assert(res.error == 0);
694         assert(res.msgs.length == 5);
695         assert(res.msgs[0].dn == s4.dn("cn=B"));
696         assert(res.msgs[0].dnsHostName == undefined);
697         assert(res.msgs[0].lastLogon == "y");
698         assert(res.msgs[1].dn == s4.dn("cn=A"));
699         assert(res.msgs[1].dnsHostName == undefined);
700         assert(res.msgs[1].lastLogon == "x");
701         assert(res.msgs[2].dn == s4.dn("cn=Z"));
702         assert(res.msgs[2].dnsHostName == "z");
703         assert(res.msgs[2].lastLogon == "z");
704         assert(res.msgs[3].dn == s4.dn("cn=C"));
705         assert(res.msgs[3].dnsHostName == undefined);
706         assert(res.msgs[3].lastLogon == "z");
707
708         /* Search by negated disjunction of local attributes */
709         attrs = new Array("dnsHostName", "lastLogon");
710         res = ldb.search("(!(|(revision=x)(dnsHostName=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
711         assert(res.error == 0);
712         assert(res.msgs[0].dn == s4.dn("cn=B"));
713         assert(res.msgs[0].dnsHostName == undefined);
714         assert(res.msgs[0].lastLogon == "y");
715         assert(res.msgs[1].dn == s4.dn("cn=A"));
716         assert(res.msgs[1].dnsHostName == undefined);
717         assert(res.msgs[1].lastLogon == "x");
718         assert(res.msgs[2].dn == s4.dn("cn=Z"));
719         assert(res.msgs[2].dnsHostName == "z");
720         assert(res.msgs[2].lastLogon == "z");
721         assert(res.msgs[3].dn == s4.dn("cn=C"));
722         assert(res.msgs[3].dnsHostName == undefined);
723         assert(res.msgs[3].lastLogon == "z");
724
725         /* Search by negated disjunction of remote attributes */
726         attrs = new Array("dnsHostName", "lastLogon");
727         res = ldb.search("(!(|(badPwdCount=x)(lastLogon=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
728         assert(res.error == 0);
729         assert(res.msgs.length == 4);
730         assert(res.msgs[0].dn == s4.dn("cn=Y"));
731         assert(res.msgs[0].dnsHostName == "y");
732         assert(res.msgs[0].lastLogon == "y");
733         assert(res.msgs[1].dn == s4.dn("cn=Z"));
734         assert(res.msgs[1].dnsHostName == "z");
735         assert(res.msgs[1].lastLogon == "z");
736         assert(res.msgs[2].dn == s4.dn("cn=C"));
737         assert(res.msgs[2].dnsHostName == undefined);
738         assert(res.msgs[2].lastLogon == "z");
739
740         /* Search by negated disjunction of local and remote attribute */
741         attrs = new Array("dnsHostName", "lastLogon");
742         res = ldb.search("(!(|(revision=x)(lastLogon=y)))", NULL, ldb.SCOPE_DEFAULT, attrs);
743         assert(res.error == 0);
744         assert(res.msgs.length == 4);
745         assert(res.msgs[0].dn == s4.dn("cn=A"));
746         assert(res.msgs[0].dnsHostName == undefined);
747         assert(res.msgs[0].lastLogon == "x");
748         assert(res.msgs[1].dn == s4.dn("cn=Z"));
749         assert(res.msgs[1].dnsHostName == "z");
750         assert(res.msgs[1].lastLogon == "z");
751         assert(res.msgs[2].dn == s4.dn("cn=C"));
752         assert(res.msgs[2].dnsHostName == undefined);
753         assert(res.msgs[2].lastLogon == "z");
754
755         println("Search by complex parse tree");
756         attrs = new Array("dnsHostName", "lastLogon");
757         res = ldb.search("(|(&(revision=x)(dnsHostName=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", NULL, ldb.SCOPE_DEFAULT, attrs);
758         assert(res.error == 0);
759         assert(res.msgs.length == 6);
760         assert(res.msgs[0].dn == s4.dn("cn=B"));
761         assert(res.msgs[0].dnsHostName == undefined);
762         assert(res.msgs[0].lastLogon == "y");
763         assert(res.msgs[1].dn == s4.dn("cn=X"));
764         assert(res.msgs[1].dnsHostName == "x");
765         assert(res.msgs[1].lastLogon == "x");
766         assert(res.msgs[2].dn == s4.dn("cn=A"));
767         assert(res.msgs[2].dnsHostName == undefined);
768         assert(res.msgs[2].lastLogon == "x");
769         assert(res.msgs[3].dn == s4.dn("cn=Z"));
770         assert(res.msgs[3].dnsHostName == "z");
771         assert(res.msgs[3].lastLogon == "z");
772         assert(res.msgs[4].dn == s4.dn("cn=C"));
773         assert(res.msgs[4].dnsHostName == undefined);
774         assert(res.msgs[4].lastLogon == "z");
775
776         /* Clean up */
777         var dns = new Array();
778         dns[0] = s4.dn("cn=A");
779         dns[1] = s4.dn("cn=B");
780         dns[2] = s4.dn("cn=C");
781         dns[3] = s4.dn("cn=X");
782         dns[4] = s4.dn("cn=Y");
783         dns[5] = s4.dn("cn=Z");
784         for (i=0;i<dns.length;i++) {
785                 var ok = ldb.del(dns[i]);
786                 assert(ok.error == 0);
787         }
788 }
789
790 function test_map_modify(ldb, s3, s4)
791 {
792         println("Running modification tests on mapped data");
793
794         var ldif;
795         var attrs;
796         var dn, dn2;
797         var res;
798         var ok;
799
800         println("Testing modification of local records");
801
802         /* Add local record */
803         dn = "cn=test,dc=idealx,dc=org";
804         ldif = "
805 dn: " + dn + "
806 cn: test
807 foo: bar
808 revision: 1
809 description: test
810 ";
811         ok = ldb.add(ldif);
812         assert(ok.error == 0);
813         /* Check it's there */
814         attrs = new Array("foo", "revision", "description");
815         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
816         assert(res.error == 0);
817         assert(res.msgs.length == 1);
818         assert(res.msgs[0].dn == dn);
819         assert(res.msgs[0].foo == "bar");
820         assert(res.msgs[0].revision == "1");
821         assert(res.msgs[0].description == "test");
822         /* Check it's not in the local db */
823         res = s4.db.search("(cn=test)", NULL, ldb.SCOPE_DEFAULT, attrs);
824         assert(res.error == 0);
825         assert(res.msgs.length == 0);
826         /* Check it's not in the remote db */
827         res = s3.db.search("(cn=test)", NULL, ldb.SCOPE_DEFAULT, attrs);
828         assert(res.error == 0);
829         assert(res.msgs.length == 0);
830
831         /* Modify local record */
832         ldif = "
833 dn: " + dn + "
834 replace: foo
835 foo: baz
836 replace: description
837 description: foo
838 ";
839         ok = ldb.modify(ldif);
840         assert(ok.error == 0);
841         /* Check in local db */
842         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
843         assert(res.error == 0);
844         assert(res.msgs.length == 1);
845         assert(res.msgs[0].dn == dn);
846         assert(res.msgs[0].foo == "baz");
847         assert(res.msgs[0].revision == "1");
848         assert(res.msgs[0].description == "foo");
849
850         /* Rename local record */
851         dn2 = "cn=toast,dc=idealx,dc=org";
852         ok = ldb.rename(dn, dn2);
853         assert(ok.error == 0);
854         /* Check in local db */
855         res = ldb.search("", dn2, ldb.SCOPE_BASE, attrs);
856         assert(res.error == 0);
857         assert(res.msgs.length == 1);
858         assert(res.msgs[0].dn == dn2);
859         assert(res.msgs[0].foo == "baz");
860         assert(res.msgs[0].revision == "1");
861         assert(res.msgs[0].description == "foo");
862
863         /* Delete local record */
864         ok = ldb.del(dn2);
865         assert(ok.error == 0);
866         /* Check it's gone */
867         res = ldb.search("", dn2, ldb.SCOPE_BASE);
868         assert(res.error == 0);
869         assert(res.msgs.length == 0);
870
871         println("Testing modification of remote records");
872
873         /* Add remote record */
874         dn = s4.dn("cn=test");
875         dn2 = s3.dn("cn=test");
876         ldif = "
877 dn: " + dn2 + "
878 cn: test
879 description: foo
880 sambaBadPasswordCount: 3
881 sambaNextRid: 1001
882 ";
883         ok = s3.db.add(ldif);
884         assert(ok.error == 0);
885         /* Check it's there */
886         attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid");
887         res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
888         assert(res.error == 0);
889         assert(res.msgs.length == 1);
890         assert(res.msgs[0].dn == dn2);
891         assert(res.msgs[0].description == "foo");
892         assert(res.msgs[0].sambaBadPasswordCount == "3");
893         assert(res.msgs[0].sambaNextRid == "1001");
894         /* Check in mapped db */
895         attrs = new Array("description", "badPwdCount", "nextRid");
896         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
897         assert(res.error == 0);
898         assert(res.msgs.length == 1);
899         assert(res.msgs[0].dn == dn);
900         assert(res.msgs[0].description == "foo");
901         assert(res.msgs[0].badPwdCount == "3");
902         assert(res.msgs[0].nextRid == "1001");
903         /* Check in local db */
904         res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
905         assert(res.error == 0);
906         assert(res.msgs.length == 0);
907
908         /* Modify remote data of remote record */
909         ldif = "
910 dn: " + dn + "
911 replace: description
912 description: test
913 replace: badPwdCount
914 badPwdCount: 4
915 ";
916         ok = ldb.modify(ldif);
917         /* Check in mapped db */
918         attrs = new Array("description", "badPwdCount", "nextRid");
919         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
920         assert(res.error == 0);
921         assert(res.msgs.length == 1);
922         assert(res.msgs[0].dn == dn);
923         assert(res.msgs[0].description == "test");
924         assert(res.msgs[0].badPwdCount == "4");
925         assert(res.msgs[0].nextRid == "1001");
926         /* Check in remote db */
927         attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid");
928         res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
929         assert(res.error == 0);
930         assert(res.msgs.length == 1);
931         assert(res.msgs[0].dn == dn2);
932         assert(res.msgs[0].description == "test");
933         assert(res.msgs[0].sambaBadPasswordCount == "4");
934         assert(res.msgs[0].sambaNextRid == "1001");
935
936         /* Rename remote record */
937         dn2 = s4.dn("cn=toast");
938         ok = ldb.rename(dn, dn2);
939         assert(ok.error == 0);
940         /* Check in mapped db */
941         dn = dn2;
942         attrs = new Array("description", "badPwdCount", "nextRid");
943         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
944         assert(res.error == 0);
945         assert(res.msgs.length == 1);
946         assert(res.msgs[0].dn == dn);
947         assert(res.msgs[0].description == "test");
948         assert(res.msgs[0].badPwdCount == "4");
949         assert(res.msgs[0].nextRid == "1001");
950         /* Check in remote db */
951         dn2 = s3.dn("cn=toast");
952         attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid");
953         res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
954         assert(res.error == 0);
955         assert(res.msgs.length == 1);
956         assert(res.msgs[0].dn == dn2);
957         assert(res.msgs[0].description == "test");
958         assert(res.msgs[0].sambaBadPasswordCount == "4");
959         assert(res.msgs[0].sambaNextRid == "1001");
960
961         /* Delete remote record */
962         ok = ldb.del(dn);
963         assert(ok.error == 0);
964         /* Check in mapped db */
965         res = ldb.search("", dn, ldb.SCOPE_BASE);
966         assert(res.error == 0);
967         assert(res.msgs.length == 0);
968         /* Check in remote db */
969         res = s3.db.search("", dn2, ldb.SCOPE_BASE);
970         assert(res.error == 0);
971         assert(res.msgs.length == 0);
972
973         /* Add remote record (same as before) */
974         dn = s4.dn("cn=test");
975         dn2 = s3.dn("cn=test");
976         ldif = "
977 dn: " + dn2 + "
978 cn: test
979 description: foo
980 sambaBadPasswordCount: 3
981 sambaNextRid: 1001
982 ";
983         ok = s3.db.add(ldif);
984         assert(ok.error == 0);
985
986         /* Modify local data of remote record */
987         ldif = "
988 dn: " + dn + "
989 add: revision
990 revision: 1
991 replace: description
992 description: test
993 ";
994         ok = ldb.modify(ldif);
995         /* Check in mapped db */
996         attrs = new Array("revision", "description");
997         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
998         assert(res.error == 0);
999         assert(res.msgs.length == 1);
1000         assert(res.msgs[0].dn == dn);
1001         assert(res.msgs[0].description == "test");
1002         assert(res.msgs[0].revision == "1");
1003         /* Check in remote db */
1004         res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
1005         assert(res.error == 0);
1006         assert(res.msgs.length == 1);
1007         assert(res.msgs[0].dn == dn2);
1008         assert(res.msgs[0].description == "test");
1009         assert(res.msgs[0].revision == undefined);
1010         /* Check in local db */
1011         res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
1012         assert(res.error == 0);
1013         assert(res.msgs.length == 1);
1014         assert(res.msgs[0].dn == dn);
1015         assert(res.msgs[0].description == undefined);
1016         assert(res.msgs[0].revision == "1");
1017
1018         /* Delete (newly) split record */
1019         ok = ldb.del(dn);
1020         assert(ok.error == 0);
1021
1022         println("Testing modification of split records");
1023
1024         /* Add split record */
1025         dn = s4.dn("cn=test");
1026         dn2 = s3.dn("cn=test");
1027         ldif = "
1028 dn: " + dn + "
1029 cn: test
1030 description: foo
1031 badPwdCount: 3
1032 nextRid: 1001
1033 revision: 1
1034 ";
1035         ok = ldb.add(ldif);
1036         assert(ok.error == 0);
1037         /* Check it's there */
1038         attrs = new Array("description", "badPwdCount", "nextRid", "revision");
1039         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
1040         assert(res.error == 0);
1041         assert(res.msgs.length == 1);
1042         assert(res.msgs[0].dn == dn);
1043         assert(res.msgs[0].description == "foo");
1044         assert(res.msgs[0].badPwdCount == "3");
1045         assert(res.msgs[0].nextRid == "1001");
1046         assert(res.msgs[0].revision == "1");
1047         /* Check in local db */
1048         res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
1049         assert(res.error == 0);
1050         assert(res.msgs.length == 1);
1051         assert(res.msgs[0].dn == dn);
1052         assert(res.msgs[0].description == undefined);
1053         assert(res.msgs[0].badPwdCount == undefined);
1054         assert(res.msgs[0].nextRid == undefined);
1055         assert(res.msgs[0].revision == "1");
1056         /* Check in remote db */
1057         attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision");
1058         res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
1059         assert(res.error == 0);
1060         assert(res.msgs.length == 1);
1061         assert(res.msgs[0].dn == dn2);
1062         assert(res.msgs[0].description == "foo");
1063         assert(res.msgs[0].sambaBadPasswordCount == "3");
1064         assert(res.msgs[0].sambaNextRid == "1001");
1065         assert(res.msgs[0].revision == undefined);
1066
1067         /* Modify of split record */
1068         ldif = "
1069 dn: " + dn + "
1070 replace: description
1071 description: test
1072 replace: badPwdCount
1073 badPwdCount: 4
1074 replace: revision
1075 revision: 2
1076 ";
1077         ok = ldb.modify(ldif);
1078         assert(ok.error == 0);
1079         /* Check in mapped db */
1080         attrs = new Array("description", "badPwdCount", "nextRid", "revision");
1081         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
1082         assert(res.error == 0);
1083         assert(res.msgs.length == 1);
1084         assert(res.msgs[0].dn == dn);
1085         assert(res.msgs[0].description == "test");
1086         assert(res.msgs[0].badPwdCount == "4");
1087         assert(res.msgs[0].nextRid == "1001");
1088         assert(res.msgs[0].revision == "2");
1089         /* Check in local db */
1090         res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
1091         assert(res.error == 0);
1092         assert(res.msgs.length == 1);
1093         assert(res.msgs[0].dn == dn);
1094         assert(res.msgs[0].description == undefined);
1095         assert(res.msgs[0].badPwdCount == undefined);
1096         assert(res.msgs[0].nextRid == undefined);
1097         assert(res.msgs[0].revision == "2");
1098         /* Check in remote db */
1099         attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision");
1100         res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
1101         assert(res.error == 0);
1102         assert(res.msgs.length == 1);
1103         assert(res.msgs[0].dn == dn2);
1104         assert(res.msgs[0].description == "test");
1105         assert(res.msgs[0].sambaBadPasswordCount == "4");
1106         assert(res.msgs[0].sambaNextRid == "1001");
1107         assert(res.msgs[0].revision == undefined);
1108
1109         /* Rename split record */
1110         dn2 = s4.dn("cn=toast");
1111         ok = ldb.rename(dn, dn2);
1112         assert(ok.error == 0);
1113         /* Check in mapped db */
1114         dn = dn2;
1115         attrs = new Array("description", "badPwdCount", "nextRid", "revision");
1116         res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
1117         assert(res.error == 0);
1118         assert(res.msgs.length == 1);
1119         assert(res.msgs[0].dn == dn);
1120         assert(res.msgs[0].description == "test");
1121         assert(res.msgs[0].badPwdCount == "4");
1122         assert(res.msgs[0].nextRid == "1001");
1123         assert(res.msgs[0].revision == "2");
1124         /* Check in local db */
1125         res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
1126         assert(res.error == 0);
1127         assert(res.msgs.length == 1);
1128         assert(res.msgs[0].dn == dn);
1129         assert(res.msgs[0].description == undefined);
1130         assert(res.msgs[0].badPwdCount == undefined);
1131         assert(res.msgs[0].nextRid == undefined);
1132         assert(res.msgs[0].revision == "2");
1133         /* Check in remote db */
1134         dn2 = s3.dn("cn=toast");
1135         attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision");
1136         res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
1137         assert(res.error == 0);
1138         assert(res.msgs.length == 1);
1139         assert(res.msgs[0].dn == dn2);
1140         assert(res.msgs[0].description == "test");
1141         assert(res.msgs[0].sambaBadPasswordCount == "4");
1142         assert(res.msgs[0].sambaNextRid == "1001");
1143         assert(res.msgs[0].revision == undefined);
1144
1145         /* Delete split record */
1146         ok = ldb.del(dn);
1147         assert(ok.error == 0);
1148         /* Check in mapped db */
1149         res = ldb.search("", dn, ldb.SCOPE_BASE);
1150         assert(res.error == 0);
1151         assert(res.msgs.length == 0);
1152         /* Check in local db */
1153         res = s4.db.search("", dn, ldb.SCOPE_BASE);
1154         assert(res.error == 0);
1155         assert(res.msgs.length == 0);
1156         /* Check in remote db */
1157         res = s3.db.search("", dn2, ldb.SCOPE_BASE);
1158         assert(res.error == 0);
1159         assert(res.msgs.length == 0);
1160 }
1161
1162 function make_dn(rdn)
1163 {
1164         return rdn + ",sambaDomainName=TESTS," + this.BASEDN;
1165 }
1166
1167 function make_s4dn(rdn)
1168 {
1169         return rdn + "," + this.BASEDN;
1170 }
1171
1172 var ldb = ldb_init();
1173
1174 sys = sys_init();
1175 var ldbfile = prefix + "/" + "test.ldb";
1176 var ldburl = "tdb://" + ldbfile;
1177
1178 var samba4 = new Object("samba4 partition info");
1179 samba4.file = prefix + "/" + "samba4.ldb";
1180 samba4.url = "tdb://" + samba4.file;
1181 samba4.BASEDN = "dc=vernstok,dc=nl";
1182 samba4.db = ldb_init();
1183 samba4.dn = make_s4dn;
1184
1185 var samba3 = new Object("samba3 partition info");
1186 samba3.file = prefix + "/" + "samba3.ldb";
1187 samba3.url = "tdb://" + samba3.file;
1188 samba3.BASEDN = "cn=Samba3Sam";
1189 samba3.db = ldb_init();
1190 samba3.dn = make_dn;
1191
1192 var templates = new Object("templates partition info");
1193 templates.file = prefix + "/" + "templates.ldb";
1194 templates.url = "tdb://" + templates.file;
1195 templates.BASEDN = "cn=templates";
1196 templates.db = ldb_init();
1197
1198 sys.unlink(ldbfile);
1199 sys.unlink(samba3.file);
1200 sys.unlink(templates.file);
1201 sys.unlink(samba4.file);
1202
1203 var ok = ldb.connect(ldburl);
1204 assert(ok);
1205 var ok = samba3.db.connect(samba3.url);
1206 assert(ok);
1207 var ok = templates.db.connect(templates.url);
1208 assert(ok);
1209 var ok = samba4.db.connect(samba4.url);
1210 assert(ok);
1211
1212 setup_data(samba3, sys.file_load(datadir + "/" + "samba3.ldif"));
1213 setup_data(templates, sys.file_load(datadir + "/" + "provision_samba3sam_templates.ldif"));
1214 setup_modules(ldb, samba3, samba4, sys.file_load(datadir + "/" + "provision_samba3sam.ldif"));
1215
1216 ldb = ldb_init();
1217 var ok = ldb.connect(ldburl);
1218 assert(ok);
1219
1220 test_s3sam_search(ldb);
1221 test_s3sam_modify(ldb, samba3);
1222
1223 sys.unlink(ldbfile);
1224 sys.unlink(samba3.file);
1225 sys.unlink(templates.file);
1226 sys.unlink(samba4.file);
1227
1228 ldb = ldb_init();
1229 var ok = ldb.connect(ldburl);
1230 assert(ok);
1231 samba3.db = ldb_init();
1232 var ok = samba3.db.connect(samba3.url);
1233 assert(ok);
1234 templates.db = ldb_init();
1235 var ok = templates.db.connect(templates.url);
1236 assert(ok);
1237 samba4.db = ldb_init();
1238 var ok = samba4.db.connect(samba4.url);
1239 assert(ok);
1240
1241 setup_data(templates, sys.file_load(datadir + "/" + "provision_samba3sam_templates.ldif"));
1242 setup_modules(ldb, samba3, samba4, sys.file_load(datadir + "provision_samba3sam.ldif"));
1243
1244 ldb = ldb_init();
1245 var ok = ldb.connect(ldburl);
1246 assert(ok);
1247
1248 test_map_search(ldb, samba3, samba4);
1249 test_map_modify(ldb, samba3, samba4);
1250
1251 sys.unlink(ldbfile);
1252 sys.unlink(samba3.file);
1253 sys.unlink(samba4.file);
1254
1255 return 0;