radix: Implement radix_tree_destroy()
[akaros.git] / user / utest / efence.c
1 #include <utest/utest.h>
2 #include <errno.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <math.h>
6 #include <limits.h>
7 #include <signal.h>
8 #include <pthread.h>
9 #include <setjmp.h>
10
11 TEST_SUITE("EFENCE");
12
13 /* <--- Begin definition of test cases ---> */
14
15 /* The guts of this test came from electric fence's tstheap:
16  *
17  *  Electric Fence - Red-Zone memory allocator.
18  *  Bruce Perens, 1988, 1993
19  *
20  *  For email below, drop spaces and <spam-buster> tag.
21  *  MODIFIED:  March 20, 2014 (jric<spam-buster> @ <spam-buster> chegg DOT com)
22  */
23
24 #define POOL_SIZE 1024
25 #define LARGEST_BUFFER 30000
26 #define TEST_DURATION 1000
27
28 static void *pool[POOL_SIZE];
29
30 bool test_alloc_and_free(void)
31 {
32         void **element;
33         size_t size;
34
35         for (int count = 0; count < TEST_DURATION; count++) {
36                 element = &pool[(int)(drand48() * POOL_SIZE)];
37                 size = (size_t)(drand48() * (LARGEST_BUFFER + 1));
38                 if (*element) {
39                         free(*element);
40                         *element = 0;
41                 } else if (size > 0) {
42                         *element = malloc(size);
43                         *(uint8_t*)(*element) = 0xab;
44                         *(uint8_t*)(*element + size - 1) = 0xcd;
45                 }
46         }
47         /* Surviving without page faulting is success. */
48         return TRUE;
49 }
50
51 /* The pointer Needs to be volatile, so that blob = malloc() gets assigned
52  * before the fault. */
53 static char *volatile blob;
54 static jmp_buf save;
55 static void *fault_addr;
56
57 static void segv_action(int signr, siginfo_t *si, void *arg)
58 {
59         fault_addr = si->si_addr;
60         longjmp(save, 1);
61 }
62
63 static struct sigaction sigact = {.sa_sigaction = segv_action, 0};
64
65 bool test_catching_fault(void)
66 {
67         pthread_yield();        /* link in pth for intra-thread signals (SIGSEGV) */
68         sigaction(SIGSEGV, &sigact, 0);
69         blob = malloc(PGSIZE);
70         if (!setjmp(save)) {
71                 /* First time through, we'll try to pagefault. */
72                 blob[PGSIZE + 1] = 0;
73                 UT_ASSERT_FMT("Tried to fault, but didn't!", FALSE);
74         }
75         /* Second time, we'll return via setjmp */
76         UT_ASSERT_FMT("Fault addr was %p, should be %p",
77                       fault_addr == blob + PGSIZE + 1, fault_addr,
78                       blob + PGSIZE + 1);
79         return TRUE;
80 }
81
82 /* <--- End definition of test cases ---> */
83
84 struct utest utests[] = {
85         UTEST_REG(alloc_and_free),
86         UTEST_REG(catching_fault),
87 };
88 int num_utests = sizeof(utests) / sizeof(struct utest);
89
90 int main(int argc, char *argv[])
91 {
92         // Run test suite passing it all the args as whitelist of what tests to run.
93         char **whitelist = &argv[1];
94         int whitelist_len = argc - 1;
95
96         RUN_TEST_SUITE(utests, num_utests, whitelist, whitelist_len);
97 }