| 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 |
| |
| |
| @@ -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 () |