You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

469 lines
21 KiB

// test_media_delivery_sql.c — SQL-таблицы + протокольные структуры media_delivery
//
// Покрытие:
// 1. Создание таблиц block_availability + super_sync + индексов
// 2. INSERT OR REPLACE (upsert) — дубликат не создаёт вторую строку
// 3. SELECT с фильтром по block_uuid, сортировка timestamp DESC
// 4. SELECT с id > N, сортировка ASC, LIMIT
// 5. super_sync: INSERT OR REPLACE + SELECT (дефолт 0)
// 6. DELETE WHERE node_id=?
// 7. DELETE WHERE node_id!=? (чистка чужих при выключении суперузла)
// 8. Размеры packed-структур
// 9. Проверка полей packed-структур (нет padding-сюрпризов)
// 10. Построение/разбор MEDIA_QUERY
// 11. Построение/разбор MEDIA_HAVE_BLOCK
// 12. Построение/разбор MEDIA_SUPER_HELLO
#include "../src/media_delivery/media_delivery_proto.h"
#include "../lib/debug_config.h"
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
static int g_passed = 0, g_failed = 0, g_total = 0;
#define TEST(name) do { g_total++; printf(" %-50s", name); } while(0)
#define OK() do { g_passed++; printf("OK\n"); } while(0)
#define FAIL(fmt, ...) do { g_failed++; printf("FAIL: " fmt "\n", ##__VA_ARGS__); } while(0)
static void make_uuid(uint8_t buf[16]) {
for (int i = 0; i < 16; i++) buf[i] = (uint8_t)(rand() & 0xFF);
}
static sqlite3* make_db(void) {
sqlite3* db = NULL;
sqlite3_open(":memory:", &db);
sqlite3_exec(db, "PRAGMA journal_mode=memory", NULL, NULL, NULL);
return db;
}
static int create_tables(sqlite3* db) {
const char* sql_ba =
"CREATE TABLE IF NOT EXISTS block_availability ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" block_uuid BLOB NOT NULL,"
" group_id INTEGER NOT NULL,"
" node_id INTEGER NOT NULL,"
" chunk INTEGER NOT NULL,"
" timestamp INTEGER NOT NULL,"
" status INTEGER NOT NULL DEFAULT 1)"; // 0=processing, 1=completed
int rc = sqlite3_exec(db, sql_ba, NULL, NULL, NULL);
if (rc != SQLITE_OK) return -1;
sqlite3_exec(db, "CREATE UNIQUE INDEX IF NOT EXISTS idx_ba_uuid_node ON block_availability(block_uuid, node_id)", NULL, NULL, NULL);
sqlite3_exec(db, "CREATE INDEX IF NOT EXISTS idx_ba_id ON block_availability(id)", NULL, NULL, NULL);
sqlite3_exec(db, "CREATE INDEX IF NOT EXISTS idx_ba_node_id ON block_availability(node_id)", NULL, NULL, NULL);
const char* sql_ss =
"CREATE TABLE IF NOT EXISTS super_sync ("
" peer_node_id INTEGER PRIMARY KEY,"
" last_recv_id INTEGER NOT NULL DEFAULT 0)";
rc = sqlite3_exec(db, sql_ss, NULL, NULL, NULL);
return (rc == SQLITE_OK) ? 0 : -1;
}
static int table_exists(sqlite3* db, const char* name) {
sqlite3_stmt* s = NULL;
int ok = 0;
if (sqlite3_prepare_v2(db, "SELECT name FROM sqlite_master WHERE type='table' AND name=?", -1, &s, NULL) == SQLITE_OK) {
sqlite3_bind_text(s, 1, name, -1, SQLITE_STATIC);
ok = (sqlite3_step(s) == SQLITE_ROW);
sqlite3_finalize(s);
}
return ok;
}
static int index_exists(sqlite3* db, const char* name) {
sqlite3_stmt* s = NULL;
int ok = 0;
if (sqlite3_prepare_v2(db, "SELECT name FROM sqlite_master WHERE type='index' AND name=?", -1, &s, NULL) == SQLITE_OK) {
sqlite3_bind_text(s, 1, name, -1, SQLITE_STATIC);
ok = (sqlite3_step(s) == SQLITE_ROW);
sqlite3_finalize(s);
}
return ok;
}
static int count_rows(sqlite3* db, const char* table) {
char sql[128]; snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s", table);
sqlite3_stmt* s = NULL;
int n = -1;
if (sqlite3_prepare_v2(db, sql, -1, &s, NULL) == SQLITE_OK) {
if (sqlite3_step(s) == SQLITE_ROW) n = sqlite3_column_int(s, 0);
sqlite3_finalize(s);
}
return n;
}
/* ── test cases ── */
static void test_tables(void) {
TEST("create tables exist"); {
sqlite3* db = make_db();
if (create_tables(db) != 0) { FAIL("create_tables failed"); sqlite3_close(db); return; }
int ba = table_exists(db, "block_availability");
int ss = table_exists(db, "super_sync");
if (ba && ss) OK(); else FAIL("ba=%d ss=%d", ba, ss);
sqlite3_close(db);
}
TEST("create tables idempotent"); {
sqlite3* db = make_db();
if (create_tables(db) != 0) { FAIL("first create"); sqlite3_close(db); return; }
if (create_tables(db) != 0) { FAIL("second create"); sqlite3_close(db); return; }
OK();
sqlite3_close(db);
}
TEST("indices exist"); {
sqlite3* db = make_db();
create_tables(db);
int i1 = index_exists(db, "idx_ba_uuid_node");
int i2 = index_exists(db, "idx_ba_id");
int i3 = index_exists(db, "idx_ba_node_id");
if (i1 && i2 && i3) OK(); else FAIL("i1=%d i2=%d i3=%d", i1, i2, i3);
sqlite3_close(db);
}
}
static void test_ba_insert(void) {
TEST("ba_insert basic"); {
sqlite3* db = make_db(); create_tables(db);
uint8_t uuid[16]; make_uuid(uuid);
uint64_t gid = 0x100, nid = 0x200;
const char* sql = "INSERT INTO block_availability(block_uuid,group_id,node_id,chunk,timestamp) VALUES(?,?,?,?,?)";
for (int i = 0; i < 3; i++) {
sqlite3_stmt* s = NULL;
sqlite3_prepare_v2(db, sql, -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC);
sqlite3_bind_int64(s, 2, (sqlite3_int64)gid);
sqlite3_bind_int64(s, 3, (sqlite3_int64)(nid + (uint64_t)i));
sqlite3_bind_int(s, 4, i);
sqlite3_bind_int64(s, 5, (sqlite3_int64)time(NULL));
sqlite3_step(s); sqlite3_finalize(s);
}
int n = count_rows(db, "block_availability");
if (n == 3) OK(); else FAIL("expected 3 rows got %d", n);
sqlite3_close(db);
}
TEST("ba_insert upsert (unique uuid+node)"); {
sqlite3* db = make_db(); create_tables(db);
uint8_t uuid[16]; make_uuid(uuid);
const char* sql = "INSERT OR REPLACE INTO block_availability(block_uuid,group_id,node_id,chunk,timestamp) VALUES(?,?,?,?,?)";
for (int pass = 0; pass < 2; pass++) {
sqlite3_stmt* s = NULL;
sqlite3_prepare_v2(db, sql, -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC);
sqlite3_bind_int64(s, 2, (sqlite3_int64)1);
sqlite3_bind_int64(s, 3, (sqlite3_int64)0x300);
sqlite3_bind_int(s, 4, 0);
sqlite3_bind_int64(s, 5, (sqlite3_int64)(pass + 100));
sqlite3_step(s); sqlite3_finalize(s);
}
int n = count_rows(db, "block_availability");
if (n == 1) OK(); else FAIL("expected 1 row (upsert) got %d", n);
sqlite3_close(db);
}
}
static void test_ba_find(void) {
TEST("ba_find nodes by uuid"); {
sqlite3* db = make_db(); create_tables(db);
uint8_t uuid[16]; make_uuid(uuid);
const char* ins = "INSERT INTO block_availability(block_uuid,group_id,node_id,chunk,timestamp) VALUES(?,?,?,?,?)";
for (int i = 0; i < 5; i++) {
sqlite3_stmt* s = NULL; sqlite3_prepare_v2(db, ins, -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC);
sqlite3_bind_int64(s, 2, (sqlite3_int64)1);
sqlite3_bind_int64(s, 3, (sqlite3_int64)(0x10 + i));
sqlite3_bind_int(s, 4, i);
sqlite3_bind_int64(s, 5, (sqlite3_int64)(2000 - i));
sqlite3_step(s); sqlite3_finalize(s);
}
const char* q = "SELECT node_id FROM block_availability WHERE block_uuid=? ORDER BY timestamp DESC LIMIT 3";
sqlite3_stmt* s = NULL;
sqlite3_prepare_v2(db, q, -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC);
int count = 0, first_node = -1;
while (sqlite3_step(s) == SQLITE_ROW) { if (count == 0) first_node = sqlite3_column_int(s, 0); count++; }
sqlite3_finalize(s);
if (count == 3 && first_node == 0x10) OK(); else FAIL("count=%d first_node=0x%x", count, first_node);
sqlite3_close(db);
}
}
static void test_ba_get_since(void) {
TEST("ba_get_since id > N"); {
sqlite3* db = make_db(); create_tables(db);
uint8_t uuid[16]; make_uuid(uuid);
const char* ins = "INSERT INTO block_availability(block_uuid,group_id,node_id,chunk,timestamp) VALUES(?,?,?,?,?)";
for (int i = 0; i < 6; i++) {
sqlite3_stmt* s = NULL; sqlite3_prepare_v2(db, ins, -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC);
sqlite3_bind_int64(s, 2, (sqlite3_int64)1);
sqlite3_bind_int64(s, 3, (sqlite3_int64)(0x20 + i));
sqlite3_bind_int(s, 4, i);
sqlite3_bind_int64(s, 5, (sqlite3_int64)1000);
sqlite3_step(s); sqlite3_finalize(s);
}
const char* q = "SELECT id FROM block_availability WHERE id > ? ORDER BY id ASC LIMIT 4";
sqlite3_stmt* s = NULL;
sqlite3_prepare_v2(db, q, -1, &s, NULL);
sqlite3_bind_int64(s, 1, 1);
int count = 0;
while (sqlite3_step(s) == SQLITE_ROW) count++;
sqlite3_finalize(s);
if (count == 4) OK(); else FAIL("expected 4 rows got %d", count);
sqlite3_close(db);
}
}
/* ── status column tests ── */
static void test_ba_status(void) {
/* processing→completed: DELETE old + INSERT new, ids don't reuse */
TEST("ba_complete: new id > processing id"); {
sqlite3* db = make_db(); create_tables(db);
uint8_t uuid[16]; for (int i = 0; i < 16; i++) uuid[i] = (uint8_t)(0xAA + i);
sqlite3_stmt* s = NULL;
/* 1. INSERT processing (status=0) */
sqlite3_prepare_v2(db, "INSERT INTO block_availability(block_uuid,group_id,node_id,chunk,timestamp,status) VALUES(?,1,0xAA,0,100,0)", -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC);
sqlite3_step(s); sqlite3_finalize(s);
/* 2. get processing id */
int64_t pid = -1;
sqlite3_prepare_v2(db, "SELECT id FROM block_availability WHERE node_id=0xAA AND status=0", -1, &s, NULL);
if (sqlite3_step(s) == SQLITE_ROW) pid = sqlite3_column_int64(s, 0);
sqlite3_finalize(s);
/* 3. DELETE processing + INSERT completed (new id) */
sqlite3_exec(db, "DELETE FROM block_availability WHERE block_uuid=x'AAABACADAEAFB0B1B2B3B4B5B6B7B8B9' AND node_id=0xAA AND status=0", NULL, NULL, NULL);
sqlite3_prepare_v2(db, "INSERT INTO block_availability(block_uuid,group_id,node_id,chunk,timestamp,status) VALUES(?,1,0xAA,0,200,1)", -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC);
sqlite3_step(s); sqlite3_finalize(s);
/* 4. get completed id */
int64_t cid = -1;
sqlite3_prepare_v2(db, "SELECT id,status FROM block_availability WHERE node_id=0xAA", -1, &s, NULL);
int st = -1;
if (sqlite3_step(s) == SQLITE_ROW) { cid = sqlite3_column_int64(s, 0); st = sqlite3_column_int(s, 1); }
sqlite3_finalize(s);
int n = count_rows(db, "block_availability");
if (n == 1 && st == 1 && cid > pid) OK(); else FAIL("rows=%d status=%d pid=%lld cid=%lld (expected 1 row, status=1, cid>pid)", n, st, (long long)pid, (long long)cid);
sqlite3_close(db);
}
/* completed already exists → no-op, no duplicate */
TEST("ba_complete: no-op when completed exists"); {
sqlite3* db = make_db(); create_tables(db);
uint8_t uuid[16]; for (int i = 0; i < 16; i++) uuid[i] = (uint8_t)(0xBB + i);
sqlite3_stmt* s = NULL;
/* 1. INSERT completed */
sqlite3_prepare_v2(db, "INSERT INTO block_availability(block_uuid,group_id,node_id,chunk,timestamp,status) VALUES(?,1,0xBB,0,300,1)", -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC);
sqlite3_step(s); sqlite3_finalize(s);
int64_t id1 = -1;
sqlite3_prepare_v2(db, "SELECT id FROM block_availability WHERE node_id=0xBB", -1, &s, NULL);
if (sqlite3_step(s) == SQLITE_ROW) id1 = sqlite3_column_int64(s, 0);
sqlite3_finalize(s);
/* 2. DELETE processing (none) + check completed exists + skip INSERT */
sqlite3_exec(db, "DELETE FROM block_availability WHERE block_uuid=x'BBBCBDBEBFC0C1C2C3C4C5C6C7C8C9' AND node_id=0xBB AND status=0", NULL, NULL, NULL);
int exists = 0;
sqlite3_prepare_v2(db, "SELECT 1 FROM block_availability WHERE block_uuid=? AND node_id=0xBB AND status=1", -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC);
exists = (sqlite3_step(s) == SQLITE_ROW);
sqlite3_finalize(s);
/* 3. Don't insert if exists */
int64_t id2 = -1;
sqlite3_prepare_v2(db, "SELECT id FROM block_availability WHERE node_id=0xBB", -1, &s, NULL);
if (sqlite3_step(s) == SQLITE_ROW) id2 = sqlite3_column_int64(s, 0);
sqlite3_finalize(s);
int n = count_rows(db, "block_availability");
if (n == 1 && exists && id2 == id1) OK(); else FAIL("rows=%d exists=%d id1=%lld id2=%lld (expected 1 row, same id)", n, exists, (long long)id1, (long long)id2);
sqlite3_close(db);
}
/* processing after completed INSERT → CONSTRAINT violation */
TEST("ba_processing after completed: constraint violation"); {
sqlite3* db = make_db(); create_tables(db);
uint8_t uuid[16]; for (int i = 0; i < 16; i++) uuid[i] = (uint8_t)(0xCC + i);
sqlite3_stmt* s = NULL;
/* 1. INSERT completed */
sqlite3_prepare_v2(db, "INSERT INTO block_availability(block_uuid,group_id,node_id,chunk,timestamp,status) VALUES(?,1,0xCC,0,400,1)", -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC);
sqlite3_step(s); sqlite3_finalize(s);
/* 2. try INSERT processing (same uuid+node) → must fail with unique constraint */
int rc = SQLITE_OK;
sqlite3_prepare_v2(db, "INSERT INTO block_availability(block_uuid,group_id,node_id,chunk,timestamp,status) VALUES(?,1,0xCC,0,500,0)", -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC);
rc = sqlite3_step(s);
sqlite3_finalize(s);
/* 3. completed is still there, unchanged */
int n = count_rows(db, "block_availability");
int64_t ts_check = -1;
sqlite3_prepare_v2(db, "SELECT timestamp FROM block_availability WHERE node_id=0xCC", -1, &s, NULL);
if (sqlite3_step(s) == SQLITE_ROW) ts_check = sqlite3_column_int64(s, 0);
sqlite3_finalize(s);
if (n == 1 && rc == SQLITE_CONSTRAINT && ts_check == 400) OK();
else FAIL("rows=%d rc=%d ts=%lld (expected 1 row, CONSTRAINT, ts=400)", n, rc, (long long)ts_check);
sqlite3_close(db);
}
}
static void test_ss_ops(void) {
TEST("super_sync insert+select"); {
sqlite3* db = make_db(); create_tables(db);
sqlite3_exec(db, "INSERT OR REPLACE INTO super_sync(peer_node_id,last_recv_id) VALUES(0xAA, 42)", NULL, NULL, NULL);
sqlite3_stmt* s = NULL;
sqlite3_prepare_v2(db, "SELECT last_recv_id FROM super_sync WHERE peer_node_id=?", -1, &s, NULL);
sqlite3_bind_int64(s, 1, 0xAA);
int v = -1;
if (sqlite3_step(s) == SQLITE_ROW) v = sqlite3_column_int(s, 0);
sqlite3_finalize(s);
if (v == 42) OK(); else FAIL("expected 42 got %d", v);
sqlite3_close(db);
}
TEST("super_sync default 0"); {
sqlite3* db = make_db(); create_tables(db);
sqlite3_stmt* s = NULL;
sqlite3_prepare_v2(db, "SELECT last_recv_id FROM super_sync WHERE peer_node_id=?", -1, &s, NULL);
sqlite3_bind_int64(s, 1, 0xCC);
int v = -1;
if (sqlite3_step(s) == SQLITE_ROW) v = sqlite3_column_int(s, 0);
else v = 0; /* no row = default */
sqlite3_finalize(s);
if (v == 0) OK(); else FAIL("expected 0 got %d", v);
sqlite3_close(db);
}
}
static void test_ba_delete(void) {
TEST("ba_delete by node_id"); {
sqlite3* db = make_db(); create_tables(db);
uint8_t uuid[16]; make_uuid(uuid);
const char* ins = "INSERT INTO block_availability(block_uuid,group_id,node_id,chunk,timestamp) VALUES(?,?,?,?,?)";
sqlite3_stmt* s = NULL;
sqlite3_prepare_v2(db, ins, -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC); sqlite3_bind_int64(s, 2, 1);
sqlite3_bind_int64(s, 3, 0x500); sqlite3_bind_int(s, 4, 0);
sqlite3_bind_int64(s, 5, 100); sqlite3_step(s); sqlite3_finalize(s);
sqlite3_prepare_v2(db, ins, -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC); sqlite3_bind_int64(s, 2, 1);
sqlite3_bind_int64(s, 3, 0x600); sqlite3_bind_int(s, 4, 0);
sqlite3_bind_int64(s, 5, 100); sqlite3_step(s); sqlite3_finalize(s);
if (count_rows(db, "block_availability") != 2) { FAIL("setup failed"); sqlite3_close(db); return; }
sqlite3_exec(db, "DELETE FROM block_availability WHERE node_id=0x500", NULL, NULL, NULL);
int n = count_rows(db, "block_availability");
if (n == 1) OK(); else FAIL("expected 1 got %d", n);
sqlite3_close(db);
}
TEST("ba_delete foreign (node_id != self)"); {
sqlite3* db = make_db(); create_tables(db);
uint8_t uuid[16]; make_uuid(uuid);
const char* ins = "INSERT INTO block_availability(block_uuid,group_id,node_id,chunk,timestamp) VALUES(?,?,?,?,?)";
sqlite3_stmt* s = NULL;
for (int i = 0; i < 3; i++) {
sqlite3_prepare_v2(db, ins, -1, &s, NULL);
sqlite3_bind_blob(s, 1, uuid, 16, SQLITE_STATIC); sqlite3_bind_int64(s, 2, 1);
sqlite3_bind_int64(s, 3, (sqlite3_int64)(0x700 + i)); sqlite3_bind_int(s, 4, i);
sqlite3_bind_int64(s, 5, 100); sqlite3_step(s); sqlite3_finalize(s);
}
char buf[128]; snprintf(buf, sizeof(buf), "DELETE FROM block_availability WHERE node_id!=0x700");
sqlite3_exec(db, buf, NULL, NULL, NULL);
int n = count_rows(db, "block_availability");
if (n == 1) OK(); else FAIL("expected 1 (self) got %d", n);
sqlite3_close(db);
}
}
static void test_proto_sizes(void) {
TEST("packed struct sizes"); {
int ok = 1;
if (sizeof(struct media_pkt_query) != 27) { FAIL("query: %zu != 27", sizeof(struct media_pkt_query)); ok = 0; }
if (sizeof(struct media_pkt_have_block) != 117) { FAIL("have_block: %zu != 117", sizeof(struct media_pkt_have_block)); ok = 0; }
if (sizeof(struct media_pkt_super_hello) != 17) { FAIL("super_hello: %zu != 17", sizeof(struct media_pkt_super_hello)); ok = 0; }
if (sizeof(struct media_pkt_super_ack) != 5) { FAIL("super_ack: %zu != 5", sizeof(struct media_pkt_super_ack)); ok = 0; }
if (sizeof(struct media_pkt_block_req) != 53) { FAIL("block_req: %zu != 53", sizeof(struct media_pkt_block_req)); ok = 0; }
if (sizeof(struct media_pkt_cancel) != 37) { FAIL("cancel: %zu != 37", sizeof(struct media_pkt_cancel)); ok = 0; }
if (sizeof(struct media_pkt_block_done) != 105) { FAIL("block_done: %zu != 105", sizeof(struct media_pkt_block_done)); ok = 0; }
if (sizeof(struct media_pkt_query_resp_entry) != 30) { FAIL("query_resp_entry: %zu != 30", sizeof(struct media_pkt_query_resp_entry)); ok = 0; }
if (ok) OK();
/* continue running even if sizes mismatch */
}
}
static void test_proto_build(void) {
TEST("build MEDIA_QUERY"); {
uint8_t mid[16]; memset(mid, 0xAB, 16);
uint8_t bids[32]; memset(bids, 0xCD, 32);
uint8_t pkt[256];
struct media_pkt_query* q = (struct media_pkt_query*)pkt;
q->subcmd = MEDIA_SUBCMD_QUERY;
q->group_id = 0x12345678;
memcpy(q->media_id, mid, 16);
q->num_blocks = 2;
memcpy(pkt + MEDIA_QUERY_HDR_SIZE, bids, 32);
if (q->subcmd == MEDIA_SUBCMD_QUERY && q->group_id == 0x12345678 &&
q->num_blocks == 2 && memcmp(q->media_id, mid, 16) == 0 &&
memcmp(pkt + MEDIA_QUERY_HDR_SIZE, bids, 32) == 0) OK();
else FAIL();
}
TEST("build MEDIA_HAVE_BLOCK"); {
struct media_pkt_have_block hb;
memset(&hb, 0, sizeof(hb));
hb.subcmd = MEDIA_SUBCMD_HAVE_BLOCK;
hb.group_id = 0xAA;
hb.chunk = 5;
hb.timestamp = 999;
if (hb.subcmd == MEDIA_SUBCMD_HAVE_BLOCK && hb.group_id == 0xAA &&
hb.chunk == 5 && hb.timestamp == 999) OK();
else FAIL();
}
TEST("build MEDIA_SUPER_HELLO"); {
struct media_pkt_super_hello sh;
sh.subcmd = MEDIA_SUBCMD_SUPER_HELLO;
sh.last_recv_id = 12345;
sh.group_id = 0x11223344;
if (sh.subcmd == MEDIA_SUBCMD_SUPER_HELLO && sh.last_recv_id == 12345 && sh.group_id == 0x11223344) OK();
else FAIL();
}
}
int main(void) {
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR);
srand((unsigned)time(NULL));
printf("=== test_media_delivery_sql ===\n");
test_tables();
test_ba_insert();
test_ba_find();
test_ba_get_since();
test_ba_status();
test_ss_ops();
test_ba_delete();
test_proto_sizes();
test_proto_build();
printf("\n%d/%d passed, %d failed\n", g_passed, g_total, g_failed);
return g_failed > 0 ? 1 : 0;
}