about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2018-07-02 12:38:33 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2018-07-02 12:38:33 +0000
commit3cb4106b13aa883f3b704aa4026b78fd36db3756 (patch)
tree7909fa214055aa344a71b515c8781c03db32ab79
parent42c3adc8841167026bb8409cb5e4390a32bff49a (diff)
downloadnsss-3cb4106b13aa883f3b704aa4026b78fd36db3756.tar.gz
nsss-3cb4106b13aa883f3b704aa4026b78fd36db3756.tar.xz
nsss-3cb4106b13aa883f3b704aa4026b78fd36db3756.zip
Add test framework, fix some bugs
-rw-r--r--.gitignore1
-rw-r--r--Makefile12
-rw-r--r--package/deps.mak9
-rw-r--r--package/targets.mak5
-rw-r--r--src/libnsss/nsss_switch_grp_get.c8
-rw-r--r--src/libnsss/nsss_switch_grp_read.c3
-rw-r--r--src/nsssd/nsssd_main.c4
-rw-r--r--src/tests/deps-exe/test-all-fallback4
-rw-r--r--src/tests/deps-exe/test-switch4
-rw-r--r--src/tests/deps-exe/test-unix2
-rwxr-xr-xsrc/tests/test-all-fallback.baseline7
-rw-r--r--src/tests/test-all-fallback.c (renamed from tests/src/test-all.c)11
-rwxr-xr-xsrc/tests/test-switch.baseline7
-rw-r--r--src/tests/test-switch.c83
-rwxr-xr-xsrc/tests/test-switch.wrapper21
-rwxr-xr-xsrc/tests/test-unix.baseline7
-rw-r--r--src/tests/test-unix.c (renamed from tests/src/test-unix.c)11
-rwxr-xr-xtools/run-test.sh22
18 files changed, 207 insertions, 14 deletions
diff --git a/.gitignore b/.gitignore
index a3a3520..85df6b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
 /libnsssd.so.xyzzy
 /nsssd-unix
 /nsssd-nslcd
