skip to content
==> tests/wire.c <==
1/* The encoding's bytes, reads back, the short-read and UTF-8 errors with jobs.rs's text. */
2#include "mesh/jobs/wire.h"
3#include "mesh/check.h"
4
5#include <stdlib.h>
6#include <string.h>
7
8int main(void) {
9    msb w = {0};
10    mj_w_u8(&w, 1);
11    mj_w_u32(&w, 0x04030201);
12    mj_w_u64(&w, 0x0807060504030201u);
13    mj_w_str(&w, "p");
14    mj_ranges r = mj_ranges_of(1, 5);
15    mj_w_ranges(&w, &r);
16    static const uint8_t want[] = {1, 1, 2, 3, 4, 1, 2, 3, 4, 5, 6, 7, 8, 1, 0, 0, 0, 'p',
17                                   1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0};
18    CHECK_U(w.n, sizeof want);
19    CHECK(memcmp(w.p, want, sizeof want) == 0);
20    mj_rd rd = mj_rd_new(w.p, w.n);
21    uint8_t a;
22    uint32_t b;
23    uint64_t c;
24    char *s = NULL;
25    mj_ranges back = {0};
26    CHECK(mj_rd_u8(&rd, &a) && a == 1 && mj_rd_u32(&rd, &b) && b == 0x04030201 && mj_rd_u64(&rd, &c) && c == 0x0807060504030201u);
27    CHECK(mj_rd_str(&rd, &s) && strcmp(s, "p") == 0 && mj_rd_ranges(&rd, &back) && mj_ranges_eq(&back, &r) && mj_rd_done(&rd));
28    free(s);
29    /* Short: what was left, what was wanted, where. */
30    CHECK(!mj_rd_u32(&rd, &b));
31    CHECK_S(rd.err, "job frame: short (0 of 4 bytes at 38)");
32    CHECK(!mj_rd_u8(&rd, &a)); /* still failed, first message kept */
33    CHECK_S(rd.err, "job frame: short (0 of 4 bytes at 38)");
34    mj_rd_free(&rd);
35    /* Not UTF-8: an overlong, a surrogate, a truncated sequence; valid ones pass. */
36    static const uint8_t bad[][8] = {{2, 0, 0, 0, 0xc0, 0xaf}, {3, 0, 0, 0, 0xed, 0xa0, 0x80}, {1, 0, 0, 0, 0xe2}};
37    static const size_t badn[] = {6, 7, 5};
38    for (int i = 0; i < 3; i++) {
39        mj_rd x = mj_rd_new(bad[i], badn[i]);
40        CHECK(!mj_rd_str(&x, &s));
41        CHECK_S(x.err, "job frame: not UTF-8");
42        mj_rd_free(&x);
43    }
44    CHECK(mj_utf8_ok((const uint8_t *)"caf\xc3\xa9 \xf0\x9f\x98\x80", 10));
45    CHECK(!mj_utf8_ok((const uint8_t *)"\xf4\x90\x80\x80", 4));
46    /* from_utf8_lossy: a maximal invalid prefix is one U+FFFD (values from Rust). */
47    static const struct { const char *in; size_t n; const char *out; } lossy[] = {
48        {"ok", 2, "ok"}, {"a\xff" "b", 3, "a\xef\xbf\xbd" "b"}, {"\xe2\x82", 2, "\xef\xbf\xbd"}, {"\xe2\x82" "x", 3, "\xef\xbf\xbd" "x"},
49        {"\xed\xa0\x80", 3, "\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd"}, {"\xf0\x9f\x98", 3, "\xef\xbf\xbd"},
50        {"\xc0\xaf", 2, "\xef\xbf\xbd\xef\xbf\xbd"}, {"\xf4\x90\x80\x80", 4, "\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd"},
51    };
52    for (size_t i = 0; i < sizeof lossy / sizeof *lossy; i++) {
53        char *l = mj_utf8_lossy((const uint8_t *)lossy[i].in, lossy[i].n);
54        CHECK_S(l, lossy[i].out);
55        free(l);
56    }
57    mj_ranges_free(&r);
58    mj_ranges_free(&back);
59    msb_free(&w);
60    return mesh_check_done();
61}