skip to content
==> tests/reply.c <==
1/* Answered, dropped unanswered, answered too late, and across threads. */
2#include "mesh/check.h"
3#include "mesh/buf.h"
4#include "mesh/reply.h"
5
6#include <stdlib.h>
7
8#include <pthread.h>
9
10static void *answer_later(void *arg) {
11    mesh_sleep_us(20000);
12    mesh_reply_okf(arg, "%s %d", "blink", 412);
13    return NULL;
14}
15
16int main(void) {
17    mesh_reply *r = mesh_reply_new();
18    mesh_reply_ok(mesh_reply_sender(r), "slot 3");
19    mesh_result x;
20    CHECK_I(mesh_reply_wait(r, 100, &x), MESH_CHAN_OK);
21    CHECK(x.ok);
22    CHECK_S(x.text, "slot 3");
23    mesh_result_free(&x);
24    mesh_reply_release(r);
25
26    /* Dropped unanswered: the waiter knows at once. */
27    r = mesh_reply_new();
28    mesh_reply_drop(mesh_reply_sender(r));
29    int64_t t0 = mesh_mono_ms();
30    CHECK_I(mesh_reply_wait(r, 5000, &x), MESH_CHAN_CLOSED);
31    CHECK(mesh_mono_ms() - t0 < 1000);
32    mesh_reply_release(r);
33
34    /* A thread answers within the timeout. */
35    r = mesh_reply_new();
36    pthread_t th;
37    pthread_create(&th, NULL, answer_later, mesh_reply_sender(r));
38    CHECK_I(mesh_reply_wait(r, 5000, &x), MESH_CHAN_OK);
39    CHECK_S(x.text, "blink 412");
40    mesh_result_free(&x);
41    pthread_join(th, NULL);
42    mesh_reply_release(r);
43
44    /* Too late: the waiter gave up; the answer is freed with the channel (no leak under ASan). */
45    r = mesh_reply_new();
46    mesh_reply *s = mesh_reply_sender(r);
47    CHECK_I(mesh_reply_wait(r, 10, &x), MESH_CHAN_TIMEOUT);
48    mesh_reply_release(r);
49    mesh_reply_errf(s, "no program %s", "\"x\"");
50
51    /* Values and bytes; clones. */
52    r = mesh_reply_new();
53    mesh_reply *c = mesh_reply_clone(r);
54    mesh_reply_value(mesh_reply_sender(r), 7);
55    mesh_reply_bytes(c, "abc", 3);
56    CHECK_I(mesh_reply_wait(r, 100, &x), MESH_CHAN_OK);
57    CHECK_U(x.value, 7);
58    CHECK_I(mesh_reply_wait(r, 100, &x), MESH_CHAN_OK);
59    CHECK_U(x.len, 3);
60    CHECK(x.bytes[0] == 'a' && x.bytes[2] == 'c');
61    mesh_result_free(&x);
62    mesh_reply_release(r);
63
64    /* A pointer payload: taken, or freed with the channel when nobody waits. */
65    r = mesh_reply_new();
66    mesh_reply_ptr(mesh_reply_sender(r), mesh_xstrdup("inventory"), free);
67    CHECK_I(mesh_reply_wait(r, 100, &x), MESH_CHAN_OK);
68    CHECK_S(x.ptr, "inventory");
69    mesh_result_free(&x);
70    mesh_reply_release(r);
71    r = mesh_reply_new();
72    s = mesh_reply_sender(r);
73    mesh_reply_release(r);
74    mesh_reply_ptr(s, mesh_xstrdup("nobody"), free);
75    return mesh_check_done();
76}