skip to content
==> tests/publish.c <==
1/* publish.rs's rings_are_per_slot, full_ring_and_rewind and policies. */
2#include "mesh/check.h"
3#include "mesh/publish.h"
4
5#include <stdlib.h>
6#include <string.h>
7
8static mesh_mailbox mb;
9
10/* Plays a node of slot s: completes ticket t with result r. */
11static void complete(uint32_t s, uint32_t t, uint32_t r) {
12    size_t c = mesh_prog_ctl(s), e = c + MESH_P_RING + MESH_ENTRY_BYTES * (size_t)(t % MESH_PROG_RING);
13    CHECK_U(mesh_mailbox_get(mb, e + MESH_E_SEQ), t + 1);
14    size_t k = mesh_mailbox_get(mb, e + MESH_E_SLOT);
15    mesh_mailbox_set(mb, c + MESH_P_RESULTS + 4 * k, r);
16    mesh_mailbox_publish(mb, c + MESH_P_MARKS + 4 * k, t + 1);
17}
18
19static mesh_manifest man(const char *extra) {
20    char text[512];
21    snprintf(text, sizeof text, "name = \"p\"\nabi = 6\nview_bytes = 0x1000\n%s", extra);
22    mesh_manifest m;
23    char *err = NULL;
24    if (!mesh_manifest_parse(text, strlen(text), &m, &err)) { fprintf(stderr, "%s\n", err); abort(); }
25    return m;
26}
27
28static size_t collect(mesh_pring *r, uint32_t *ticket, uint32_t *res) {
29    mesh_done *d;
30    size_t n;
31    mesh_pring_collect(r, mb, &d, &n);
32    if (n && ticket) *ticket = d[0].out.ticket;
33    if (n && res) *res = d[0].result;
34    free(d);
35    return n;
36}
37
38#define MS(x) ((int64_t)(x) * 1000000)
39
40int main(void) {
41    mb = mesh_mailbox_test();
42    mesh_pring a, b;
43    mesh_pring_init(&a, 0);
44    mesh_pring_init(&b, 5);
45    uint32_t t;
46    CHECK(mesh_pring_publish(&a, mb, MESH_OP_TASK, 9, mesh_kind_of(MESH_TK_AUTO), &t) && t == 0);
47    CHECK(mesh_pring_publish(&b, mb, 7, 1, mesh_kind_of(MESH_TK_AUTO), &t) && t == 0);
48    CHECK(mesh_pring_publish(&b, mb, 7, 2, mesh_kind_of(MESH_TK_AUTO), &t) && t == 1);
49    size_t e = mesh_prog_ctl(5) + MESH_P_RING + MESH_ENTRY_BYTES;
50    CHECK(mesh_mailbox_get(mb, e + MESH_E_OP) == 7 && mesh_mailbox_get(mb, e + MESH_E_ARG) == 2 && mesh_mailbox_get(mb, e + MESH_E_SEQ) == 2);
51    CHECK_U(mesh_mailbox_get64(mb, mesh_prog_ctl(5) + MESH_P_RING_TAIL), 2);
52    complete(5, 1, 33);
53    uint32_t tk = 99, res = 0;
54    CHECK_U(collect(&b, &tk, &res), 1);
55    CHECK(tk == 1 && res == 33);
56    CHECK(collect(&a, NULL, NULL) == 0 && !mesh_pring_idle(&a));
57    complete(0, 0, 34);
58    CHECK(collect(&a, NULL, &res) == 1 && res == 34);
59    CHECK(mesh_pring_idle(&a));
60
61    /* full_ring_and_rewind */
62    mesh_pring r;
63    mesh_pring_init(&r, 2);
64    int ok = 1;
65    for (uint32_t i = 0; i < MESH_PROG_RING; i++) ok &= mesh_pring_publish(&r, mb, 0, i, mesh_kind_of(MESH_TK_AUTO), &t) && t == i;
66    CHECK(ok);
67    CHECK(!mesh_pring_publish(&r, mb, 0, 0, mesh_kind_of(MESH_TK_AUTO), &t));
68    complete(2, 5, 0);
69    collect(&r, NULL, NULL);
70    CHECK(!mesh_pring_can_publish(&r));
71    complete(2, 0, 0);
72    collect(&r, NULL, NULL);
73    CHECK(mesh_pring_publish(&r, mb, 0, 0, mesh_kind_of(MESH_TK_AUTO), &t) && t == MESH_PROG_RING);
74    mesh_done *d;
75    size_t n;
76    mesh_pring_collect(&r, mb, &d, &n);
77    ok = 1;
78    for (size_t i = 0; i < n; i++) ok &= d[i].out.ticket != MESH_PROG_RING;
79    CHECK(ok);
80    free(d);
81    mesh_mailbox_set(mb, mesh_prog_ctl(2) + MESH_P_RING_HEAD, r.tail + 7);
82    mesh_mailbox_set(mb, mesh_prog_ctl(2) + MESH_P_ONLINE, 3);
83    mesh_out *lost;
84    mesh_pring_rewind(&r, mb, &lost, &n);
85    CHECK_U(n, MESH_PROG_RING - 1);
86    free(lost);
87    CHECK(mesh_mailbox_get(mb, mesh_prog_ctl(2) + MESH_P_RING_HEAD) == r.tail && mesh_mailbox_get(mb, mesh_prog_ctl(2) + MESH_P_ONLINE) == 0);
88    CHECK(mesh_pring_idle(&r));
89    mesh_pring_free(&r);
90
91    /* policies */
92    int64_t t0 = 1000000000000ll, last = t0;
93    mesh_manifest m = man("policy = \"continuous\"\nfanout = 3");
94    mesh_pring_init(&r, 0);
95    mesh_pring_free(&a);
96    CHECK_U(mesh_publish_auto(mb, &m, 0, &r, &last, t0), 3);
97    CHECK_U(mesh_publish_auto(mb, &m, 0, &r, &last, t0), 0);
98    uint32_t tl = r.tail;
99    complete(0, tl - 3, 0);
100    complete(0, tl - 2, 0);
101    collect(&r, NULL, NULL);
102    CHECK_U(mesh_publish_auto(mb, &m, 0, &r, &last, t0), 0);
103    complete(0, tl - 1, 0);
104    collect(&r, NULL, NULL);
105    CHECK_U(mesh_publish_auto(mb, &m, 0, &r, &last, t0), 3);
106    mesh_manifest_free(&m);
107    mesh_pring_free(&r);
108    m = man("policy = \"continuous\"\nfanout = 4\nin_flight = \"free\"");
109    mesh_pring_init(&r, 1);
110    CHECK_U(mesh_publish_auto(mb, &m, 0, &r, &last, t0), 4);
111    complete(1, 1, 0);
112    collect(&r, NULL, NULL);
113    CHECK_U(mesh_publish_auto(mb, &m, 0, &r, &last, t0), 1);
114    CHECK(mesh_pring_publish(&r, mb, 3, 0, mesh_kind_of(MESH_TK_INIT), &t));
115    CHECK_U(mesh_publish_auto(mb, &m, 0, &r, &last, t0), 0);
116    mesh_manifest_free(&m);
117    mesh_pring_free(&r);
118    m = man("policy = \"periodic\"\nhz = 10\nfanout = 2\nin_flight = \"free\"\narg = \"view_u32:0x1c\"");
119    mesh_mailbox_set(mb, 0x100000 + 0x1c, 40);
120    mesh_pring_init(&r, 3);
121    last = t0;
122    CHECK_U(mesh_publish_auto(mb, &m, 0x100000, &r, &last, t0 + MS(50)), 0);
123    CHECK_U(mesh_publish_auto(mb, &m, 0x100000, &r, &last, t0 + MS(100)), 2);
124    CHECK(last == t0 + MS(100));
125    e = mesh_prog_ctl(3) + MESH_P_RING;
126    CHECK(mesh_mailbox_get(mb, e + MESH_E_ARG) == 40 && mesh_mailbox_get(mb, e + MESH_ENTRY_BYTES + MESH_E_ARG) == 41);
127    int64_t late = t0 + MS(5000);
128    CHECK_U(mesh_publish_auto(mb, &m, 0x100000, &r, &last, late), 2);
129    CHECK(last == late);
130    CHECK_U(mesh_publish_auto(mb, &m, 0x100000, &r, &last, late), 0);
131    mesh_manifest_free(&m);
132    mesh_pring_free(&r);
133    m = man("policy = \"continuous\"\nfanout = 2");
134    mesh_pring_init(&r, 6);
135    for (uint32_t i = 0; i < MESH_PROG_RING - 1; i++) mesh_pring_publish(&r, mb, 3, i, mesh_kind_of(MESH_TK_INIT), &t);
136    CHECK_U(mesh_pring_room(&r), 1);
137    CHECK_U(mesh_publish_auto(mb, &m, 0, &r, &last, late), 0);
138    complete(6, 0, 0);
139    collect(&r, NULL, NULL);
140    CHECK_U(mesh_pring_room(&r), 2);
141    CHECK_U(mesh_publish_auto(mb, &m, 0, &r, &last, late), 2);
142    mesh_manifest_free(&m);
143    mesh_pring_free(&r);
144    m = man("");
145    mesh_pring_init(&r, 4);
146    CHECK_U(mesh_publish_auto(mb, &m, 0, &r, &last, late), 0);
147    mesh_manifest_free(&m);
148    mesh_pring_free(&r);
149    m = man("policy = \"periodic\"\nhz = 10\nfanout = 4");
150    mesh_pring_init(&r, 7);
151    last = t0;
152    CHECK_U(mesh_publish_parts(mb, &m, 0, &r, &last, t0 + MS(100), 3), 2);
153    e = mesh_prog_ctl(7) + MESH_P_RING;
154    CHECK(mesh_mailbox_get(mb, e + MESH_E_ARG) == 0 && mesh_mailbox_get(mb, e + MESH_ENTRY_BYTES + MESH_E_ARG) == 1);
155    CHECK_U(mesh_pring_auto_in_flight(&r), 2);
156    CHECK_U(mesh_publish_parts(mb, &m, 0, &r, &last, t0 + MS(200), 3), 0);
157    mesh_pring r2;
158    mesh_pring_init(&r2, 8);
159    int64_t last2 = t0;
160    CHECK_U(mesh_publish_parts(mb, &m, 0, &r2, &last2, t0 + MS(100), 9), 2);
161    e = mesh_prog_ctl(8) + MESH_P_RING;
162    CHECK(mesh_mailbox_get(mb, e + MESH_E_ARG) == 0 && mesh_mailbox_get(mb, e + MESH_ENTRY_BYTES + MESH_E_ARG) == 3);
163    mesh_pring r3;
164    mesh_pring_init(&r3, 9);
165    CHECK_U(mesh_publish_parts(mb, &m, 0, &r3, &last2, t0 + MS(1000), 0), 0);
166    CHECK(mesh_pring_publish(&r, mb, MESH_OP_FOLLOW, 2, mesh_kind_of(MESH_TK_FOLLOW), &t));
167    CHECK(mesh_pring_auto_in_flight(&r) == 2 && mesh_pring_follow_in_flight(&r) == 1);
168    mesh_manifest_free(&m);
169    mesh_pring_free(&r);
170    mesh_pring_free(&r2);
171    mesh_pring_free(&r3);
172    mesh_pring_free(&b);
173    free(mb.base);
174    return mesh_check_done();
175}