skip to content
==> 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}