aboutsummaryrefslogtreecommitdiffstats
path: root/prototypes/connections/test-program.c
blob: 6a4a19d83159ec8abd55df5b890dc34715888c4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "program.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 PureProgram parse(const char *source) {
    PureProgram program;
    char error[160];
    if (!pure_program_parse(source, strlen(source), &program, error, sizeof(error))) {
        fprintf(stderr, "%s\n", error); exit(1);
    }
    return program;
}
static void invalid(const char *source) {
    PureProgram program;
    memset(&program, 0x5a, sizeof(program));
    unsigned char original[sizeof(program)];
    memcpy(original, &program, sizeof(program));
    char error[160];
    CHECK(!pure_program_parse(source, strlen(source), &program, error, sizeof(error)));
    CHECK(*error && !memcmp(original, &program, sizeof(program)));
}
int main(void) {
    char source[4096];
    snprintf(source, sizeof(source), "%s %s", get, put);
    PureProgram plan = parse(source);
    CHECK(plan.read.to_end && plan.write.to_end && !plan.reply_input);
    CHECK(!plan.view_definitions && !plan.read_required && !plan.input_required);
    snprintf(source, sizeof(source), "%s on put { let a = range(request.body, 2, 10); "
        "let b = range(a, 3, 4); let alias = b; "
        "let saved = store.write(request.key, request.revision, alias); reply(saved, b); }", get);
    plan = parse(source);
    CHECK(plan.write.offset == 5 && plan.write.length == 4 && !plan.write.to_end);
    CHECK(plan.reply.offset == 5 && plan.reply.length == 4 && plan.reply_input);
    CHECK(plan.input_required == 12 && plan.range_definitions == 2 && plan.view_definitions == 3);
    /* Ordered reference views keep even unused bounds failures observable. */
    unsigned char bytes[160];
    for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)(i * 7);
    size_t comparisons = 0;
    for (size_t a = 0; a < 4; ++a) for (size_t b = 0; b < 6; ++b)
        for (size_t c = 0; c <= b; ++c) for (size_t d = 0; d <= b - c; ++d) {
            size_t unused_end = (a + b + c) % 12;
            snprintf(source, sizeof(source), "on get { let o = store.read(request.key); "
                "let unused = range(o.body, %zu, 0); let first = range(o.body, %zu, %zu); "
                "let second = range(first, %zu, %zu); reply(o, second); } %s",
                unused_end, a, b, c, d, put);
            plan = parse(source);
            for (size_t n = 0; n < 16; ++n) {
                bool reference_ok = unused_end <= n && a <= n && b <= n - a;
                PureSpan selected;
                bool prepared_ok = n >= plan.read_required &&
                    pure_region_span(plan.read, (PureSpan){bytes, n}, &selected);
                CHECK(reference_ok == prepared_ok);
                if (reference_ok) {
                    CHECK(selected.size == d);
                    CHECK(!d || !memcmp(selected.data, bytes + a + c, d));
                }
                ++comparisons;
            }
        }
    snprintf(source, sizeof(source), "on get { let o = store.read(request.key); reply(o); } %s", put);
    plan = parse(source);
    CHECK(!plan.read.to_end && !plan.read.length);
    const char *bad_get[] = {
        "on get { let o = store.read(request.key); let x = range(o.body, 0, 2); let y = range(x, 2, 1); reply(o, y); }",
        "on get { let o = store.read(request.key); let x = range(o.body, 184467440737095516160, 1); reply(o, x); }",
        "on get { let o = store.read(request.key); let x = range(o.body, 1449984, 1); reply(o, x); }",
        "on get { let o = store.read(request.key); let o = o.body; reply(o); }",
        "on get { let o = store.read(request.key); let x = x; reply(o, x); }",
        "on get { let o = store.read(request.key); let x = store.read(request.key); reply(x); }",
        "on get { let o = store.read(request.key); reply(o, request.body); }",
        "on get { let o = store.read(request.key); let x = o.body; reply(x); }",
        "on get { let o = store.read(request.key); reply(o.body); }",
        "on get { let o = store.read(request.key); reply(o); let x = o.body; }",
        "on get { let o = store.read(request.key); reply(o);", "on get {}"
    };
    for (size_t i = 0; i < sizeof(bad_get) / sizeof(*bad_get); ++i) {
        snprintf(source, sizeof(source), "%s %s", bad_get[i], put); invalid(source);
    }
    const char *bad_put[] = {
        "on put { let s = store.write(request.key, request.revision, request.body); let b = range(request.body, 0, 1); reply(s, b); }",
        "on put { let s = store.write(request.key, request.revision, request.body); reply(s, s.body); }",
        "on put { let s = store.read(request.key); reply(s); }"
    };
    for (size_t i = 0; i < sizeof(bad_put) / sizeof(*bad_put); ++i) {
        snprintf(source, sizeof(source), "%s %s", get, bad_put[i]); invalid(source);
    }
    invalid(get);
    snprintf(source, sizeof(source), "%s %s %s", get, get, put); invalid(source);
    snprintf(source, sizeof(source), "%s %s garbage", get, put); invalid(source);
    snprintf(source, sizeof(source), "on get { let o = store.read(request.key); ");
    for (size_t i = 0; i < 32; ++i) {
        size_t used = strlen(source);
        snprintf(source + used, sizeof(source) - used, "let x%zu = o.body; ", i);
    }
    size_t used = strlen(source);
    snprintf(source + used, sizeof(source) - used, "reply(o); } %s", put); invalid(source);
    char oversized[PURE_PROGRAM_LIMIT + 1];
    memset(oversized, ' ', sizeof(oversized));
    char error[160];
    CHECK(!pure_program_parse(oversized, sizeof(oversized), &plan, error, sizeof(error)));
    const char embedded[] = "on get\0{}";
    CHECK(!pure_program_parse(embedded, sizeof(embedded) - 1, &plan, error, sizeof(error)));
    PureSpan selected;
    CHECK(pure_region_span((PureRegion){0}, (PureSpan){0}, &selected) && !selected.data && !selected.size);
    printf("{\"program\":\"prepare-views-preserve-guards-types-effects-and-atomic-install\","
           "\"boundary_semantic_comparisons\":%zu}\n", comparisons);
    return 0;
}