SmartestHome/pebble-presence/test/wireformat_test.c

73 lines
3.1 KiB
C

/*
* Round-trips the JS writer's real output through the C reader.
*
* The writer (src/pkjs/index.js) and the reader (src/c/main.c) are two implementations
* of one format, in two languages, that never run in the same process. Nothing but a
* test like this can catch them drifting apart — and drift decodes as plausible-looking
* garbage rather than as an error, which is the failure worth spending a harness on.
*
* Build: see run-tests.sh. Reads the payload as hex on stdin.
*/
#include "pebble_stub.h"
/* main.c includes <pebble.h>; the build passes -include pebble_stub.h and -Dpebble_h
so that include resolves to nothing. See run-tests.sh. */
#define main pebble_main /* keep main.c's entry point out of the way */
#include "../src/c/main.c"
#undef main
static int failures = 0;
static void check(const char *label, bool ok) {
printf(" %s %s\n", ok ? "PASS" : "FAIL", label);
if (!ok) failures++;
}
int main(void) {
static uint8_t buffer[4096];
uint16_t length = 0;
unsigned int byte;
while (scanf("%2x", &byte) == 1 && length < sizeof(buffer)) buffer[length++] = (uint8_t)byte;
printf("payload: %u bytes\n", length);
bool ok = parse_plan(buffer, length);
check("parses", ok);
if (!ok) { printf(" status: %s\n", s_status); return 1; }
check("room count is 3", s_room_count == 3);
check("room 0 is named Kitchen", strcmp(s_rooms[0].name, "Kitchen") == 0);
check("room 0 is occupied", s_rooms[0].state == 1);
check("room 0 has 4 vertices", s_rooms[0].vertex_count == 4);
check("room 0 has 1 occupant", s_rooms[0].occupant_count == 1);
check("occupant initial is A", s_rooms[0].occupants[0].initial == 'A');
check("occupant colour index 0", s_rooms[0].occupants[0].colour == 0);
check("occupant has a position", s_rooms[0].occupants[0].has_position);
check("occupant name survived", strcmp(s_rooms[0].occupants[0].name, "Amir") == 0);
check("room 1 is named Loggia", strcmp(s_rooms[1].name, "Loggia") == 0);
/* A radar target outranks "HA never reports this area": somebody IS in there, and a
positive detection beats no data. The first draft of this test asserted the
opposite and was wrong. */
check("room 1 is occupied (radar, nobody named)", s_rooms[1].state == 1);
check("room 1 has an anonymous target", s_rooms[1].target_count == 1);
check("room 1 has no occupants", s_rooms[1].occupant_count == 0);
check("room 2 is the unknown state", s_rooms[2].state == 2);
check("room 2 has no targets", s_rooms[2].target_count == 0);
check("1 unplaced person", s_unplaced_count == 1);
check("unplaced is Bibi", strcmp(s_unplaced[0].name, "Bibi") == 0);
/* A truncated payload must be refused wholesale, never half-decoded: a plan missing
its last rooms looks exactly like a real plan. */
bool truncated = parse_plan(buffer, length / 2);
check("truncated payload refused", !truncated && s_room_count == 0);
/* A version bump on the phone must not decode as garbage here. */
buffer[0] = 99;
check("wrong version refused", !parse_plan(buffer, length));
printf(failures ? "\nFAILURES: %d\n" : "\nall wire-format checks passed\n", failures);
return failures ? 1 : 0;
}