==> tests/view_alloc.c <==1/* programs.rs's heap_first_fit and heap_double_free. */
2#include "mesh/check.h"
3#include "mesh/view_alloc.h"
4
5#include <signal.h>
6#include <stdlib.h>
7#include <sys/wait.h>
8#include <unistd.h>
9
10int main(void) {
11 static mesh_view_heap h;
12 mesh_view_heap_init(&h);
13 CHECK_U(mesh_view_heap_free_pages(&h), MESH_VIEW_PAGES);
14 uint32_t a, b, c, x;
15 CHECK(mesh_view_heap_alloc(&h, 0, &x) && x == 0);
16 CHECK(mesh_view_heap_alloc(&h, 0x1000, &a));
17 CHECK(mesh_view_heap_alloc(&h, 0x1001, &b));
18 CHECK(mesh_view_heap_alloc(&h, 1, &c));
19 CHECK(a == 0x100000 && b == 0x101000 && c == 0x103000);
20 CHECK_U(mesh_view_heap_free_pages(&h), MESH_VIEW_PAGES - 4);
21 mesh_view_heap_free(&h, b, 0x1001);
22 CHECK(mesh_view_heap_alloc(&h, 0x800, &x) && x == 0x101000);
23 CHECK(mesh_view_heap_alloc(&h, 0x3000, &x) && x == 0x104000);
24 CHECK(mesh_view_heap_alloc(&h, 0x1000, &x) && x == 0x102000);
25 mesh_view_heap_init(&h);
26 uint32_t all;
27 CHECK(mesh_view_heap_alloc(&h, (uint32_t)(MESH_VIEW_PAGES * MESH_VIEW_PAGE), &all) && all == MESH_VIEW_HEAP);
28 CHECK(!mesh_view_heap_alloc(&h, 1, &x));
29 CHECK_U(mesh_view_heap_largest_run(&h), 0);
30 mesh_view_heap_free(&h, all, (uint32_t)(MESH_VIEW_PAGES * MESH_VIEW_PAGE));
31 CHECK(mesh_view_heap_alloc(&h, 1, &x) && x == MESH_VIEW_HEAP);
32 CHECK_U(mesh_view_heap_largest_run(&h), MESH_VIEW_PAGES - 1);
33
34 /* A double free aborts (the Rust panics "freeing a free page"). */
35 pid_t pid = fork();
36 if (pid == 0) {
37 close(2);
38 static mesh_view_heap d;
39 mesh_view_heap_init(&d);
40 uint32_t o;
41 mesh_view_heap_alloc(&d, 1, &o);
42 mesh_view_heap_free(&d, o, 1);
43 mesh_view_heap_free(&d, o, 1);
44 _exit(0);
45 }
46 int st = 0;
47 waitpid(pid, &st, 0);
48 CHECK(WIFSIGNALED(st) && WTERMSIG(st) == SIGABRT);
49 return mesh_check_done();
50}