new string.h implementation & tests
This commit is contained in:
24
host_test/Makefile
Normal file
24
host_test/Makefile
Normal file
@@ -0,0 +1,24 @@
|
||||
rose_objects = string.o
|
||||
objects = main.o
|
||||
CFLAGS = -m32 -mgeneral-regs-only -march=i386 -fno-stack-protector -Wno-int-conversion -c -Iinclude
|
||||
LFLAGS = -m32
|
||||
|
||||
all: test
|
||||
./test
|
||||
|
||||
test: $(objects) $(rose_objects)
|
||||
clang $(LFLAGS) -o $@ $^
|
||||
|
||||
%.o: ../%.nasm
|
||||
nasm -f elf32 -o $@ $<
|
||||
objcopy --prefix-symbols=rose_ $@
|
||||
|
||||
%.o: %.c
|
||||
clang $(CFLAGS) -ffunction-sections -fdata-sections -Os -o $@ $<
|
||||
|
||||
%.o: ../%.c
|
||||
clang $(CFLAGS) -nostdlib -ffunction-sections -fdata-sections -Os -o $@ $<
|
||||
objcopy --prefix-symbols=rose_ $@
|
||||
|
||||
clean:
|
||||
rm -f $(objects) $(rose_objects) test
|
14
host_test/main.c
Normal file
14
host_test/main.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "str_test.c"
|
||||
|
||||
int main() {
|
||||
int fail = 0;
|
||||
puts("\t--- Host tests for ROSE ---\n");
|
||||
|
||||
fail |= do_str_test();
|
||||
|
||||
puts(fail ? "\n\t--- ROSE FAILED TEST ---" : "\n\t--- ROSE PASSED TEST ---");
|
||||
return fail;
|
||||
}
|
||||
|
297
host_test/str_test.c
Normal file
297
host_test/str_test.c
Normal file
@@ -0,0 +1,297 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/random.h>
|
||||
|
||||
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;
|
||||
}
|
Reference in New Issue
Block a user