1 #!/usr/bin/env smbscript
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
11 var options = GetOptions(ARGV, "POPT_AUTOHELP", "POPT_COMMON_SAMBA");
12 if (options == undefined) {
13 println("Failed to parse options");
17 libinclude("base.js");
19 if (options.ARGV.length != 2) {
20 println("Usage: samba3sam.js <TESTDIR> <DATADIR>");
24 var prefix = options.ARGV[0];
25 var datadir = options.ARGV[1];
27 function setup_data(obj, ldif)
29 assert(ldif != undefined);
30 ldif = substitute_var(ldif, obj);
31 assert(ldif != undefined);
32 var ok = obj.db.add(ldif);
36 function setup_modules(ldb, s3, s4, ldif)
38 assert(ldif != undefined);
39 ldif = substitute_var(ldif, s4);
40 assert(ldif != undefined);
41 var ok = ldb.add(ldif);
46 @FROM: " + s4.BASEDN + "
47 @TO: " + s3.BASEDN + "
50 @LIST: rootdse,paged_results,server_sort,extended_dn,asq,samldb,objectclass,password_hash,operational,objectguid,rdn_name,samba3sam,partition
53 partition: " + s4.BASEDN + ":" + s4.url + "
54 partition: " + s3.BASEDN + ":" + s3.url + "
55 replicateEntries: @SUBCLASSES
56 replicateEntries: @ATTRIBUTES
57 replicateEntries: @INDEXLIST
59 var ok = ldb.add(ldif);
63 function test_s3sam_search(ldb)
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");
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");
75 println("Looking up by old name of renamed attribute");
76 var msg = ldb.search("(displayName=Backup Operators)");
77 assert(msg.length == 0);
79 println("Looking up mapped entry containing SID");
80 var msg = ldb.search("(cn=Replicator)");
81 assert(msg.length == 1);
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");
86 println("Checking mapping of objectClass");
87 var oc = msg[0].objectClass;
88 assert(oc != undefined);
90 assert(oc[i] == "posixGroup" || oc[i] == "group");
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"));
103 function test_s3sam_modify(ldb, s3)
105 println("Adding a record that will be fallbacked");
107 dn: cn=Foo,dc=idealx,dc=org
111 showInAdvancedViewOnly: TRUE
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'));
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");
127 println("Adding record that will be mapped");
129 dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
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");
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");
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");
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");
162 println("Adding attribute...");
164 dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
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");
177 println("Modifying attribute...");
179 dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
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");
191 println("Deleting attribute...");
193 dn: cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl
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);
204 println("Renaming record...");
205 ok = ldb.rename("cn=Niemand,sambaDomainName=TESTS,dc=vernstok,dc=nl", "cn=Niemand,dc=vernstok,dc=nl");
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");
212 println("Deleting record...");
213 ok = ldb.del("cn=Niemand,dc=vernstok,dc=nl");
216 println("Checking whether record is gone...");
217 msg = ldb.search("(cn=Niemand)");
218 assert(msg.length == 0);
221 function test_map_search(ldb, s3, s4)
223 println("Running search tests on mapped data");
228 /* Add a set of split records */
230 dn: " + s4.dn("cn=X") + "
239 objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
240 primaryGroupID: 1-5-21-4231626423-2410014848-2360679739-512
242 dn: " + s4.dn("cn=Y") + "
252 dn: " + s4.dn("cn=Z") + "
262 ldif = substitute_var(ldif, s4);
263 assert(ldif != undefined);
264 var ok = ldb.add(ldif);
267 /* Add a set of remote records */
269 dn: " + s3.dn("cn=A") + "
270 objectClass: posixAccount
273 sambaBadPasswordCount: x
276 sambaSID: S-1-5-21-4231626423-2410014848-2360679739-552
277 sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-512
279 dn: " + s3.dn("cn=B") + "
283 sambaBadPasswordCount: x
287 dn: " + s3.dn("cn=C") + "
291 sambaBadPasswordCount: y
295 ldif = substitute_var(ldif, s3);
296 assert(ldif != undefined);
297 var ok = s3.db.add(ldif);
300 println("Testing search by DN");
302 /* Search remote record by local DN */
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");
312 /* Search remote record by remote DN */
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");
323 /* Search split record by local DN */
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");
333 /* Search split record by remote DN */
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");
344 println("Testing search by attribute");
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 == s4.dn("cn=Y"));
352 assert(res[0].objectCategory == "y");
353 assert(res[0].lastLogon == "y");
354 assert(res[1].dn == s4.dn("cn=X"));
355 assert(res[1].objectCategory == "x");
356 assert(res[1].lastLogon == "x");
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 == s4.dn("cn=Z"));
364 assert(res[0].objectCategory == "z");
365 assert(res[0].lastLogon == "z");
366 assert(res[1].dn == s4.dn("cn=C"));
367 assert(res[1].objectCategory == undefined);
368 assert(res[1].lastLogon == "z");
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 == s4.dn("cn=B"));
376 assert(res[0].objectCategory == undefined);
377 assert(res[0].lastLogon == "y");
378 assert(res[1].dn == s4.dn("cn=A"));
379 assert(res[1].objectCategory == undefined);
380 assert(res[1].lastLogon == "x");
382 /* Search by converted attribute */
383 attrs = new Array("objectCategory", "lastLogon", "objectSid");
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);
389 res = ldb.search("(objectSid=*)", NULL, ldb. SCOPE_DEFAULT, attrs);
390 assert(res != undefined);
391 assert(res.length == 2);
392 assert(res[0].dn == s4.dn("cn=X"));
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 == s4.dn("cn=A"));
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");
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 == s4.dn("cn=A"));
409 assert(res[0].objectCategory == undefined);
410 assert(res[0].lastLogon == "x");
411 assert(res[0].primaryGroupID == "1-5-21-4231626423-2410014848-2360679739-512");
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... */
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]);
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);
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 == s4.dn("cn=X"));
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 == s4.dn("cn=A"));
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");
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 == s4.dn("cn=B"));
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");
462 assert(res[1].dn == s4.dn("cn=X"));
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 == s4.dn("cn=A"));
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");
473 println("Testing search by parse tree");
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 == s4.dn("cn=Y"));
481 assert(res[0].objectCategory == "y");
482 assert(res[0].lastLogon == "y");
483 assert(res[1].dn == s4.dn("cn=X"));
484 assert(res[1].objectCategory == "x");
485 assert(res[1].lastLogon == "x");
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 == s4.dn("cn=X"));
493 assert(res[0].objectCategory == "x");
494 assert(res[0].lastLogon == "x");
495 assert(res[1].dn == s4.dn("cn=A"));
496 assert(res[1].objectCategory == undefined);
497 assert(res[1].lastLogon == "x");
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 == s4.dn("cn=Y"));
505 assert(res[0].objectCategory == "y");
506 assert(res[0].lastLogon == "y");
507 assert(res[1].dn == s4.dn("cn=X"));
508 assert(res[1].objectCategory == "x");
509 assert(res[1].lastLogon == "x");
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);
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 == s4.dn("cn=Y"));
526 assert(res[0].objectCategory == "y");
527 assert(res[0].lastLogon == "y");
528 assert(res[1].dn == s4.dn("cn=X"));
529 assert(res[1].objectCategory == "x");
530 assert(res[1].lastLogon == "x");
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 == s4.dn("cn=B"));
538 assert(res[0].objectCategory == undefined);
539 assert(res[0].lastLogon == "y");
540 assert(res[1].dn == s4.dn("cn=X"));
541 assert(res[1].objectCategory == "x");
542 assert(res[1].lastLogon == "x");
543 assert(res[2].dn == s4.dn("cn=A"));
544 assert(res[2].objectCategory == undefined);
545 assert(res[2].lastLogon == "x");
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 == s4.dn("cn=Y"));
553 assert(res[0].objectCategory == "y");
554 assert(res[0].lastLogon == "y");
555 assert(res[1].dn == s4.dn("cn=B"));
556 assert(res[1].objectCategory == undefined);
557 assert(res[1].lastLogon == "y");
558 assert(res[2].dn == s4.dn("cn=X"));
559 assert(res[2].objectCategory == "x");
560 assert(res[2].lastLogon == "x");
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);
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 == s4.dn("cn=B"));
574 assert(res[0].objectCategory == undefined);
575 assert(res[0].lastLogon == "y");
576 assert(res[1].dn == s4.dn("cn=A"));
577 assert(res[1].objectCategory == undefined);
578 assert(res[1].lastLogon == "x");
579 assert(res[2].dn == s4.dn("cn=Z"));
580 assert(res[2].objectCategory == "z");
581 assert(res[2].lastLogon == "z");
582 assert(res[3].dn == s4.dn("cn=C"));
583 assert(res[3].objectCategory == undefined);
584 assert(res[3].lastLogon == "z");
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 == s4.dn("cn=Z"));
592 assert(res[0].objectCategory == "z");
593 assert(res[0].lastLogon == "z");
594 assert(res[1].dn == s4.dn("cn=C"));
595 assert(res[1].objectCategory == undefined);
596 assert(res[1].lastLogon == "z");
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 == s4.dn("cn=B"));
604 assert(res[0].objectCategory == undefined);
605 assert(res[0].lastLogon == "y");
606 assert(res[1].dn == s4.dn("cn=A"));
607 assert(res[1].objectCategory == undefined);
608 assert(res[1].lastLogon == "x");
609 assert(res[2].dn == s4.dn("cn=Z"));
610 assert(res[2].objectCategory == "z");
611 assert(res[2].lastLogon == "z");
612 assert(res[3].dn == s4.dn("cn=C"));
613 assert(res[3].objectCategory == undefined);
614 assert(res[3].lastLogon == "z");
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 == s4.dn("cn=Y"));
622 assert(res[0].objectCategory == "y");
623 assert(res[0].lastLogon == "y");
624 assert(res[1].dn == s4.dn("cn=B"));
625 assert(res[1].objectCategory == undefined);
626 assert(res[1].lastLogon == "y");
627 assert(res[2].dn == s4.dn("cn=Z"));
628 assert(res[2].objectCategory == "z");
629 assert(res[2].lastLogon == "z");
630 assert(res[3].dn == s4.dn("cn=C"));
631 assert(res[3].objectCategory == undefined);
632 assert(res[3].lastLogon == "z");
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 == s4.dn("cn=B"));
640 assert(res[0].objectCategory == undefined);
641 assert(res[0].lastLogon == "y");
642 assert(res[1].dn == s4.dn("cn=A"));
643 assert(res[1].objectCategory == undefined);
644 assert(res[1].lastLogon == "x");
645 assert(res[2].dn == s4.dn("cn=Z"));
646 assert(res[2].objectCategory == "z");
647 assert(res[2].lastLogon == "z");
648 assert(res[3].dn == s4.dn("cn=C"));
649 assert(res[3].objectCategory == undefined);
650 assert(res[3].lastLogon == "z");
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 == s4.dn("cn=B"));
657 assert(res[0].objectCategory == undefined);
658 assert(res[0].lastLogon == "y");
659 assert(res[1].dn == s4.dn("cn=A"));
660 assert(res[1].objectCategory == undefined);
661 assert(res[1].lastLogon == "x");
662 assert(res[2].dn == s4.dn("cn=Z"));
663 assert(res[2].objectCategory == "z");
664 assert(res[2].lastLogon == "z");
665 assert(res[3].dn == s4.dn("cn=C"));
666 assert(res[3].objectCategory == undefined);
667 assert(res[3].lastLogon == "z");
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 == s4.dn("cn=Y"));
675 assert(res[0].objectCategory == "y");
676 assert(res[0].lastLogon == "y");
677 assert(res[1].dn == s4.dn("cn=Z"));
678 assert(res[1].objectCategory == "z");
679 assert(res[1].lastLogon == "z");
680 assert(res[2].dn == s4.dn("cn=C"));
681 assert(res[2].objectCategory == undefined);
682 assert(res[2].lastLogon == "z");
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 == s4.dn("cn=A"));
690 assert(res[0].objectCategory == undefined);
691 assert(res[0].lastLogon == "x");
692 assert(res[1].dn == s4.dn("cn=Z"));
693 assert(res[1].objectCategory == "z");
694 assert(res[1].lastLogon == "z");
695 assert(res[2].dn == s4.dn("cn=C"));
696 assert(res[2].objectCategory == undefined);
697 assert(res[2].lastLogon == "z");
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 == s4.dn("cn=B"));
705 assert(res[0].objectCategory == undefined);
706 assert(res[0].lastLogon == "y");
707 assert(res[1].dn == s4.dn("cn=X"));
708 assert(res[1].objectCategory == "x");
709 assert(res[1].lastLogon == "x");
710 assert(res[2].dn == s4.dn("cn=A"));
711 assert(res[2].objectCategory == undefined);
712 assert(res[2].lastLogon == "x");
713 assert(res[3].dn == s4.dn("cn=Z"));
714 assert(res[3].objectCategory == "z");
715 assert(res[3].lastLogon == "z");
716 assert(res[4].dn == s4.dn("cn=C"));
717 assert(res[4].objectCategory == undefined);
718 assert(res[4].lastLogon == "z");
721 var dns = new Array();
722 dns[0] = s4.dn("cn=A");
723 dns[1] = s4.dn("cn=B");
724 dns[2] = s4.dn("cn=C");
725 dns[3] = s4.dn("cn=X");
726 dns[4] = s4.dn("cn=Y");
727 dns[5] = s4.dn("cn=Z");
728 for (i=0;i<dns.length;i++) {
729 var ok = ldb.del(dns[i]);
734 function test_map_modify(ldb, s3, s4)
736 println("Running modification tests on mapped data");
744 println("Testing modification of local records");
746 /* Add local record */
747 dn = "cn=test,dc=idealx,dc=org";
757 /* Check it's there */
758 attrs = new Array("foo", "revision", "description");
759 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
760 assert(res != undefined);
761 assert(res.length == 1);
762 assert(res[0].dn == dn);
763 assert(res[0].foo == "bar");
764 assert(res[0].revision == "1");
765 assert(res[0].description == "test");
766 /* Check it's not in the local db */
767 res = s4.db.search("(cn=test)", NULL, ldb.SCOPE_DEFAULT, attrs);
768 assert(res != undefined);
769 assert(res.length == 0);
770 /* Check it's not in the remote db */
771 res = s3.db.search("(cn=test)", NULL, ldb.SCOPE_DEFAULT, attrs);
772 assert(res != undefined);
773 assert(res.length == 0);
775 /* Modify local record */
783 ok = ldb.modify(ldif);
785 /* Check in local db */
786 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
787 assert(res != undefined);
788 assert(res.length == 1);
789 assert(res[0].dn == dn);
790 assert(res[0].foo == "baz");
791 assert(res[0].revision == "1");
792 assert(res[0].description == "foo");
794 /* Rename local record */
795 dn2 = "cn=toast,dc=idealx,dc=org";
796 ok = ldb.rename(dn, dn2);
798 /* Check in local db */
799 res = ldb.search("", dn2, ldb.SCOPE_BASE, attrs);
800 assert(res != undefined);
801 assert(res.length == 1);
802 assert(res[0].dn == dn2);
803 assert(res[0].foo == "baz");
804 assert(res[0].revision == "1");
805 assert(res[0].description == "foo");
807 /* Delete local record */
810 /* Check it's gone */
811 res = ldb.search("", dn2, ldb.SCOPE_BASE);
812 assert(res != undefined);
813 assert(res.length == 0);
815 println("Testing modification of remote records");
817 /* Add remote record */
818 dn = s4.dn("cn=test");
819 dn2 = s3.dn("cn=test");
824 sambaBadPasswordCount: 3
827 ok = s3.db.add(ldif);
829 /* Check it's there */
830 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid");
831 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
832 assert(res != undefined);
833 assert(res.length == 1);
834 assert(res[0].dn == dn2);
835 assert(res[0].description == "foo");
836 assert(res[0].sambaBadPasswordCount == "3");
837 assert(res[0].sambaNextRid == "1001");
838 /* Check in mapped db */
839 attrs = new Array("description", "badPwdCount", "nextRid");
840 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
841 assert(res != undefined);
842 assert(res.length == 1);
843 assert(res[0].dn == dn);
844 assert(res[0].description == "foo");
845 assert(res[0].badPwdCount == "3");
846 assert(res[0].nextRid == "1001");
847 /* Check in local db */
848 res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
849 assert(res != undefined);
850 assert(res.length == 0);
852 /* Modify remote data of remote record */
860 ok = ldb.modify(ldif);
861 /* Check in mapped db */
862 attrs = new Array("description", "badPwdCount", "nextRid");
863 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
864 assert(res != undefined);
865 assert(res.length == 1);
866 assert(res[0].dn == dn);
867 assert(res[0].description == "test");
868 assert(res[0].badPwdCount == "4");
869 assert(res[0].nextRid == "1001");
870 /* Check in remote db */
871 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid");
872 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
873 assert(res != undefined);
874 assert(res.length == 1);
875 assert(res[0].dn == dn2);
876 assert(res[0].description == "test");
877 assert(res[0].sambaBadPasswordCount == "4");
878 assert(res[0].sambaNextRid == "1001");
880 /* Rename remote record */
881 dn2 = s4.dn("cn=toast");
882 ok = ldb.rename(dn, dn2);
884 /* Check in mapped db */
886 attrs = new Array("description", "badPwdCount", "nextRid");
887 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
888 assert(res != undefined);
889 assert(res.length == 1);
890 assert(res[0].dn == dn);
891 assert(res[0].description == "test");
892 assert(res[0].badPwdCount == "4");
893 assert(res[0].nextRid == "1001");
894 /* Check in remote db */
895 dn2 = s3.dn("cn=toast");
896 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid");
897 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
898 assert(res != undefined);
899 assert(res.length == 1);
900 assert(res[0].dn == dn2);
901 assert(res[0].description == "test");
902 assert(res[0].sambaBadPasswordCount == "4");
903 assert(res[0].sambaNextRid == "1001");
905 /* Delete remote record */
908 /* Check in mapped db */
909 res = ldb.search("", dn, ldb.SCOPE_BASE);
910 assert(res != undefined);
911 assert(res.length == 0);
912 /* Check in remote db */
913 res = s3.db.search("", dn2, ldb.SCOPE_BASE);
914 assert(res != undefined);
915 assert(res.length == 0);
917 /* Add remote record (same as before) */
918 dn = s4.dn("cn=test");
919 dn2 = s3.dn("cn=test");
924 sambaBadPasswordCount: 3
927 ok = s3.db.add(ldif);
930 /* Modify local data of remote record */
938 ok = ldb.modify(ldif);
939 /* Check in mapped db */
940 attrs = new Array("revision", "description");
941 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
942 assert(res != undefined);
943 assert(res.length == 1);
944 assert(res[0].dn == dn);
945 assert(res[0].description == "test");
946 assert(res[0].revision == "1");
947 /* Check in remote db */
948 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
949 assert(res != undefined);
950 assert(res.length == 1);
951 assert(res[0].dn == dn2);
952 assert(res[0].description == "test");
953 assert(res[0].revision == undefined);
954 /* Check in local db */
955 res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
956 assert(res != undefined);
957 assert(res.length == 1);
958 assert(res[0].dn == dn);
959 assert(res[0].description == undefined);
960 assert(res[0].revision == "1");
962 /* Delete (newly) split record */
966 println("Testing modification of split records");
968 /* Add split record */
969 dn = s4.dn("cn=test");
970 dn2 = s3.dn("cn=test");
981 /* Check it's there */
982 attrs = new Array("description", "badPwdCount", "nextRid", "revision");
983 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
984 assert(res != undefined);
985 assert(res.length == 1);
986 assert(res[0].dn == dn);
987 assert(res[0].description == "foo");
988 assert(res[0].badPwdCount == "3");
989 assert(res[0].nextRid == "1001");
990 assert(res[0].revision == "1");
991 /* Check in local db */
992 res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
993 assert(res != undefined);
994 assert(res.length == 1);
995 assert(res[0].dn == dn);
996 assert(res[0].description == undefined);
997 assert(res[0].badPwdCount == undefined);
998 assert(res[0].nextRid == undefined);
999 assert(res[0].revision == "1");
1000 /* Check in remote db */
1001 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision");
1002 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
1003 assert(res != undefined);
1004 assert(res.length == 1);
1005 assert(res[0].dn == dn2);
1006 assert(res[0].description == "foo");
1007 assert(res[0].sambaBadPasswordCount == "3");
1008 assert(res[0].sambaNextRid == "1001");
1009 assert(res[0].revision == undefined);
1011 /* Modify of split record */
1014 replace: description
1016 replace: badPwdCount
1021 ok = ldb.modify(ldif);
1023 /* Check in mapped db */
1024 attrs = new Array("description", "badPwdCount", "nextRid", "revision");
1025 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
1026 assert(res != undefined);
1027 assert(res.length == 1);
1028 assert(res[0].dn == dn);
1029 assert(res[0].description == "test");
1030 assert(res[0].badPwdCount == "4");
1031 assert(res[0].nextRid == "1001");
1032 assert(res[0].revision == "2");
1033 /* Check in local db */
1034 res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
1035 assert(res != undefined);
1036 assert(res.length == 1);
1037 assert(res[0].dn == dn);
1038 assert(res[0].description == undefined);
1039 assert(res[0].badPwdCount == undefined);
1040 assert(res[0].nextRid == undefined);
1041 assert(res[0].revision == "2");
1042 /* Check in remote db */
1043 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision");
1044 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
1045 assert(res != undefined);
1046 assert(res.length == 1);
1047 assert(res[0].dn == dn2);
1048 assert(res[0].description == "test");
1049 assert(res[0].sambaBadPasswordCount == "4");
1050 assert(res[0].sambaNextRid == "1001");
1051 assert(res[0].revision == undefined);
1053 /* Rename split record */
1054 dn2 = s4.dn("cn=toast");
1055 ok = ldb.rename(dn, dn2);
1057 /* Check in mapped db */
1059 attrs = new Array("description", "badPwdCount", "nextRid", "revision");
1060 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
1061 assert(res != undefined);
1062 assert(res.length == 1);
1063 assert(res[0].dn == dn);
1064 assert(res[0].description == "test");
1065 assert(res[0].badPwdCount == "4");
1066 assert(res[0].nextRid == "1001");
1067 assert(res[0].revision == "2");
1068 /* Check in local db */
1069 res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
1070 assert(res != undefined);
1071 assert(res.length == 1);
1072 assert(res[0].dn == dn);
1073 assert(res[0].description == undefined);
1074 assert(res[0].badPwdCount == undefined);
1075 assert(res[0].nextRid == undefined);
1076 assert(res[0].revision == "2");
1077 /* Check in remote db */
1078 dn2 = s3.dn("cn=toast");
1079 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision");
1080 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
1081 assert(res != undefined);
1082 assert(res.length == 1);
1083 assert(res[0].dn == dn2);
1084 assert(res[0].description == "test");
1085 assert(res[0].sambaBadPasswordCount == "4");
1086 assert(res[0].sambaNextRid == "1001");
1087 assert(res[0].revision == undefined);
1089 /* Delete split record */
1092 /* Check in mapped db */
1093 res = ldb.search("", dn, ldb.SCOPE_BASE);
1094 assert(res != undefined);
1095 assert(res.length == 0);
1096 /* Check in local db */
1097 res = s4.db.search("", dn, ldb.SCOPE_BASE);
1098 assert(res != undefined);
1099 assert(res.length == 0);
1100 /* Check in remote db */
1101 res = s3.db.search("", dn2, ldb.SCOPE_BASE);
1102 assert(res != undefined);
1103 assert(res.length == 0);
1106 function make_dn(rdn)
1108 return rdn + ",sambaDomainName=TESTS," + this.BASEDN;
1112 var ldbfile = prefix + "/" + "test.ldb";
1113 var ldburl = "tdb://" + ldbfile;
1115 var samba4 = new Object("samba4 partition info");
1116 samba4.file = prefix + "/" + "samba4.ldb";
1117 samba4.url = "tdb://" + samba4.file;
1118 samba4.BASEDN = "dc=vernstok,dc=nl";
1119 samba4.db = ldb_init();
1120 samba4.dn = make_dn;
1122 var samba3 = new Object("samba3 partition info");
1123 samba3.file = prefix + "/" + "samba3.ldb";
1124 samba3.url = "tdb://" + samba3.file;
1125 samba3.BASEDN = "cn=Samba3Sam," + samba4.BASEDN;
1126 samba3.db = ldb_init();
1127 samba3.dn = make_dn;
1129 sys.unlink(ldbfile);
1130 sys.unlink(samba3.file);
1131 sys.unlink(samba4.file);
1133 var ok = ldb.connect(ldburl);
1135 var ok = samba3.db.connect(samba3.url);
1137 var ok = samba4.db.connect(samba4.url);
1140 setup_data(samba3, sys.file_load(datadir + "/" + "samba3.ldif"));
1141 setup_modules(ldb, samba3, samba4, sys.file_load(datadir + "/" + "provision_samba3sam.ldif"));
1144 var ok = ldb.connect(ldburl);
1147 test_s3sam_search(ldb);
1148 test_s3sam_modify(ldb, samba3);
1150 sys.unlink(ldbfile);
1151 sys.unlink(samba3.file);
1152 sys.unlink(samba4.file);
1155 var ok = ldb.connect(ldburl);
1157 samba3.db = ldb_init();
1158 var ok = samba3.db.connect(samba3.url);
1160 samba4.db = ldb_init();
1161 var ok = samba4.db.connect(samba4.url);
1164 setup_modules(ldb, samba3, samba4, sys.file_load(datadir + "provision_samba3sam.ldif"));
1167 var ok = ldb.connect(ldburl);
1170 test_map_search(ldb, samba3, samba4);
1171 test_map_modify(ldb, samba3, samba4);
1173 sys.unlink(ldbfile);
1174 sys.unlink(samba3.file);
1175 sys.unlink(samba4.file);