Initial commit: OTA chunk transfer protocol implementation

- Protocol definition with 6-byte header (chunk_idx: 2B, payload: N B, crc32: 4B)
- Node.js server with chunk-based HTTP delivery
- C client library with resumable download support
- CRC32 implementation (IEEE 802.3)
- Test suites for both server and CRC32
- 1024B default chunk size (0.59% overhead)
This commit is contained in:
km
2026-03-30 06:35:25 +09:00
commit b1c3ec3af4
10 changed files with 1522 additions and 0 deletions
+95
View File
@@ -0,0 +1,95 @@
/**
* @file test_crc32.c
* @brief CRC32 Test Suite
*/
#include "protocol.h"
#include <stdio.h>
#include <string.h>
static int passed = 0;
static int failed = 0;
#define TEST_ASSERT(cond, msg) do { \
if (cond) { \
printf("[PASS] %s\n", msg); \
passed++; \
} else { \
printf("[FAIL] %s\n", msg); \
failed++; \
} \
} while(0)
/* Test vector from IEEE 802.3 */
static void test_crc32_basic(void) {
printf("\n--- CRC32 Basic Tests ---\n");
/* Test 1: Empty data */
uint32_t crc = chunk_crc32(NULL, 0);
TEST_ASSERT(crc == 0x00000000UL, "Empty data CRC = 0x00000000");
/* Test 2: Single byte */
uint8_t data1[] = {0x41}; /* 'A' */
crc = chunk_crc32(data1, 1);
TEST_ASSERT(crc == 0xD3D99E8BUL, "Single byte 'A' CRC = 0xD3D99E8B");
/* Test 3: "foobar" */
uint8_t data2[] = "foobar";
crc = chunk_crc32(data2, 6);
TEST_ASSERT(crc == 0x9EF61F95UL, "'foobar' CRC = 0x9EF61F95");
/* Test 4: Incremental update */
uint32_t crc1 = chunk_crc32((uint8_t*)"foo", 3);
uint32_t crc2 = chunk_crc32_update(crc1, (uint8_t*)"bar", 3);
uint32_t crc3 = chunk_crc32(data2, 6);
TEST_ASSERT(crc2 == crc3, "Incremental update matches single call");
}
/* Test chunk size calculations */
static void test_chunk_calculations(void) {
printf("\n--- Chunk Calculation Tests ---\n");
/* Test 1: Exact multiple */
uint16_t chunks = chunk_calc_total_chunks(4096, 1024);
TEST_ASSERT(chunks == 4, "4096/1024 = 4 chunks");
/* Test 2: Not exact multiple */
chunks = chunk_calc_total_chunks(4097, 1024);
TEST_ASSERT(chunks == 5, "4097/1024 = 5 chunks");
/* Test 3: Last chunk payload size */
uint16_t payload = chunk_calc_payload_size(4097, 4, 1024);
TEST_ASSERT(payload == 1, "Last chunk of 4097 bytes = 1 byte");
/* Test 4: Middle chunk payload size */
payload = chunk_calc_payload_size(4097, 2, 1024);
TEST_ASSERT(payload == 1024, "Middle chunk = 1024 bytes");
}
/* Test CRC32 table initialization */
static void test_crc32_table(void) {
printf("\n--- CRC32 Table Tests ---\n");
/* Call multiple times to verify idempotent initialization */
chunk_crc32((uint8_t*)"test", 4);
chunk_crc32((uint8_t*)"test", 4);
chunk_crc32((uint8_t*)"test", 4);
TEST_ASSERT(1, "Multiple initializations OK");
}
int main(void) {
printf("========================================\n");
printf(" CRC32 Test Suite\n");
printf("========================================\n");
test_crc32_basic();
test_chunk_calculations();
test_crc32_table();
printf("\n========================================\n");
printf(" Results: %d passed, %d failed\n", passed, failed);
printf("========================================\n");
return failed == 0 ? 0 : 1;
}