aboutsummaryrefslogtreecommitdiffstats
path: root/tests/src/test_random.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/src/test_random.c')
-rw-r--r--tests/src/test_random.c176
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);
+}