You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
6.2 KiB
239 lines
6.2 KiB
commit 0897c551c0a098020f145885de06a5c10e5cc96b |
|
Author: Carlos O'Donell <carlos@systemhalted.org> |
|
Date: Wed Jan 21 10:08:18 2015 -0500 |
|
|
|
tst-getpw: Rewrite. |
|
|
|
The test is rewritten to look for the testable conditions and |
|
exit once they are all detected. This prevents the test from |
|
iterating over 2000 UIDs and looking up each one. It speeds up |
|
the test and prevents it from failing if the system under test |
|
has an NSS-based passwd that is slower than the test timeout. |
|
|
|
See: |
|
https://sourceware.org/ml/libc-alpha/2015-01/msg00394.html |
|
|
|
diff --git a/pwd/tst-getpw.c b/pwd/tst-getpw.c |
|
index 059c9e0..e3e101b 100644 |
|
--- a/pwd/tst-getpw.c |
|
+++ b/pwd/tst-getpw.c |
|
@@ -1,4 +1,4 @@ |
|
-/* Copyright (C) 1999 Free Software Foundation, Inc. |
|
+/* Copyright (C) 1999-2016 Free Software Foundation, Inc. |
|
This file is part of the GNU C Library. |
|
|
|
The GNU C Library is free software; you can redistribute it and/or |
|
@@ -15,26 +15,100 @@ |
|
License along with the GNU C Library; if not, see |
|
<http://www.gnu.org/licenses/>. */ |
|
|
|
+#include <stdio.h> |
|
#include <pwd.h> |
|
+#include <errno.h> |
|
+#include <stdbool.h> |
|
+ |
|
+/* We want to test getpw by calling it with a uid that does |
|
+ exist and one that doesn't exist. We track if we've met those |
|
+ conditions and exit. We also track if we've failed due to lack |
|
+ of memory. That constitutes all of the standard failure cases. */ |
|
+bool seen_hit; |
|
+bool seen_miss; |
|
+bool seen_oom; |
|
+ |
|
+/* How many errors we've had while running the test. */ |
|
+int errors; |
|
|
|
static void |
|
check (uid_t uid) |
|
{ |
|
+ int ret; |
|
char buf[1024]; |
|
|
|
- (void) getpw (uid, buf); |
|
+ ret = getpw (uid, buf); |
|
+ |
|
+ /* Successfully read a password line. */ |
|
+ if (ret == 0 && !seen_hit) |
|
+ { |
|
+ printf ("PASS: Read a password line given a uid.\n"); |
|
+ seen_hit = true; |
|
+ } |
|
+ |
|
+ /* Failed to read a password line. Why? */ |
|
+ if (ret == -1) |
|
+ { |
|
+ /* No entry? Technically the errno could be any number |
|
+ of values including ESRCH, EBADP or EPERM depending |
|
+ on the quality of the nss module that implements the |
|
+ underlying lookup. It should be 0 for getpw.*/ |
|
+ if (errno == 0 && !seen_miss) |
|
+ { |
|
+ printf ("PASS: Found an invalid uid.\n"); |
|
+ seen_miss = true; |
|
+ return; |
|
+ } |
|
+ |
|
+ /* Out of memory? */ |
|
+ if (errno == ENOMEM && !seen_oom) |
|
+ { |
|
+ printf ("FAIL: Failed with ENOMEM.\n"); |
|
+ seen_oom = true; |
|
+ errors++; |
|
+ } |
|
+ |
|
+ /* We don't expect any other values for errno. */ |
|
+ if (errno != ENOMEM && errno != 0) |
|
+ errors++; |
|
+ } |
|
} |
|
|
|
-int |
|
-main (void) |
|
+static int |
|
+do_test (void) |
|
{ |
|
+ int ret; |
|
uid_t uid; |
|
|
|
- /* Just call it a different number of times the range should be |
|
- large enough to find some existing and some non existing uids. */ |
|
+ /* Should return -1 and set errnot to EINVAL. */ |
|
+ ret = getpw (0, NULL); |
|
+ if (ret == -1 && errno == EINVAL) |
|
+ { |
|
+ printf ("PASS: NULL buffer returns -1 and sets errno to EINVAL.\n"); |
|
+ } |
|
+ else |
|
+ { |
|
+ printf ("FAIL: NULL buffer did not return -1 or set errno to EINVAL.\n"); |
|
+ errors++; |
|
+ } |
|
+ |
|
+ /* Look for one matching uid, one non-found uid and then stop. |
|
+ Set an upper limit at the 16-bit UID mark; no need to go farther. */ |
|
+ for (uid = 0; uid < ((uid_t) 65535); ++uid) |
|
+ { |
|
+ check (uid); |
|
+ if (seen_miss && seen_hit) |
|
+ break; |
|
+ } |
|
|
|
- for (uid = 0; uid < 2000; ++uid) |
|
- check (uid); |
|
+ if (!seen_hit) |
|
+ printf ("FAIL: Did not read even one password line given a uid.\n"); |
|
|
|
- return 0; |
|
+ if (!seen_miss) |
|
+ printf ("FAIL: Did not find even one invalid uid.\n"); |
|
+ |
|
+ return errors; |
|
} |
|
+ |
|
+#define TEST_FUNCTION do_test () |
|
+#include "../test-skeleton.c" |
|
License along with the GNU C Library; if not, see |
|
<http://www.gnu.org/licenses/>. */ |
|
|
|
+#include <stdio.h> |
|
#include <pwd.h> |
|
+#include <errno.h> |
|
+#include <stdbool.h> |
|
+ |
|
+/* We want to test getpw by calling it with a uid that does |
|
+ exist and one that doesn't exist. We track if we've met those |
|
+ conditions and exit. We also track if we've failed due to lack |
|
+ of memory. That constitutes all of the standard failure cases. */ |
|
+bool seen_hit; |
|
+bool seen_miss; |
|
+bool seen_oom; |
|
+ |
|
+/* How many errors we've had while running the test. */ |
|
+int errors; |
|
|
|
static void |
|
check (uid_t uid) |
|
{ |
|
+ int ret; |
|
char buf[1024]; |
|
|
|
- (void) getpw (uid, buf); |
|
+ ret = getpw (uid, buf); |
|
+ |
|
+ /* Successfully read a password line. */ |
|
+ if (ret == 0 && !seen_hit) |
|
+ { |
|
+ printf ("PASS: Read a password line given a uid.\n"); |
|
+ seen_hit = true; |
|
+ } |
|
+ |
|
+ /* Failed to read a password line. Why? */ |
|
+ if (ret == -1) |
|
+ { |
|
+ /* No entry? Technically the errno could be any number |
|
+ of values including ESRCH, EBADP or EPERM depending |
|
+ on the quality of the nss module that implements the |
|
+ underlying lookup. It should be 0 for getpw.*/ |
|
+ if (errno == 0 && !seen_miss) |
|
+ { |
|
+ printf ("PASS: Found an invalid uid.\n"); |
|
+ seen_miss = true; |
|
+ return; |
|
+ } |
|
+ |
|
+ /* Out of memory? */ |
|
+ if (errno == ENOMEM && !seen_oom) |
|
+ { |
|
+ printf ("FAIL: Failed with ENOMEM.\n"); |
|
+ seen_oom = true; |
|
+ errors++; |
|
+ } |
|
+ |
|
+ /* We don't expect any other values for errno. */ |
|
+ if (errno != ENOMEM && errno != 0) |
|
+ errors++; |
|
+ } |
|
} |
|
|
|
static int |
|
do_test (void) |
|
{ |
|
+ int ret; |
|
uid_t uid; |
|
|
|
- /* Just call it a different number of times the range should be |
|
- large enough to find some existing and some non existing uids. */ |
|
+ /* Should return -1 and set errnot to EINVAL. */ |
|
+ ret = getpw (0, NULL); |
|
+ if (ret == -1 && errno == EINVAL) |
|
+ { |
|
+ printf ("PASS: NULL buffer returns -1 and sets errno to EINVAL.\n"); |
|
+ } |
|
+ else |
|
+ { |
|
+ printf ("FAIL: NULL buffer did not return -1 or set errno to EINVAL.\n"); |
|
+ errors++; |
|
+ } |
|
+ |
|
+ /* Look for one matching uid, one non-found uid and then stop. |
|
+ Set an upper limit at the 16-bit UID mark; no need to go farther. */ |
|
+ for (uid = 0; uid < ((uid_t) 65535); ++uid) |
|
+ { |
|
+ check (uid); |
|
+ if (seen_miss && seen_hit) |
|
+ break; |
|
+ } |
|
+ |
|
+ if (!seen_hit) |
|
+ printf ("FAIL: Did not read even one password line given a uid.\n"); |
|
|
|
- for (uid = 0; uid < 2000; ++uid) |
|
- check (uid); |
|
+ if (!seen_miss) |
|
+ printf ("FAIL: Did not find even one invalid uid.\n"); |
|
|
|
- return 0; |
|
+ return errors; |
|
} |
|
|
|
#define TEST_FUNCTION do_test ()
|
|
|