diff options
| author | eunhhu <[email protected]> | 2026-09-24 17:14:54 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-24 17:14:54 +0100 |
| commit | b1ce1927022d374198441afafeb27199fc8a052a (patch) | |
| tree | 6021f175f4c67ed03b44240eaa2f90d846f12f6f /prototypes/connections/test-fields.c | |
| parent | d34f9426d5317a1948f12f229439946728bc342a (diff) | |
| download | pure-b1ce1927022d374198441afafeb27199fc8a052a.tar.gz pure-b1ce1927022d374198441afafeb27199fc8a052a.zip | |
Establish native micro runtime checkpoint
Diffstat (limited to 'prototypes/connections/test-fields.c')
| -rw-r--r-- | prototypes/connections/test-fields.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/prototypes/connections/test-fields.c b/prototypes/connections/test-fields.c new file mode 100644 index 0000000..63dfc3e --- /dev/null +++ b/prototypes/connections/test-fields.c @@ -0,0 +1,153 @@ +#include "program.h" +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0) +static const char get[] = "on get { let o = store.read(request.key); reply(o, o.body); }"; +static const char put[] = "on put { let s = store.write(request.key, request.revision, request.body); reply(s); }"; +static const char layout[] = "layout Envelope { marker: bytes[1]; start: u32le; count: u32le; text: bytes; }"; +static PureProgram parse(const char *source) { + PureProgram p; + char error[160]; + if (!pure_program_parse(source, strlen(source), &p, error, sizeof(error))) { + fprintf(stderr, "%s\n", error); exit(1); + } + return p; +} +static void invalid(const char *source) { + PureProgram p; + memset(&p, 0x5a, sizeof(p)); + unsigned char before[sizeof(p)]; + memcpy(before, &p, sizeof(p)); + char error[160]; + CHECK(!pure_program_parse(source, strlen(source), &p, error, sizeof(error))); + CHECK(*error && !memcmp(before, &p, sizeof(p))); +} +static void encode(unsigned char *at, uint32_t value) { + for (unsigned i = 0; i < 4; ++i) at[i] = (unsigned char)(value >> (8 * i)); +} +int main(void) { + char source[8000]; + snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); " + "let alias = input; let start = alias.start; let text = alias.text; " + "let selected = range(text, start, alias.count); let result = selected; " + "let saved = store.write(request.key, request.revision, result); reply(saved, selected); }", layout, get); + PureProgram p = parse(source); + CHECK(p.input_steps == 1 && p.input_required == 9 && p.write_step == 1 && p.reply_step == 1); + CHECK(p.steps[0].source.offset == 9 && p.steps[0].source.to_end); + CHECK(p.steps[0].offset.value == 1 && p.steps[0].offset.from_u32le); + CHECK(p.steps[0].length.value == 5 && p.steps[0].length.from_u32le); + unsigned char bytes[609]; + for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)(i * 13); + PureSpan stored, returned; + for (size_t n = 0; n < 9; ++n) { + CHECK(!pure_program_input(&p, (PureSpan){bytes, n}, &stored, &returned)); + CHECK(!stored.size && !returned.size); + } + const uint32_t offsets[] = {0, 1, 255, 257, 599, 600, 601, UINT32_MAX}; + const uint32_t counts[] = {0, 1, 2, 260, 600, UINT32_MAX}; + size_t comparisons = 0; + for (size_t i = 0; i < sizeof(offsets) / sizeof(*offsets); ++i) + for (size_t j = 0; j < sizeof(counts) / sizeof(*counts); ++j) { + uint32_t start = offsets[i], count = counts[j]; + encode(bytes + 1, start); + encode(bytes + 5, count); + bool expected = start <= 600 && count <= 600 - start; + CHECK(pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned) == expected); + if (expected) { + CHECK(stored.size == count && returned.size == count && stored.data == returned.data); + CHECK(!count || stored.data == bytes + 9 + start); + } else CHECK(!stored.size && !returned.size); + ++comparisons; + } + snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); " + "let first = range(input.text, input.start, input.count); let second = range(first, 1, 2); " + "let saved = store.write(request.key, request.revision, second); reply(saved, second); }", layout, get); + p = parse(source); + CHECK(p.input_steps == 2 && p.steps[1].source_step == 1); + encode(bytes + 1, 3); encode(bytes + 5, 4); + CHECK(pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned)); + CHECK(stored.size == 2 && stored.data == bytes + 13); + encode(bytes + 5, 2); + CHECK(!pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned)); + snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); " + "let unused = range(input.text, input.start, input.count); " + "let saved = store.write(request.key, request.revision, input.text); reply(saved); }", layout, get); + p = parse(source); + encode(bytes + 1, UINT32_MAX); + CHECK(!pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned)); + + snprintf(source, sizeof(source), "%s on get { let o = store.read(request.key); " + "let input = view(Envelope, o.body); reply(o, input.text); } %s", layout, put); + p = parse(source); + CHECK(p.read.to_end && p.read.offset == 9 && p.read_required == 9 && !p.input_steps); + snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); " + "let selection = range(input.text, 2, 3); let saved = store.write(request.key, request.revision, selection); reply(saved); }", layout, get); + p = parse(source); + CHECK(!p.input_steps && p.write.offset == 11 && p.write.length == 3 && p.input_required == 14); + snprintf(source, sizeof(source), "layout Empty { body: bytes; } %s on put { let input = view(Empty, request.body); " + "let saved = store.write(request.key, request.revision, input.body); reply(saved, input.body); }", get); + p = parse(source); + CHECK(pure_program_input(&p, (PureSpan){0}, &stored, &returned) && !stored.size && !returned.size); + + const char *bad_layout[] = { + "layout E {}", "layout E { x: bytes; y: u32le; }", "layout E { x: u32le; x: bytes; }", + "layout E { x: bytes[1449985]; }", "layout E { x: bytes[1449984]; y: u32le; }", + "layout E { x: bytes[184467440737095516160]; }", "layout E { x: u64le; }", + "layout E { x: u32le; } layout E { y: bytes; }" + }; + for (size_t i = 0; i < sizeof(bad_layout) / sizeof(*bad_layout); ++i) { + snprintf(source, sizeof(source), "%s %s %s", bad_layout[i], get, put); invalid(source); + } + const char *bad_input[] = { + "let input = view(Missing, request.body);", + "let input = view(Envelope, request.body); let x = input.missing;", + "let input = view(Envelope, request.body); let x = range(input.text, input.text, 1);", + "let short = range(request.body, 0, 8); let input = view(Envelope, short);", + "let input = view(Envelope, request.body); let x = range(input.text, input.start, 20); let y = view(Envelope, x);" + }; + for (size_t i = 0; i < sizeof(bad_input) / sizeof(*bad_input); ++i) { + snprintf(source, sizeof(source), "%s %s on put { %s let saved = store.write(request.key, request.revision, request.body); reply(saved); }", layout, get, bad_input[i]); + invalid(source); + } + snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); " + "let saved = store.write(request.key, request.revision, input.start); reply(saved); }", layout, get); + invalid(source); + snprintf(source, sizeof(source), "%s on get { let o = store.read(request.key); let input = view(Envelope, o.body); " + "let x = range(input.text, input.start, input.count); reply(o, x); } %s", layout, put); + invalid(source); + for (size_t count = 8; count <= 9; ++count) { + snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); ", layout, get); + for (size_t i = 0; i < count; ++i) { + size_t used = strlen(source); + snprintf(source + used, sizeof(source) - used, "let v%zu = range(input.text, input.start, input.count); ", i); + } + size_t used = strlen(source); + snprintf(source + used, sizeof(source) - used, "let saved = store.write(request.key, request.revision, input.text); reply(saved); }"); + if (count == 8) CHECK(parse(source).input_steps == 8); else invalid(source); + } + for (size_t count = 4; count <= 5; ++count) { + source[0] = 0; + for (size_t i = 0; i < count; ++i) { + size_t used = strlen(source); + snprintf(source + used, sizeof(source) - used, "layout L%zu { body: bytes; } ", i); + } + size_t used = strlen(source); + snprintf(source + used, sizeof(source) - used, "%s %s", get, put); + if (count == 4) (void)parse(source); else invalid(source); + } + for (size_t count = 16; count <= 17; ++count) { + strcpy(source, "layout L { "); + for (size_t i = 0; i < count; ++i) { + size_t used = strlen(source); + snprintf(source + used, sizeof(source) - used, "f%zu: u32le; ", i); + } + size_t used = strlen(source); + snprintf(source + used, sizeof(source) - used, "} %s %s", get, put); + if (count == 16) (void)parse(source); else invalid(source); + } + printf("{\"fields\":\"named-layouts-unaligned-u32le-tail-dynamic-ranges-aliases-failures-limits\"," + "\"data_boundary_cases\":%zu}\n", comparisons); + return 0; +} |
