skip to content
==> tests/compose.c <==
1/* place.rs: gather_scatter_state, composer_matches_frames. */
2#include "mesh/check.h"
3#include "mesh/place_compose.h"
4
5#include <stdlib.h>
6
7static mps_spec spec(void) {
8    mps_region st[] = {{0x0, 0x8}, {0x100, 0x4}}, out[] = {{0x1000, 0x40}, {0x1400, 0x40}};
9    return mps_new(2, st, 2, 0x4, out, 2, 0x2000, 4);
10}
11
12/* A fake view: byte i of region (o, n) is (o + i) ^ salt. */
13static void view(void *ctx, uint32_t o, uint32_t n, uint8_t *out) {
14    uint8_t salt = (uint8_t)(uintptr_t)ctx;
15    for (uint32_t i = 0; i < n; i++) out[i] = (uint8_t)(o + i) ^ salt;
16}
17
18typedef struct {
19    uint32_t off[4], len[4];
20    uint8_t b[4][16];
21    int n;
22} writes;
23
24static void rec(void *ctx, uint32_t off, const uint8_t *b, uint32_t len) {
25    writes *w = ctx;
26    w->off[w->n] = off, w->len[w->n] = len;
27    memcpy(w->b[w->n++], b, len);
28}
29
30static bool region_is(const uint8_t *b, uint32_t o, uint32_t n, uint8_t salt) {
31    for (uint32_t i = 0; i < n; i++)
32        if (b[i] != ((uint8_t)(o + i) ^ salt)) return false;
33    return true;
34}
35
36int main(void) {
37    mps_spec s = spec();
38    mpw_bytes st = mpc_read_state(&s, view, (void *)0);
39    CHECK_U(st.n, 12);
40    writes w = {0};
41    char *err = NULL;
42    CHECK(mpc_write_state(&s, st.b, st.n, rec, &w, &err));
43    CHECK(w.n == 2 && w.off[0] == 0 && w.len[0] == 8 && w.off[1] == 0x100 && region_is(w.b[1], 0x100, 4, 0));
44    CHECK(!mpc_write_state(&s, st.b + 1, st.n - 1, rec, &w, &err));
45    CHECK_S(err, "state of 11 bytes, the manifest declares 12");
46    free(err);
47    mpw_bytes d = mpc_gather(&s, 0xa, view, (void *)0);
48    CHECK_U(d.n, 2 * mps_part_bytes(&s));
49    CHECK(region_is(d.b, 0x1010, 16, 0));
50    uint8_t buf[0x80] = {0};
51    CHECK(mpc_scatter(&s, buf, sizeof buf, 0xa, d.b, d.n, &err));
52    CHECK(region_is(buf + 0x10, 0x1010, 16, 0) && region_is(buf + 0x70, 0x1430, 16, 0));
53    bool zero = true;
54    for (int i = 0; i < 0x10; i++) zero &= buf[i] == 0;
55    CHECK(zero);
56    CHECK(!mpc_scatter(&s, buf, sizeof buf, 0xe, d.b, d.n, &err));
57    CHECK_S(err, "frame data of 64 bytes, parts 0xe need 96");
58    free(err);
59    CHECK_U(mpc_sys_nibbles(0xa, 3), 0x3030);
60    mpw_bytes_free(&st), mpw_bytes_free(&d);
61
62    /* composer_matches_frames */
63    uint64_t t = 1000;
64    mpc_composer c = {0};
65    mpw_bytes p0 = mpc_gather(&s, 3, view, (void *)1), p2 = mpc_gather(&s, 4, view, (void *)2), p3 = mpc_gather(&s, 8, view, (void *)3);
66    mpc_whole wh;
67    CHECK(mpc_add(&c, &s, 5, 3, 0, p0.b, p0.n, t, &wh, &err) == 0);
68    CHECK(mpc_add(&c, &s, 6, 8, 2, p3.b, p3.n, t, &wh, &err) == 0);
69    CHECK(mpc_add(&c, &s, 6, 3, 0, p0.b, p0.n, t, &wh, &err) == 0);
70    CHECK(mpc_add(&c, &s, 6, 4, 1, p2.b, p2.n, t + 2000, &wh, &err) == 1);
71    CHECK(wh.frame == 6 && wh.sys == 0x2100 && wh.t0 == t);
72    CHECK(region_is(wh.buf, 0x1000, 16, 1) && region_is(wh.buf + 0x20, 0x1020, 16, 2) && region_is(wh.buf + 0x70, 0x1430, 16, 3));
73    free(wh.buf);
74    CHECK_U(c.n, 0);
75    CHECK(mpc_add(&c, &s, 5, 4, 1, p2.b, p2.n, t, &wh, &err) == 0);
76    CHECK(mpc_add(&c, &s, 5, 4, 1, p2.b, p2.n, t, &wh, &err) == -1);
77    CHECK_S(err, "frame 5: parts 0x4 arrived twice");
78    free(err);
79    for (uint32_t f = 10; f < 30; f++) mpc_add(&c, &s, f, 3, 0, p0.b, p0.n, t, &wh, &err);
80    CHECK_U(c.n, MPC_PENDING);
81    mpc_clear(&c);
82    mpw_bytes_free(&p0), mpw_bytes_free(&p2), mpw_bytes_free(&p3);
83    mps_free(&s);
84    return mesh_check_done();
85}