141 lines
4.2 KiB
C
141 lines
4.2 KiB
C
/* Frame parser tests against the recovered 0x1bb1b11b framing. */
|
|
#include "mag160c/mag160c.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
static void put32(uint8_t *p, uint32_t v) {
|
|
p[0] = (uint8_t)v;
|
|
p[1] = (uint8_t)(v >> 8);
|
|
p[2] = (uint8_t)(v >> 16);
|
|
p[3] = (uint8_t)(v >> 24);
|
|
}
|
|
|
|
static void test_parse_valid(void) {
|
|
uint8_t frame[0x40];
|
|
memset(frame, 0xaa, sizeof(frame));
|
|
put32(frame + 0x00, 0x1bb1b11b);
|
|
put32(frame + 0x04, 42);
|
|
put32(frame + 0x08, 4);
|
|
put32(frame + 0x0c, 1);
|
|
put32(frame + 0x10, 1000);
|
|
frame[0x1c] = 0x34;
|
|
frame[0x1d] = 0x12;
|
|
put32(frame + 0x1c + 4, 0x1bb1b11c);
|
|
|
|
mag160c_frame_header_t h;
|
|
const uint16_t *pixels = NULL;
|
|
assert(mag160c_frame_parse(frame, sizeof(frame), &h, &pixels) == MAG160C_OK);
|
|
assert(h.marker == 0x1bb1b11b);
|
|
assert(h.frame_counter == 42);
|
|
assert(h.data_length == 4);
|
|
assert(h.frame_type == 1);
|
|
assert(h.period_shutter == 1000);
|
|
assert(h.trailing_marker == 0x1bb1b11c);
|
|
assert(pixels[0] == 0x1234);
|
|
}
|
|
|
|
static void test_parse_rejects(void) {
|
|
uint8_t frame[0x40];
|
|
memset(frame, 0, sizeof(frame));
|
|
mag160c_frame_header_t h;
|
|
const uint16_t *pixels = NULL;
|
|
|
|
memset(frame, 0, sizeof(frame));
|
|
assert(mag160c_frame_parse(frame, sizeof(frame), &h, &pixels) ==
|
|
MAG160C_ERR_BAD_FRAME);
|
|
|
|
put32(frame + 0x00, 0x1bb1b11b);
|
|
put32(frame + 0x08, 4);
|
|
put32(frame + 0x0c, 2); /* bad type */
|
|
assert(mag160c_frame_parse(frame, sizeof(frame), &h, &pixels) ==
|
|
MAG160C_ERR_BAD_FRAME);
|
|
|
|
put32(frame + 0x0c, 0);
|
|
put32(frame + 0x1c + 4, 0xdeadbeef); /* bad trailer */
|
|
assert(mag160c_frame_parse(frame, sizeof(frame), &h, &pixels) ==
|
|
MAG160C_ERR_BAD_FRAME);
|
|
}
|
|
|
|
static void test_stream_split(void) {
|
|
uint8_t frame[0x40];
|
|
memset(frame, 0xaa, sizeof(frame));
|
|
put32(frame + 0x00, 0x1bb1b11b);
|
|
put32(frame + 0x04, 7);
|
|
put32(frame + 0x08, 4);
|
|
put32(frame + 0x0c, 1);
|
|
frame[0x1c] = 0x78;
|
|
frame[0x1d] = 0x56;
|
|
put32(frame + 0x1c + 4, 0x1bb1b11c);
|
|
|
|
mag160c_frame_stream_t s;
|
|
mag160c_frame_stream_init(&s, 0x40);
|
|
assert(s.buf != NULL);
|
|
|
|
uint8_t out[0x100];
|
|
size_t len = 99;
|
|
const size_t total = 0x38 + 4; /* 0x3c */
|
|
|
|
/* feed one byte at a time; the frame completes exactly at total bytes */
|
|
for (size_t i = 0; i + 1 < total; ++i) {
|
|
len = 99;
|
|
assert(mag160c_frame_stream_push(&s, frame + i, 1, out, sizeof(out), &len) ==
|
|
MAG160C_OK);
|
|
assert(len == 0);
|
|
}
|
|
len = 99;
|
|
assert(mag160c_frame_stream_push(&s, frame + total - 1, 1, out, sizeof(out),
|
|
&len) == MAG160C_OK);
|
|
assert(len == total);
|
|
|
|
mag160c_frame_header_t h;
|
|
const uint16_t *pixels = NULL;
|
|
assert(mag160c_frame_parse(out, len, &h, &pixels) == MAG160C_OK);
|
|
assert(h.frame_counter == 7);
|
|
assert(pixels[0] == 0x5678);
|
|
|
|
/* trailing 4 bytes of the 0x40-byte test frame must not form a frame */
|
|
len = 99;
|
|
assert(mag160c_frame_stream_push(&s, frame + total, 4, out, sizeof(out),
|
|
&len) == MAG160C_OK);
|
|
assert(len == 0);
|
|
|
|
mag160c_frame_stream_destroy(&s);
|
|
}
|
|
|
|
static void test_stream_resync(void) {
|
|
uint8_t frame[0x40];
|
|
memset(frame, 0xaa, sizeof(frame));
|
|
put32(frame + 0x00, 0x1bb1b11b);
|
|
put32(frame + 0x08, 4);
|
|
put32(frame + 0x0c, 0);
|
|
frame[0x1c] = 0x11;
|
|
frame[0x1d] = 0x22;
|
|
put32(frame + 0x1c + 4, 0x1bb1b11c);
|
|
|
|
mag160c_frame_stream_t s;
|
|
mag160c_frame_stream_init(&s, 0x40);
|
|
|
|
/* garbage prefix (4-byte aligned) then the frame */
|
|
const uint8_t garbage[] = {0x00, 0xff, 0x12, 0x34};
|
|
uint8_t out[0x100];
|
|
size_t len = 0;
|
|
assert(mag160c_frame_stream_push(&s, garbage, sizeof(garbage), out, sizeof(out),
|
|
&len) == MAG160C_OK);
|
|
assert(len == 0);
|
|
assert(mag160c_frame_stream_push(&s, frame, sizeof(frame), out, sizeof(out),
|
|
&len) == MAG160C_OK);
|
|
assert(len == 0x38 + 4);
|
|
mag160c_frame_stream_destroy(&s);
|
|
}
|
|
|
|
int main(void) {
|
|
test_parse_valid();
|
|
test_parse_rejects();
|
|
test_stream_split();
|
|
test_stream_resync();
|
|
printf("test_frame: all passed\n");
|
|
return 0;
|
|
}
|