/* * test_lup_ota_parser.c — 验证 lup_feed_byte_ota 0x9F 帧解析器 * * 测试向量来自 DLD960LoopBootloader 源码 (back_9F_pre_ok/addr_ok/data): * pre_ok : 9F 01 00 02 A5 00 A8 (CHECK = 01+00+02+A5+00 = A8) * addr_ok: 9F 01 00 02 A6 00 A9 * addr_err:9F 01 00 02 A6 01 AA * data : 9F 02 A7 * * 编译: gcc -I../BLE/OnlyUpdateApp_Peripheral/APP/include -o test_lup_ota_parser test_lup_ota_parser.c */ #include #include #include /* ---- mock: 从 loop_uart_proto.h 复制的最小依赖 ---- */ #define LUP_MAGIC 0x7F #define LUP_MAGIC_OTA 0x9F #define LUP_MAX_VALUE_LEN 64 #define LUP_MAX_PKG_LEN (1 + 3 + LUP_MAX_VALUE_LEN + 2) typedef enum { LUP_FRAME_STATE_IDLE = 0, LUP_FRAME_STATE_HEADER, LUP_FRAME_STATE_VALUE, LUP_FRAME_STATE_CHECK, LUP_FRAME_STATE_COMPLETE, LUP_FRAME_STATE_OTA_LEN, LUP_FRAME_STATE_OTA_CMD, LUP_FRAME_STATE_OTA_CHECK } LUP_FrameState; typedef struct { LUP_FrameState state; uint8_t buf[LUP_MAX_PKG_LEN]; uint16_t idx; uint16_t value_len; uint16_t value_idx; } LUP_FrameParser; static LUP_FrameParser g_lup_parser; static void lup_frame_reset(void) { g_lup_parser.state = LUP_FRAME_STATE_IDLE; g_lup_parser.idx = 0; g_lup_parser.value_len = 0; g_lup_parser.value_idx = 0; memset(g_lup_parser.buf, 0, sizeof(g_lup_parser.buf)); } static const uint8_t *lup_frame_data(void) { return g_lup_parser.buf; } static uint16_t lup_frame_len(void) { return g_lup_parser.idx; } /* ---- 嵌入被测函数体 (从 loop_uart_proto.c 提取) ---- */ int lup_feed_byte_ota(uint8_t byte) { LUP_FrameParser *p = &g_lup_parser; switch (p->state) { case LUP_FRAME_STATE_IDLE: if (byte == LUP_MAGIC_OTA) { p->buf[0] = byte; p->idx = 1; p->state = LUP_FRAME_STATE_HEADER; } break; case LUP_FRAME_STATE_HEADER: p->buf[p->idx++] = byte; if (p->idx == 3) { p->state = LUP_FRAME_STATE_OTA_LEN; } break; case LUP_FRAME_STATE_OTA_LEN: p->buf[p->idx++] = byte; { uint8_t len_field = p->buf[3]; uint16_t data_bytes; if (len_field < 1) { data_bytes = 0; } else { data_bytes = len_field - 1; } if (data_bytes > LUP_MAX_VALUE_LEN) { lup_frame_reset(); break; } p->value_len = data_bytes; p->value_idx = 0; } p->state = LUP_FRAME_STATE_OTA_CMD; break; case LUP_FRAME_STATE_OTA_CMD: p->buf[p->idx++] = byte; if (p->value_len > 0) { p->state = LUP_FRAME_STATE_VALUE; } else { p->state = LUP_FRAME_STATE_OTA_CHECK; } break; case LUP_FRAME_STATE_VALUE: p->buf[p->idx++] = byte; p->value_idx++; if (p->value_idx >= p->value_len) { p->state = LUP_FRAME_STATE_OTA_CHECK; } break; case LUP_FRAME_STATE_OTA_CHECK: p->buf[p->idx++] = byte; { uint8_t sum = 0; uint16_t i; for (i = 1; i < (uint16_t)(p->idx - 1); i++) { sum += p->buf[i]; } if (sum == p->buf[p->idx - 1]) { p->state = LUP_FRAME_STATE_COMPLETE; return 1; } lup_frame_reset(); } break; case LUP_FRAME_STATE_COMPLETE: lup_frame_reset(); break; default: lup_frame_reset(); break; } return 0; } /* ---- 测试辅助 ---- */ static int fails = 0; /* 喂完整帧, 断言: 帧完成 且 len 正确 */ static void feed_frame(const uint8_t *frame, int len, const char *name) { int i, done = 0; lup_frame_reset(); for (i = 0; i < len; i++) { if (lup_feed_byte_ota(frame[i])) { done = 1; break; } } if (!done) { printf("FAIL %s: frame not completed\n", name); fails++; return; } if ((int)lup_frame_len() != len) { printf("FAIL %s: len=%d expected %d\n", name, (int)lup_frame_len(), len); fails++; return; } if (memcmp(lup_frame_data(), frame, len) != 0) { printf("FAIL %s: content mismatch\n", name); fails++; return; } printf("PASS %s\n", name); } /* 喂错误校验帧, 断言: 解析失败 (reset 回 IDLE) */ static void feed_bad(const uint8_t *frame, int len, const char *name) { int i, done = 0; lup_frame_reset(); for (i = 0; i < len; i++) { if (lup_feed_byte_ota(frame[i])) { done = 1; break; } } if (done) { printf("FAIL %s: bad checksum accepted\n", name); fails++; return; } if (g_lup_parser.state != LUP_FRAME_STATE_IDLE) { printf("FAIL %s: parser not reset to IDLE (state=%d)\n", name, g_lup_parser.state); fails++; return; } printf("PASS %s\n", name); } int main(void) { uint8_t f1[] = {0x9F, 0x01, 0x00, 0x02, 0xA5, 0x00, 0xA8}; /* pre_ok */ uint8_t f2[] = {0x9F, 0x01, 0x00, 0x02, 0xA6, 0x00, 0xA9}; /* addr_ok */ uint8_t f3[] = {0x9F, 0x01, 0x00, 0x02, 0xA6, 0x01, 0xAA}; /* addr_err */ uint8_t f4[] = {0x9F, 0x05, 0x00, 0x02, 0xA7, 0x00, 0xAE}; /* data ACK sub=5 ok */ uint8_t f5[] = {0x9F, 0x34, 0x12, 0x02, 0xA7, 0x01, 0xF0}; /* data ACK sub=0x1234 err */ uint8_t bad[] = {0x9F, 0x01, 0x00, 0x02, 0xA5, 0x00, 0xA9}; /* CHECK 错 */ uint8_t v7f[] = {0x7F, 0x00, 0x04, 0x4A, 0x00, 0x4E, 0x4E}; /* 0x7F 帧不应被解析 */ feed_frame(f1, sizeof(f1), "pre_ok (9F 01 00 02 A5 00 A8)"); feed_frame(f2, sizeof(f2), "addr_ok (9F 01 00 02 A6 00 A9)"); feed_frame(f3, sizeof(f3), "addr_err(9F 01 00 02 A6 01 AA)"); feed_frame(f4, sizeof(f4), "data ack sub=5 (9F 05 00 02 A7 00 AE)"); feed_frame(f5, sizeof(f5), "data ack sub=0x1234 err (9F 34 12 02 A7 01 F0)"); feed_bad(bad, sizeof(bad), "bad checksum rejected"); /* 0x7F 帧: IDLE 不认 → 应无帧完成, 状态回 IDLE */ { int i, done = 0; lup_frame_reset(); for (i = 0; i < (int)sizeof(v7f); i++) { if (lup_feed_byte_ota(v7f[i])) { done = 1; break; } } if (done) { printf("FAIL 0x7F frame parsed by ota parser\n"); fails++; } else if (g_lup_parser.state != LUP_FRAME_STATE_IDLE) { printf("FAIL 0x7F frame left parser non-IDLE (state=%d)\n", g_lup_parser.state); fails++; } else { printf("PASS 0x7F frame ignored by ota parser\n"); } } /* 粘帧: 两帧连续 → 各自解析成功 */ { uint8_t glue[14]; int i, done_cnt = 0; memcpy(glue, f1, 7); memcpy(glue + 7, f2, 7); lup_frame_reset(); for (i = 0; i < 14; i++) { if (lup_feed_byte_ota(glue[i])) { done_cnt++; if (done_cnt == 1 && memcmp(lup_frame_data(), f1, 7) != 0) { printf("FAIL glue frame1 mismatch\n"); fails++; } if (done_cnt == 2 && memcmp(lup_frame_data(), f2, 7) != 0) { printf("FAIL glue frame2 mismatch\n"); fails++; } lup_frame_reset(); } } if (done_cnt != 2) { printf("FAIL glue: %d frames completed, expected 2\n", done_cnt); fails++; } else { printf("PASS glued frames parsed independently\n"); } } printf("\n%s (%d failures)\n", fails ? "FAILED" : "ALL PASS", fails); return fails ? 1 : 0; }