diff options
Diffstat (limited to 'tests/src/test_random.c')
| -rw-r--r-- | tests/src/test_random.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/tests/src/test_random.c b/tests/src/test_random.c new file mode 100644 index 0000000..f7247e2 --- /dev/null +++ b/tests/src/test_random.c @@ -0,0 +1,176 @@ +/** + * @file test_random.c + * @brief Randomized correctness test for malloc/free. + * + * Allocates random-sized blocks in TINY, SMALL, and LARGE ranges, + * fills them with a deterministic pattern, then verifies the data. + * Run with system malloc and LD_PRELOAD — output must match. + * + * Usage: test_random <seed> <count> + */ + +#include <stdlib.h> +#include <unistd.h> + +#define TINY_MAX 128 +#define SMALL_MAX 1024 +#define LARGE_MAX 8192 + +static void +_s_put_str (const char *str) +{ + const char *p; + + p = str; + while (*p) + p++; + write (1, str, (size_t)(p - str)); +} + +static void +_s_put_nbr (int n) +{ + char buf[12]; + int i; + + i = (int)sizeof (buf); + if (n == 0) + buf[--i] = '0'; + while (n > 0) + { + buf[--i] = '0' + (n % 10); + n /= 10; + } + write (1, buf + i, (size_t)(sizeof (buf) - i)); +} + +static unsigned char +_s_pattern (int seed, int alloc_index, int byte_index) +{ + return ((unsigned char)((seed * 31 + alloc_index * 7 + byte_index) & 0xFF)); +} + +static size_t +_s_rand_range (size_t min, size_t max) +{ + return (min + (size_t)rand () % (max - min + 1)); +} + +static int +_s_test_category (const char *label, size_t min, size_t max, int seed, + int base_index, int count) +{ + void *blocks[count]; + size_t sizes[count]; + unsigned char *data; + int fail; + int i; + int j; + + fail = 0; + i = 0; + while (i < count) + { + sizes[i] = _s_rand_range (min, max); + blocks[i] = malloc (sizes[i]); + if (!blocks[i]) + { + _s_put_str (label); + _s_put_str ("["); + _s_put_nbr (i); + _s_put_str ("]: malloc FAILED\n"); + fail = 1; + i++; + continue; + } + data = (unsigned char *)blocks[i]; + j = 0; + while (j < (int)sizes[i]) + { + data[j] = _s_pattern (seed, base_index + i, j); + j++; + } + i++; + } + i = 0; + while (i < count) + { + if (!blocks[i]) + { + i++; + continue; + } + data = (unsigned char *)blocks[i]; + j = 0; + while (j < (int)sizes[i]) + { + if (data[j] != _s_pattern (seed, base_index + i, j)) + { + _s_put_str (label); + _s_put_str ("["); + _s_put_nbr (i); + _s_put_str ("]: FAIL at byte "); + _s_put_nbr (j); + _s_put_str ("\n"); + fail = 1; + break; + } + j++; + } + if (j == (int)sizes[i]) + { + _s_put_str (label); + _s_put_str ("["); + _s_put_nbr (i); + _s_put_str ("]: OK ("); + _s_put_nbr ((int)sizes[i]); + _s_put_str (" bytes)\n"); + } + i++; + } + i = 0; + while (i < count) + { + free (blocks[i]); + i++; + } + return (fail); +} + +static int +_s_atoi (const char *str) +{ + int n; + + n = 0; + while (*str) + { + n = n * 10 + (*str - '0'); + str++; + } + return (n); +} + +int +main (int argc, char **argv) +{ + int seed; + int count; + int fail; + + if (argc != 3) + { + _s_put_str ("usage: test_random <seed> <count>\n"); + return (1); + } + seed = _s_atoi (argv[1]); + count = _s_atoi (argv[2]); + srand ((unsigned int)seed); + fail = 0; + fail |= _s_test_category ("TINY", 1, TINY_MAX, seed, 0, count); + fail |= _s_test_category ("SMALL", TINY_MAX + 1, SMALL_MAX, seed, count, + count); + fail |= _s_test_category ("LARGE", SMALL_MAX + 1, LARGE_MAX, seed, count * 2, + count); + return (fail); +} |
