#include #include #include #include int rose_memcmp(const void *s1, const void *s2, size_t n); const char *MEMCMP_S0 = "0000000000000000"; const char *MEMCMP_S1 = "0000000000000001"; const char *MEMCMP_S2 = "0000000000000002"; int test_memcmp() { int res, test, fail = 0; res = rose_memcmp(MEMCMP_S0, MEMCMP_S0, 0); test = res == 0; printf("%s\tmemcmp n=0\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_memcmp(MEMCMP_S0, MEMCMP_S1, 1); test = res == 0; printf("%s\tmemcmp n=1, strings equal\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_memcmp(MEMCMP_S0, MEMCMP_S1, 2); test = res == 0; printf("%s\tmemcmp n=2, strings equal\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_memcmp(MEMCMP_S0, MEMCMP_S1, 3); test = res == 0; printf("%s\tmemcmp n=3, strings equal\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_memcmp(MEMCMP_S0, MEMCMP_S1, 4); test = res == 0; printf("%s\tmemcmp n=4, strings equal\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_memcmp(MEMCMP_S0, MEMCMP_S1, 15); test = res == 0; printf("%s\tmemcmp n=15, strings equal\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_memcmp(MEMCMP_S0, MEMCMP_S1, 16); test = res == -1; printf("%s\tmemcmp n=16, first less\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_memcmp(MEMCMP_S2, MEMCMP_S1, 16); test = res == 1; printf("%s\tmemcmp n=16, first greater\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_memcmp(&MEMCMP_S1[1], &MEMCMP_S2[1], 1000000); test = res == -1; printf("%s\tmemcmp n=1000000, first less\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_memcmp(&MEMCMP_S2[1], &MEMCMP_S1[1], 1000000); test = res == 1; printf("%s\tmemcmp n=1000000, first greater\n", test ? "PASS" : "FAIL"); fail |= !test; return fail; } int rose_strcmp(const void *s1, const void *s2); const char *STRCMP_S0 = "0000000000000000"; const char *STRCMP_S1 = "0000000000000001"; const char *STRCMP_S2 = "0000000000000002"; int test_strcmp() { int res, test, fail = 0; res = rose_strcmp(STRCMP_S0, STRCMP_S0); test = res == 0; printf("%s\tstrcmp, strings equal\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_strcmp(&STRCMP_S0[1], STRCMP_S0); test = res == -'0'; printf("%s\tstrcmp, first shorter\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_strcmp(STRCMP_S0, &STRCMP_S0[1]); test = res == '0'; printf("%s\tstrcmp, second shorter\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_strcmp(STRCMP_S0, STRCMP_S1); test = res == -1; printf("%s\tstrcmp, first less\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_strcmp(STRCMP_S2, STRCMP_S1); test = res == 1; printf("%s\tstrcmp, first greater\n", test ? "PASS" : "FAIL"); fail |= !test; char n = 0; res = rose_strcmp(&n, &n); test = res == 0; printf("%s\tstrcmp, empty strings\n", test ? "PASS" : "FAIL"); fail |= !test; return fail; } /* Thanks Plasma Ofthedawn! */ int rose_strlen(const void *s1); const char STRLEN_S0[] = {'a', 'b', 'c', 'd', 'e', '\0'}; const char STRLEN_S1[] = {'\0', 'a', 'b', 'c', '\0'}; const char STRLEN_S2[] = {'\1', '\xff', '\0'}; int test_strlen() { int res, test, fail = 0; res = rose_strlen(STRLEN_S0); test = res == 5; printf("%s\tstrlen, normal string. is %d, should be 5\n", test ? "PASS" : "FAIL", res); fail |= !test; res = rose_strlen(STRLEN_S1); test = res == 0; printf("%s\tstrlen, length 0. is %d, should be 0\n", test ? "PASS" : "FAIL", res); fail |= !test; res = rose_strlen(STRLEN_S2); test = res == 2; printf("%s\tstrlen, weird charcacters. is %d, should be 2\n", test ? "PASS" : "FAIL", res); fail |= !test; return fail; } void *rose_memcpy(void *dest, const void *src, size_t n); int test_memcpy() { void *res; int test, fail = 0; const size_t n = 1 << 20; char *d = malloc(n); char *s = malloc(n); getrandom(s, n, 0); s[15] = 0; d[15] = 1; res = rose_memcpy(d, s, 15); test = res == d && d[15] == 1 && memcmp(s, d, 15) == 0; printf("%s\tmemcpy, length 15\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_memcpy(d, s, n); test = res == d && memcmp(s, d, n) == 0; printf("%s\tmemcpy, length %d\n", test ? "PASS" : "FAIL", n); fail |= !test; d[0] = s[0] - 1; res = rose_memcpy(d, s, 0); test = res == d && memcmp(d, s, 1) == -1; printf("%s\tmemcpy, length 0\n", test ? "PASS" : "FAIL"); fail |= !test; free(d); free(s); return fail; } char *rose_strcpy(char *restrict dst, const char *restrict src); int test_strcpy() { void *res; int test, fail = 0; const size_t n = 1 << 16; char *d = malloc(n); char *s = malloc(n); getrandom(s, n, 0); for (int i = 1; i < 256; i++) s[i - 1] = i; s[n-1] = 0; // fix very unlikely case res = rose_strcpy(d, s); test = res == d && strcmp(s, d) == 0; printf("%s\tstrcpy, random string\n", test ? "PASS" : "FAIL"); fail |= !test; d[0] = 1; s[0] = 0; res = rose_strcpy(d, s); test = res == d && d[0] == 0; printf("%s\tstrcpy, length 0\n", test ? "PASS" : "FAIL"); fail |= !test; free(d); free(s); return fail; } void *rose_memset(void *s, int c, size_t n); int test_memset() { void *res; int test, fail = 0; const size_t n = 1 << 16; char *s = malloc(n); char *d = malloc(n); const int c = 0x42; memset(d, c, n); res = rose_memset(s, c, n); test = res == s && memcmp(s, d, n) == 0; printf("%s\tmemset, length %d\n", test ? "PASS" : "FAIL", n); fail |= !test; res = rose_memset(s, 0, 1); test = res == s && s[0] == 0 && s[1] == c; printf("%s\tmemset, bound check\n", test ? "PASS" : "FAIL"); fail |= !test; res = rose_memset(s, c, 0); test = res == s && s[0] == 0; printf("%s\tmemset, length 0\n", test ? "PASS" : "FAIL"); fail |= !test; free(s); free(d); return fail; } char *rose_strncpy(char *restrict dst, const char *restrict src, size_t dsize); int test_strncpy() { void *res; int test, fail = 0; const size_t n = 1 << 16; char *d = malloc(n); char *s = malloc(n); char *x = malloc(n); getrandom(s, n, 0); for (int i = 1; i < 256; i++) s[i - 1] = i; strncpy(x, s, n); res = rose_strncpy(d, s, n); test = res == d && memcmp(x, d, n) == 0; printf("%s\tstrcpy, random string, length %d\n", test ? "PASS" : "FAIL", n); fail |= !test; memset(s, 0x42, n); strncpy(x, s, 255); x[255] = 0; d[255] = 1; res = rose_strncpy(d, s, 255); test = res == d && memcmp(x, d, 256) == -1; printf("%s\tstrcpy, bounds check\n", test ? "PASS" : "FAIL"); fail |= !test; d[0] = 1; res = rose_strncpy(d, s, 0); test = res == d && d[0] == 1; printf("%s\tstrcpy, length 0\n", test ? "PASS" : "FAIL"); fail |= !test; free(d); free(s); free(x); return fail; } int do_str_test() { int fail = 0; puts("[String Tests]"); fail |= test_memcmp(); fail |= test_strcmp(); fail |= test_strlen(); fail |= test_memcpy(); fail |= test_strcpy(); fail |= test_memset(); fail |= test_strncpy(); puts(fail ? "STRING TESTS FAILED" : "STRING TESTS PASSED"); return fail; }