289 lines
7.2 KiB
C
289 lines
7.2 KiB
C
#include <ft/test.h>
|
|
#include <ft/all-tests.h>
|
|
#include <string.h>
|
|
#include "memarray.h"
|
|
|
|
//---
|
|
// Utilities
|
|
//---
|
|
|
|
/* Fill buffer with non-zero and position-sensitive data */
|
|
static void fill(uint8_t *buf, int size, int start)
|
|
{
|
|
for(int i = 0; i < size; i++) buf[i] = start+i;
|
|
}
|
|
/* Clear buffer */
|
|
static void clear(uint8_t *buf, int size, int value)
|
|
{
|
|
for(int i = 0; i < size; i++) buf[i] = value;
|
|
}
|
|
/* Check buffer equality (returns zero on equal) */
|
|
static int cmp(uint8_t *left, uint8_t *right, int size)
|
|
{
|
|
for(int i = 0; i < size; i++) if(left[i] != right[i]) return 1;
|
|
return 0;
|
|
}
|
|
|
|
//---
|
|
// Naive functions (baseline)
|
|
//---
|
|
|
|
static void *naive_memcpy(void *_dst, void const *_src, size_t len)
|
|
{
|
|
uint8_t *dst = _dst;
|
|
uint8_t const *src = _src;
|
|
|
|
while(len--) *dst++ = *src++;
|
|
return _dst;
|
|
}
|
|
static void *naive_memset(void *_dst, int byte, size_t len)
|
|
{
|
|
uint8_t *dst = _dst;
|
|
|
|
while(len--) *dst++ = byte;
|
|
return _dst;
|
|
}
|
|
static void *naive_memmove(void *dst, void const *src, size_t len)
|
|
{
|
|
uint8_t tmp[len];
|
|
naive_memcpy(tmp, src, len);
|
|
naive_memcpy(dst, tmp, len);
|
|
return dst;
|
|
}
|
|
static int naive_memcmp(void const *_s1, void const *_s2, size_t len)
|
|
{
|
|
uint8_t const *s1 = _s1, *s2 = _s2;
|
|
|
|
for(size_t i = 0; i < len; i++)
|
|
{
|
|
if(s1[i] != s2[i]) return s1[i] - s2[i];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//---
|
|
// memset
|
|
//---
|
|
|
|
static int _string_memset_func(memarray_args_t const *args)
|
|
{
|
|
fill(args->full_buf1, args->full_size, 0);
|
|
fill(args->full_buf2, args->full_size, 0);
|
|
|
|
memset(args->buf1, 0, args->size);
|
|
naive_memset(args->buf2, 0, args->size);
|
|
|
|
return cmp(args->full_buf1, args->full_buf2, args->full_size);
|
|
}
|
|
|
|
uint8_t _string_memset_rc[MEMARRAY_RC_SINGLE];
|
|
|
|
static void _string_memset(ft_test *t)
|
|
{
|
|
memarray_single(_string_memset_rc, _string_memset_func);
|
|
memarray_assert(_string_memset_rc, t);
|
|
}
|
|
|
|
static jwidget *_string_memset_widget(GUNUSED ft_test *t)
|
|
{
|
|
return memarray_widget(_string_memset_rc);
|
|
}
|
|
|
|
ft_test ft_string_memset = {
|
|
.name = "Configurations of memset",
|
|
.function = _string_memset,
|
|
.widget = _string_memset_widget,
|
|
};
|
|
|
|
//---
|
|
// memcpy
|
|
//---
|
|
|
|
static int _string_memcpy_func(memarray_args_t const *args)
|
|
{
|
|
fill(args->full_left1, args->full_size, 0);
|
|
fill(args->full_left2, args->full_size, 0);
|
|
clear(args->full_right1, args->full_size, 0);
|
|
clear(args->full_right2, args->full_size, 0);
|
|
|
|
memcpy(args->right1, args->left1, args->size);
|
|
naive_memcpy(args->right2, args->left2, args->size);
|
|
|
|
return cmp(args->full_right1, args->full_right2, args->full_size);
|
|
}
|
|
|
|
uint8_t _string_memcpy_rc[MEMARRAY_RC_DOUBLE];
|
|
|
|
static void _string_memcpy(ft_test *t)
|
|
{
|
|
memarray_double(_string_memcpy_rc, false, _string_memcpy_func);
|
|
memarray_assert(_string_memcpy_rc, t);
|
|
}
|
|
|
|
static jwidget *_string_memcpy_widget(GUNUSED ft_test *t)
|
|
{
|
|
return memarray_widget(_string_memcpy_rc);
|
|
}
|
|
|
|
ft_test ft_string_memcpy = {
|
|
.name = "Configurations of memcpy",
|
|
.function = _string_memcpy,
|
|
.widget = _string_memcpy_widget,
|
|
};
|
|
|
|
//---
|
|
// memmove
|
|
//---
|
|
|
|
static int _string_memmove_func(memarray_args_t const *args)
|
|
{
|
|
fill(args->full_left1, args->full_size, 0);
|
|
fill(args->full_left2, args->full_size, 0);
|
|
fill(args->full_right1, args->full_size, 0);
|
|
fill(args->full_right2, args->full_size, 0);
|
|
|
|
memmove(args->right1, args->left1, args->size);
|
|
naive_memmove(args->right2, args->left2, args->size);
|
|
|
|
return cmp(args->full_right1, args->full_right2, args->full_size);
|
|
}
|
|
|
|
uint8_t _string_memmove_rc[MEMARRAY_RC_DOUBLE_OVERLAP];
|
|
|
|
static void _string_memmove(ft_test *t)
|
|
{
|
|
memarray_double(_string_memmove_rc, true, _string_memmove_func);
|
|
memarray_assert(_string_memmove_rc, t);
|
|
}
|
|
|
|
static jwidget *_string_memmove_widget(GUNUSED ft_test *t)
|
|
{
|
|
return memarray_widget(_string_memmove_rc);
|
|
}
|
|
|
|
ft_test ft_string_memmove = {
|
|
.name = "Configurations of memmove",
|
|
.function = _string_memmove,
|
|
.widget = _string_memmove_widget,
|
|
};
|
|
|
|
//---
|
|
// memcmp
|
|
//---
|
|
|
|
static int _string_memcmp_func(memarray_args_t const *args)
|
|
{
|
|
/* Create data that matches in the given regions */
|
|
fill(args->full_left1, args->full_size, args->left1 - args->full_left1);
|
|
fill(args->full_right1, args->full_size, args->right1 - args->full_right1);
|
|
|
|
/* Check equality */
|
|
if(memcmp(args->left1, args->right1, args->size) !=
|
|
naive_memcmp(args->left1, args->right1, args->size)) return 1;
|
|
|
|
/* Check that changing single bytes changes the result */
|
|
for(size_t i = 0; i < args->size / 4; i++) {
|
|
((uint8_t *)args->right1)[i] ^= 0xff;
|
|
if(memcmp(args->left1, args->right1, args->size) !=
|
|
naive_memcmp(args->left1, args->right1, args->size)) return 1;
|
|
((uint8_t *)args->right1)[i] ^= 0xff;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint8_t _string_memcmp_rc[MEMARRAY_RC_DOUBLE];
|
|
|
|
static void _string_memcmp(ft_test *t)
|
|
{
|
|
memarray_double(_string_memcmp_rc, false, _string_memcmp_func);
|
|
memarray_assert(_string_memcmp_rc, t);
|
|
}
|
|
|
|
static jwidget *_string_memcmp_widget(GUNUSED ft_test *t)
|
|
{
|
|
return memarray_widget(_string_memcmp_rc);
|
|
}
|
|
|
|
ft_test ft_string_memcmp = {
|
|
.name = "Configurations of memcmp",
|
|
.function = _string_memcmp,
|
|
.widget = _string_memcmp_widget,
|
|
};
|
|
|
|
//---
|
|
// memchr
|
|
//---
|
|
|
|
static int _string_memchr_func(memarray_args_t const *args)
|
|
{
|
|
/* Start at 2, and search for byte 1 (inserted manually). Fill the region
|
|
around with 1s to make sure they are ignored */
|
|
clear(args->full_buf1, args->full_size, 0);
|
|
fill(args->buf1, args->size, 2);
|
|
|
|
/* Check that no byte is found initially */
|
|
if(memchr(args->buf1, 0x01, args->size)) return 1;
|
|
|
|
/* We'll try bytes at all of these locations */
|
|
char *p1 = (char *)args->buf1;
|
|
char *p2 = (char *)args->buf1 + (args->size / 4);
|
|
char *p3 = (char *)args->buf1 + (3 * args->size / 4);
|
|
char *p4 = (char *)args->buf1 + (args->size - 1);
|
|
|
|
*p1 = 0x01;
|
|
*p2 = 0x01;
|
|
*p3 = 0x01;
|
|
*p4 = 0x01;
|
|
|
|
/* First byte in the area */
|
|
if(memchr(args->buf1, 0x01, args->size) != p1) return 1;
|
|
*p1 = 0x02;
|
|
|
|
/* First quarter */
|
|
if(memchr(args->buf1, 0x01, args->size) != p2) return 1;
|
|
*p2 = 0x02;
|
|
|
|
/* Third quarter */
|
|
if(memchr(args->buf1, 0x01, args->size) != p3) return 1;
|
|
*p3 = 0x02;
|
|
|
|
/* Last byte */
|
|
if(memchr(args->buf1, 0x01, args->size) != p4) return 1;
|
|
*p4 = 0x02;
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint8_t _string_memchr_rc[MEMARRAY_RC_SINGLE];
|
|
|
|
static void _string_memchr(ft_test *t)
|
|
{
|
|
#define memchr_dist(str, byte, size) ({ \
|
|
void const *_str = (str); \
|
|
memchr(_str, byte, size) - _str; \
|
|
})
|
|
|
|
ft_assert(t, memchr("xyztu", 'x', 0) == NULL);
|
|
ft_assert(t, memchr_dist("xyztu", 'x', 5) == 0);
|
|
ft_assert(t, memchr_dist("xyztu", 'y', 5) == 1);
|
|
ft_assert(t, memchr_dist("xyztu", 'z', 5) == 2);
|
|
ft_assert(t, memchr_dist("xyztu", 't', 5) == 3);
|
|
ft_assert(t, memchr_dist("xyztu", 'u', 5) == 4);
|
|
ft_assert(t, memchr("xyztu", 'v', 5) == NULL);
|
|
|
|
memarray_single(_string_memchr_rc, _string_memchr_func);
|
|
memarray_assert(_string_memchr_rc, t);
|
|
}
|
|
|
|
static jwidget *_string_memchr_widget(GUNUSED ft_test *t)
|
|
{
|
|
return memarray_widget(_string_memchr_rc);
|
|
}
|
|
|
|
ft_test ft_string_memchr = {
|
|
.name = "Configurations of memchr",
|
|
.function = _string_memchr,
|
|
.widget = _string_memchr_widget,
|
|
};
|