Files
trikkeSensors/tests/transport_fixture.c

135 lines
4.5 KiB
C

#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_FATAL ||
!sender.pending || mock.begin_calls != 4 || mock.poll_calls != 3 ||
trikke_transport_sender_step(
&sender, &transport, packet, sizeof(packet)) !=
TRIKKE_TRANSPORT_FATAL ||
mock.begin_calls != 4 || mock.poll_calls != 4) {
return fail(6, "retry after acceptance must fail closed without resubmit");
}
trikke_transport_sender_init(&sender);
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;
}