+/test-*
diff --git a/Makefile b/Makefile
index f755dbf..72677e7 100644
--- a/Makefile
+++ b/Makefile
@@ -61,7 +61,7 @@ ALL_INCLUDES := $(wildcard src/include/$(package)/*.h)
 all: $(ALL_LIBS) $(ALL_BINS) $(ALL_INCLUDES) src/include/pwd.h src/include/grp.h src/include/shadow.h
 
 clean:
-	@exec rm -f $(ALL_LIBS) $(ALL_BINS) $(wildcard src/*/*.o src/*/*.lo) $(EXTRA_TARGETS)
+	@exec rm -f $(ALL_LIBS) $(ALL_BINS) $(wildcard src/*/*.o src/*/*.lo) $(TEST_BINS) $(EXTRA_TARGETS)
 
 distclean: clean
 	@exec rm -f config.mak src/include/$(package)/config.h
@@ -90,6 +90,12 @@ install-lib: $(STATIC_LIBS:lib%.a.xyzzy=$(DESTDIR)$(libdir)/lib%.a)
 install-include: $(ALL_INCLUDES:src/include/$(package)/%.h=$(DESTDIR)$(includedir)/$(package)/%.h) $(DESTDIR)$(includedir)/pwd.h $(DESTDIR)$(includedir)/grp.h $(DESTDIR)$(includedir)/shadow.h
 install-data: $(ALL_DATA:src/etc/%=$(DESTDIR)$(datadir)/%)
 
+tests: $(TEST_BINS)
+
+check: tests
+	@for i in $(TEST_BINS) ; do ./tools/run-test.sh $$i || exit 1 ; done
+
+
 ifneq ($(exthome),)
 
 $(DESTDIR)$(exthome): $(DESTDIR)$(home)
@@ -145,7 +151,7 @@ $(DESTDIR)$(includedir)/shadow.h: src/include/shadow.h
 %.lo: %.c
 	exec $(REALCC) $(CPPFLAGS_ALL) $(CFLAGS_ALL) $(CFLAGS_SHARED) -c -o $@ $<
 
-$(ALL_BINS):
+$(ALL_BINS) $(TEST_BINS):
 	exec $(REALCC) -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL) $(LDFLAGS_NOSHARED) $^ $(EXTRA_LIBS) $(LDLIBS)
 
 lib%.a.xyzzy:
@@ -155,6 +161,6 @@ lib%.a.xyzzy:
 lib%.so.xyzzy:
 	exec $(REALCC) -o $@ $(CFLAGS_ALL) $(CFLAGS_SHARED) $(LDFLAGS_ALL) $(LDFLAGS_SHARED) -Wl,-soname,$(patsubst lib%.so.xyzzy,lib%.so.$(version_M),$@) $^ $(EXTRA_LIBS) $(LDLIBS)
 
-.PHONY: it all clean distclean tgz strip install install-dynlib install-bin install-lib install-include install-data
+.PHONY: it all clean distclean tgz strip install install-dynlib install-bin install-lib install-include install-data tests check
 
 .DELETE_ON_ERROR:
diff --git a/package/deps.mak b/package/deps.mak
index db56346..7182106 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -139,6 +139,9 @@ src/nsssd/nsssd-nslcd.o src/nsssd/nsssd-nslcd.lo: src/nsssd/nsssd-nslcd.c src/in
 src/nsssd/nsssd-unix.o src/nsssd/nsssd-unix.lo: src/nsssd/nsssd-unix.c src/include/nsss/grp-unix.h src/include/nsss/nsssd.h src/include/nsss/pwd-unix.h src/include/nsss/shadow-unix.h
 src/nsssd/nsssd_convert.o src/nsssd/nsssd_convert.lo: src/nsssd/nsssd_convert.c src/include/nsss/grp-def.h src/include/nsss/nsssd.h src/include/nsss/pwd-def.h src/include/nsss/shadow-def.h
 src/nsssd/nsssd_main.o src/nsssd/nsssd_main.lo: src/nsssd/nsssd_main.c src/include/nsss/grp-def.h src/include/nsss/nsss-switch.h src/include/nsss/nsssd.h src/include/nsss/pwd-def.h src/include/nsss/shadow-def.h
+src/tests/test-all-fallback.o src/tests/test-all-fallback.lo: src/tests/test-all-fallback.c src/include/nsss/grp-def.h src/include/nsss/nsss-all.h src/include/nsss/pwd-def.h
+src/tests/test-switch.o src/tests/test-switch.lo: src/tests/test-switch.c src/include/nsss/grp-def.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-def.h
+src/tests/test-unix.o src/tests/test-unix.lo: src/tests/test-unix.c src/include/nsss/grp-def.h src/include/nsss/nsss-unix.h src/include/nsss/pwd-def.h
 
 ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
 libnsss.a.xyzzy: src/libnsss/nsss_all_endgrent.o src/libnsss/nsss_all_endpwent.o src/libnsss/nsss_all_endspent.o src/libnsss/nsss_all_errno.o src/libnsss/nsss_all_getgrent.o src/libnsss/nsss_all_getgrent_r.o src/libnsss/nsss_all_getgrgid.o src/libnsss/nsss_all_getgrgid_r.o src/libnsss/nsss_all_getgrnam.o src/libnsss/nsss_all_getgrnam_r.o src/libnsss/nsss_all_getpwent.o src/libnsss/nsss_all_getpwent_r.o src/libnsss/nsss_all_getpwnam.o src/libnsss/nsss_all_getpwnam_r.o src/libnsss/nsss_all_getpwuid.o src/libnsss/nsss_all_getpwuid_r.o src/libnsss/nsss_all_getspent.o src/libnsss/nsss_all_getspent_r.o src/libnsss/nsss_all_getspnam.o src/libnsss/nsss_all_getspnam_r.o src/libnsss/nsss_all_setgrent.o src/libnsss/nsss_all_setpwent.o src/libnsss/nsss_all_setspent.o src/libnsss/nsss_grp_copy.o src/libnsss/nsss_grp_here.o src/libnsss/nsss_pwd_copy.o src/libnsss/nsss_pwd_here.o src/libnsss/nsss_shadow_copy.o src/libnsss/nsss_shadow_here.o src/libnsss/nsss_switch_end.o src/libnsss/nsss_switch_endgrent.o src/libnsss/nsss_switch_endpwent.o src/libnsss/nsss_switch_endspent.o src/libnsss/nsss_switch_getgrent.o src/libnsss/nsss_switch_getgrent_r.o src/libnsss/nsss_switch_getgrgid.o src/libnsss/nsss_switch_getgrgid_r.o src/libnsss/nsss_switch_getgrnam.o src/libnsss/nsss_switch_getgrnam_r.o src/libnsss/nsss_switch_getpwent.o src/libnsss/nsss_switch_getpwent_r.o src/libnsss/nsss_switch_getpwnam.o src/libnsss/nsss_switch_getpwnam_r.o src/libnsss/nsss_switch_getpwuid.o src/libnsss/nsss_switch_getpwuid_r.o src/libnsss/nsss_switch_getspent.o src/libnsss/nsss_switch_getspent_r.o src/libnsss/nsss_switch_getspnam.o src/libnsss/nsss_switch_getspnam_r.o src/libnsss/nsss_switch_grp_end.o src/libnsss/nsss_switch_grp_get.o src/libnsss/nsss_switch_grp_getbygid.o src/libnsss/nsss_switch_grp_getbyname.o src/libnsss/nsss_switch_grp_read.o src/libnsss/nsss_switch_grp_rewind.o src/libnsss/nsss_switch_here.o src/libnsss/nsss_switch_op.o src/libnsss/nsss_switch_pwd_end.o src/libnsss/nsss_switch_pwd_get.o src/libnsss/nsss_switch_pwd_getbyname.o src/libnsss/nsss_switch_pwd_getbyuid.o src/libnsss/nsss_switch_pwd_read.o src/libnsss/nsss_switch_pwd_rewind.o src/libnsss/nsss_switch_setgrent.o src/libnsss/nsss_switch_setpwent.o src/libnsss/nsss_switch_setspent.o src/libnsss/nsss_switch_shadow_end.o src/libnsss/nsss_switch_shadow_get.o src/libnsss/nsss_switch_shadow_getbyname.o src/libnsss/nsss_switch_shadow_read.o src/libnsss/nsss_switch_shadow_rewind.o src/libnsss/nsss_switch_start.o src/libnsss/nsss_unix_end.o src/libnsss/nsss_unix_endgrent.o src/libnsss/nsss_unix_endpwent.o src/libnsss/nsss_unix_endspent.o src/libnsss/nsss_unix_field.o src/libnsss/nsss_unix_getgrent.o src/libnsss/nsss_unix_getgrent_r.o src/libnsss/nsss_unix_getgrgid.o src/libnsss/nsss_unix_getgrgid_r.o src/libnsss/nsss_unix_getgrnam.o src/libnsss/nsss_unix_getgrnam_r.o src/libnsss/nsss_unix_getpwent.o src/libnsss/nsss_unix_getpwent_r.o src/libnsss/nsss_unix_getpwnam.o src/libnsss/nsss_unix_getpwnam_r.o src/libnsss/nsss_unix_getpwuid.o src/libnsss/nsss_unix_getpwuid_r.o src/libnsss/nsss_unix_getspent.o src/libnsss/nsss_unix_getspent_r.o src/libnsss/nsss_unix_getspnam.o src/libnsss/nsss_unix_getspnam_r.o src/libnsss/nsss_unix_grp_get.o src/libnsss/nsss_unix_grp_getbygid.o src/libnsss/nsss_unix_grp_getbyname.o src/libnsss/nsss_unix_grp_here.o src/libnsss/nsss_unix_maybe_start.o src/libnsss/nsss_unix_pwd_get.o src/libnsss/nsss_unix_pwd_getbyname.o src/libnsss/nsss_unix_pwd_getbyuid.o src/libnsss/nsss_unix_pwd_here.o src/libnsss/nsss_unix_rewind.o src/libnsss/nsss_unix_setgrent.o src/libnsss/nsss_unix_setpwent.o src/libnsss/nsss_unix_setspent.o src/libnsss/nsss_unix_shadow_get.o src/libnsss/nsss_unix_shadow_getbyname.o src/libnsss/nsss_unix_shadow_here.o src/libnsss/nsss_unix_start.o
@@ -158,3 +161,9 @@ nsssd-nslcd: EXTRA_LIBS :=
 nsssd-nslcd: src/nsssd/nsssd-nslcd.o ${LIBNSSSD} -lskarnet
 nsssd-unix: EXTRA_LIBS :=
 nsssd-unix: src/nsssd/nsssd-unix.o ${LIBNSSS} ${LIBNSSSD} -lskarnet
+test-all-fallback: EXTRA_LIBS := ${SOCKET_LIB} ${TAINNOW_LIB}
+test-all-fallback: src/tests/test-all-fallback.o ${LIBNSSS} -lskarnet
+test-switch: EXTRA_LIBS := ${SOCKET_LIB} ${TAINNOW_LIB}
+test-switch: src/tests/test-switch.o ${LIBNSSS} -lskarnet
+test-unix: EXTRA_LIBS :=
+test-unix: src/tests/test-unix.o ${LIBNSSS} -lskarnet
diff --git a/package/targets.mak b/package/targets.mak
index 2dd3b81..e58f396 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -4,4 +4,9 @@ nsssd-nslcd
 
 LIBEXEC_TARGETS :=
 
+TEST_BINS := \
+test-switch \
+test-unix \
+test-all-fallback
+
 LIB_DEFS := NSSS=nsss NSSSD=nsssd
diff --git a/src/libnsss/nsss_switch_grp_get.c b/src/libnsss/nsss_switch_grp_get.c
index 4cfb67e..65da4e3 100644
--- a/src/libnsss/nsss_switch_grp_get.c
+++ b/src/libnsss/nsss_switch_grp_get.c
@@ -8,10 +8,10 @@
 
 int nsss_switch_grp_get (nsss_switch_t *a, struct group *gr, stralloc *sa, genalloc *ga, tain_t const *deadline, tain_t *stamp)
 {
-  char c = NSSS_SWITCH_GRP_GET ;
-  if (!ipc_timed_send(buffer_fd(&a->b), &c, 1, deadline, stamp)) return 0 ;
-  if (!buffer_timed_get(&a->b, &c, 1, deadline, stamp)) return 0 ;
-  if ((unsigned char)c == 255) return 0 ;
+  unsigned char c = NSSS_SWITCH_GRP_GET ;
+  if (!ipc_timed_send(buffer_fd(&a->b), (char *)&c, 1, deadline, stamp)) return 0 ;
+  if (!buffer_timed_get(&a->b, (char *)&c, 1, deadline, stamp)) return 0 ;
+  if (c == 255) return 0 ;
   if (c) return (errno = c, 0) ;
   return nsss_switch_grp_read(&a->b, gr, sa, ga, deadline, stamp) ;
 }
diff --git a/src/libnsss/nsss_switch_grp_read.c b/src/libnsss/nsss_switch_grp_read.c
index 6152484..74b981b 100644
--- a/src/libnsss/nsss_switch_grp_read.c
+++ b/src/libnsss/nsss_switch_grp_read.c
@@ -1,5 +1,6 @@
 /* ISC license. */
 
+
 #include <stdint.h>
 #include <string.h>
 #include <errno.h>
@@ -33,7 +34,7 @@ int nsss_switch_grp_read (buffer *b, struct group *gr, stralloc *sa, genalloc *g
   uint32_unpack_big(buf, &x) ; grtmp.gr_gid = x ;
   uint32_unpack_big(buf + 4, &total) ;
   uint32_unpack_big(buf + 8, &n) ;
-  if (n >= 0x30000000u) return (errno = EPROTO, 0) ;
+  if (total < 2 || n >= 0x30000000u) return (errno = EPROTO, 0) ;
   if (!stralloc_readyplus(sa, total)) return 0 ;
   if (!genalloc_readyplus(char *, ga, n+1)) return 0 ;
   if (!buffer_timed_get(b, sa->s + sa->len, total, deadline, stamp)) return 0 ;
diff --git a/src/nsssd/nsssd_main.c b/src/nsssd/nsssd_main.c
index 8673df4..585b995 100644
--- a/src/nsssd/nsssd_main.c
+++ b/src/nsssd/nsssd_main.c
@@ -92,8 +92,8 @@ static inline void print_gr (struct group const *gr)
   if (len > 0xffffffffu || n > 0x30000000u) { answer(ENAMETOOLONG) ; return ; }
   put1("", 1) ;
   uint32_pack_big(pack, gr->gr_gid) ;
-  uint32_pack_big(pack, len) ;
-  uint32_pack_big(pack, n) ;
+  uint32_pack_big(pack + 4, len) ;
+  uint32_pack_big(pack + 8, n) ;
   put1(pack, 12) ;
   put1(gr->gr_name, namelen) ;
   put1(gr->gr_passwd, passwdlen) ;
diff --git a/src/tests/deps-exe/test-all-fallback b/src/tests/deps-exe/test-all-fallback
new file mode 100644
index 0000000..704fc90
--- /dev/null
+++ b/src/tests/deps-exe/test-all-fallback
@@ -0,0 +1,4 @@
+${LIBNSSS}
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/tests/deps-exe/test-switch b/src/tests/deps-exe/test-switch
new file mode 100644
index 0000000..704fc90
--- /dev/null
+++ b/src/tests/deps-exe/test-switch
@@ -0,0 +1,4 @@
+${LIBNSSS}
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/tests/deps-exe/test-unix b/src/tests/deps-exe/test-unix
new file mode 100644
index 0000000..bbe01a8
--- /dev/null
+++ b/src/tests/deps-exe/test-unix
@@ -0,0 +1,2 @@
+${LIBNSSS}
+-lskarnet
diff --git a/src/tests/test-all-fallback.baseline b/src/tests/test-all-fallback.baseline
new file mode 100755
index 0000000..31fba7e
--- /dev/null
+++ b/src/tests/test-all-fallback.baseline
@@ -0,0 +1,7 @@
+#!/bin/sh -e
+
+cat /etc/passwd
+echo
+id -u root
+echo
+cat /etc/group
diff --git a/tests/src/test-all.c b/src/tests/test-all-fallback.c
index 147868a..666d2f7 100644
--- a/tests/src/test-all.c
+++ b/src/tests/test-all-fallback.c
@@ -2,12 +2,15 @@
 
 #include <errno.h>
 #include <skalibs/buffer.h>
+#include <skalibs/strerr2.h>
 #include <skalibs/lolstdio.h>
-#include <nsss/pwd.h>
+#include <nsss/pwd-def.h>
+#include <nsss/grp-def.h>
 #include <nsss/nsss-all.h>
 
 int main (void)
 {
+  PROG = "test-all-fallback" ;
   for (;;)
   {
     struct passwd *pw ;
@@ -19,9 +22,13 @@ int main (void)
   if (errno)
     strerr_diefu1sys(111, "nsss_all_getpwent") ;
   nsss_all_endpwent() ;
-  buffer_flush(buffer_1) ;
   lolprintf("\n") ;
 
+  {
+    struct passwd *pw = nsss_all_getpwnam("root") ;
+    lolprintf("%u\n\n", (unsigned int)pw->pw_uid) ;
+  }
+
   for (;;)
   {
     struct group *gr ;
diff --git a/src/tests/test-switch.baseline b/src/tests/test-switch.baseline
new file mode 100755
index 0000000..31fba7e
--- /dev/null
+++ b/src/tests/test-switch.baseline
@@ -0,0 +1,7 @@
+#!/bin/sh -e
+
+cat /etc/passwd
+echo
+id -u root
+echo
+cat /etc/group
diff --git a/src/tests/test-switch.c b/src/tests/test-switch.c
new file mode 100644
index 0000000..0133777
--- /dev/null
+++ b/src/tests/test-switch.c
@@ -0,0 +1,83 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/buffer.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/lolstdio.h>
+#include <skalibs/tai.h>
+#include <nsss/pwd-def.h>
+#include <nsss/grp-def.h>
+#include <nsss/nsss-switch.h>
+
+#define S "./.test-switch-socket"
+
+int main (void)
+{
+  nsss_switch_t a = NSSS_SWITCH_ZERO ;
+  stralloc sa = STRALLOC_ZERO ;
+  genalloc ga = GENALLOC_ZERO ;
+  tain_t deadline ;
+  PROG = "test-switch" ;
+  tain_now_g() ;
+  tain_from_millisecs(&deadline, 10000) ;
+  tain_add_g(&deadline, &deadline) ;
+
+  if (!nsss_switch_start_g(&a, NSSS_SWITCH_PWD, S, &deadline))
+    strerr_diefu1sys(111, "nsss_switch_start") ;
+
+  for (;;)
+  {
+    struct passwd pw ;
+    errno = 0 ;
+    if (!nsss_switch_pwd_get_g(&a, &pw, &sa, &deadline)) break ;
+    lolprintf("%s:%s:%d:%d:%s:%s:%s\n", pw.pw_name, pw.pw_passwd, (int)pw.pw_uid, (int)pw.pw_gid, pw.pw_gecos, pw.pw_dir, pw.pw_shell) ;
+    sa.len = 0 ;
+  }
+  if (errno)
+    strerr_diefu1sys(111, "nsss_switch_pwd_get") ;
+  if (!nsss_switch_pwd_end_g(&a, &deadline))
+    strerr_diefu1sys(111, "nsss_switch_pwd_end") ;
+  lolprintf("\n") ;
+
+  {
+    struct passwd pw ;
+    if (!nsss_switch_pwd_getbyname_g(&a, &pw, &sa, "root", &deadline))
+      strerr_diefu1sys(111, "nsss_switch_pwd_getbyname") ;
+    lolprintf("%u\n\n", (unsigned int)pw.pw_uid) ;
+    sa.len = 0 ;
+  }
+
+  if (!nsss_switch_start_g(&a, NSSS_SWITCH_GRP, S, &deadline))
+    strerr_diefu1sys(111, "nsss_switch_start") ;
+  nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+  buffer_flush(buffer_1) ;
+
+  for (;;)
+  {
+    struct group gr ;
+    char **p ;
+    errno = 0 ;
+    if (!nsss_switch_grp_get_g(&a, &gr, &sa, &ga, &deadline)) break ;
+    p = gr.gr_mem ;
+    lolprintf("%s:%s:%d:", gr.gr_name, gr.gr_passwd, (int)gr.gr_gid) ;
+    buffer_flush(buffer_1) ;
+    if (*p)
+    {
+      while (*p) lolprintf("%s,", *p++) ;
+      buffer_unput(buffer_1, 1) ;
+    }
+    buffer_put(buffer_1, "\n", 1) ;
+    sa.len = 0 ;
+    genalloc_setlen(char *, &ga, 0) ;
+  }
+  if (errno)
+    strerr_diefu1sys(111, "nsss_switch_grp_get") ;
+  if (!nsss_switch_grp_end_g(&a, &deadline))
+    strerr_diefu1sys(111, "nsss_switch_grp_end") ;
+  nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+
+  buffer_flush(buffer_1) ;  
+  return 0 ;
+}
diff --git a/src/tests/test-switch.wrapper b/src/tests/test-switch.wrapper
new file mode 100755
index 0000000..5117400
--- /dev/null
+++ b/src/tests/test-switch.wrapper
@@ -0,0 +1,21 @@
+#!/bin/sh -e
+
+S=./.test-switch-socket
+F=./.test-switch-fifo
+
+pid=0
+
+cleanup () {
+  kill $pid
+  rm -f $S
+}
+
+mkfifo $F
+head -n 1 < $F >/dev/null &
+pid=$!
+s6-ipcserver -1 -- $S ./nsssd-unix > $F &
+wait $pid
+pid=$!
+rm -f $F
+trap cleanup TERM INT EXIT
+./test-switch
diff --git a/src/tests/test-unix.baseline b/src/tests/test-unix.baseline
new file mode 100755
index 0000000..31fba7e
--- /dev/null
+++ b/src/tests/test-unix.baseline
@@ -0,0 +1,7 @@
+#!/bin/sh -e
+
+cat /etc/passwd
+echo
+id -u root
+echo
+cat /etc/group
diff --git a/tests/src/test-unix.c b/src/tests/test-unix.c
index e62fa01..98b6ae8 100644
--- a/tests/src/test-unix.c
+++ b/src/tests/test-unix.c
@@ -2,12 +2,15 @@
 
 #include <errno.h>
 #include <skalibs/buffer.h>
+#include <skalibs/strerr2.h>
 #include <skalibs/lolstdio.h>
-#include <nsss/pwd.h>
+#include <nsss/pwd-def.h>
+#include <nsss/grp-def.h>
 #include <nsss/nsss-unix.h>
 
 int main (void)
 {
+  PROG = "test-unix" ;
   for (;;)
   {
     struct passwd *pw ;
@@ -19,9 +22,13 @@ int main (void)
   if (errno)
     strerr_diefu1sys(111, "nsss_unix_getpwent") ;
   nsss_unix_endpwent() ;
-  buffer_flush(buffer_1) ;
   lolprintf("\n") ;
 
+  {
+    struct passwd *pw = nsss_unix_getpwnam("root") ;
+    lolprintf("%u\n\n", (unsigned int)pw->pw_uid) ;
+  }
+
   for (;;)
   {
     struct group *gr ;
diff --git a/tools/run-test.sh b/tools/run-test.sh
new file mode 100755
index 0000000..d651b09
--- /dev/null
+++ b/tools/run-test.sh
@@ -0,0 +1,22 @@
+#!/bin/sh -e
+
+prog="$1"
+
+if test -x "./src/tests/${prog}.wrapper" ; then
+  cmd="./src/tests/${prog}.wrapper $prog"
+else
+  cmd="./$prog"
+fi
+
+if test -r "./src/tests/${prog}.expected" ; then
+  cp -f "./src/tests/${prog}.expected" "./${prog}.expected"
+elif test -x "./src/tests/${prog}.baseline" ; then
+  "./src/tests/${prog}.baseline" > "./${prog}.expected"
+else
+  echo "run-test.sh: fatal: missing baseline for $prog" 1>&2 ; exit 100
+fi
+
+$cmd | diff "./${prog}.expected" -
+
+rm -f "./${prog}.expected"
+echo "run-test.sh: info: $prog: pass" 1>&2