Added a small, automated test file for the core memory functions.
This commit is contained in:
parent
262ba283ac
commit
0c9ee5f4f8
|
@ -28,5 +28,12 @@ SECTIONS
|
|||
_bdata = . ;
|
||||
*(.data);
|
||||
_edata = . ;
|
||||
|
||||
/* Provide a default */
|
||||
_end = . ;
|
||||
} > ram
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,14 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#include "string.h"
|
||||
#include "fxlib.h"
|
||||
|
||||
#include "fxlib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "memfunctest.h"
|
||||
|
||||
// unused
|
||||
void conv_to_hex(char x, char* a, char* b) {
|
||||
*a = (x >> 4) & 0xf;
|
||||
|
@ -34,25 +36,26 @@ int main(void) {
|
|||
//char* out;
|
||||
char out[20] = {0};
|
||||
|
||||
while (1) {
|
||||
Bdisp_AllClr_DD();
|
||||
Bdisp_AllClr_DD();
|
||||
|
||||
locate(1, 1);
|
||||
Print((unsigned char*) in);
|
||||
locate(1, 1);
|
||||
Print((unsigned char*) in);
|
||||
|
||||
//out = (char*) malloc(strlen(in) + 1);
|
||||
strcpy(out, in);
|
||||
locate(1, 2);
|
||||
Print((unsigned char*) out);
|
||||
//free(out);
|
||||
//out = (char*) malloc(strlen(in) + 1);
|
||||
strcpy(out, in);
|
||||
locate(1, 2);
|
||||
Print((unsigned char*) out);
|
||||
//free(out);
|
||||
|
||||
Bdisp_PutDisp_DD();
|
||||
GetKey(&key);
|
||||
}
|
||||
locate(1, 3);
|
||||
memfunctest();
|
||||
|
||||
return 0;
|
||||
Bdisp_PutDisp_DD();
|
||||
while(1) GetKey(&key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void initialize(void) {
|
||||
main();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* 4-abyte buffer alignement */
|
||||
#define ALIGN(n) __attribute__((aligned(n)))
|
||||
/* Unused parameters */
|
||||
#define UNUSED __attribute__((unused))
|
||||
|
||||
//---
|
||||
// Basic setup
|
||||
//---
|
||||
|
||||
/* Source buffer, used as a data source when copying */
|
||||
ALIGN(4) static uint8_t src[256];
|
||||
/* Destination buffer, used as destination when copying or clearing */
|
||||
ALIGN(4) static uint8_t dst[256];
|
||||
/* System buffer, used to reproduce the behavior on the system and compare */
|
||||
ALIGN(4) static uint8_t sys[256];
|
||||
/* Temporary buffer, used by the naive memmove() */
|
||||
ALIGN(4) static uint8_t tmp[256];
|
||||
|
||||
/* fill() - fill a buffer with non-zero data */
|
||||
static void fill(uint8_t *buf)
|
||||
{
|
||||
for(int i = 0; i < 256; i++) buf[i] = i;
|
||||
}
|
||||
|
||||
/* clear() - clear a buffer with zeros */
|
||||
static void clear(uint8_t *buf)
|
||||
{
|
||||
for(int i = 0; i < 256; i++) buf[i] = 0;
|
||||
}
|
||||
|
||||
/* cmp() - check that some two buffers are equal
|
||||
Returns non-zero if the buffers differ. */
|
||||
static int cmp(uint8_t *lft, uint8_t *rgt)
|
||||
{
|
||||
for(int i = 0; i < 256; i++) if(lft[i] != rgt[i]) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---
|
||||
// Naive functions (reference behaviour)
|
||||
//---
|
||||
|
||||
/* naive_memcpy() - bytewise copy */
|
||||
static void *naive_memcpy(void *_dst, const void *_src, size_t len)
|
||||
{
|
||||
uint8_t *dst = _dst;
|
||||
uint8_t const *src = _src;
|
||||
|
||||
while(len--) *dst++ = *src++;
|
||||
return _dst;
|
||||
}
|
||||
|
||||
/* naive_memset() - bytewise set */
|
||||
static void *naive_memset(void *_dst, int byte, size_t len)
|
||||
{
|
||||
uint8_t *dst = _dst;
|
||||
|
||||
while(len--) *dst++ = byte;
|
||||
return _dst;
|
||||
}
|
||||
|
||||
/* naive_memmove() - bytewise copy with buffer */
|
||||
static void *naive_memmove(void *_dst, const void *_src, size_t len)
|
||||
{
|
||||
naive_memcpy(tmp, _src, len);
|
||||
naive_memcpy(_dst, tmp, len);
|
||||
return _dst;
|
||||
}
|
||||
|
||||
//---
|
||||
// Testing functions
|
||||
//---
|
||||
|
||||
static int test_memcpy(int off_dst, int off_src, size_t len)
|
||||
{
|
||||
clear(dst);
|
||||
clear(sys);
|
||||
|
||||
memcpy(dst + off_dst, src + off_src, len);
|
||||
naive_memcpy(sys + off_dst, src + off_src, len);
|
||||
|
||||
return cmp(dst, sys);
|
||||
}
|
||||
|
||||
static int test_memset(int off_dst, UNUSED int off_src, size_t len)
|
||||
{
|
||||
fill(dst);
|
||||
fill(sys);
|
||||
|
||||
memset(dst + off_dst, 0, len);
|
||||
naive_memset(sys + off_dst, 0, len);
|
||||
|
||||
return cmp(dst, sys);
|
||||
}
|
||||
|
||||
static int test_memmove(int off_dst, int off_src, size_t len)
|
||||
{
|
||||
fill(dst);
|
||||
fill(sys);
|
||||
|
||||
memmove(dst + off_dst, dst + off_src, len);
|
||||
naive_memmove(sys + off_dst, sys + off_src, len);
|
||||
|
||||
return cmp(dst, sys);
|
||||
}
|
||||
|
||||
//---
|
||||
// Automated tests
|
||||
//
|
||||
// These tests are meant to check all size/alignment scenarios for the
|
||||
// core memory functions. Two intervals of sizes are tested:
|
||||
// - 12..15 bytes, expected to be handled naively
|
||||
// - 192..195 bytes, expected to trigger alignment-related optimizations
|
||||
// For each of these intervals, all alignments possibilities are tested:
|
||||
// - 4n + { 0,1,2,3 } for the source address
|
||||
// - 4n + { 0,1,2,3 } for destination address
|
||||
// Also, the source and destination regions are made to overlap to allow
|
||||
// non-trivial memmove() cases to be checked.
|
||||
//
|
||||
// The testing function non-zero if one or more tests fail.
|
||||
//---
|
||||
|
||||
/* test() - check core memory functions in various size/alignment scenarios
|
||||
|
||||
The function to test takes three arguments: two buffer offsets and the size
|
||||
of the operation. Bounds need no be checked. It must return 0 in case of
|
||||
success and non-zero in case of failure.
|
||||
|
||||
@func Function to test, will be called with various sizes and alignments
|
||||
@count If non-null, set to number of tests performed
|
||||
Returns the number of failed tests; thus, non-zero indicates failure. */
|
||||
static int test(int (*func)(int off_dst, int off_src, size_t size), int *count)
|
||||
{
|
||||
/* Number of failed tests */
|
||||
int failed = 0;
|
||||
/* Number of tests */
|
||||
int tests = 0;
|
||||
|
||||
/* For each source and destination alignment... */
|
||||
for(int dst_al = 0; dst_al < 4; dst_al++)
|
||||
for(int src_al = 0; src_al < 4; src_al++)
|
||||
/* For each "alignment" of operation size... */
|
||||
for(int len_al = 0; len_al < 4; len_al++)
|
||||
{
|
||||
/* Try a small size first */
|
||||
failed += !!func(96 + dst_al, 96 + src_al, 12 + len_al);
|
||||
/* Then a medium region without overlapping */
|
||||
failed += !!func(4 + dst_al, 128 + src_al, 92 + len_al);
|
||||
/* A large region with left-right overlapping */
|
||||
failed += !!func(64 + dst_al, 96 + src_al, 128 + len_al);
|
||||
/* A large region with right-left overlapping */
|
||||
failed += !!func(96 + dst_al, 64 + src_al, 128 + len_al);
|
||||
|
||||
tests += 4;
|
||||
}
|
||||
|
||||
if(count) *count = tests;
|
||||
return failed;
|
||||
}
|
||||
|
||||
//---
|
||||
// Main function
|
||||
//---
|
||||
|
||||
/* memfunctest() - check the bejavior of the core memory functions
|
||||
Returns non-zero if any test fails. */
|
||||
int memfunctest(void)
|
||||
{
|
||||
int count = 0, failed = 0, count_one, failed_one;
|
||||
fill(src);
|
||||
|
||||
failed_one = test(test_memcpy, &count_one);
|
||||
failed += failed_one;
|
||||
count += count_one;
|
||||
|
||||
failed_one = test(test_memset, &count_one);
|
||||
failed += failed_one;
|
||||
count += count_one;
|
||||
|
||||
failed_one = test(test_memmove, &count_one);
|
||||
failed += failed_one;
|
||||
count += count_one;
|
||||
|
||||
char str[21];
|
||||
sprintf(str, "Score: %d/%d.", count - failed, count);
|
||||
Print(str);
|
||||
|
||||
return (failed != 0);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
//---
|
||||
// memfunctest - Check the behaviour of the core memory functions
|
||||
//
|
||||
// This small program checks that memcpy(), memset() and memmove() work
|
||||
// properly in all source/destination alignment, size, overlap scenarios.
|
||||
// It also checks both small and large areas to trigger usual optimizations.
|
||||
//---
|
||||
|
||||
#ifndef __MEMFUNCTEST_H__
|
||||
#define __MEMFUNCTEST_H__
|
||||
|
||||
/* memfunctest() - check the bejavior of the core memory functions
|
||||
Displays the test result on the screen.
|
||||
Returns non-zero if any test fails. */
|
||||
int memfunctest(void);
|
||||
|
||||
#endif /* __MEMFUNCTEST_H__ */
|
Loading…
Reference in New Issue