|
|
|
|
@ -78,6 +78,34 @@ static void test_signed_blocks(void) {
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] signed blocks: canonical bytes, all field classes, wrong key and malformed sizes"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Wire сохраняет все 64 бита и не меняет выход при усечении; путь не допускает повторного посещения. */ |
|
|
|
|
static void test_wire(void) { |
|
|
|
|
uint8_t wire[STREAM_WIRE_HEADER + 8]; |
|
|
|
|
struct stream_message input = {.descriptor = descriptor, .sender_epoch = UINT64_MAX, .receiver_epoch = UINT64_MAX - 1, |
|
|
|
|
.handle = UINT64_MAX - 2, .command = STREAM_CMD_SUBSCRIBE, .subblock = 7}; |
|
|
|
|
stream_wire_header(wire, &input); stream_write_be(wire + STREAM_WIRE_HEADER, UINT64_MAX - 3, 8); |
|
|
|
|
struct stream_message parsed; |
|
|
|
|
CHECK(stream_wire_parse(wire, sizeof(wire), &parsed) == STREAM_OK); |
|
|
|
|
CHECK(parsed.sender_epoch == input.sender_epoch && parsed.receiver_epoch == input.receiver_epoch && parsed.handle == input.handle); |
|
|
|
|
CHECK(parsed.descriptor.group_id == descriptor.group_id && parsed.descriptor.source_epoch == descriptor.source_epoch); |
|
|
|
|
CHECK(parsed.subblock == 7 && parsed.length == 8 && stream_read_be(parsed.payload, 8) == UINT64_MAX - 3); |
|
|
|
|
for (size_t i = 0; i < STREAM_WIRE_HEADER; i++) { |
|
|
|
|
memset(&parsed, 0xa5, sizeof(parsed)); uint8_t before[sizeof(parsed)]; memcpy(before, &parsed, sizeof(parsed)); |
|
|
|
|
CHECK(stream_wire_parse(wire, i, &parsed) == STREAM_ERR_FORMAT && !memcmp(before, &parsed, sizeof(parsed))); |
|
|
|
|
} |
|
|
|
|
wire[1]++; CHECK(stream_wire_parse(wire, sizeof(wire), &parsed) == STREAM_ERR_FORMAT); wire[1]--; |
|
|
|
|
wire[2] = 255; CHECK(stream_wire_parse(wire, sizeof(wire), &parsed) == STREAM_ERR_FORMAT); |
|
|
|
|
struct stream_path path = {.nodes = {descriptor.source_node_id, 1, 2}, .count = 3}, read; |
|
|
|
|
uint8_t encoded[1 + STREAM_PATH_MAX * 8]; size_t used = 0, length = stream_path_write(encoded, &path); |
|
|
|
|
CHECK(stream_path_parse(encoded, length, &read, &used) == STREAM_OK && used == length && read.count == 3 && read.nodes[2] == 2); |
|
|
|
|
CHECK(stream_path_validate(&read, descriptor.source_node_id, 2, 3) == STREAM_OK); |
|
|
|
|
CHECK(stream_path_validate(&read, descriptor.source_node_id, 2, 1) == STREAM_ERR_FORMAT); |
|
|
|
|
read.nodes[2] = 1; CHECK(stream_path_validate(&read, descriptor.source_node_id, 1, 0) == STREAM_ERR_FORMAT); |
|
|
|
|
for (size_t i = 0; i < length; i++) CHECK(stream_path_parse(encoded, i, &read, &used) == STREAM_ERR_FORMAT); |
|
|
|
|
encoded[0] = STREAM_PATH_MAX + 1; CHECK(stream_path_parse(encoded, sizeof(encoded), &read, &used) == STREAM_ERR_FORMAT); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] stream wire: 64-bit fields, truncation, version, path repeats/receiver loop and size"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Любая пара потерь при 6+2 восстанавливается из подписанных блоков, отсутствующие блоки не регенерируются. */ |
|
|
|
|
static void test_fec_and_padding(void) { |
|
|
|
|
struct stream_encoder *encoder = NULL; |
|
|
|
|
@ -317,6 +345,7 @@ int main(void) {
|
|
|
|
|
for (unsigned i = 0; i < sizeof(private_key); i++) private_key[i] = (uint8_t)(i * 37 + 11); |
|
|
|
|
size_t allocations = u_get_allocated_count(); |
|
|
|
|
test_signed_blocks(); CHECK(u_get_allocated_count() == allocations); |
|
|
|
|
test_wire(); CHECK(u_get_allocated_count() == allocations); |
|
|
|
|
test_fec_and_padding(); CHECK(u_get_allocated_count() == allocations); |
|
|
|
|
test_ring_and_conflicts(); CHECK(u_get_allocated_count() == allocations); |
|
|
|
|
test_relative_metrics(); CHECK(u_get_allocated_count() == allocations); |
|
|
|
|
|