2 a simple UESS test harness for AIX
4 Andrew Tridgell <tridge@au.ibm.com>
9 uess_test <MODULE_NAME> <nloops>
11 for example "uess_test LDAP" will load the LDAP module using methods.cfg
12 and will call directly into the supplied methods
14 If nloops is not supplied then 1 is assumed. Note that the built-in
15 memory leak checking can only be performed with nloops > 1
18 You can force uess_test not to free the gr_passwd entry in struct group by setting the
19 environment variable "DONT_FREE_GR_PASSWD". This is needed for the AIX 5.2 LDAP module,
20 as it incorrectly returns a constant string in that field.
23 I also strongly recommend you run this test program with the following malloc debug options set:
25 MALLOCDEBUG=validate_ptrs,report_allocations,record_allocations
29 Thanks to Julianne Haugh for assistance in understanding the UESS interface.
39 #include <sys/types.h>
44 static struct secmethod_table *methods;
47 #define INVALID_STRING "INVALID"
48 #define INVALID_INT 123456
53 static void test_attrlist(void)
58 if (!methods->method_attrlist) {
59 printf("WARNING: module has no method_attrlist\n");
63 printf("\ntesting method_attrlist\n");
65 a = methods->method_attrlist();
67 printf("ERROR: attrlist failed - %s\n", strerror(errno));
73 printf("\tattrib '%s' flags=0x%x type=%d\n",
74 a[i]->al_name, a[i]->al_flags, a[i]->al_type);
84 static void test_userlist(void)
88 char *attribs = "users";
91 if (!methods->method_getentry) {
92 printf("WARNING: module has no method_getentry\n");
96 printf("\ntesting method_getentry(ALL, user)\n");
98 ret = methods->method_getentry("ALL", "user", &attribs, &a, 1);
100 printf("ERROR: method_getentry failed ret=%d - %s\n", ret, strerror(errno));
105 printf("\tattr_flag=%d ptr=%p\n", a.attr_flag, a.attr_un.au_char);
106 for (s=a.attr_un.au_char; s && *s; s += strlen(s) + 1) {
107 printf("\t'%s'\n", s);
110 free(a.attr_un.au_char);
112 /* try an invalid table */
113 printf("Trying an invalid table\n");
114 ret = methods->method_getentry("ALL", INVALID_STRING, &attribs, &a, 1);
115 if (ret == 0 || errno != ENOSYS) {
116 printf("ERROR: method_getentry expected\n\t%d/%s\n", -1, strerror(ENOSYS));
117 printf("got\t%d/%s\n", ret, strerror(errno));
121 printf("Trying an invalid user\n");
122 ret = methods->method_getentry(INVALID_STRING, "user", &attribs, &a, 1);
123 if (ret == 0 || errno != ENOENT) {
124 printf("ERROR: method_getentry expected\n\t%d/%s\n", -1, strerror(ENOENT));
125 printf("got\t%d/%s\n", ret, strerror(errno));
134 static void test_grouplist(void)
138 char *attribs = "groups";
141 if (!methods->method_getentry) {
142 printf("WARNING: module has no method_getentry\n");
146 printf("\ntesting method_getentry(ALL, group)\n");
148 ret = methods->method_getentry("ALL", "group", &attribs, &a, 1);
150 printf("ERROR: method_getentry failed ret=%d - %s\n", ret, strerror(errno));
155 printf("\tattr_flag=%d ptr=%p\n", a.attr_flag, a.attr_un.au_char);
156 for (s=a.attr_un.au_char; s && *s; s += strlen(s) + 1) {
157 printf("\t'%s'\n", s);
160 free(a.attr_un.au_char);
163 printf("Trying an invalid group\n");
164 ret = methods->method_getentry(INVALID_STRING, "group", &attribs, &a, 1);
165 if (ret == 0 || errno != ENOENT) {
166 printf("ERROR: method_getentry expected\n\t%d/%s\n", -1, strerror(ENOENT));
167 printf("got\t%d/%s\n", ret, strerror(errno));
173 static void show_pwd(struct passwd *pwd)
175 printf("\t%s:%s:%d:%d:%s:%s:%s\n",
185 static void free_pwd(struct passwd *pwd)
188 free(pwd->pw_passwd);
196 static void show_grp(struct group *grp)
200 printf("\t%s:%s:%d: ",
205 if (!grp->gr_mem[0]) {
210 for (i=0; grp->gr_mem[i+1]; i++) {
211 printf("%s, ", grp->gr_mem[i]);
213 printf("%s\n", grp->gr_mem[i]);
216 static void free_grp(struct group *grp)
221 if (!getenv("DONT_FREE_GR_PASSWD")) {
222 free(grp->gr_passwd);
230 for (i=0; grp->gr_mem[i]; i++) {
231 free(grp->gr_mem[i]);
242 static void test_getpwnam(char *name)
246 printf("\ntesting method_getpwnam for user '%s'\n", name);
248 pwd = methods->method_getpwnam(name);
250 if (strcmp(name, INVALID_STRING) == 0) {
251 if (pwd || errno != ENOENT) {
252 printf("ERROR: method_getpwnam expected\n\t%p/%s\n", 0, strerror(ENOENT));
253 printf("got\t%p/%s\n", pwd, strerror(errno));
260 printf("ERROR: method_getpwnam failed - %s\n", strerror(errno));
272 static void test_getpwuid(int uid)
276 printf("\ntesting method_getpwuid for uid %d\n", uid);
278 pwd = methods->method_getpwuid(uid);
280 if (uid == INVALID_INT) {
281 if (pwd || errno != ENOENT) {
282 printf("ERROR: method_getpwuid expected\n\t%p/%s\n", 0, strerror(ENOENT));
283 printf("got\t%p/%s\n", pwd, strerror(errno));
290 printf("ERROR: method_getpwuid failed - %s\n", strerror(errno));
303 static void test_getgrnam(char *name)
307 printf("\ntesting method_getgrnam for group '%s'\n", name);
309 grp = methods->method_getgrnam(name);
310 if (strcmp(name, INVALID_STRING) == 0) {
311 if (grp || errno != ENOENT) {
312 printf("ERROR: method_getgrnam expected\n\t%p/%s\n", 0, strerror(ENOENT));
313 printf("got\t%p/%s\n", grp, strerror(errno));
321 printf("ERROR: method_getgrnam failed - %s\n", strerror(errno));
331 test method_getgracct
333 static void test_getgracct(char *name)
338 printf("\ntesting method_getgracct for group '%s'\n", name);
340 grp = methods->method_getgracct((void *)name, 1);
342 if (strcmp(name, INVALID_STRING) == 0) {
343 if (grp || errno != ENOENT) {
344 printf("ERROR: method_getgracct expected\n\t%p/%s\n", 0, strerror(ENOENT));
345 printf("got\t%p/%s\n", grp, strerror(errno));
352 printf("ERROR: method_getgracct(name, 1) failed - %s\n", strerror(errno));
361 grp = methods->method_getgracct((void *)&gid, 0);
363 printf("ERROR: method_getgracct(gid, 0) failed - %s\n", strerror(errno));
375 static void test_getgrset(char *name)
379 printf("\ntesting method_getgrset for user '%s'\n", name);
381 grps = methods->method_getgrset(name);
383 if (strcmp(name, INVALID_STRING) == 0) {
384 if (grps || errno != ENOENT) {
385 printf("ERROR: method_getgrset expected\n\t%p/%s\n", 0, strerror(ENOENT));
386 printf("got\t%p/%s\n", grps, strerror(errno));
393 printf("ERROR: method_getgrset failed - %s\n", strerror(errno));
398 printf("\t%s\n", grps);
404 test method_normalize
406 static void test_normalize(char *name)
409 char shortname[S_NAMELEN];
411 printf("\ntesting method_normalize for user '%s' (namelen=%d)\n",
414 ret = methods->method_normalize(name, shortname);
416 if (strcmp(name, INVALID_STRING) == 0) {
417 /* there seems to be no defined behaviour for this?! */
422 printf("ERROR: method_normalize failed - %s\n", strerror(errno));
427 printf("\t%s\n", shortname);
433 static void test_getgrgid(int gid)
437 printf("\ntesting method_getgrgid for gid %d\n", gid);
439 grp = methods->method_getgrgid(gid);
440 if (gid == INVALID_INT) {
441 if (grp || errno != ENOENT) {
442 printf("ERROR: method_getgrgid expected\n\t%p/%s\n", 0, strerror(ENOENT));
443 printf("got\t%p/%s\n", grp, strerror(errno));
450 printf("ERROR: method_getgrgid failed - %s\n", strerror(errno));
463 static void forallusers(void (*fn)(char *name))
467 char *attribs = "users";
470 if (!methods->method_getentry) {
473 ret = methods->method_getentry("ALL", "user", &attribs, &a, 1);
477 for (s=a.attr_un.au_char; s && *s; s += strlen(s) + 1) {
481 free(a.attr_un.au_char);
490 static void forallgroups(void (*fn)(char *name))
494 char *attribs = "groups";
497 if (!methods->method_getentry) {
500 ret = methods->method_getentry("ALL", "group", &attribs, &a, 1);
504 for (s=a.attr_un.au_char; s && *s; s += strlen(s) + 1) {
508 free(a.attr_un.au_char);
516 static void foralluids(void (*fn)(int uid))
520 char *attribs = "users";
523 if (!methods->method_getentry) {
526 ret = methods->method_getentry("ALL", "user", &attribs, &a, 1);
530 for (s=a.attr_un.au_char; s && *s; s += strlen(s) + 1) {
532 char *id_attribs = S_ID;
533 ret = methods->method_getentry(s, "user", &id_attribs, &a2, 1);
535 printf("ERROR: failed to get S_ID for '%s' - ret=%d - %s\n",
536 s, ret, strerror(errno));
539 fn(a2.attr_un.au_int);
542 free(a.attr_un.au_char);
550 static void forallgids(void (*fn)(int gid))
554 char *attribs = "groups";
557 if (!methods->method_getentry) {
560 ret = methods->method_getentry("ALL", "group", &attribs, &a, 1);
564 for (s=a.attr_un.au_char; s && *s; s += strlen(s) + 1) {
566 char *id_attribs = S_ID;
567 ret = methods->method_getentry(s, "group", &id_attribs, &a2, 1);
569 printf("ERROR: failed to get S_ID for '%s' - ret=%d - %s\n",
570 s, ret, strerror(errno));
573 fn(a2.attr_un.au_int);
576 free(a.attr_un.au_char);
583 the main test harness
585 static void uess_test(void)
593 if (methods->method_getpwnam) {
594 forallusers(test_getpwnam);
596 if (methods->method_getpwuid) {
597 foralluids(test_getpwuid);
599 if (methods->method_getgrset) {
600 forallusers(test_getgrset);
602 if (methods->method_normalize) {
603 forallusers(test_normalize);
605 if (methods->method_getgrnam) {
606 forallgroups(test_getgrnam);
608 if (methods->method_getgracct) {
609 forallgroups(test_getgracct);
611 if (methods->method_getgrgid) {
612 forallgids(test_getgrgid);
618 return the current size of the heap (in blocks)
620 static unsigned long heap_size(void)
622 struct mallinfo m = mallinfo();
623 return m.ordblks + m.smblks;
627 struct secmethod_desc {
630 struct secmethod_table *methods;
633 extern struct secmethod_desc *_load_secmethod(const char *name);
635 int main(int argc, const char *argv[])
638 struct secmethod_desc *r;
640 unsigned long prev_alloc = 0;
643 printf("Usage: uess_test <MODULE_NAME> <nloops>\n");
650 nloops = atoi(argv[2]);
655 r = _load_secmethod(name);
658 printf("Unable to load module '%s'\n", name);
662 printf("Loaded '%s' with path '%s'\n", r->name, r->module_path);
663 printf("method_version=%d\n", r->methods->method_version);
665 methods = r->methods;
667 for (i=0;i<nloops; i++) {
670 printf("Test loop %d\n", i);
676 if (prev_alloc && hsize > prev_alloc) {
677 printf("ERROR: heap grew by %d blocks. Probable memory leak\n",
684 if (err_count != 0) {
685 printf("WARNING: %d errors detected\n", err_count);