/* * test_voice_frame — serialize/parse round-trips for the 14-byte UDP media header. */ #include #include #include #include #include "net/voice_frame.h" using namespace voicecat::net; static int g_failures = 0; #define CHECK(cond) \ do { if (!(cond)) { \ std::printf("FAIL [%s:%d]: %s\n", __FILE__, __LINE__, #cond); \ ++g_failures; \ }} while (0) static void test_header_round_trip() { VoiceFrame f; f.type = kFrameVoice; f.flags = kFlagMarker | kFlagFecPresent; f.codec = kCodecOpus; f.ssrc = 0xDEADBEEF; f.seq = 0xAB12; f.timestamp = 0x12345678; uint8_t buf[kVoiceHeaderSize]; serialize_header(f, buf); VoiceFrame out{}; CHECK(parse_header(buf, kVoiceHeaderSize, out)); CHECK(out.type == f.type); CHECK(out.flags == f.flags); CHECK(out.codec == f.codec); CHECK(out.ssrc == f.ssrc); CHECK(out.seq == f.seq); CHECK(out.timestamp == f.timestamp); } static void test_empty_payload_packet() { VoiceFrame f; f.type = kFrameKeepalive; f.ssrc = 42; uint8_t buf[kVoiceHeaderSize]; serialize_header(f, buf); VoiceFrame out{}; CHECK(parse_header(buf, kVoiceHeaderSize, out)); CHECK(out.type == kFrameKeepalive); CHECK(out.ssrc == 42); } static void test_payload_packet() { std::vector payload(60, 0xAB); VoiceFrame f; f.ssrc = 0x00000001; f.seq = 0x0001; f.timestamp = 960; f.payload = payload; // Serialize full wire packet std::vector wire(kVoiceHeaderSize + payload.size()); serialize_header(f, wire.data()); std::memcpy(wire.data() + kVoiceHeaderSize, payload.data(), payload.size()); VoiceFrame out{}; CHECK(parse_header(wire.data(), wire.size(), out)); CHECK(out.ssrc == f.ssrc); CHECK(out.seq == f.seq); CHECK(out.timestamp == f.timestamp); // Payload starts at kVoiceHeaderSize CHECK(wire.size() - kVoiceHeaderSize == 60); CHECK(wire[kVoiceHeaderSize] == 0xAB); } static void test_udp_binding_packet() { uint8_t token[16]; for (int i = 0; i < 16; ++i) token[i] = static_cast(i); auto pkt = make_udp_binding_packet(token, 16); CHECK(pkt.size() == kVoiceHeaderSize + 16); CHECK(pkt[0] == kFrameUdpBinding); CHECK(std::memcmp(pkt.data() + kVoiceHeaderSize, token, 16) == 0); } static void test_parse_too_short() { uint8_t buf[10] = {}; VoiceFrame out{}; CHECK(!parse_header(buf, 10, out)); } static void test_big_endian_layout() { VoiceFrame f; f.ssrc = 0x01020304; f.seq = 0x0506; f.timestamp = 0x0708090A; uint8_t buf[kVoiceHeaderSize]; serialize_header(f, buf); // ssrc at [4..7] CHECK(buf[4] == 0x01 && buf[5] == 0x02 && buf[6] == 0x03 && buf[7] == 0x04); // seq at [8..9] CHECK(buf[8] == 0x05 && buf[9] == 0x06); // timestamp at [10..13] CHECK(buf[10] == 0x07 && buf[11] == 0x08 && buf[12] == 0x09 && buf[13] == 0x0A); } int main() { test_header_round_trip(); test_empty_payload_packet(); test_payload_packet(); test_udp_binding_packet(); test_parse_too_short(); test_big_endian_layout(); if (g_failures == 0) { std::printf("voice_frame: all tests passed\n"); return 0; } std::printf("voice_frame: %d test(s) FAILED\n", g_failures); return 1; }