aboutsummaryrefslogtreecommitdiffstats
path: root/prototypes/workbench/native/peer-wire-test.c
blob: 7b281455d33e46b37e399ed967ee5d40a89e4ea3 (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
#include "peer-wire.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <string.h>

/* Codec test double; no VM instance or TLS process is needed to check the
 * on-wire representation and malformed-frame rejection. */
double pure_scalar_get_state(PureScalar *scalar, uint32_t id) {
    (void)scalar;
    return id == 0 ? 12.5 : -0.0;
}
int main(void) {
    PureScalarState states[] = {{"x", 0}, {"y", 0}};
    PureScalarInput inputs[] = {
        {"key", "Space", NULL, PURE_KEY},
        {"point", NULL, "shape", PURE_POINT},
        {"routed", NULL, NULL, PURE_ROUTED},
        {"value", NULL, NULL, PURE_VALUE},
    };
    PureScalarTarget targets[] = {{2, 0, 1, "shape"}};
    PureScalarPlan plan = {.state_count = 2, .input_count = 4, .target_count = 1,
                           .states = states, .inputs = inputs, .targets = targets};
    for (unsigned i = 0; i < 32; ++i) plan.identity[i] = (unsigned char)(i + 1);
    PureNativeApp app = {.plan = &plan, .revision = 7, .stored_revision = 3};
    unsigned char hello[PURE_PEER_HELLO_BYTES];
    pure_peer_hello(&app, hello);
    int64_t revision = -1, stored = -1;
    assert(pure_peer_check_hello(hello, sizeof(hello), &plan, &revision, &stored));
    assert(revision == 7 && stored == 3 && !memcmp(hello, "PUR1", 4));
    hello[4] ^= 1;
    assert(!pure_peer_check_hello(hello, sizeof(hello), &plan, &revision, &stored));
    hello[4] ^= 1;
    assert(!pure_peer_check_hello(hello, sizeof(hello) - 1, &plan, &revision, &stored));

    unsigned char wire[PURE_PEER_REQUEST_MAX];
    PurePeerRequest request = {.operation = PURE_PEER_STATE};
    assert(pure_peer_encode_request(&request, &plan, wire) == 1);
    PurePeerRequest decoded;
    assert(pure_peer_decode_request(wire, 1, &plan, &decoded) && decoded.operation == PURE_PEER_STATE);
    assert(!pure_peer_decode_request(wire, 2, &plan, &decoded));
    request = (PurePeerRequest){.operation = PURE_PEER_SAVE, .expected = 0x0102030405060708LL};
    assert(pure_peer_encode_request(&request, &plan, wire) == 9);
    assert(wire[1] == 1 && wire[8] == 8);
    assert(pure_peer_decode_request(wire, 9, &plan, &decoded) && decoded.expected == request.expected);
    wire[1] = 255;
    assert(!pure_peer_decode_request(wire, 9, &plan, &decoded));

    request = (PurePeerRequest){.operation = PURE_PEER_ACTION, .expected = 7,
        .action = {.input = 0, .phase = PURE_DOWN, .target = UINT32_MAX}};
    assert(pure_peer_encode_request(&request, &plan, wire) == 12);
    assert(pure_peer_decode_request(wire, 12, &plan, &decoded) && decoded.action.input == 0);
    request.action = (PureAction){.input = 3, .phase = PURE_CHANGE, .target = UINT32_MAX, .x = 12.5};
    assert(pure_peer_encode_request(&request, &plan, wire) == 20);
    assert(pure_peer_decode_request(wire, 20, &plan, &decoded) && decoded.action.x == 12.5);
    memset(wire + 12, 255, 8);
    assert(!pure_peer_decode_request(wire, 20, &plan, &decoded));
    request.action = (PureAction){.input = 1, .phase = PURE_MOVE, .target = UINT32_MAX, .x = 100, .y = -0.0};
    assert(pure_peer_encode_request(&request, &plan, wire) == 28);
    assert(pure_peer_decode_request(wire, 28, &plan, &decoded) && decoded.action.x == 100 && signbit(decoded.action.y));
    request.action = (PureAction){.input = 2, .phase = PURE_UP, .target = 0, .x = 5, .y = 6};
    assert(pure_peer_encode_request(&request, &plan, wire) == 28);
    assert(pure_peer_decode_request(wire, 28, &plan, &decoded) && decoded.action.target == 0);
    wire[11] = 1;
    assert(!pure_peer_decode_request(wire, 28, &plan, &decoded));
    request.action = (PureAction){.input = UINT32_MAX, .phase = PURE_FRAME, .target = UINT32_MAX};
    assert(pure_peer_encode_request(&request, &plan, wire) == 12);
    assert(pure_peer_decode_request(wire, 12, &plan, &decoded) && decoded.action.phase == PURE_FRAME);

    unsigned char reply[PURE_PEER_REPLY_MAX];
    size_t length = pure_peer_encode_reply(&app, PURE_CONFLICT, reply);
    assert(length == 42 && reply[0] == 2 && reply[25] == 2);
    PurePeerReply decoded_reply;
    assert(pure_peer_decode_reply(reply, length, &plan, &decoded_reply));
    assert(decoded_reply.revision == 7 && decoded_reply.stored_revision == 3);
    assert(decoded_reply.states[0] == 12.5 && signbit(decoded_reply.states[1]));
    reply[25] = 3;
    assert(!pure_peer_decode_reply(reply, length, &plan, &decoded_reply));
    reply[25] = 2;
    assert(!pure_peer_decode_reply(reply, length - 1, &plan, &decoded_reply));
    reply[0] = 255;
    assert(!pure_peer_decode_reply(reply, length, &plan, &decoded_reply));
    puts("peer wire: bounded identity, revisions, actions, finite states and malformed frames pass");
    return 0;
}