==> 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}