diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/Makefile | 31 | ||||
| -rw-r--r-- | tests/test_alloc.c | 159 | ||||
| -rw-r--r-- | tests/test_atoi.c | 58 | ||||
| -rw-r--r-- | tests/test_case.c | 36 | ||||
| -rw-r--r-- | tests/test_cmp.c | 279 | ||||
| -rw-r--r-- | tests/test_is.c | 43 | ||||
| -rw-r--r-- | tests/test_mem.c | 296 | ||||
| -rw-r--r-- | tests/test_search.c | 285 | ||||
| -rw-r--r-- | tests/test_strl.c | 252 | ||||
| -rw-r--r-- | tests/test_strlen.c | 109 |
10 files changed, 1548 insertions, 0 deletions
diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..319fa22 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,31 @@ +CC = cc +CFLAGS = +LIB = ../libft.a + +TESTS = test_strlen test_is test_mem test_cmp test_case test_strl test_search \ + test_atoi test_alloc + +all: $(TESTS) + @for t in $(TESTS); do \ + echo "--- Running $$t ---"; \ + ./$$t; \ + done + +test_%: test_%.c $(LIB) + $(CC) $(CFLAGS) -o $@ $< $(LIB) + +# Tests comparing against BSD functions (strlcpy, strlcat, strnstr) +# need -lbsd since these are not part of glibc by default. +test_strl: test_strl.c $(LIB) + $(CC) $(CFLAGS) -o $@ $< $(LIB) -lbsd + +test_search: test_search.c $(LIB) + $(CC) $(CFLAGS) -o $@ $< $(LIB) -lbsd + +$(LIB): + $(MAKE) -C .. + +clean: + rm -f $(TESTS) + +.PHONY: all clean diff --git a/tests/test_alloc.c b/tests/test_alloc.c new file mode 100644 index 0000000..191fbbb --- /dev/null +++ b/tests/test_alloc.c @@ -0,0 +1,159 @@ +#include "../libft.h" +#include "test_utils.h" + +static void +_s_ft_strdup_null (void) +{ + _s_sink = (size_t)ft_strdup (NULL); +} +static void +_s_libc_strdup_null (void) +{ + _s_sink = (size_t)strdup (NULL); +} + +/* ====================================== + * calloc + * ====================================== */ + +static void +_s_test_calloc (void) +{ + int i; + char label[64]; + + printf ("-- calloc --\n"); + + /* zeroed memory */ + { + char *ft_p = ft_calloc (100, 1); + char *libc_p = calloc (100, 1); + _s_check ("zeroed", ft_p && libc_p && memcmp (ft_p, libc_p, 100) == 0); + free (ft_p); + free (libc_p); + } + + /* nmemb=0 */ + { + void *p = ft_calloc (0, 10); + _s_check ("nmemb=0 not NULL", p != NULL); + free (p); + } + + /* size=0 */ + { + void *p = ft_calloc (10, 0); + _s_check ("size=0 not NULL", p != NULL); + free (p); + } + + /* overflow protection */ + { + void *p = ft_calloc ((size_t)-1, 2); + _s_check ("overflow returns NULL", p == NULL); + } + + /* single byte */ + { + unsigned char *p = ft_calloc (1, 1); + _s_check ("single byte zeroed", p && *p == 0); + free (p); + } + + /* randomized: check all bytes are zero */ + srand (time (NULL)); + for (i = 0; i < 50; i++) + { + size_t nmemb = rand () % 500 + 1; + size_t size = rand () % 50 + 1; + unsigned char *ft_p = ft_calloc (nmemb, size); + unsigned char *libc_p = calloc (nmemb, size); + int ok = 1; + size_t j; + if (!ft_p || !libc_p) + { + ok = 0; + } + else + { + for (j = 0; j < nmemb * size; j++) + { + if (ft_p[j] != 0) + { + ok = 0; + break; + } + } + } + snprintf (label, sizeof (label), "random nmemb=%zu size=%zu", nmemb, + size); + _s_check (label, ok); + free (ft_p); + free (libc_p); + } +} + +/* ====================================== + * strdup + * ====================================== */ + +static void +_s_test_strdup (void) +{ + int i; + char label[64]; + + printf ("-- strdup --\n"); + + /* NULL */ + _s_check_both_crash ("strdup NULL", _s_ft_strdup_null, _s_libc_strdup_null); + + /* empty string */ + { + char *p = ft_strdup (""); + _s_check ("empty", p && strcmp (p, "") == 0); + free (p); + } + + /* returns independent copy */ + { + char src[] = "hello"; + char *p = ft_strdup (src); + _s_check ("independent copy", p && p != src && strcmp (p, src) == 0); + src[0] = 'X'; + _s_check ("mutation safe", p[0] == 'h'); + free (p); + } + + /* randomized */ + for (i = 0; i < 50; i++) + { + int len = rand () % 500 + 1; + char *src = malloc (len + 1); + int j; + char *ft_p; + char *libc_p; + if (!src) + continue; + for (j = 0; j < len; j++) + src[j] = 'A' + rand () % 26; + src[len] = '\0'; + ft_p = ft_strdup (src); + libc_p = strdup (src); + snprintf (label, sizeof (label), "random len=%d", len); + _s_check (label, ft_p && libc_p && strcmp (ft_p, libc_p) == 0); + free (src); + free (ft_p); + free (libc_p); + } +} + +int +main (void) +{ + printf ("=== alloc functions ===\n"); + _s_test_calloc (); + _s_test_strdup (); + _s_print_results (); + return (_s_fail != 0); +} diff --git a/tests/test_atoi.c b/tests/test_atoi.c new file mode 100644 index 0000000..196a081 --- /dev/null +++ b/tests/test_atoi.c @@ -0,0 +1,58 @@ +#include "../libft.h" +#include "test_utils.h" +#include <limits.h> + +static void +_s_ft_atoi_null (void) +{ + _s_sink_i = ft_atoi (NULL); +} +static void +_s_libc_atoi_null (void) +{ + _s_sink_i = atoi (NULL); +} + +int +main (void) +{ + int i; + char buf[64]; + char label[64]; + + printf ("=== ft_atoi ===\n"); + + /* NULL */ + _s_check_both_crash ("atoi NULL", _s_ft_atoi_null, _s_libc_atoi_null); + + /* edge cases */ + _s_check_eq_int ("zero", ft_atoi ("0"), atoi ("0")); + _s_check_eq_int ("INT_MAX", ft_atoi ("2147483647"), atoi ("2147483647")); + _s_check_eq_int ("INT_MIN", ft_atoi ("-2147483648"), atoi ("-2147483648")); + _s_check_eq_int ("negative", ft_atoi ("-42"), atoi ("-42")); + _s_check_eq_int ("explicit +", ft_atoi ("+42"), atoi ("+42")); + _s_check_eq_int ("leading spaces", ft_atoi (" 42"), atoi (" 42")); + _s_check_eq_int ("leading tabs", ft_atoi ("\t\n\v\f\r 42"), + atoi ("\t\n\v\f\r 42")); + _s_check_eq_int ("trailing chars", ft_atoi ("42abc"), atoi ("42abc")); + _s_check_eq_int ("empty string", ft_atoi (""), atoi ("")); + _s_check_eq_int ("only spaces", ft_atoi (" "), atoi (" ")); + _s_check_eq_int ("only sign", ft_atoi ("-"), atoi ("-")); + _s_check_eq_int ("sign then space", ft_atoi ("- 42"), atoi ("- 42")); + _s_check_eq_int ("double sign", ft_atoi ("--42"), atoi ("--42")); + _s_check_eq_int ("space between", ft_atoi ("4 2"), atoi ("4 2")); + _s_check_eq_int ("leading zeros", ft_atoi ("00042"), atoi ("00042")); + + /* randomized */ + srand (time (NULL)); + for (i = 0; i < 50; i++) + { + int v = rand () - RAND_MAX / 2; + snprintf (buf, sizeof (buf), "%d", v); + snprintf (label, sizeof (label), "random %s", buf); + _s_check_eq_int (label, ft_atoi (buf), atoi (buf)); + } + + _s_print_results (); + return (_s_fail != 0); +} diff --git a/tests/test_case.c b/tests/test_case.c new file mode 100644 index 0000000..44b567a --- /dev/null +++ b/tests/test_case.c @@ -0,0 +1,36 @@ +#include "../libft.h" +#include "test_utils.h" +#include <ctype.h> + +static void +_s_test_func (const char *name, int (*ft) (int), int (*libc) (int)) +{ + int i; + int ok; + + ok = 1; + for (i = -1; i <= 255; i++) + { + if (ft (i) != libc (i)) + { + printf (" FAIL %s(%d): ft=%d libc=%d\n", name, i, ft (i), libc (i)); + _s_fail++; + ok = 0; + } + } + if (ok) + { + printf (" PASS %s (all -1..255)\n", name); + _s_pass++; + } +} + +int +main (void) +{ + printf ("=== case functions ===\n"); + _s_test_func ("ft_toupper", ft_toupper, toupper); + _s_test_func ("ft_tolower", ft_tolower, tolower); + _s_print_results (); + return (_s_fail != 0); +} diff --git a/tests/test_cmp.c b/tests/test_cmp.c new file mode 100644 index 0000000..eea0aea --- /dev/null +++ b/tests/test_cmp.c @@ -0,0 +1,279 @@ +#include "../libft.h" +#include "test_utils.h" + +static void +_s_ft_memchr_null (void) +{ + _s_sink = (size_t)ft_memchr (NULL, 'a', 10); +} +static void +_s_libc_memchr_null (void) +{ + _s_sink = (size_t)memchr (NULL, 'a', 10); +} +static void +_s_ft_memcmp_null_s1 (void) +{ + _s_sink_i = ft_memcmp (NULL, "abc", 3); +} +static void +_s_libc_memcmp_null_s1 (void) +{ + _s_sink_i = memcmp (NULL, "abc", 3); +} +static void +_s_ft_memcmp_null_s2 (void) +{ + _s_sink_i = ft_memcmp ("abc", NULL, 3); +} +static void +_s_libc_memcmp_null_s2 (void) +{ + _s_sink_i = memcmp ("abc", NULL, 3); +} +static void +_s_ft_strncmp_null_s1 (void) +{ + _s_sink_i = ft_strncmp (NULL, "abc", 3); +} +static void +_s_libc_strncmp_null_s1 (void) +{ + _s_sink_i = strncmp (NULL, "abc", 3); +} +static void +_s_ft_strncmp_null_s2 (void) +{ + _s_sink_i = ft_strncmp ("abc", NULL, 3); +} +static void +_s_libc_strncmp_null_s2 (void) +{ + _s_sink_i = strncmp ("abc", NULL, 3); +} + +/* ====================================== + * memchr + * ====================================== */ + +static void +_s_test_memchr (void) +{ + char buf[] = "Hello, World!"; + char all[256]; + int i; + char label[64]; + + printf ("-- memchr --\n"); + + /* NULL */ + _s_check_both_crash ("memchr NULL", _s_ft_memchr_null, _s_libc_memchr_null); + + /* find existing char */ + _s_check ("find 'W'", ft_memchr (buf, 'W', 13) == memchr (buf, 'W', 13)); + + /* find first byte */ + _s_check ("find 'H'", ft_memchr (buf, 'H', 13) == memchr (buf, 'H', 13)); + + /* find last byte */ + _s_check ("find '!'", ft_memchr (buf, '!', 13) == memchr (buf, '!', 13)); + + /* not found */ + _s_check ("not found 'z'", + ft_memchr (buf, 'z', 13) == memchr (buf, 'z', 13)); + + /* n=0 */ + _s_check ("n=0", ft_memchr (buf, 'H', 0) == NULL); + + /* char beyond n */ + _s_check ("beyond n", ft_memchr (buf, '!', 5) == memchr (buf, '!', 5)); + + /* search for null byte */ + _s_check ("find '\\0'", ft_memchr (buf, '\0', 14) == memchr (buf, '\0', 14)); + + /* int truncation to unsigned char */ + _s_check ("int truncation", + ft_memchr (buf, 'H' + 256, 13) == memchr (buf, 'H' + 256, 13)); + + /* all byte values */ + for (i = 0; i < 256; i++) + all[i] = i; + for (i = 0; i < 256; i++) + { + snprintf (label, sizeof (label), "byte %d", i); + _s_check (label, ft_memchr (all, i, 256) == memchr (all, i, 256)); + } + + /* randomized */ + srand (time (NULL)); + for (i = 0; i < 50; i++) + { + unsigned char rnd[256]; + int len = rand () % 256 + 1; + int c = rand () % 256; + int j; + for (j = 0; j < len; j++) + rnd[j] = rand () % 256; + snprintf (label, sizeof (label), "random len=%d c=%d", len, c); + _s_check (label, ft_memchr (rnd, c, len) == memchr (rnd, c, len)); + } +} + +/* ====================================== + * memcmp + * ====================================== */ + +static void +_s_test_memcmp (void) +{ + int i; + unsigned char a[256]; + unsigned char b[256]; + size_t len; + int pos; + char label[64]; + + printf ("-- memcmp --\n"); + + /* NULL */ + _s_check_both_crash ("memcmp NULL s1", _s_ft_memcmp_null_s1, + _s_libc_memcmp_null_s1); + _s_check_both_crash ("memcmp NULL s2", _s_ft_memcmp_null_s2, + _s_libc_memcmp_null_s2); + + /* equal */ + _s_check ("equal", _s_sign (ft_memcmp ("abc", "abc", 3)) + == _s_sign (memcmp ("abc", "abc", 3))); + + /* first less */ + _s_check ("less", _s_sign (ft_memcmp ("abc", "abd", 3)) + == _s_sign (memcmp ("abc", "abd", 3))); + + /* first greater */ + _s_check ("greater", _s_sign (ft_memcmp ("abd", "abc", 3)) + == _s_sign (memcmp ("abd", "abc", 3))); + + /* n=0 */ + _s_check ("n=0", _s_sign (ft_memcmp ("abc", "xyz", 0)) + == _s_sign (memcmp ("abc", "xyz", 0))); + + /* difference at last byte */ + _s_check ("diff at end", _s_sign (ft_memcmp ("abcd", "abce", 4)) + == _s_sign (memcmp ("abcd", "abce", 4))); + + /* unsigned comparison: 0 vs 200 */ + { + unsigned char x[] = { 0 }; + unsigned char y[] = { 200 }; + _s_check ("unsigned 0 vs 200", + _s_sign (ft_memcmp (x, y, 1)) == _s_sign (memcmp (x, y, 1))); + } + + /* randomized */ + srand (time (NULL)); + for (i = 0; i < 50; i++) + { + len = rand () % 255 + 1; + for (pos = 0; pos < (int)len; pos++) + a[pos] = b[pos] = rand () % 256; + /* introduce a random difference sometimes */ + if (i % 2 == 0) + { + pos = rand () % len; + b[pos] = (a[pos] + 1 + rand () % 255) % 256; + } + snprintf (label, sizeof (label), "random len=%zu", len); + _s_check (label, _s_sign (ft_memcmp (a, b, len)) + == _s_sign (memcmp (a, b, len))); + } +} + +/* ====================================== + * strncmp + * ====================================== */ + +static void +_s_test_strncmp (void) +{ + int i; + char a[128]; + char b[128]; + int len; + char label[64]; + + printf ("-- strncmp --\n"); + + /* NULL */ + _s_check_both_crash ("strncmp NULL s1", _s_ft_strncmp_null_s1, + _s_libc_strncmp_null_s1); + _s_check_both_crash ("strncmp NULL s2", _s_ft_strncmp_null_s2, + _s_libc_strncmp_null_s2); + + /* equal strings */ + _s_check ("equal", _s_sign (ft_strncmp ("abc", "abc", 3)) + == _s_sign (strncmp ("abc", "abc", 3))); + + /* less */ + _s_check ("less", _s_sign (ft_strncmp ("abc", "abd", 3)) + == _s_sign (strncmp ("abc", "abd", 3))); + + /* greater */ + _s_check ("greater", _s_sign (ft_strncmp ("abd", "abc", 3)) + == _s_sign (strncmp ("abd", "abc", 3))); + + /* n=0 */ + _s_check ("n=0", _s_sign (ft_strncmp ("abc", "xyz", 0)) + == _s_sign (strncmp ("abc", "xyz", 0))); + + /* n larger than strings */ + _s_check ("n > len", _s_sign (ft_strncmp ("abc", "abc", 100)) + == _s_sign (strncmp ("abc", "abc", 100))); + + /* difference beyond n */ + _s_check ("diff beyond n", _s_sign (ft_strncmp ("abcX", "abcY", 3)) + == _s_sign (strncmp ("abcX", "abcY", 3))); + + /* empty strings */ + _s_check ("both empty", + _s_sign (ft_strncmp ("", "", 5)) == _s_sign (strncmp ("", "", 5))); + + /* one empty */ + _s_check ("s1 empty", _s_sign (ft_strncmp ("", "a", 5)) + == _s_sign (strncmp ("", "a", 5))); + _s_check ("s2 empty", _s_sign (ft_strncmp ("a", "", 5)) + == _s_sign (strncmp ("a", "", 5))); + + /* different lengths, equal prefix */ + _s_check ("shorter s1", _s_sign (ft_strncmp ("ab", "abc", 5)) + == _s_sign (strncmp ("ab", "abc", 5))); + + /* unsigned comparison */ + _s_check ("unsigned", _s_sign (ft_strncmp ("\xff", "\x01", 1)) + == _s_sign (strncmp ("\xff", "\x01", 1))); + + /* randomized */ + for (i = 0; i < 50; i++) + { + len = rand () % 64 + 1; + for (int j = 0; j < len; j++) + a[j] = b[j] = 'A' + rand () % 26; + a[len] = '\0'; + b[len] = '\0'; + if (i % 2 == 0) + b[rand () % len] = 'A' + rand () % 26; + snprintf (label, sizeof (label), "random n=%d", len); + _s_check (label, _s_sign (ft_strncmp (a, b, len)) + == _s_sign (strncmp (a, b, len))); + } +} + +int +main (void) +{ + printf ("=== comparison functions ===\n"); + _s_test_memchr (); + _s_test_memcmp (); + _s_test_strncmp (); + _s_print_results (); + return (_s_fail != 0); +} diff --git a/tests/test_is.c b/tests/test_is.c new file mode 100644 index 0000000..1af5d40 --- /dev/null +++ b/tests/test_is.c @@ -0,0 +1,43 @@ +#include "../libft.h" +#include "test_utils.h" +#include <ctype.h> + +static void +_s_test_func (const char *name, int (*ft) (int), int (*libc) (int)) +{ + int i; + int ft_r; + int libc_r; + int ok; + + ok = 1; + for (i = -1; i <= 255; i++) + { + ft_r = !!ft (i); + libc_r = !!libc (i); + if (ft_r != libc_r) + { + printf (" FAIL %s(%d): ft=%d libc=%d\n", name, i, ft_r, libc_r); + _s_fail++; + ok = 0; + } + } + if (ok) + { + printf (" PASS %s (all -1..255)\n", name); + _s_pass++; + } +} + +int +main (void) +{ + printf ("=== is* functions ===\n"); + _s_test_func ("ft_isalpha", ft_isalpha, isalpha); + _s_test_func ("ft_isdigit", ft_isdigit, isdigit); + _s_test_func ("ft_isalnum", ft_isalnum, isalnum); + _s_test_func ("ft_isascii", ft_isascii, isascii); + _s_test_func ("ft_isprint", ft_isprint, isprint); + _s_print_results (); + return (_s_fail != 0); +} diff --git a/tests/test_mem.c b/tests/test_mem.c new file mode 100644 index 0000000..adbe12d --- /dev/null +++ b/tests/test_mem.c @@ -0,0 +1,296 @@ +#include "../libft.h" +#include "test_utils.h" +#include <strings.h> + +static void +_s_ft_memset_null (void) +{ + _s_sink = (size_t)ft_memset (NULL, 'A', 10); +} +static void +_s_libc_memset_null (void) +{ + _s_sink = (size_t)memset (NULL, 'A', 10); +} +static void +_s_ft_bzero_null (void) +{ + ft_bzero (NULL, 10); +} +static void +_s_libc_bzero_null (void) +{ + bzero (NULL, 10); +} +static void +_s_ft_memcpy_null_dst (void) +{ + char buf[10]; + _s_sink = (size_t)ft_memcpy (NULL, buf, 10); +} +static void +_s_libc_memcpy_null_dst (void) +{ + char buf[10]; + _s_sink = (size_t)memcpy (NULL, buf, 10); +} +static void +_s_ft_memcpy_null_src (void) +{ + char buf[10]; + _s_sink = (size_t)ft_memcpy (buf, NULL, 10); +} +static void +_s_libc_memcpy_null_src (void) +{ + char buf[10]; + _s_sink = (size_t)memcpy (buf, NULL, 10); +} +static void +_s_ft_memmove_null_dst (void) +{ + char buf[10]; + _s_sink = (size_t)ft_memmove (NULL, buf, 10); +} +static void +_s_libc_memmove_null_dst (void) +{ + char buf[10]; + _s_sink = (size_t)memmove (NULL, buf, 10); +} +static void +_s_ft_memmove_null_src (void) +{ + char buf[10]; + _s_sink = (size_t)ft_memmove (buf, NULL, 10); +} +static void +_s_libc_memmove_null_src (void) +{ + char buf[10]; + _s_sink = (size_t)memmove (buf, NULL, 10); +} + +/* ====================================== + * memset + * ====================================== */ + +static void +_s_test_memset (void) +{ + char ft_buf[256]; + char libc_buf[256]; + int i; + int c; + size_t len; + void *ret; + char label[64]; + + printf ("-- memset --\n"); + + /* NULL */ + _s_check_both_crash ("memset NULL", _s_ft_memset_null, _s_libc_memset_null); + + /* zero length */ + memset (ft_buf, 'X', 256); + memset (libc_buf, 'X', 256); + ft_memset (ft_buf, 'A', 0); + memset (libc_buf, 'A', 0); + _s_check ("n=0", memcmp (ft_buf, libc_buf, 256) == 0); + + /* return value */ + ret = ft_memset (ft_buf, 'B', 10); + _s_check ("return value", ret == ft_buf); + + /* randomized */ + srand (time (NULL)); + for (i = 0; i < 50; i++) + { + c = rand () % 256; + len = rand () % 256; + ft_memset (ft_buf, c, len); + memset (libc_buf, c, len); + snprintf (label, sizeof (label), "random c=%d len=%zu", c, len); + _s_check (label, memcmp (ft_buf, libc_buf, len) == 0); + } +} + +/* ====================================== + * bzero + * ====================================== */ + +static void +_s_test_bzero (void) +{ + char ft_buf[256]; + char libc_buf[256]; + int i; + size_t len; + char label[64]; + + printf ("-- bzero --\n"); + + /* NULL */ + _s_check_both_crash ("bzero NULL", _s_ft_bzero_null, _s_libc_bzero_null); + + /* zero length */ + memset (ft_buf, 'X', 256); + memset (libc_buf, 'X', 256); + ft_bzero (ft_buf, 0); + bzero (libc_buf, 0); + _s_check ("n=0", memcmp (ft_buf, libc_buf, 256) == 0); + + /* full clear */ + memset (ft_buf, 'X', 256); + memset (libc_buf, 'X', 256); + ft_bzero (ft_buf, 256); + bzero (libc_buf, 256); + _s_check ("n=256", memcmp (ft_buf, libc_buf, 256) == 0); + + /* randomized */ + for (i = 0; i < 50; i++) + { + len = rand () % 256; + memset (ft_buf, 'Z', 256); + memset (libc_buf, 'Z', 256); + ft_bzero (ft_buf, len); + bzero (libc_buf, len); + snprintf (label, sizeof (label), "random len=%zu", len); + _s_check (label, memcmp (ft_buf, libc_buf, 256) == 0); + } +} + +/* ====================================== + * memcpy + * ====================================== */ + +static void +_s_test_memcpy (void) +{ + char src[256]; + char ft_dst[256]; + char libc_dst[256]; + int i; + size_t len; + void *ret; + char label[64]; + + printf ("-- memcpy --\n"); + + /* NULL */ + _s_check_both_crash ("memcpy NULL dst", _s_ft_memcpy_null_dst, + _s_libc_memcpy_null_dst); + _s_check_both_crash ("memcpy NULL src", _s_ft_memcpy_null_src, + _s_libc_memcpy_null_src); + + /* fill source with pattern */ + for (i = 0; i < 256; i++) + src[i] = i; + + /* zero length */ + memset (ft_dst, 'X', 256); + memset (libc_dst, 'X', 256); + ft_memcpy (ft_dst, src, 0); + memcpy (libc_dst, src, 0); + _s_check ("n=0", memcmp (ft_dst, libc_dst, 256) == 0); + + /* return value */ + ret = ft_memcpy (ft_dst, src, 10); + _s_check ("return value", ret == ft_dst); + + /* NULL src and dst with n=0 */ + ret = ft_memcpy (NULL, NULL, 0); + _s_check ("NULL,NULL,0", ret == NULL); + + /* randomized */ + for (i = 0; i < 50; i++) + { + len = rand () % 256; + memset (ft_dst, 0, 256); + memset (libc_dst, 0, 256); + ft_memcpy (ft_dst, src, len); + memcpy (libc_dst, src, len); + snprintf (label, sizeof (label), "random len=%zu", len); + _s_check (label, memcmp (ft_dst, libc_dst, 256) == 0); + } +} + +/* ====================================== + * memmove + * ====================================== */ + +static void +_s_test_memmove (void) +{ + char ft_buf[256]; + char libc_buf[256]; + int i; + size_t len; + size_t offset; + void *ret; + char label[64]; + + printf ("-- memmove --\n"); + + /* NULL */ + _s_check_both_crash ("memmove NULL dst", _s_ft_memmove_null_dst, + _s_libc_memmove_null_dst); + _s_check_both_crash ("memmove NULL src", _s_ft_memmove_null_src, + _s_libc_memmove_null_src); + + /* return value */ + memset (ft_buf, 'A', 256); + ret = ft_memmove (ft_buf, ft_buf + 10, 10); + _s_check ("return value", ret == ft_buf); + + /* NULL src and dst with n=0 */ + ret = ft_memmove (NULL, NULL, 0); + _s_check ("NULL,NULL,0", ret == NULL); + + /* forward overlap: src before dest */ + for (i = 0; i < 256; i++) + ft_buf[i] = libc_buf[i] = i; + ft_memmove (ft_buf + 10, ft_buf, 100); + memmove (libc_buf + 10, libc_buf, 100); + _s_check ("forward overlap", memcmp (ft_buf, libc_buf, 256) == 0); + + /* backward overlap: dest before src */ + for (i = 0; i < 256; i++) + ft_buf[i] = libc_buf[i] = i; + ft_memmove (ft_buf, ft_buf + 10, 100); + memmove (libc_buf, libc_buf + 10, 100); + _s_check ("backward overlap", memcmp (ft_buf, libc_buf, 256) == 0); + + /* non-overlapping */ + for (i = 0; i < 256; i++) + ft_buf[i] = libc_buf[i] = i; + ft_memmove (ft_buf + 128, ft_buf, 50); + memmove (libc_buf + 128, libc_buf, 50); + _s_check ("non-overlapping", memcmp (ft_buf, libc_buf, 256) == 0); + + /* randomized overlapping copies */ + for (i = 0; i < 50; i++) + { + for (int j = 0; j < 256; j++) + ft_buf[j] = libc_buf[j] = rand () % 256; + len = rand () % 128 + 1; + offset = rand () % 128; + ft_memmove (ft_buf + offset, ft_buf, len); + memmove (libc_buf + offset, libc_buf, len); + snprintf (label, sizeof (label), "random overlap len=%zu off=%zu", len, + offset); + _s_check (label, memcmp (ft_buf, libc_buf, 256) == 0); + } +} + +int +main (void) +{ + printf ("=== mem functions ===\n"); + _s_test_memset (); + _s_test_bzero (); + _s_test_memcpy (); + _s_test_memmove (); + _s_print_results (); + return (_s_fail != 0); +} diff --git a/tests/test_search.c b/tests/test_search.c new file mode 100644 index 0000000..faaaccd --- /dev/null +++ b/tests/test_search.c @@ -0,0 +1,285 @@ +#include "../libft.h" +#include "test_utils.h" +#include <bsd/string.h> + +static void +_s_ft_strchr_null (void) +{ + _s_sink = (size_t)ft_strchr (NULL, 'a'); +} +static void +_s_libc_strchr_null (void) +{ + _s_sink = (size_t)strchr (NULL, 'a'); +} +static void +_s_ft_strrchr_null (void) +{ + _s_sink = (size_t)ft_strrchr (NULL, 'a'); +} +static void +_s_libc_strrchr_null (void) +{ + _s_sink = (size_t)strrchr (NULL, 'a'); +} +static void +_s_ft_strnstr_null_big (void) +{ + _s_sink = (size_t)ft_strnstr (NULL, "abc", 10); +} +static void +_s_libc_strnstr_null_big (void) +{ + _s_sink = (size_t)strnstr (NULL, "abc", 10); +} +static void +_s_ft_strnstr_null_little (void) +{ + _s_sink = (size_t)ft_strnstr ("abc", NULL, 10); +} +static void +_s_libc_strnstr_null_little (void) +{ + _s_sink = (size_t)strnstr ("abc", NULL, 10); +} + +/* ====================================== + * strchr + * ====================================== */ + +static void +_s_test_strchr (void) +{ + char buf[] = "hello world"; + int i; + char label[64]; + + printf ("-- strchr --\n"); + + /* NULL */ + _s_check_both_crash ("strchr NULL", _s_ft_strchr_null, _s_libc_strchr_null); + + /* find first occurrence */ + _s_check ("find 'l'", ft_strchr (buf, 'l') == strchr (buf, 'l')); + + /* find first char */ + _s_check ("find 'h'", ft_strchr (buf, 'h') == strchr (buf, 'h')); + + /* find last char */ + _s_check ("find 'd'", ft_strchr (buf, 'd') == strchr (buf, 'd')); + + /* not found */ + _s_check ("not found 'z'", ft_strchr (buf, 'z') == strchr (buf, 'z')); + + /* find null terminator */ + _s_check ("find '\\0'", ft_strchr (buf, '\0') == strchr (buf, '\0')); + + /* empty string */ + _s_check ("empty + 'a'", ft_strchr ("", 'a') == strchr ("", 'a')); + _s_check ("empty + '\\0'", ft_strchr ("", '\0') == strchr ("", '\0')); + + /* int truncation to char */ + _s_check ("int truncation", + ft_strchr (buf, 'h' + 256) == strchr (buf, 'h' + 256)); + + /* all printable ASCII */ + for (i = 32; i < 127; i++) + { + snprintf (label, sizeof (label), "char %d in buf", i); + _s_check (label, ft_strchr (buf, i) == strchr (buf, i)); + } + + /* randomized */ + srand (time (NULL)); + for (i = 0; i < 50; i++) + { + char rnd[128]; + int len = rand () % 127 + 1; + int j; + int c; + for (j = 0; j < len; j++) + rnd[j] = 'A' + rand () % 52; + rnd[len] = '\0'; + c = 'A' + rand () % 52; + snprintf (label, sizeof (label), "random len=%d c=%c", len, c); + _s_check (label, ft_strchr (rnd, c) == strchr (rnd, c)); + } +} + +/* ====================================== + * strrchr + * ====================================== */ + +static void +_s_test_strrchr (void) +{ + char buf[] = "hello world"; + int i; + char label[64]; + + printf ("-- strrchr --\n"); + + /* NULL */ + _s_check_both_crash ("strrchr NULL", _s_ft_strrchr_null, + _s_libc_strrchr_null); + + /* find last occurrence */ + _s_check ("find 'l'", ft_strrchr (buf, 'l') == strrchr (buf, 'l')); + + /* only one occurrence */ + _s_check ("find 'w'", ft_strrchr (buf, 'w') == strrchr (buf, 'w')); + + /* find first char */ + _s_check ("find 'h'", ft_strrchr (buf, 'h') == strrchr (buf, 'h')); + + /* find last char */ + _s_check ("find 'd'", ft_strrchr (buf, 'd') == strrchr (buf, 'd')); + + /* not found */ + _s_check ("not found 'z'", ft_strrchr (buf, 'z') == strrchr (buf, 'z')); + + /* find null terminator */ + _s_check ("find '\\0'", ft_strrchr (buf, '\0') == strrchr (buf, '\0')); + + /* empty string */ + _s_check ("empty + 'a'", ft_strrchr ("", 'a') == strrchr ("", 'a')); + _s_check ("empty + '\\0'", ft_strrchr ("", '\0') == strrchr ("", '\0')); + + /* int truncation to char */ + _s_check ("int truncation", + ft_strrchr (buf, 'l' + 256) == strrchr (buf, 'l' + 256)); + + /* multiple occurrences */ + _s_check ("'o' last", + ft_strrchr ("foo bar boo", 'o') == strrchr ("foo bar boo", 'o')); + + /* all printable ASCII */ + for (i = 32; i < 127; i++) + { + snprintf (label, sizeof (label), "char %d in buf", i); + _s_check (label, ft_strrchr (buf, i) == strrchr (buf, i)); + } + + /* randomized */ + for (i = 0; i < 50; i++) + { + char rnd[128]; + int len = rand () % 127 + 1; + int j; + int c; + for (j = 0; j < len; j++) + rnd[j] = 'A' + rand () % 52; + rnd[len] = '\0'; + c = 'A' + rand () % 52; + snprintf (label, sizeof (label), "random len=%d c=%c", len, c); + _s_check (label, ft_strrchr (rnd, c) == strrchr (rnd, c)); + } +} + +/* ====================================== + * strnstr + * ====================================== */ + +static void +_s_test_strnstr (void) +{ + char hay[] = "hello world, hello earth"; + + printf ("-- strnstr --\n"); + + /* NULL */ + _s_check_both_crash ("strnstr NULL big", _s_ft_strnstr_null_big, + _s_libc_strnstr_null_big); + _s_check_both_crash ("strnstr NULL little", _s_ft_strnstr_null_little, + _s_libc_strnstr_null_little); + + /* empty needle */ + _s_check ("empty needle", ft_strnstr (hay, "", 24) == strnstr (hay, "", 24)); + + /* empty haystack */ + _s_check ("empty haystack", + ft_strnstr ("", "abc", 0) == strnstr ("", "abc", 0)); + _s_check ("both empty", ft_strnstr ("", "", 0) == strnstr ("", "", 0)); + + /* basic find */ + _s_check ("find 'world'", + ft_strnstr (hay, "world", 24) == strnstr (hay, "world", 24)); + + /* find at start */ + _s_check ("find 'hello'", + ft_strnstr (hay, "hello", 24) == strnstr (hay, "hello", 24)); + + /* find at end */ + _s_check ("find 'earth'", + ft_strnstr (hay, "earth", 24) == strnstr (hay, "earth", 24)); + + /* not found */ + _s_check ("not found 'xyz'", + ft_strnstr (hay, "xyz", 24) == strnstr (hay, "xyz", 24)); + + /* needle longer than len */ + _s_check ("needle beyond len", + ft_strnstr (hay, "world", 8) == strnstr (hay, "world", 8)); + + /* len=0 */ + _s_check ("len=0", + ft_strnstr (hay, "hello", 0) == strnstr (hay, "hello", 0)); + + /* exact match at boundary */ + _s_check ("exact boundary", + ft_strnstr (hay, "world", 11) == strnstr (hay, "world", 11)); + + /* one short of match */ + _s_check ("one short", + ft_strnstr (hay, "world", 10) == strnstr (hay, "world", 10)); + + /* single char needle */ + _s_check ("single char 'w'", + ft_strnstr (hay, "w", 24) == strnstr (hay, "w", 24)); + + /* needle same as haystack */ + _s_check ("needle == haystack", + ft_strnstr ("abc", "abc", 3) == strnstr ("abc", "abc", 3)); + + /* needle longer than haystack */ + _s_check ("needle > haystack", + ft_strnstr ("ab", "abc", 3) == strnstr ("ab", "abc", 3)); + + /* partial match then fail */ + _s_check ("partial match", + ft_strnstr ("aab", "ab", 3) == strnstr ("aab", "ab", 3)); + + /* randomized */ + for (int i = 0; i < 50; i++) + { + char rbig[128]; + char rlittle[16]; + int blen = rand () % 100 + 20; + int llen = rand () % 10 + 1; + size_t n; + int j; + char label[64]; + for (j = 0; j < blen; j++) + rbig[j] = 'A' + rand () % 4; + rbig[blen] = '\0'; + for (j = 0; j < llen; j++) + rlittle[j] = 'A' + rand () % 4; + rlittle[llen] = '\0'; + n = rand () % (blen + 10); + snprintf (label, sizeof (label), "random blen=%d llen=%d n=%zu", blen, + llen, n); + _s_check (label, + ft_strnstr (rbig, rlittle, n) == strnstr (rbig, rlittle, n)); + } +} + +int +main (void) +{ + printf ("=== search functions ===\n"); + _s_test_strchr (); + _s_test_strrchr (); + _s_test_strnstr (); + _s_print_results (); + return (_s_fail != 0); +} diff --git a/tests/test_strl.c b/tests/test_strl.c new file mode 100644 index 0000000..1ef29af --- /dev/null +++ b/tests/test_strl.c @@ -0,0 +1,252 @@ +#include "../libft.h" +#include "test_utils.h" +#include <bsd/string.h> + +static void +_s_ft_strlcpy_null_dst (void) +{ + _s_sink = ft_strlcpy (NULL, "abc", 10); +} +static void +_s_libc_strlcpy_null_dst (void) +{ + _s_sink = strlcpy (NULL, "abc", 10); +} +static void +_s_ft_strlcpy_null_src (void) +{ + char buf[10]; + _s_sink = ft_strlcpy (buf, NULL, 10); +} +static void +_s_libc_strlcpy_null_src (void) +{ + char buf[10]; + _s_sink = strlcpy (buf, NULL, 10); +} +static void +_s_ft_strlcat_null_dst (void) +{ + _s_sink = ft_strlcat (NULL, "abc", 10); +} +static void +_s_libc_strlcat_null_dst (void) +{ + _s_sink = strlcat (NULL, "abc", 10); +} +static void +_s_ft_strlcat_null_src (void) +{ + char buf[10] = "hi"; + _s_sink = ft_strlcat (buf, NULL, 10); +} +static void +_s_libc_strlcat_null_src (void) +{ + char buf[10] = "hi"; + _s_sink = strlcat (buf, NULL, 10); +} + +/* ====================================== + * strlcpy + * ====================================== */ + +static void +_s_test_strlcpy (void) +{ + char ft_dst[64]; + char libc_dst[64]; + size_t ft_ret; + size_t libc_ret; + int i; + size_t size; + char src[64]; + char label[64]; + + printf ("-- strlcpy --\n"); + + /* NULL */ + _s_check_both_crash ("strlcpy NULL dst", _s_ft_strlcpy_null_dst, + _s_libc_strlcpy_null_dst); + _s_check_both_crash ("strlcpy NULL src", _s_ft_strlcpy_null_src, + _s_libc_strlcpy_null_src); + + /* basic copy */ + ft_ret = ft_strlcpy (ft_dst, "hello", 64); + libc_ret = strlcpy (libc_dst, "hello", 64); + _s_check ("basic copy ret", ft_ret == libc_ret); + _s_check ("basic copy buf", strcmp (ft_dst, libc_dst) == 0); + + /* size=0 */ + memset (ft_dst, 'X', 64); + memset (libc_dst, 'X', 64); + ft_ret = ft_strlcpy (ft_dst, "hello", 0); + libc_ret = strlcpy (libc_dst, "hello", 0); + _s_check ("size=0 ret", ft_ret == libc_ret); + _s_check ("size=0 buf unchanged", ft_dst[0] == 'X'); + + /* truncation */ + ft_ret = ft_strlcpy (ft_dst, "hello world", 6); + libc_ret = strlcpy (libc_dst, "hello world", 6); + _s_check ("truncate ret", ft_ret == libc_ret); + _s_check ("truncate buf", strcmp (ft_dst, libc_dst) == 0); + _s_check ("truncate null term", ft_dst[5] == '\0'); + + /* exact fit */ + ft_ret = ft_strlcpy (ft_dst, "abc", 4); + libc_ret = strlcpy (libc_dst, "abc", 4); + _s_check ("exact fit ret", ft_ret == libc_ret); + _s_check ("exact fit buf", strcmp (ft_dst, libc_dst) == 0); + + /* empty src */ + ft_ret = ft_strlcpy (ft_dst, "", 64); + libc_ret = strlcpy (libc_dst, "", 64); + _s_check ("empty src ret", ft_ret == libc_ret); + _s_check ("empty src buf", strcmp (ft_dst, libc_dst) == 0); + + /* size=1 */ + ft_ret = ft_strlcpy (ft_dst, "hello", 1); + libc_ret = strlcpy (libc_dst, "hello", 1); + _s_check ("size=1 ret", ft_ret == libc_ret); + _s_check ("size=1 buf", ft_dst[0] == '\0'); + + /* randomized */ + srand (time (NULL)); + for (i = 0; i < 50; i++) + { + int len = rand () % 60 + 1; + int j; + for (j = 0; j < len; j++) + src[j] = 'A' + rand () % 26; + src[len] = '\0'; + size = rand () % 64; + memset (ft_dst, 'Z', 64); + memset (libc_dst, 'Z', 64); + ft_ret = ft_strlcpy (ft_dst, src, size); + libc_ret = strlcpy (libc_dst, src, size); + snprintf (label, sizeof (label), "random len=%d size=%zu", len, size); + _s_check (label, + ft_ret == libc_ret && memcmp (ft_dst, libc_dst, 64) == 0); + } +} + +/* ====================================== + * strlcat + * ====================================== */ + +static void +_s_test_strlcat (void) +{ + char ft_dst[64]; + char libc_dst[64]; + size_t ft_ret; + size_t libc_ret; + int i; + size_t size; + char label[64]; + + printf ("-- strlcat --\n"); + + /* NULL */ + _s_check_both_crash ("strlcat NULL dst", _s_ft_strlcat_null_dst, + _s_libc_strlcat_null_dst); + _s_check_both_crash ("strlcat NULL src", _s_ft_strlcat_null_src, + _s_libc_strlcat_null_src); + + /* basic concat */ + strcpy (ft_dst, "hello"); + strcpy (libc_dst, "hello"); + ft_ret = ft_strlcat (ft_dst, " world", 64); + libc_ret = strlcat (libc_dst, " world", 64); + _s_check ("basic ret", ft_ret == libc_ret); + _s_check ("basic buf", strcmp (ft_dst, libc_dst) == 0); + + /* size=0 */ + strcpy (ft_dst, "hi"); + strcpy (libc_dst, "hi"); + ft_ret = ft_strlcat (ft_dst, "abc", 0); + libc_ret = strlcat (libc_dst, "abc", 0); + _s_check ("size=0 ret", ft_ret == libc_ret); + + /* size == dstlen (no room to append) */ + strcpy (ft_dst, "hello"); + strcpy (libc_dst, "hello"); + ft_ret = ft_strlcat (ft_dst, "abc", 5); + libc_ret = strlcat (libc_dst, "abc", 5); + _s_check ("size == dstlen ret", ft_ret == libc_ret); + _s_check ("size == dstlen buf", strcmp (ft_dst, libc_dst) == 0); + + /* size less than dst len */ + strcpy (ft_dst, "hello"); + strcpy (libc_dst, "hello"); + ft_ret = ft_strlcat (ft_dst, "abc", 3); + libc_ret = strlcat (libc_dst, "abc", 3); + _s_check ("size < dstlen ret", ft_ret == libc_ret); + _s_check ("size < dstlen buf", strcmp (ft_dst, libc_dst) == 0); + + /* truncation */ + strcpy (ft_dst, "hello"); + strcpy (libc_dst, "hello"); + ft_ret = ft_strlcat (ft_dst, " world", 8); + libc_ret = strlcat (libc_dst, " world", 8); + _s_check ("truncate ret", ft_ret == libc_ret); + _s_check ("truncate buf", strcmp (ft_dst, libc_dst) == 0); + + /* exact fit */ + strcpy (ft_dst, "abc"); + strcpy (libc_dst, "abc"); + ft_ret = ft_strlcat (ft_dst, "de", 6); + libc_ret = strlcat (libc_dst, "de", 6); + _s_check ("exact fit ret", ft_ret == libc_ret); + _s_check ("exact fit buf", strcmp (ft_dst, libc_dst) == 0); + + /* empty src */ + strcpy (ft_dst, "hello"); + strcpy (libc_dst, "hello"); + ft_ret = ft_strlcat (ft_dst, "", 64); + libc_ret = strlcat (libc_dst, "", 64); + _s_check ("empty src ret", ft_ret == libc_ret); + _s_check ("empty src buf", strcmp (ft_dst, libc_dst) == 0); + + /* empty dst */ + ft_dst[0] = '\0'; + libc_dst[0] = '\0'; + ft_ret = ft_strlcat (ft_dst, "hello", 64); + libc_ret = strlcat (libc_dst, "hello", 64); + _s_check ("empty dst ret", ft_ret == libc_ret); + _s_check ("empty dst buf", strcmp (ft_dst, libc_dst) == 0); + + /* randomized */ + for (i = 0; i < 50; i++) + { + int dlen = rand () % 30; + int slen = rand () % 30 + 1; + int j; + for (j = 0; j < dlen; j++) + ft_dst[j] = libc_dst[j] = 'A' + rand () % 26; + ft_dst[dlen] = libc_dst[dlen] = '\0'; + char src[64]; + for (j = 0; j < slen; j++) + src[j] = 'a' + rand () % 26; + src[slen] = '\0'; + size = rand () % 64; + memset (ft_dst + dlen + 1, 'Z', 63 - dlen); + memset (libc_dst + dlen + 1, 'Z', 63 - dlen); + ft_ret = ft_strlcat (ft_dst, src, size); + libc_ret = strlcat (libc_dst, src, size); + snprintf (label, sizeof (label), "random dlen=%d slen=%d size=%zu", dlen, + slen, size); + _s_check (label, + ft_ret == libc_ret && memcmp (ft_dst, libc_dst, 64) == 0); + } +} + +int +main (void) +{ + printf ("=== strlcpy/strlcat ===\n"); + _s_test_strlcpy (); + _s_test_strlcat (); + _s_print_results (); + return (_s_fail != 0); +} diff --git a/tests/test_strlen.c b/tests/test_strlen.c new file mode 100644 index 0000000..ef569ff --- /dev/null +++ b/tests/test_strlen.c @@ -0,0 +1,109 @@ +#include "../libft.h" +#include "test_utils.h" + +static void +_s_call_ft_strlen_null (void) +{ + _s_sink = ft_strlen (NULL); +} + +static void +_s_call_strlen_null (void) +{ + _s_sink = strlen (NULL); +} + +static void +_s_test_empty (void) +{ + printf ("-- empty string --\n"); + _s_check_eq ("ft_strlen", ft_strlen (""), 0); + _s_check_eq ("libc strlen", strlen (""), 0); +} + +static void +_s_test_null (void) +{ + int ft_crashed; + int libc_crashed; + + printf ("-- NULL --\n"); + ft_crashed = _s_crashes (_s_call_ft_strlen_null); + libc_crashed = _s_crashes (_s_call_strlen_null); + if (ft_crashed && libc_crashed) + { + printf (" PASS both crash on NULL\n"); + _s_pass++; + } + else if (ft_crashed == libc_crashed) + { + printf (" PASS both behave the same on NULL (no crash)\n"); + _s_pass++; + } + else + { + printf (" FAIL ft_crashed=%d libc_crashed=%d\n", ft_crashed, + libc_crashed); + _s_fail++; + } +} + +static void +_s_test_random (int n) +{ + int i; + int len; + char *buf; + char label[64]; + + printf ("-- %d randomized tests --\n", n); + for (i = 0; i < n; i++) + { + len = rand () % 10000; + buf = malloc (len + 1); + if (!buf) + { + printf (" FAIL malloc\n"); + _s_fail++; + return; + } + memset (buf, 'A' + (i % 26), len); + buf[len] = '\0'; + snprintf (label, sizeof (label), "random len=%d", len); + _s_check_eq (label, ft_strlen (buf), strlen (buf)); + free (buf); + } +} + +static void +_s_test_large (void) +{ + size_t len; + char *buf; + + printf ("-- large string (100 MB) --\n"); + len = 100 * 1024 * 1024; + buf = malloc (len + 1); + if (!buf) + { + printf (" SKIP could not allocate %zu bytes\n", len); + return; + } + memset (buf, 'X', len); + buf[len] = '\0'; + _s_check_eq ("100 MB string", ft_strlen (buf), len); + free (buf); +} + +int +main (void) +{ + srand (time (NULL)); + printf ("=== ft_strlen ===\n"); + _s_test_empty (); + _s_test_null (); + _s_test_random (100); + _s_test_large (); + _s_print_results (); + return (_s_fail != 0); +} |
