harden USB telemetry transport
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "trikke_transport.h"
|
||||
|
||||
typedef struct {
|
||||
trikke_transport_status_t begin_status;
|
||||
trikke_transport_status_t poll_status;
|
||||
unsigned int begin_calls;
|
||||
unsigned int poll_calls;
|
||||
const uint8_t *packet;
|
||||
size_t packet_size;
|
||||
} mock_transport_t;
|
||||
|
||||
static int fail(int code, const char *message)
|
||||
{
|
||||
fprintf(stderr, "transport fixture failure %d: %s\n", code, message);
|
||||
return code;
|
||||
}
|
||||
|
||||
static trikke_transport_status_t mock_begin(
|
||||
void *context,
|
||||
const uint8_t *packet,
|
||||
size_t packet_size)
|
||||
{
|
||||
mock_transport_t *mock = context;
|
||||
++mock->begin_calls;
|
||||
mock->packet = packet;
|
||||
mock->packet_size = packet_size;
|
||||
return mock->begin_status;
|
||||
}
|
||||
|
||||
static trikke_transport_status_t mock_poll(void *context)
|
||||
{
|
||||
mock_transport_t *mock = context;
|
||||
++mock->poll_calls;
|
||||
return mock->poll_status;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const uint8_t packet[] = {0x54, 0x52, 0x4B, 0x31};
|
||||
mock_transport_t mock = {
|
||||
.begin_status = TRIKKE_TRANSPORT_RETRY,
|
||||
.poll_status = TRIKKE_TRANSPORT_PENDING,
|
||||
};
|
||||
const trikke_transport_t transport = {
|
||||
.context = &mock,
|
||||
.begin = mock_begin,
|
||||
.poll = mock_poll,
|
||||
};
|
||||
trikke_transport_sender_t sender;
|
||||
trikke_transport_sender_init(&sender);
|
||||
|
||||
if (trikke_transport_sender_step(
|
||||
&sender, &transport, packet, sizeof(packet)) !=
|
||||
TRIKKE_TRANSPORT_RETRY ||
|
||||
sender.pending || mock.begin_calls != 1 || mock.poll_calls != 0 ||
|
||||
mock.packet != packet || mock.packet_size != sizeof(packet)) {
|
||||
return fail(1, "zero-accept submission must remain retryable");
|
||||
}
|
||||
|
||||
mock.begin_status = TRIKKE_TRANSPORT_PENDING;
|
||||
if (trikke_transport_sender_step(
|
||||
&sender, &transport, packet, sizeof(packet)) !=
|
||||
TRIKKE_TRANSPORT_PENDING ||
|
||||
!sender.pending || mock.begin_calls != 2 || mock.poll_calls != 0) {
|
||||
return fail(2, "accepted submission must become pending");
|
||||
}
|
||||
|
||||
if (trikke_transport_sender_step(
|
||||
&sender, &transport, packet, sizeof(packet)) !=
|
||||
TRIKKE_TRANSPORT_PENDING ||
|
||||
!sender.pending || mock.begin_calls != 2 || mock.poll_calls != 1) {
|
||||
return fail(3, "pending transfer must poll without resubmission");
|
||||
}
|
||||
|
||||
mock.poll_status = TRIKKE_TRANSPORT_COMPLETE;
|
||||
if (trikke_transport_sender_step(
|
||||
&sender, &transport, packet, sizeof(packet)) !=
|
||||
TRIKKE_TRANSPORT_COMPLETE ||
|
||||
sender.pending || mock.begin_calls != 2 || mock.poll_calls != 2) {
|
||||
return fail(4, "completed transfer must return to idle");
|
||||
}
|
||||
|
||||
mock.begin_status = TRIKKE_TRANSPORT_COMPLETE;
|
||||
if (trikke_transport_sender_step(
|
||||
&sender, &transport, packet, sizeof(packet)) !=
|
||||
TRIKKE_TRANSPORT_COMPLETE ||
|
||||
sender.pending || mock.begin_calls != 3) {
|
||||
return fail(5, "synchronous completion contract");
|
||||
}
|
||||
|
||||
mock.begin_status = TRIKKE_TRANSPORT_PENDING;
|
||||
mock.poll_status = TRIKKE_TRANSPORT_RETRY;
|
||||
if (trikke_transport_sender_step(
|
||||
&sender, &transport, packet, sizeof(packet)) !=
|
||||
TRIKKE_TRANSPORT_PENDING ||
|
||||
trikke_transport_sender_step(
|
||||
&sender, &transport, packet, sizeof(packet)) !=
|
||||
TRIKKE_TRANSPORT_RETRY ||
|
||||
sender.pending) {
|
||||
return fail(6, "backend-confirmed safe retry must return to idle");
|
||||
}
|
||||
|
||||
if (trikke_transport_sender_step(
|
||||
NULL, &transport, packet, sizeof(packet)) !=
|
||||
TRIKKE_TRANSPORT_FATAL ||
|
||||
trikke_transport_sender_step(
|
||||
&sender, NULL, packet, sizeof(packet)) != TRIKKE_TRANSPORT_FATAL ||
|
||||
trikke_transport_sender_step(
|
||||
&sender, &transport, NULL, sizeof(packet)) !=
|
||||
TRIKKE_TRANSPORT_FATAL ||
|
||||
trikke_transport_sender_step(
|
||||
&sender, &transport, packet, 0) != TRIKKE_TRANSPORT_FATAL) {
|
||||
return fail(7, "invalid arguments must fail closed");
|
||||
}
|
||||
|
||||
mock.begin_status = (trikke_transport_status_t)99;
|
||||
if (trikke_transport_sender_step(
|
||||
&sender, &transport, packet, sizeof(packet)) !=
|
||||
TRIKKE_TRANSPORT_FATAL ||
|
||||
sender.pending) {
|
||||
return fail(8, "unknown backend status must fail closed");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user