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