diff options
Diffstat (limited to 'contrib/netbsd-tests/lib/libc/string/t_strlen.c')
-rw-r--r-- | contrib/netbsd-tests/lib/libc/string/t_strlen.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/contrib/netbsd-tests/lib/libc/string/t_strlen.c b/contrib/netbsd-tests/lib/libc/string/t_strlen.c new file mode 100644 index 0000000..66158fd --- /dev/null +++ b/contrib/netbsd-tests/lib/libc/string/t_strlen.c @@ -0,0 +1,199 @@ +/* $NetBSD: t_strlen.c,v 1.5 2011/07/14 07:33:20 jruoho Exp $ */ + +/* + * Written by J.T. Conklin <jtc@acorntoolworks.com> + * Public domain. + */ + +#include <atf-c.h> +#include <string.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <dlfcn.h> +#include <unistd.h> + +static void write_num(int); + +static void +write_num(int val) +{ + char buf[20]; + int i; + + for (i = sizeof buf; --i >= 0;) { + buf[i] = '0' + val % 10; + val /= 10; + if (val == 0) { + write(2, buf + i, sizeof buf - i); + return; + } + } + write(2, "overflow", 8); +} + +ATF_TC(strlen_basic); +ATF_TC_HEAD(strlen_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test strlen(3) results"); +} + +ATF_TC_BODY(strlen_basic, tc) +{ + /* try to trick the compiler */ + size_t (*strlen_fn)(const char *); + + unsigned int a, t; + size_t len; + char buf[64]; + + struct tab { + const char* val; + size_t len; + }; + + const struct tab tab[] = { + /* + * patterns that check for all combinations of leading and + * trailing unaligned characters (on a 64 bit processor) + */ + + { "", 0 }, + { "a", 1 }, + { "ab", 2 }, + { "abc", 3 }, + { "abcd", 4 }, + { "abcde", 5 }, + { "abcdef", 6 }, + { "abcdefg", 7 }, + { "abcdefgh", 8 }, + { "abcdefghi", 9 }, + { "abcdefghij", 10 }, + { "abcdefghijk", 11 }, + { "abcdefghijkl", 12 }, + { "abcdefghijklm", 13 }, + { "abcdefghijklmn", 14 }, + { "abcdefghijklmno", 15 }, + { "abcdefghijklmnop", 16 }, + { "abcdefghijklmnopq", 17 }, + { "abcdefghijklmnopqr", 18 }, + { "abcdefghijklmnopqrs", 19 }, + { "abcdefghijklmnopqrst", 20 }, + { "abcdefghijklmnopqrstu", 21 }, + { "abcdefghijklmnopqrstuv", 22 }, + { "abcdefghijklmnopqrstuvw", 23 }, + + /* + * patterns that check for the cases where the expression: + * + * ((word - 0x7f7f..7f) & 0x8080..80) + * + * returns non-zero even though there are no zero bytes in + * the word. + */ + + { "" "\xff\xff\xff\xff\xff\xff\xff\xff" "abcdefgh", 16 }, + { "a" "\xff\xff\xff\xff\xff\xff\xff\xff" "bcdefgh", 16 }, + { "ab" "\xff\xff\xff\xff\xff\xff\xff\xff" "cdefgh", 16 }, + { "abc" "\xff\xff\xff\xff\xff\xff\xff\xff" "defgh", 16 }, + { "abcd" "\xff\xff\xff\xff\xff\xff\xff\xff" "efgh", 16 }, + { "abcde" "\xff\xff\xff\xff\xff\xff\xff\xff" "fgh", 16 }, + { "abcdef" "\xff\xff\xff\xff\xff\xff\xff\xff" "gh", 16 }, + { "abcdefg" "\xff\xff\xff\xff\xff\xff\xff\xff" "h", 16 }, + { "abcdefgh" "\xff\xff\xff\xff\xff\xff\xff\xff" "", 16 }, + }; + + /* + * During testing it is useful have the rest of the program + * use a known good version! + */ + strlen_fn = dlsym(dlopen(NULL, RTLD_LAZY), "test_strlen"); + if (!strlen_fn) + strlen_fn = strlen; + + for (a = 0; a < sizeof(long); ++a) { + for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) { + + memcpy(&buf[a], tab[t].val, tab[t].len + 1); + len = strlen_fn(&buf[a]); + + if (len != tab[t].len) { + /* Write error without using printf / strlen */ + write(2, "alignment ", 10); + write_num(a); + write(2, ", test ", 7); + write_num(t); + write(2, ", got len ", 10); + write_num(len); + write(2, ", not ", 6); + write_num(tab[t].len); + write(2, ", for '", 7); + write(2, tab[t].val, tab[t].len); + write(2, "'\n", 2); + atf_tc_fail("See stderr for details"); + } + } + } +} + +ATF_TC(strlen_huge); +ATF_TC_HEAD(strlen_huge, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test strlen(3) with huge strings"); +} + +ATF_TC_BODY(strlen_huge, tc) +{ + long page; + char *str; + size_t i; + + page = sysconf(_SC_PAGESIZE); + ATF_REQUIRE(page >= 0); + + for (i = 1; i < 1000; i = i + 100) { + + str = malloc(i * page + 1); + + if (str == NULL) + continue; + + (void)memset(str, 'x', i * page); + str[i * page] = '\0'; + + ATF_REQUIRE(strlen(str) == i * page); + free(str); + } +} + +ATF_TC(strnlen_basic); +ATF_TC_HEAD(strnlen_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", "A naive test of strnlen(3)"); +} + +ATF_TC_BODY(strnlen_basic, tc) +{ + char buf[1]; + + buf[0] = '\0'; + + ATF_CHECK(strnlen(buf, 000) == 0); + ATF_CHECK(strnlen(buf, 111) == 0); + + ATF_CHECK(strnlen("xxx", 0) == 0); + ATF_CHECK(strnlen("xxx", 1) == 1); + ATF_CHECK(strnlen("xxx", 2) == 2); + ATF_CHECK(strnlen("xxx", 3) == 3); + ATF_CHECK(strnlen("xxx", 9) == 3); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, strlen_basic); + ATF_TP_ADD_TC(tp, strlen_huge); + ATF_TP_ADD_TC(tp, strnlen_basic); + + return atf_no_error(); +} |