srs/trunk/src/utest/srs_utest_kernel2.cpp
Winlin 8f87d4092b
AI: Fix naming problem in kernel module. v7.0.82 (#4479)
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
2025-09-07 21:09:08 -04:00

2518 lines
79 KiB
C++

//
// Copyright (c) 2013-2025 The SRS Authors
//
// SPDX-License-Identifier: MIT
//
#include <srs_utest_kernel2.hpp>
#include <srs_app_utility.hpp>
#include <srs_kernel_buffer.hpp>
#include <srs_kernel_error.hpp>
#include <srs_kernel_ps.hpp>
#include <srs_kernel_rtc_rtcp.hpp>
VOID TEST(KernelPSTest, PsPacketDecodeNormal)
{
srs_error_t err = srs_success;
MockPsHandler handler;
SrsPsContext context;
// Payload of GB28181 camera PS stream, the first packet:
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=0, Time=0
if (true) {
SrsRtpPacket rtp;
string raw = string(
"\x80\x60\x00\x00\x00\x00\x00\x00\x0b\xeb\xdf\xa1\x00\x00\x01\xba"
"\x44\x68\x6e\x4c\x94\x01\x01\x30\x13\xfe\xff\xff\x00\x00\xa0\x05"
"\x00\x00\x01\xbb\x00\x12\x80\x98\x09\x04\xe1\x7f\xe0\xe0\x80\xc0"
"\xc0\x08\xbd\xe0\x80\xbf\xe0\x80\x00\x00\x01\xbc\x00\x5e\xfc\xff"
"\x00\x24\x40\x0e\x48\x4b\x01\x00\x16\x9b\xa5\x22\x2e\xf7\x00\xff"
"\xff\xff\x41\x12\x48\x4b\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
"\x0a\x0b\x0c\x0d\x0e\x0f\x00\x30\x1b\xe0\x00\x1c\x42\x0e\x07\x10"
"\x10\xea\x02\x80\x01\xe0\x11\x30\x00\x00\x1c\x20\x2a\x0a\x7f\xff"
"\x00\x00\x07\x08\x1f\xfe\x50\x3c\x0f\xc0\x00\x0c\x43\x0a\x00\x90"
"\xfe\x02\xb1\x13\x01\xf4\x03\xff\xcb\x85\x54\xb9\x00\x00\x01\xe0"
"\x00\x26\x8c\x80\x07\x21\x1a\x1b\x93\x25\xff\xfc\x00\x00\x00\x01"
"\x67\x4d\x00\x1e\x9d\xa8\x28\x0f\x69\xb8\x08\x08\x0a\x00\x00\x03"
"\x00\x02\x00\x00\x03\x00\x65\x08\x00\x00\x01\xe0\x00\x0e\x8c\x00"
"\x03\xff\xff\xfc\x00\x00\x00\x01\x68\xee\x3c\x80\x00\x00\x01\xe0"
"\x00\x0e\x8c\x00\x02\xff\xfc\x00\x00\x00\x01\x06\xe5\x01\xba\x80"
"\x00\x00\x01\xe0\x35\x62\x8c\x00\x02\xff\xf8\x00\x00\x00\x01\x65",
256) +
string(1156, 'x');
if (true) {
SrsBuffer b((char *)raw.data(), raw.length());
HELPER_ASSERT_SUCCESS(rtp.decode(&b));
}
SrsRtpRawPayload *rtp_raw = dynamic_cast<SrsRtpRawPayload *>(rtp.payload());
SrsBuffer b((char *)rtp_raw->payload_, rtp_raw->nn_payload_);
// There should be three video messages.
HELPER_ASSERT_SUCCESS(context.decode(&b, &handler));
EXPECT_EQ(3, handler.msgs_.size());
}
// We use the first packet bytes to mock the RTP packet seq 1 to 8.
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=1, Time=0
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=2, Time=0
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=3, Time=0
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=4, Time=0
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=5, Time=0
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=6, Time=0
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=7, Time=0
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=8, Time=0
for (int i = 0; i < 8; i++) {
SrsRtpPacket rtp;
string raw = string("\x80\x60\x00\x01\x00\x00\x00\x00\x0b\xeb\xdf\xa1", 12) + string(1400, 'x');
if (true) {
SrsBuffer b((char *)raw.data(), raw.length());
HELPER_ASSERT_SUCCESS(rtp.decode(&b));
}
SrsRtpRawPayload *rtp_raw = dynamic_cast<SrsRtpRawPayload *>(rtp.payload());
SrsBuffer b((char *)rtp_raw->payload_, rtp_raw->nn_payload_);
// Bytes continuity for the large video frame, got nothing message yet.
HELPER_ASSERT_SUCCESS(context.decode(&b, handler.clear()));
EXPECT_EQ(0, handler.msgs_.size());
}
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=9, Time=0
if (true) {
SrsRtpPacket rtp;
string raw = string("\x80\x60\x00\x09\x00\x00\x00\x00\x0b\xeb\xdf\xa1", 12) + string(1300, 'x') + string("\x00\x00\x01\xbd\x00\x6a\x8c\x80\x07\x21\x1a\x1b\x93\x25\xff\xf8"
"\x00\x02\x00\x17\x00\x01\x80\x00\x00\xff\xa0\x05\xe0\xf1\xf0\x50"
"\x18\x52\xd6\x5c\xa2\x78\x90\x23\xf9\xf6\x64\xba\xc7\x90\x5e\xd3"
"\x80\x2f\x29\xad\x06\xee\x14\x62\xec\x6f\x77\xaa\x71\x80\xb3\x50"
"\xb8\xd1\x85\x7f\x44\x30\x4f\x44\xfd\xcd\x21\xe6\x55\x36\x08\x6c"
"\xb8\xd1\x85\x7f\x44\x30\x4f\x44\xfd\xcd\x21\xe6\x55\x36\x08\x6c"
"\xc9\xf6\x5c\x74",
100);
if (true) {
SrsBuffer b((char *)raw.data(), raw.length());
HELPER_ASSERT_SUCCESS(rtp.decode(&b));
}
SrsRtpRawPayload *rtp_raw = dynamic_cast<SrsRtpRawPayload *>(rtp.payload());
SrsBuffer b((char *)rtp_raw->payload_, rtp_raw->nn_payload_);
// There should be one large video message, might be an I frame.
HELPER_ASSERT_SUCCESS(context.decode(&b, handler.clear()));
EXPECT_EQ(1, handler.msgs_.size());
}
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=10, Time=0
if (true) {
SrsRtpPacket rtp;
string raw("\x80\x60\x00\x0a\x00\x00\x00\x00\x0b\xeb\xdf\xa1"
"\x57\xb3\xa3\xbc\x16\x2c\x3c\x9e\x69\x89\x48\xa4",
24);
if (true) {
SrsBuffer b((char *)raw.data(), raw.length());
HELPER_ASSERT_SUCCESS(rtp.decode(&b));
}
SrsRtpRawPayload *rtp_raw = dynamic_cast<SrsRtpRawPayload *>(rtp.payload());
SrsBuffer b((char *)rtp_raw->payload_, rtp_raw->nn_payload_);
// There should be a message of private stream, we ignore it, so we won't get it in callback.
HELPER_ASSERT_SUCCESS(context.decode(&b, handler.clear()));
EXPECT_EQ(0, handler.msgs_.size());
}
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=11, Time=3600
if (true) {
SrsRtpPacket rtp;
string raw = string("\x80\x60\x00\x0b\x00\x00\x0e\x10\x0b\xeb\xdf\xa1", 12) + string("\x00\x00\x01\xc0"
"\x00\x82\x8c\x80\x09\x21\x1a\x1b\xa3\x51\xff\xff\xff\xf8\xff\xf9"
"\x50\x40\x0e\xdf\xfc\x01\x2c\x2e\x84\x28\x23\x0a\x85\x82\xa2\x40"
"\x90\x50\x2c\x14\x0b\x05\x42\x41\x30\x90\x44\x28\x16\x08\x84\x82",
52) +
string(84, 'x');
if (true) {
SrsBuffer b((char *)raw.data(), raw.length());
HELPER_ASSERT_SUCCESS(rtp.decode(&b));
}
SrsRtpRawPayload *rtp_raw = dynamic_cast<SrsRtpRawPayload *>(rtp.payload());
SrsBuffer b((char *)rtp_raw->payload_, rtp_raw->nn_payload_);
// There should be one audio message.
HELPER_ASSERT_SUCCESS(context.decode(&b, handler.clear()));
EXPECT_EQ(1, handler.msgs_.size());
}
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=12, Time=3600
if (true) {
SrsRtpPacket rtp;
string raw = string("\x80\x60\x00\x0c\x00\x00\x0e\x10\x0b\xeb\xdf\xa1", 12) + string("\x00\x00\x01\xc0"
"\x00\x8a\x8c\x80\x09\x21\x1a\x1b\xb3\x7d\xff\xff\xff\xf8\xff\xf9"
"\x50\x40\x0f\xdf\xfc\x01\x2c\x2e\x88\x2a\x13\x0a\x09\x82\x41\x10"
"\x90\x58\x26\x14\x13\x05\x02\xc2\x10\xa0\x58\x4a\x14\x0a\x85\x02",
52) +
string(92, 'x');
if (true) {
SrsBuffer b((char *)raw.data(), raw.length());
HELPER_ASSERT_SUCCESS(rtp.decode(&b));
}
SrsRtpRawPayload *rtp_raw = dynamic_cast<SrsRtpRawPayload *>(rtp.payload());
SrsBuffer b((char *)rtp_raw->payload_, rtp_raw->nn_payload_);
// There should be another audio message.
HELPER_ASSERT_SUCCESS(context.decode(&b, handler.clear()));
EXPECT_EQ(1, handler.msgs_.size());
}
// PT=DynamicRTP-Type-96, SSRC=0xBEBDFA1, Seq=13, Time=3600
if (true) {
SrsRtpPacket rtp;
string raw = string("\x80\x60\x00\x0d\x00\x00\x0e\x10\x0b\xeb\xdf\xa1", 12) + string("\x00\x00\x01\xba"
"\x44\x68\x6e\xbd\x14\x01\x01\x30\x13\xfe\xff\xff\x00\x00\xa0\x06"
"\x00\x00\x01\xe0\x03\x4a\x8c\x80\x08\x21\x1a\x1b\xaf\x45\xff\xff"
"\xf8\x00\x00\x00\x01\x61\xe0\x08\xbf\x3c\xb6\x63\x68\x4b\x7f\xea",
52) +
string(816, 'x');
if (true) {
SrsBuffer b((char *)raw.data(), raw.length());
HELPER_ASSERT_SUCCESS(rtp.decode(&b));
}
SrsRtpRawPayload *rtp_raw = dynamic_cast<SrsRtpRawPayload *>(rtp.payload());
SrsBuffer b((char *)rtp_raw->payload_, rtp_raw->nn_payload_);
// There should be another audio message.
HELPER_ASSERT_SUCCESS(context.decode(&b, handler.clear()));
EXPECT_EQ(1, handler.msgs_.size());
}
}
VOID TEST(KernelPSTest, PsPacketHeaderClockDecode)
{
srs_error_t err = srs_success;
SrsPsContext context;
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x44\x68\x6e\x4c\x94\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x00686c992, pkt.system_clock_reference_base_);
EXPECT_EQ(0, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x64\x68\x6e\x4c\x94\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x10686c992, pkt.system_clock_reference_base_);
EXPECT_EQ(0, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\x68\x6e\x4c\x94\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18686c992, pkt.system_clock_reference_base_);
EXPECT_EQ(0, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe8\x6e\x4c\x94\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e86c992, pkt.system_clock_reference_base_);
EXPECT_EQ(0, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe9\x6e\x4c\x94\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e96c992, pkt.system_clock_reference_base_);
EXPECT_EQ(0, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe9\xee\x4c\x94\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e9ec992, pkt.system_clock_reference_base_);
EXPECT_EQ(0, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe9\xee\xcc\x94\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e9ed992, pkt.system_clock_reference_base_);
EXPECT_EQ(0, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe9\xee\xdc\x94\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e9edb92, pkt.system_clock_reference_base_);
EXPECT_EQ(0, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe9\xee\xdd\x94\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e9edbb2, pkt.system_clock_reference_base_);
EXPECT_EQ(0, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe9\xee\xdd\x9c\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e9edbb3, pkt.system_clock_reference_base_);
EXPECT_EQ(0, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe9\xee\xdd\x9e\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e9edbb3, pkt.system_clock_reference_base_);
EXPECT_EQ(0x100, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe9\xee\xdd\x9f\x01" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e9edbb3, pkt.system_clock_reference_base_);
EXPECT_EQ(0x180, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe9\xee\xdd\x9f\x11" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e9edbb3, pkt.system_clock_reference_base_);
EXPECT_EQ(0x188, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe9\xee\xdd\x9f\x19" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e9edbb3, pkt.system_clock_reference_base_);
EXPECT_EQ(0x18c, pkt.system_clock_reference_extension_);
}
if (true) {
SrsPsPacket pkt(&context);
SrsBuffer b((char *)"\x00\x00\x01\xba" /*start*/ "\x74\xe9\xee\xdd\x9f\x1b" /*clock*/ "\x01\x30\x13\xf8" /*mux*/, 14);
HELPER_ASSERT_SUCCESS(pkt.decode(&b));
EXPECT_EQ(0x18e9edbb3, pkt.system_clock_reference_base_);
EXPECT_EQ(0x18d, pkt.system_clock_reference_extension_);
}
}
VOID TEST(KernelLogTest, LogLevelString)
{
#ifdef SRS_LOG_LEVEL_V2
EXPECT_STREQ("FORB", srs_log_level_strings[SrsLogLevelForbidden]);
EXPECT_STREQ("TRACE", srs_log_level_strings[SrsLogLevelVerbose]);
EXPECT_STREQ("DEBUG", srs_log_level_strings[SrsLogLevelInfo]);
EXPECT_STREQ("INFO", srs_log_level_strings[SrsLogLevelTrace]);
EXPECT_STREQ("WARN", srs_log_level_strings[SrsLogLevelWarn]);
EXPECT_STREQ("ERROR", srs_log_level_strings[SrsLogLevelError]);
EXPECT_STREQ("OFF", srs_log_level_strings[SrsLogLevelDisabled]);
#else
EXPECT_STREQ("Forb", srs_log_level_strings[SrsLogLevelForbidden]);
EXPECT_STREQ("Verb", srs_log_level_strings[SrsLogLevelVerbose]);
EXPECT_STREQ("Debug", srs_log_level_strings[SrsLogLevelInfo]);
EXPECT_STREQ("Trace", srs_log_level_strings[SrsLogLevelTrace]);
EXPECT_STREQ("Warn", srs_log_level_strings[SrsLogLevelWarn]);
EXPECT_STREQ("Error", srs_log_level_strings[SrsLogLevelError]);
EXPECT_STREQ("Off", srs_log_level_strings[SrsLogLevelDisabled]);
#endif
}
VOID TEST(KernelLogTest, LogLevelStringV2)
{
EXPECT_EQ(srs_get_log_level("verbose"), SrsLogLevelVerbose);
EXPECT_EQ(srs_get_log_level("info"), SrsLogLevelInfo);
EXPECT_EQ(srs_get_log_level("trace"), SrsLogLevelTrace);
EXPECT_EQ(srs_get_log_level("warn"), SrsLogLevelWarn);
EXPECT_EQ(srs_get_log_level("error"), SrsLogLevelError);
EXPECT_EQ(srs_get_log_level("off"), SrsLogLevelDisabled);
EXPECT_EQ(srs_get_log_level_v2("trace"), SrsLogLevelVerbose);
EXPECT_EQ(srs_get_log_level_v2("debug"), SrsLogLevelInfo);
EXPECT_EQ(srs_get_log_level_v2("info"), SrsLogLevelTrace);
EXPECT_EQ(srs_get_log_level_v2("warn"), SrsLogLevelWarn);
EXPECT_EQ(srs_get_log_level_v2("error"), SrsLogLevelError);
EXPECT_EQ(srs_get_log_level_v2("off"), SrsLogLevelDisabled);
}
VOID TEST(KernelFileWriterTest, RealfileTest)
{
srs_error_t err;
string filename = _srs_tmp_file_prefix + "test-realfile.log";
MockFileRemover disposer(filename);
if (true) {
SrsFileWriter f;
HELPER_EXPECT_SUCCESS(f.open(filename));
EXPECT_TRUE(f.is_open());
EXPECT_EQ(0, f.tellg());
HELPER_EXPECT_SUCCESS(f.write((void *)"HelloWorld", 10, NULL));
EXPECT_EQ(10, f.tellg());
f.seek2(5);
EXPECT_EQ(5, f.tellg());
HELPER_EXPECT_SUCCESS(f.write((void *)"HelloWorld", 10, NULL));
EXPECT_EQ(15, f.tellg());
off_t v = 0;
HELPER_EXPECT_SUCCESS(f.lseek(0, SEEK_CUR, &v));
EXPECT_EQ(15, v);
HELPER_EXPECT_SUCCESS(f.lseek(0, SEEK_SET, &v));
EXPECT_EQ(0, v);
HELPER_EXPECT_SUCCESS(f.lseek(10, SEEK_SET, &v));
EXPECT_EQ(10, v);
HELPER_EXPECT_SUCCESS(f.lseek(0, SEEK_END, &v));
EXPECT_EQ(15, v);
// There are 5 bytes empty lagging in file.
HELPER_EXPECT_SUCCESS(f.lseek(5, SEEK_END, &v));
EXPECT_EQ(20, v);
HELPER_EXPECT_SUCCESS(f.write((void *)"HelloWorld", 10, NULL));
EXPECT_EQ(30, f.tellg());
HELPER_EXPECT_SUCCESS(f.lseek(0, SEEK_SET, &v));
EXPECT_EQ(0, v);
HELPER_EXPECT_SUCCESS(f.write((void *)"HelloWorld", 10, NULL));
EXPECT_EQ(10, f.tellg());
}
SrsFileReader fr;
HELPER_ASSERT_SUCCESS(fr.open(filename));
// "HelloWorldWorld\0\0\0\0\0HelloWorld"
string str;
HELPER_ASSERT_SUCCESS(srs_io_readall(&fr, str));
EXPECT_STREQ("HelloWorldWorld", str.c_str());
EXPECT_STREQ("HelloWorld", str.substr(20).c_str());
}
VOID TEST(KernelRTMPExtTest, ExtRTMPTest)
{
srs_error_t err;
// For legacy RTMP specification, without ext tag header.
if (true) {
SrsFormat f;
HELPER_ASSERT_SUCCESS(f.initialize());
HELPER_EXPECT_SUCCESS(f.on_video(0, (char *)"\x17\x01\x00\x00\x12", 5));
// Verify the frame type, codec id, avc packet type and composition time.
EXPECT_EQ(SrsVideoAvcFrameTypeKeyFrame, f.video_->frame_type_);
EXPECT_EQ(SrsVideoCodecIdAVC, f.vcodec_->id_);
EXPECT_EQ(SrsVideoAvcFrameTraitNALU, f.video_->avc_packet_type_);
EXPECT_EQ(0x12, f.video_->cts_);
}
// For new RTMP enhanced specification, with ext tag header.
if (true) {
SrsFormat f;
HELPER_ASSERT_SUCCESS(f.initialize());
HELPER_EXPECT_SUCCESS(f.on_video(0, (char *)"\x91hvc1\x00\x00\x12", 8));
// Verify the frame type, codec id, avc packet type and composition time.
EXPECT_EQ(SrsVideoAvcFrameTypeKeyFrame, f.video_->frame_type_);
EXPECT_EQ(SrsVideoCodecIdHEVC, f.vcodec_->id_);
EXPECT_EQ(SrsVideoHEVCFrameTraitPacketTypeCodedFrames, f.video_->avc_packet_type_);
EXPECT_EQ(0x12, f.video_->cts_);
}
// If packet type is 3, which is coded frame X, the composition time is 0.
if (true) {
SrsFormat f;
HELPER_ASSERT_SUCCESS(f.initialize());
HELPER_EXPECT_SUCCESS(f.on_video(0, (char *)"\x93hvc1", 5));
// Verify the frame type, codec id, avc packet type and composition time.
EXPECT_EQ(SrsVideoAvcFrameTypeKeyFrame, f.video_->frame_type_);
EXPECT_EQ(SrsVideoCodecIdHEVC, f.vcodec_->id_);
EXPECT_EQ(SrsVideoHEVCFrameTraitPacketTypeCodedFramesX, f.video_->avc_packet_type_);
EXPECT_EQ(0, f.video_->cts_);
}
// Should fail if only 1 byte for ext tag header, should be more bytes for fourcc.
if (true) {
SrsFormat f;
HELPER_ASSERT_SUCCESS(f.initialize());
HELPER_EXPECT_FAILED(f.on_video(0, (char *)"\x91", 1));
}
// Should fail if only 5 bytes for ext tag header, should be more bytes for fourcc.
if (true) {
SrsFormat f;
HELPER_ASSERT_SUCCESS(f.initialize());
HELPER_EXPECT_FAILED(f.on_video(0, (char *)"\x91hvc1", 5));
}
// Should fail if codec id is hvc2 for ext tag header, should be hvc1.
if (true) {
SrsFormat f;
HELPER_ASSERT_SUCCESS(f.initialize());
HELPER_EXPECT_FAILED(f.on_video(0, (char *)"\x93hvc2", 5));
}
// Should fail if codec id is mvc1 for ext tag header, should be hvc1.
if (true) {
SrsFormat f;
HELPER_ASSERT_SUCCESS(f.initialize());
HELPER_EXPECT_FAILED(f.on_video(0, (char *)"\x93mvc1", 5));
}
}
VOID TEST(KernelCodecTest, VideoFormatSepcialMProtect_DJI_M30)
{
srs_error_t err;
SrsFormat f;
HELPER_EXPECT_SUCCESS(f.initialize());
// Frame 80442, the sequence header, wireshark filter:
// rtmpt && rtmpt.video.type==1 && rtmpt.video.format==7
HELPER_EXPECT_SUCCESS(f.on_video(0, (char *)""
"\x17\x00\x00\x00\x00\x01\x64\x00\x28\xff\xe1\x00\x12\x67\x64\x00"
"\x28\xac\xb4\x03\xc0\x11\x34\xa4\x14\x18\x18\x1b\x42\x84\xd4\x01"
"\x00\x05\x68\xee\x06\xf2\xc0",
39));
MockProtectedBuffer buffer;
if (buffer.alloc(9)) {
EXPECT_TRUE(false) << "mmap failed, errno=" << errno;
return;
}
// Frame 82749
memcpy(buffer.data_, "\x27\x01\x00\x00\x00\x00\x00\x00\x00", buffer.size_);
HELPER_EXPECT_SUCCESS(f.on_video(0, buffer.data_, buffer.size_));
}
VOID TEST(KernelCodecTest, VideoFormatSepcialAsan_DJI_M30)
{
srs_error_t err;
SrsFormat f;
HELPER_EXPECT_SUCCESS(f.initialize());
// Frame 80442, the sequence header, wireshark filter:
// rtmpt && rtmpt.video.type==1 && rtmpt.video.format==7
HELPER_EXPECT_SUCCESS(f.on_video(0, (char *)""
"\x17\x00\x00\x00\x00\x01\x64\x00\x28\xff\xe1\x00\x12\x67\x64\x00"
"\x28\xac\xb4\x03\xc0\x11\x34\xa4\x14\x18\x18\x1b\x42\x84\xd4\x01"
"\x00\x05\x68\xee\x06\xf2\xc0",
39));
// Frame 82749
char data[9];
memcpy(data, "\x27\x01\x00\x00\x00\x00\x00\x00\x00", sizeof(data));
HELPER_EXPECT_SUCCESS(f.on_video(0, data, sizeof(data)));
}
VOID TEST(KernelCodecTest, VideoFormatRbspSimple)
{
// |---------------------|----------------------------|
// | rbsp | nalu with emulation bytes |
// |---------------------|----------------------------|
// | 0x00 0x00 0x00 | 0x00 0x00 0x03 0x00 |
// | 0x00 0x00 0x01 | 0x00 0x00 0x03 0x01 |
// | 0x00 0x00 0x02 | 0x00 0x00 0x03 0x02 |
// | 0x00 0x00 0x03 | 0x00 0x00 0x03 0x03 |
// | 0x00 0x00 0x03 0x04 | 0x00 0x00 0x03 0x04 |
// |---------------------|----------------------------|
if (true) {
vector<uint8_t> nalu = {0x00, 0x00, 0x03, 0x00};
vector<uint8_t> expect = {0x00, 0x00, 0x00};
vector<uint8_t> rbsp(nalu.size());
SrsBuffer b((char *)nalu.data(), nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
if (true) {
vector<uint8_t> nalu = {0x00, 0x00, 0x03, 0x01};
vector<uint8_t> expect = {0x00, 0x00, 0x01};
SrsBuffer b((char *)nalu.data(), nalu.size());
vector<uint8_t> rbsp(nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
if (true) {
vector<uint8_t> nalu = {0x00, 0x00, 0x03, 0x02};
vector<uint8_t> expect = {0x00, 0x00, 0x02};
SrsBuffer b((char *)nalu.data(), nalu.size());
vector<uint8_t> rbsp(nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
if (true) {
vector<uint8_t> nalu = {0x00, 0x00, 0x03, 0x03};
vector<uint8_t> expect = {0x00, 0x00, 0x03};
SrsBuffer b((char *)nalu.data(), nalu.size());
vector<uint8_t> rbsp(nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
if (true) {
vector<uint8_t> nalu = {0x00, 0x00, 0x03, 0x04};
vector<uint8_t> expect = {0x00, 0x00, 0x03, 0x04};
SrsBuffer b((char *)nalu.data(), nalu.size());
vector<uint8_t> rbsp(nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
if (true) {
vector<uint8_t> nalu = {0x00, 0x00, 0x03, 0xff};
vector<uint8_t> expect = {0x00, 0x00, 0x03, 0xff};
SrsBuffer b((char *)nalu.data(), nalu.size());
vector<uint8_t> rbsp(nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
}
VOID TEST(KernelCodecTest, VideoFormatRbspEdge)
{
if (true) {
vector<uint8_t> nalu = {0x00, 0x00, 0x03};
vector<uint8_t> expect = {0x00, 0x00, 0x03};
vector<uint8_t> rbsp(nalu.size());
SrsBuffer b((char *)nalu.data(), nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
if (true) {
vector<uint8_t> nalu = {0xff, 0x00, 0x00, 0x03};
vector<uint8_t> expect = {0xff, 0x00, 0x00, 0x03};
vector<uint8_t> rbsp(nalu.size());
SrsBuffer b((char *)nalu.data(), nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
for (uint16_t v = 0x01; v <= 0xff; v++) {
vector<uint8_t> nalu = {(uint8_t)v, 0x00, 0x00, 0x03};
vector<uint8_t> expect = {(uint8_t)v, 0x00, 0x00, 0x03};
vector<uint8_t> rbsp(nalu.size());
SrsBuffer b((char *)nalu.data(), nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
}
VOID TEST(KernelCodecTest, VideoFormatRbspNormal)
{
for (uint16_t v = 0x01; v <= 0xff; v++) {
vector<uint8_t> nalu = {0x00, (uint8_t)v, 0x03, 0x00};
vector<uint8_t> expect = {0x00, (uint8_t)v, 0x03, 0x00};
vector<uint8_t> rbsp(nalu.size());
SrsBuffer b((char *)nalu.data(), nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
for (uint16_t v = 0x01; v <= 0xff; v++) {
vector<uint8_t> nalu = {(uint8_t)v, 0x00, 0x03, 0x00};
vector<uint8_t> expect = {(uint8_t)v, 0x00, 0x03, 0x00};
vector<uint8_t> rbsp(nalu.size());
SrsBuffer b((char *)nalu.data(), nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
for (uint16_t v = 0x00; v <= 0xff; v++) {
vector<uint8_t> nalu = {0x00, 0x00, (uint8_t)v};
vector<uint8_t> expect = {0x00, 0x00, (uint8_t)v};
vector<uint8_t> rbsp(nalu.size());
SrsBuffer b((char *)nalu.data(), nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
for (uint16_t v = 0x00; v <= 0xff; v++) {
vector<uint8_t> nalu = {0x00, (uint8_t)v};
vector<uint8_t> expect = {0x00, (uint8_t)v};
vector<uint8_t> rbsp(nalu.size());
SrsBuffer b((char *)nalu.data(), nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
for (uint16_t v = 0x00; v <= 0xff; v++) {
vector<uint8_t> nalu = {(uint8_t)v};
vector<uint8_t> expect = {(uint8_t)v};
vector<uint8_t> rbsp(nalu.size());
SrsBuffer b((char *)nalu.data(), nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
for (uint16_t v = 0x00; v <= 0xff; v++) {
vector<uint8_t> nalu = {(uint8_t)v, (uint8_t)v};
vector<uint8_t> expect = {(uint8_t)v, (uint8_t)v};
vector<uint8_t> rbsp(nalu.size());
SrsBuffer b((char *)nalu.data(), nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
for (uint16_t v = 0x00; v <= 0xff; v++) {
vector<uint8_t> nalu = {(uint8_t)v, (uint8_t)v, (uint8_t)v};
vector<uint8_t> expect = {(uint8_t)v, (uint8_t)v, (uint8_t)v};
vector<uint8_t> rbsp(nalu.size());
SrsBuffer b((char *)nalu.data(), nalu.size());
int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp);
ASSERT_EQ(nb_rbsp, (int)expect.size());
EXPECT_TRUE(srs_bytes_equal(rbsp.data(), expect.data(), nb_rbsp));
}
}
VOID TEST(KernelCodecTest, HEVCDuplicatedCode)
{
EXPECT_NE(ERROR_HEVC_NALU_UEV, ERROR_STREAM_CASTER_HEVC_VPS);
EXPECT_NE(ERROR_HEVC_NALU_SEV, ERROR_STREAM_CASTER_HEVC_SPS);
}
VOID TEST(KernelMemoryBlockTest, MemoryBlockBasic)
{
// Test basic construction and destruction
if (true) {
SrsMemoryBlock block;
EXPECT_EQ(0, block.size());
EXPECT_EQ(NULL, block.payload());
}
// Test create with size
if (true) {
SrsMemoryBlock block;
block.create(1024);
EXPECT_EQ(1024, block.size());
EXPECT_NE((char *)NULL, block.payload());
}
// Test create with data
if (true) {
SrsMemoryBlock block;
char test_data[] = "Hello, World!";
int test_size = strlen(test_data);
block.create(test_data, test_size);
EXPECT_EQ(test_size, block.size());
EXPECT_NE((char *)NULL, block.payload());
EXPECT_EQ(0, memcmp(block.payload(), test_data, test_size));
}
// Test attach
if (true) {
SrsMemoryBlock block;
char *test_data = new char[100];
memset(test_data, 0x42, 100);
block.attach(test_data, 100);
EXPECT_EQ(100, block.size());
EXPECT_EQ(test_data, block.payload());
// Memory will be freed by block destructor
}
}
VOID TEST(KernelMemoryBlockTest, SharedMemoryBlock)
{
// Test basic shared memory block usage
if (true) {
SrsSharedPtr<SrsMemoryBlock> shared_block(new SrsMemoryBlock());
shared_block->create(1024);
EXPECT_EQ(1024, shared_block->size());
EXPECT_NE((char *)NULL, shared_block->payload());
// Test sharing
SrsSharedPtr<SrsMemoryBlock> shared_copy = shared_block;
EXPECT_EQ(shared_block->payload(), shared_copy->payload());
EXPECT_EQ(shared_block->size(), shared_copy->size());
}
// Test multiple references
if (true) {
SrsSharedPtr<SrsMemoryBlock> original(new SrsMemoryBlock());
char test_data[] = "Shared memory test data";
original->create(test_data, strlen(test_data));
// Create multiple references
SrsSharedPtr<SrsMemoryBlock> copy1 = original;
SrsSharedPtr<SrsMemoryBlock> copy2 = original;
SrsSharedPtr<SrsMemoryBlock> copy3 = copy1;
// All should point to the same memory
EXPECT_EQ(original->payload(), copy1->payload());
EXPECT_EQ(original->payload(), copy2->payload());
EXPECT_EQ(original->payload(), copy3->payload());
// All should have the same size
EXPECT_EQ(original->size(), copy1->size());
EXPECT_EQ(original->size(), copy2->size());
EXPECT_EQ(original->size(), copy3->size());
// Verify data integrity
EXPECT_EQ(0, memcmp(original->payload(), test_data, strlen(test_data)));
EXPECT_EQ(0, memcmp(copy1->payload(), test_data, strlen(test_data)));
EXPECT_EQ(0, memcmp(copy2->payload(), test_data, strlen(test_data)));
EXPECT_EQ(0, memcmp(copy3->payload(), test_data, strlen(test_data)));
}
}
VOID TEST(KernelBufferTest, SrsBufferConstructorAndBasics)
{
// Test constructor with valid data
char data[10] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A};
SrsBuffer buf(data, 10);
// Test basic properties
EXPECT_EQ(10, buf.size());
EXPECT_EQ(0, buf.pos());
EXPECT_EQ(10, buf.left());
EXPECT_FALSE(buf.empty());
EXPECT_EQ(data, buf.data());
EXPECT_EQ(data, buf.head());
// Test constructor with NULL data
SrsBuffer null_buf(NULL, 0);
EXPECT_EQ(0, null_buf.size());
EXPECT_EQ(0, null_buf.pos());
EXPECT_EQ(0, null_buf.left());
EXPECT_TRUE(null_buf.empty());
EXPECT_EQ(NULL, null_buf.data());
EXPECT_EQ(NULL, null_buf.head());
}
VOID TEST(KernelBufferTest, SrsBufferCopy)
{
char data[5] = {0x10, 0x20, 0x30, 0x40, 0x50};
SrsBuffer buf(data, 5);
// Move position forward
buf.read_1bytes();
buf.read_1bytes();
EXPECT_EQ(2, buf.pos());
// Test copy preserves position
SrsBuffer *copy = buf.copy();
EXPECT_EQ(5, copy->size());
EXPECT_EQ(2, copy->pos());
EXPECT_EQ(3, copy->left());
EXPECT_EQ(data, copy->data());
EXPECT_EQ(data + 2, copy->head());
// Verify copy is independent
copy->read_1bytes();
EXPECT_EQ(3, copy->pos());
EXPECT_EQ(2, buf.pos()); // Original unchanged
srs_freep(copy);
}
VOID TEST(KernelBufferTest, SrsBufferSizeAndSetSize)
{
char data[10];
SrsBuffer buf(data, 10);
EXPECT_EQ(10, buf.size());
// Test set_size
buf.set_size(5);
EXPECT_EQ(5, buf.size());
EXPECT_EQ(5, buf.left());
// Test set_size with larger value
buf.set_size(15);
EXPECT_EQ(15, buf.size());
EXPECT_EQ(15, buf.left());
// Test set_size with zero
buf.set_size(0);
EXPECT_EQ(0, buf.size());
EXPECT_EQ(0, buf.left());
EXPECT_TRUE(buf.empty());
}
VOID TEST(KernelBufferTest, SrsBufferPositionAndHead)
{
char data[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (char)0x88};
SrsBuffer buf(data, 8);
// Initial state
EXPECT_EQ(0, buf.pos());
EXPECT_EQ(data, buf.head());
// After reading some bytes
buf.read_1bytes();
EXPECT_EQ(1, buf.pos());
EXPECT_EQ(data + 1, buf.head());
buf.read_2bytes();
EXPECT_EQ(3, buf.pos());
EXPECT_EQ(data + 3, buf.head());
// Skip to end
buf.skip(5);
EXPECT_EQ(8, buf.pos());
EXPECT_EQ(data + 8, buf.head());
EXPECT_TRUE(buf.empty());
}
VOID TEST(KernelBufferTest, SrsBufferLeftAndEmpty)
{
char data[6];
SrsBuffer buf(data, 6);
// Initial state
EXPECT_EQ(6, buf.left());
EXPECT_FALSE(buf.empty());
// After reading
buf.read_1bytes();
EXPECT_EQ(5, buf.left());
EXPECT_FALSE(buf.empty());
buf.read_4bytes();
EXPECT_EQ(1, buf.left());
EXPECT_FALSE(buf.empty());
buf.read_1bytes();
EXPECT_EQ(0, buf.left());
EXPECT_TRUE(buf.empty());
}
VOID TEST(KernelBufferTest, SrsBufferRequire)
{
char data[10];
SrsBuffer buf(data, 10);
// Test require with available bytes
EXPECT_TRUE(buf.require(1));
EXPECT_TRUE(buf.require(10));
EXPECT_FALSE(buf.require(11));
// After consuming some bytes
buf.read_4bytes();
EXPECT_TRUE(buf.require(1));
EXPECT_TRUE(buf.require(6));
EXPECT_FALSE(buf.require(7));
// At the end
buf.read_4bytes();
buf.read_2bytes();
EXPECT_FALSE(buf.require(1));
EXPECT_TRUE(buf.require(0));
// Test require with zero and negative values
buf.skip(-10); // Reset to beginning
EXPECT_TRUE(buf.require(0));
// Note: According to header comment, require should assert for negative values
// but we won't test that as it would crash the test
}
VOID TEST(KernelBufferTest, SrsBufferSkipOperations)
{
char data[10] = {0};
SrsBuffer buf(data, 10);
// Test basic properties first
EXPECT_EQ(0, buf.pos());
EXPECT_EQ(10, buf.size());
EXPECT_EQ(data, buf.data());
// Test simple forward skip
buf.skip(1);
EXPECT_EQ(1, buf.pos());
EXPECT_EQ(9, buf.left());
}
VOID TEST(KernelBufferTest, SrsBufferRead1Bytes)
{
char data[4] = {0x12, 0x34, 0x56, 0x78};
SrsBuffer buf(data, 4);
// Test reading 1-byte values
EXPECT_EQ(0x12, buf.read_1bytes());
EXPECT_EQ(1, buf.pos());
EXPECT_EQ(0x34, buf.read_1bytes());
EXPECT_EQ(2, buf.pos());
EXPECT_EQ(0x56, buf.read_1bytes());
EXPECT_EQ(3, buf.pos());
EXPECT_EQ(0x78, buf.read_1bytes());
EXPECT_EQ(4, buf.pos());
EXPECT_TRUE(buf.empty());
// Test with signed values
char signed_data[2] = {(char)0xFF, (char)0x80};
SrsBuffer signed_buf(signed_data, 2);
EXPECT_EQ(-1, signed_buf.read_1bytes());
EXPECT_EQ(-128, signed_buf.read_1bytes());
}
VOID TEST(KernelBufferTest, SrsBufferRead2Bytes)
{
char data[8] = {0x12, 0x34, 0x56, 0x78, (char)0x9A, (char)0xBC, (char)0xDE, (char)0xF0};
SrsBuffer buf(data, 8);
// Test big-endian 2-byte reads
EXPECT_EQ(0x1234, buf.read_2bytes());
EXPECT_EQ(2, buf.pos());
EXPECT_EQ(0x5678, buf.read_2bytes());
EXPECT_EQ(4, buf.pos());
// Test little-endian 2-byte reads
buf.skip(-4); // Reset to beginning
EXPECT_EQ(0x3412, buf.read_le2bytes());
EXPECT_EQ(2, buf.pos());
EXPECT_EQ(0x7856, buf.read_le2bytes());
EXPECT_EQ(4, buf.pos());
// Continue with remaining bytes
EXPECT_EQ((int16_t)0x9ABC, buf.read_2bytes());
EXPECT_EQ((int16_t)0xDEF0, buf.read_2bytes());
EXPECT_TRUE(buf.empty());
}
VOID TEST(KernelBufferTest, SrsBufferRead3Bytes)
{
char data[9] = {0x12, 0x34, 0x56, 0x78, (char)0x9A, (char)0xBC, (char)0xDE, (char)0xF0, 0x11};
SrsBuffer buf(data, 9);
// Test big-endian 3-byte reads
EXPECT_EQ(0x123456, buf.read_3bytes());
EXPECT_EQ(3, buf.pos());
EXPECT_EQ(0x789ABC, buf.read_3bytes());
EXPECT_EQ(6, buf.pos());
// Test little-endian 3-byte reads
buf.skip(-6); // Reset to beginning
EXPECT_EQ(0x563412, buf.read_le3bytes());
EXPECT_EQ(3, buf.pos());
EXPECT_EQ(0xBC9A78, buf.read_le3bytes());
EXPECT_EQ(6, buf.pos());
// Read remaining bytes
EXPECT_EQ(0xDEF011, buf.read_3bytes());
EXPECT_TRUE(buf.empty());
}
VOID TEST(KernelBufferTest, SrsBufferRead4Bytes)
{
char data[12] = {0x12, 0x34, 0x56, 0x78, (char)0x9A, (char)0xBC, (char)0xDE, (char)0xF0,
0x11, 0x22, 0x33, 0x44};
SrsBuffer buf(data, 12);
// Test big-endian 4-byte reads
EXPECT_EQ(0x12345678, buf.read_4bytes());
EXPECT_EQ(4, buf.pos());
EXPECT_EQ((int32_t)0x9ABCDEF0, buf.read_4bytes());
EXPECT_EQ(8, buf.pos());
// Test little-endian 4-byte reads
buf.skip(-8); // Reset to beginning
EXPECT_EQ(0x78563412, buf.read_le4bytes());
EXPECT_EQ(4, buf.pos());
EXPECT_EQ((int32_t)0xF0DEBC9A, buf.read_le4bytes());
EXPECT_EQ(8, buf.pos());
// Read remaining bytes
EXPECT_EQ(0x11223344, buf.read_4bytes());
EXPECT_TRUE(buf.empty());
}
VOID TEST(KernelBufferTest, SrsBufferRead8Bytes)
{
char data[16] = {0x12, 0x34, 0x56, 0x78, (char)0x9A, (char)0xBC, (char)0xDE, (char)0xF0,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (char)0x88};
SrsBuffer buf(data, 16);
// Test big-endian 8-byte reads
EXPECT_EQ(0x123456789ABCDEF0LL, buf.read_8bytes());
EXPECT_EQ(8, buf.pos());
// Test little-endian 8-byte reads
buf.skip(-8); // Reset to beginning
EXPECT_EQ(0xF0DEBC9A78563412LL, buf.read_le8bytes());
EXPECT_EQ(8, buf.pos());
// Read remaining bytes
EXPECT_EQ(0x1122334455667788LL, buf.read_8bytes());
EXPECT_TRUE(buf.empty());
// Test with maximum values
char max_data[8] = {(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF,
(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF};
SrsBuffer max_buf(max_data, 8);
EXPECT_EQ(-1LL, max_buf.read_8bytes());
}
VOID TEST(KernelBufferTest, SrsBufferReadString)
{
char data[] = "Hello, World! This is a test string.";
SrsBuffer buf(data, strlen(data));
// Test reading strings of various lengths
std::string str1 = buf.read_string(5);
EXPECT_STREQ("Hello", str1.c_str());
EXPECT_EQ(5, buf.pos());
std::string str2 = buf.read_string(2);
EXPECT_STREQ(", ", str2.c_str());
EXPECT_EQ(7, buf.pos());
std::string str3 = buf.read_string(6);
EXPECT_STREQ("World!", str3.c_str());
EXPECT_EQ(13, buf.pos());
// Test reading zero-length string
std::string empty_str = buf.read_string(0);
EXPECT_STREQ("", empty_str.c_str());
EXPECT_EQ(13, buf.pos()); // Position unchanged
// Test reading remaining string
int remaining = buf.left();
std::string remaining_str = buf.read_string(remaining);
EXPECT_STREQ(" This is a test string.", remaining_str.c_str());
EXPECT_TRUE(buf.empty());
// Test with binary data containing null bytes
char binary_data[6] = {0x41, 0x00, 0x42, 0x00, 0x43, 0x44};
SrsBuffer binary_buf(binary_data, 6);
std::string binary_str = binary_buf.read_string(6);
EXPECT_EQ(6, binary_str.length());
EXPECT_EQ(0x41, binary_str[0]);
EXPECT_EQ(0x00, binary_str[1]);
EXPECT_EQ(0x42, binary_str[2]);
EXPECT_EQ(0x00, binary_str[3]);
EXPECT_EQ(0x43, binary_str[4]);
EXPECT_EQ(0x44, binary_str[5]);
}
VOID TEST(KernelBufferTest, SrsBufferReadBytes)
{
char data[10] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, (char)0x80, (char)0x90, (char)0xA0};
SrsBuffer buf(data, 10);
// Test reading bytes into buffer
char output[4];
buf.read_bytes(output, 4);
EXPECT_EQ(0x10, output[0]);
EXPECT_EQ(0x20, output[1]);
EXPECT_EQ(0x30, output[2]);
EXPECT_EQ(0x40, output[3]);
EXPECT_EQ(4, buf.pos());
// Test reading more bytes
char output2[3];
buf.read_bytes(output2, 3);
EXPECT_EQ(0x50, output2[0]);
EXPECT_EQ(0x60, output2[1]);
EXPECT_EQ(0x70, output2[2]);
EXPECT_EQ(7, buf.pos());
// Test reading zero bytes
char output3[1] = {(char)0xFF};
buf.read_bytes(output3, 0);
EXPECT_EQ((char)0xFF, output3[0]); // Should be unchanged
EXPECT_EQ(7, buf.pos()); // Position unchanged
// Test reading remaining bytes
char output4[3];
buf.read_bytes(output4, 3);
EXPECT_EQ((char)0x80, output4[0]);
EXPECT_EQ((char)0x90, output4[1]);
EXPECT_EQ((char)0xA0, output4[2]);
EXPECT_TRUE(buf.empty());
}
VOID TEST(KernelBufferTest, SrsBufferWrite1Bytes)
{
char data[8];
SrsBuffer buf(data, 8);
// Test writing 1-byte values
buf.write_1bytes(0x12);
EXPECT_EQ(1, buf.pos());
EXPECT_EQ(0x12, data[0]);
buf.write_1bytes(0x34);
EXPECT_EQ(2, buf.pos());
EXPECT_EQ(0x34, data[1]);
// Test writing signed values
buf.write_1bytes(-1);
EXPECT_EQ(3, buf.pos());
EXPECT_EQ((char)0xFF, data[2]);
buf.write_1bytes(-128);
EXPECT_EQ(4, buf.pos());
EXPECT_EQ((char)0x80, data[3]);
// Test writing maximum positive value
buf.write_1bytes(127);
EXPECT_EQ(5, buf.pos());
EXPECT_EQ(0x7F, data[4]);
// Verify we can read back what we wrote
buf.skip(-5); // Reset to beginning
EXPECT_EQ(0x12, buf.read_1bytes());
EXPECT_EQ(0x34, buf.read_1bytes());
EXPECT_EQ(-1, buf.read_1bytes());
EXPECT_EQ(-128, buf.read_1bytes());
EXPECT_EQ(127, buf.read_1bytes());
}
VOID TEST(KernelBufferTest, SrsBufferWrite2Bytes)
{
char data[16];
SrsBuffer buf(data, 16);
// Test big-endian 2-byte writes
buf.write_2bytes(0x1234);
EXPECT_EQ(2, buf.pos());
EXPECT_EQ(0x12, data[0]);
EXPECT_EQ(0x34, data[1]);
buf.write_2bytes(0x5678);
EXPECT_EQ(4, buf.pos());
EXPECT_EQ(0x56, data[2]);
EXPECT_EQ(0x78, data[3]);
// Test little-endian 2-byte writes
buf.write_le2bytes(0x9ABC);
EXPECT_EQ(6, buf.pos());
EXPECT_EQ((char)0xBC, data[4]);
EXPECT_EQ((char)0x9A, data[5]);
buf.write_le2bytes(0xDEF0);
EXPECT_EQ(8, buf.pos());
EXPECT_EQ((char)0xF0, data[6]);
EXPECT_EQ((char)0xDE, data[7]);
// Test with negative values
buf.write_2bytes(-1);
EXPECT_EQ(10, buf.pos());
EXPECT_EQ((char)0xFF, data[8]);
EXPECT_EQ((char)0xFF, data[9]);
// Verify we can read back what we wrote
buf.skip(-10); // Reset to beginning
EXPECT_EQ(0x1234, buf.read_2bytes());
EXPECT_EQ(0x5678, buf.read_2bytes());
EXPECT_EQ((int16_t)0x9ABC, buf.read_le2bytes());
EXPECT_EQ((int16_t)0xDEF0, buf.read_le2bytes());
EXPECT_EQ(-1, buf.read_2bytes());
}
VOID TEST(KernelBufferTest, SrsBufferWrite3Bytes)
{
char data[18];
SrsBuffer buf(data, 18);
// Test big-endian 3-byte writes
buf.write_3bytes(0x123456);
EXPECT_EQ(3, buf.pos());
EXPECT_EQ(0x12, data[0]);
EXPECT_EQ(0x34, data[1]);
EXPECT_EQ(0x56, data[2]);
buf.write_3bytes(0x789ABC);
EXPECT_EQ(6, buf.pos());
EXPECT_EQ(0x78, data[3]);
EXPECT_EQ((char)0x9A, data[4]);
EXPECT_EQ((char)0xBC, data[5]);
// Test little-endian 3-byte writes
buf.write_le3bytes(0xDEF012);
EXPECT_EQ(9, buf.pos());
EXPECT_EQ(0x12, data[6]);
EXPECT_EQ((char)0xF0, data[7]);
EXPECT_EQ((char)0xDE, data[8]);
buf.write_le3bytes(0x345678);
EXPECT_EQ(12, buf.pos());
EXPECT_EQ(0x78, data[9]);
EXPECT_EQ(0x56, data[10]);
EXPECT_EQ(0x34, data[11]);
// Test with maximum 3-byte value
buf.write_3bytes(0xFFFFFF);
EXPECT_EQ(15, buf.pos());
EXPECT_EQ((char)0xFF, data[12]);
EXPECT_EQ((char)0xFF, data[13]);
EXPECT_EQ((char)0xFF, data[14]);
// Verify we can read back what we wrote
buf.skip(-15); // Reset to beginning
EXPECT_EQ(0x123456, buf.read_3bytes());
EXPECT_EQ(0x789ABC, buf.read_3bytes());
EXPECT_EQ(0xDEF012, buf.read_le3bytes());
EXPECT_EQ(0x345678, buf.read_le3bytes());
EXPECT_EQ(0xFFFFFF, buf.read_3bytes());
}
VOID TEST(KernelBufferTest, SrsBufferWrite4Bytes)
{
char data[24];
SrsBuffer buf(data, 24);
// Test big-endian 4-byte writes
buf.write_4bytes(0x12345678);
EXPECT_EQ(4, buf.pos());
EXPECT_EQ(0x12, data[0]);
EXPECT_EQ(0x34, data[1]);
EXPECT_EQ(0x56, data[2]);
EXPECT_EQ(0x78, data[3]);
buf.write_4bytes((int32_t)0x9ABCDEF0);
EXPECT_EQ(8, buf.pos());
EXPECT_EQ((char)0x9A, data[4]);
EXPECT_EQ((char)0xBC, data[5]);
EXPECT_EQ((char)0xDE, data[6]);
EXPECT_EQ((char)0xF0, data[7]);
// Test little-endian 4-byte writes
buf.write_le4bytes(0x11223344);
EXPECT_EQ(12, buf.pos());
EXPECT_EQ(0x44, data[8]);
EXPECT_EQ(0x33, data[9]);
EXPECT_EQ(0x22, data[10]);
EXPECT_EQ(0x11, data[11]);
buf.write_le4bytes(0x55667788);
EXPECT_EQ(16, buf.pos());
EXPECT_EQ((char)0x88, data[12]);
EXPECT_EQ(0x77, data[13]);
EXPECT_EQ(0x66, data[14]);
EXPECT_EQ(0x55, data[15]);
// Test with negative values
buf.write_4bytes(-1);
EXPECT_EQ(20, buf.pos());
EXPECT_EQ((char)0xFF, data[16]);
EXPECT_EQ((char)0xFF, data[17]);
EXPECT_EQ((char)0xFF, data[18]);
EXPECT_EQ((char)0xFF, data[19]);
// Verify we can read back what we wrote
buf.skip(-20); // Reset to beginning
EXPECT_EQ(0x12345678, buf.read_4bytes());
EXPECT_EQ((int32_t)0x9ABCDEF0, buf.read_4bytes());
EXPECT_EQ(0x11223344, buf.read_le4bytes());
EXPECT_EQ(0x55667788, buf.read_le4bytes());
EXPECT_EQ(-1, buf.read_4bytes());
}
VOID TEST(KernelBufferTest, SrsBufferWrite8Bytes)
{
char data[32];
SrsBuffer buf(data, 32);
// Test big-endian 8-byte writes
buf.write_8bytes(0x123456789ABCDEF0LL);
EXPECT_EQ(8, buf.pos());
EXPECT_EQ(0x12, data[0]);
EXPECT_EQ(0x34, data[1]);
EXPECT_EQ(0x56, data[2]);
EXPECT_EQ(0x78, data[3]);
EXPECT_EQ((char)0x9A, data[4]);
EXPECT_EQ((char)0xBC, data[5]);
EXPECT_EQ((char)0xDE, data[6]);
EXPECT_EQ((char)0xF0, data[7]);
buf.write_8bytes(0x1122334455667788LL);
EXPECT_EQ(16, buf.pos());
EXPECT_EQ(0x11, data[8]);
EXPECT_EQ(0x22, data[9]);
EXPECT_EQ(0x33, data[10]);
EXPECT_EQ(0x44, data[11]);
EXPECT_EQ(0x55, data[12]);
EXPECT_EQ(0x66, data[13]);
EXPECT_EQ(0x77, data[14]);
EXPECT_EQ((char)0x88, data[15]);
// Test little-endian 8-byte writes
buf.write_le8bytes(0xAABBCCDDEEFF0011LL);
EXPECT_EQ(24, buf.pos());
EXPECT_EQ(0x11, data[16]);
EXPECT_EQ(0x00, data[17]);
EXPECT_EQ((char)0xFF, data[18]);
EXPECT_EQ((char)0xEE, data[19]);
EXPECT_EQ((char)0xDD, data[20]);
EXPECT_EQ((char)0xCC, data[21]);
EXPECT_EQ((char)0xBB, data[22]);
EXPECT_EQ((char)0xAA, data[23]);
// Test with negative values
buf.write_8bytes(-1LL);
EXPECT_EQ(32, buf.pos());
for (int i = 24; i < 32; i++) {
EXPECT_EQ((char)0xFF, data[i]);
}
// Verify we can read back what we wrote
buf.skip(-32); // Reset to beginning
EXPECT_EQ(0x123456789ABCDEF0LL, buf.read_8bytes());
EXPECT_EQ(0x1122334455667788LL, buf.read_8bytes());
EXPECT_EQ((int64_t)0xAABBCCDDEEFF0011LL, buf.read_le8bytes());
EXPECT_EQ(-1LL, buf.read_8bytes());
}
VOID TEST(KernelBufferTest, SrsBufferWriteString)
{
char data[64];
SrsBuffer buf(data, 64);
// Test writing simple string
std::string str1 = "Hello";
buf.write_string(str1);
EXPECT_EQ(5, buf.pos());
EXPECT_EQ('H', data[0]);
EXPECT_EQ('e', data[1]);
EXPECT_EQ('l', data[2]);
EXPECT_EQ('l', data[3]);
EXPECT_EQ('o', data[4]);
// Test writing string with special characters
std::string str2 = ", World!";
buf.write_string(str2);
EXPECT_EQ(13, buf.pos());
EXPECT_EQ(',', data[5]);
EXPECT_EQ(' ', data[6]);
EXPECT_EQ('W', data[7]);
EXPECT_EQ('!', data[12]);
// Test writing empty string
std::string empty_str = "";
buf.write_string(empty_str);
EXPECT_EQ(13, buf.pos()); // Position unchanged
// Test writing string with null bytes
std::string binary_str;
binary_str.push_back(0x41);
binary_str.push_back(0x00);
binary_str.push_back(0x42);
binary_str.push_back(0x00);
binary_str.push_back(0x43);
buf.write_string(binary_str);
EXPECT_EQ(18, buf.pos());
EXPECT_EQ(0x41, data[13]);
EXPECT_EQ(0x00, data[14]);
EXPECT_EQ(0x42, data[15]);
EXPECT_EQ(0x00, data[16]);
EXPECT_EQ(0x43, data[17]);
// Verify we can read back what we wrote
buf.skip(-18); // Reset to beginning
std::string read_str1 = buf.read_string(5);
EXPECT_STREQ("Hello", read_str1.c_str());
std::string read_str2 = buf.read_string(8);
EXPECT_STREQ(", World!", read_str2.c_str());
std::string read_binary = buf.read_string(5);
EXPECT_EQ(5, read_binary.length());
EXPECT_EQ(0x41, read_binary[0]);
EXPECT_EQ(0x00, read_binary[1]);
EXPECT_EQ(0x42, read_binary[2]);
EXPECT_EQ(0x00, read_binary[3]);
EXPECT_EQ(0x43, read_binary[4]);
}
VOID TEST(KernelBufferTest, SrsBufferWriteBytes)
{
char data[32];
SrsBuffer buf(data, 32);
// Test writing byte array
char input1[6] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60};
buf.write_bytes(input1, 6);
EXPECT_EQ(6, buf.pos());
for (int i = 0; i < 6; i++) {
EXPECT_EQ(input1[i], data[i]);
}
// Test writing another byte array
char input2[4] = {0x70, (char)0x80, (char)0x90, (char)0xA0};
buf.write_bytes(input2, 4);
EXPECT_EQ(10, buf.pos());
for (int i = 0; i < 4; i++) {
EXPECT_EQ(input2[i], data[6 + i]);
}
// Test writing zero bytes
char input3[1] = {(char)0xFF};
buf.write_bytes(input3, 0);
EXPECT_EQ(10, buf.pos()); // Position unchanged
// Test writing bytes with null values
char input4[5] = {(char)0xB0, 0x00, (char)0xC0, 0x00, (char)0xD0};
buf.write_bytes(input4, 5);
EXPECT_EQ(15, buf.pos());
for (int i = 0; i < 5; i++) {
EXPECT_EQ(input4[i], data[10 + i]);
}
// Verify we can read back what we wrote
buf.skip(-15); // Reset to beginning
char output1[6];
buf.read_bytes(output1, 6);
for (int i = 0; i < 6; i++) {
EXPECT_EQ(input1[i], output1[i]);
}
char output2[4];
buf.read_bytes(output2, 4);
for (int i = 0; i < 4; i++) {
EXPECT_EQ(input2[i], output2[i]);
}
char output4[5];
buf.read_bytes(output4, 5);
for (int i = 0; i < 5; i++) {
EXPECT_EQ(input4[i], output4[i]);
}
}
VOID TEST(KernelBufferTest, SrsBufferEdgeCases)
{
// Test with very small buffer
char small_data[1];
SrsBuffer small_buf(small_data, 1);
small_buf.write_1bytes(0x42);
EXPECT_EQ(1, small_buf.pos());
EXPECT_TRUE(small_buf.empty());
small_buf.skip(-1);
EXPECT_EQ(0x42, small_buf.read_1bytes());
EXPECT_TRUE(small_buf.empty());
// Test position tracking with mixed operations
char mixed_data[16];
SrsBuffer mixed_buf(mixed_data, 16);
mixed_buf.write_4bytes(0x12345678);
EXPECT_EQ(4, mixed_buf.pos());
mixed_buf.skip(-2);
EXPECT_EQ(2, mixed_buf.pos());
EXPECT_EQ(0x5678, mixed_buf.read_2bytes());
EXPECT_EQ(4, mixed_buf.pos());
mixed_buf.write_2bytes((int16_t)0x9ABC);
EXPECT_EQ(6, mixed_buf.pos());
// Verify data integrity
mixed_buf.skip(-6);
EXPECT_EQ(0x12345678, mixed_buf.read_4bytes());
EXPECT_EQ((int16_t)0x9ABC, mixed_buf.read_2bytes());
// Test boundary conditions
char boundary_data[8];
SrsBuffer boundary_buf(boundary_data, 8);
// Fill buffer completely
boundary_buf.write_8bytes(0x123456789ABCDEF0LL);
EXPECT_EQ(8, boundary_buf.pos());
EXPECT_TRUE(boundary_buf.empty());
EXPECT_EQ(0, boundary_buf.left());
// Reset and verify
boundary_buf.skip(-8);
EXPECT_EQ(0, boundary_buf.pos());
EXPECT_FALSE(boundary_buf.empty());
EXPECT_EQ(8, boundary_buf.left());
EXPECT_EQ(0x123456789ABCDEF0LL, boundary_buf.read_8bytes());
}
VOID TEST(KernelBitBufferTest, Constructor)
{
char data[4] = {0x12, 0x34, 0x56, 0x78};
SrsBuffer buffer(data, 4);
SrsBitBuffer bb(&buffer);
// Test initial state
EXPECT_FALSE(bb.empty());
EXPECT_EQ(32, bb.left_bits());
}
VOID TEST(KernelBitBufferTest, EmptyBuffer)
{
SrsBuffer buffer(NULL, 0);
SrsBitBuffer bb(&buffer);
EXPECT_TRUE(bb.empty());
EXPECT_EQ(0, bb.left_bits());
}
VOID TEST(KernelBitBufferTest, ReadBit)
{
// Test reading individual bits from 0x80 (10000000)
char data[1] = {(char)0x80};
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
EXPECT_EQ(1, bb.read_bit()); // First bit is 1
EXPECT_EQ(0, bb.read_bit()); // Second bit is 0
EXPECT_EQ(0, bb.read_bit()); // Third bit is 0
EXPECT_EQ(0, bb.read_bit()); // Fourth bit is 0
EXPECT_EQ(0, bb.read_bit()); // Fifth bit is 0
EXPECT_EQ(0, bb.read_bit()); // Sixth bit is 0
EXPECT_EQ(0, bb.read_bit()); // Seventh bit is 0
EXPECT_EQ(0, bb.read_bit()); // Eighth bit is 0
EXPECT_TRUE(bb.empty());
EXPECT_EQ(0, bb.left_bits());
}
VOID TEST(KernelBitBufferTest, ReadBitMultipleBytes)
{
// Test reading bits across byte boundaries: 0xFF00 (11111111 00000000)
char data[2] = {(char)0xFF, 0x00};
SrsBuffer buffer(data, 2);
SrsBitBuffer bb(&buffer);
// Read first 8 bits (all 1s)
for (int i = 0; i < 8; i++) {
EXPECT_EQ(1, bb.read_bit());
}
// Read next 8 bits (all 0s)
for (int i = 0; i < 8; i++) {
EXPECT_EQ(0, bb.read_bit());
}
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, RequireBits)
{
char data[4] = {0x12, 0x34, 0x56, 0x78};
SrsBuffer buffer(data, 4);
SrsBitBuffer bb(&buffer);
EXPECT_TRUE(bb.require_bits(1));
EXPECT_TRUE(bb.require_bits(32));
EXPECT_FALSE(bb.require_bits(33));
EXPECT_FALSE(bb.require_bits(-1));
// After reading some bits
bb.read_bits(16);
EXPECT_TRUE(bb.require_bits(16));
EXPECT_FALSE(bb.require_bits(17));
}
VOID TEST(KernelBitBufferTest, SkipBits)
{
char data[2] = {0x12, 0x34};
SrsBuffer buffer(data, 2);
SrsBitBuffer bb(&buffer);
EXPECT_EQ(16, bb.left_bits());
bb.skip_bits(4);
EXPECT_EQ(12, bb.left_bits());
bb.skip_bits(8);
EXPECT_EQ(4, bb.left_bits());
bb.skip_bits(4);
EXPECT_EQ(0, bb.left_bits());
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, ReadBits)
{
// Test reading 0x12 (00010010) bit by bit and in groups
char data[1] = {0x12};
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
// Read first 4 bits: 0001 = 1
int32_t value = bb.read_bits(4);
EXPECT_EQ(1, value);
// Read next 4 bits: 0010 = 2
value = bb.read_bits(4);
EXPECT_EQ(2, value);
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, ReadBitsLargeValue)
{
// Test reading 0x12345678
char data[4] = {0x12, 0x34, 0x56, 0x78};
SrsBuffer buffer(data, 4);
SrsBitBuffer bb(&buffer);
int32_t value = bb.read_bits(32);
EXPECT_EQ(0x12345678, value);
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, ReadBitsAcrossByteBoundary)
{
// Test reading bits that span across byte boundaries
// 0x12 = 00010010, 0x34 = 00110100
char data[2] = {0x12, 0x34};
SrsBuffer buffer(data, 2);
SrsBitBuffer bb(&buffer);
// Read 12 bits: 000100100011 = 0x123
int32_t value = bb.read_bits(12);
EXPECT_EQ(0x123, value);
// Read remaining 4 bits: 0100 = 4
value = bb.read_bits(4);
EXPECT_EQ(4, value);
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, Read8Bits)
{
char data[2] = {0x12, 0x34};
SrsBuffer buffer(data, 2);
SrsBitBuffer bb(&buffer);
// Test fast path (byte-aligned)
int8_t value = bb.read_8bits();
EXPECT_EQ(0x12, value);
value = bb.read_8bits();
EXPECT_EQ(0x34, value);
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, Read8BitsNonAligned)
{
char data[2] = {0x12, 0x34};
SrsBuffer buffer(data, 2);
SrsBitBuffer bb(&buffer);
// Read 4 bits first to make it non-aligned
bb.read_bits(4);
// Now read 8 bits (should use slow path)
int8_t value = bb.read_8bits();
EXPECT_EQ(0x23, value); // 0010 0011 from remaining bits
// Read remaining 4 bits
int32_t remaining = bb.read_bits(4);
EXPECT_EQ(4, remaining);
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, Read16Bits)
{
char data[4] = {0x12, 0x34, 0x56, 0x78};
SrsBuffer buffer(data, 4);
SrsBitBuffer bb(&buffer);
// Test fast path (byte-aligned)
int16_t value = bb.read_16bits();
EXPECT_EQ(0x1234, value);
value = bb.read_16bits();
EXPECT_EQ(0x5678, value);
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, Read16BitsNonAligned)
{
char data[3] = {0x12, 0x34, 0x56};
SrsBuffer buffer(data, 3);
SrsBitBuffer bb(&buffer);
// Read 4 bits first to make it non-aligned
bb.read_bits(4);
// Now read 16 bits (should use slow path)
int16_t value = bb.read_16bits();
EXPECT_EQ(0x2345, value); // From remaining bits
// Read remaining 4 bits
int32_t remaining = bb.read_bits(4);
EXPECT_EQ(6, remaining);
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, Read32Bits)
{
char data[8] = {0x12, 0x34, 0x56, 0x78, (char)0x9A, (char)0xBC, (char)0xDE, (char)0xF0};
SrsBuffer buffer(data, 8);
SrsBitBuffer bb(&buffer);
// Test fast path (byte-aligned)
int32_t value = bb.read_32bits();
EXPECT_EQ(0x12345678, value);
value = bb.read_32bits();
EXPECT_EQ((int32_t)0x9ABCDEF0, value);
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, Read32BitsNonAligned)
{
char data[5] = {0x12, 0x34, 0x56, 0x78, (char)0x9A};
SrsBuffer buffer(data, 5);
SrsBitBuffer bb(&buffer);
// Read 4 bits first to make it non-aligned
bb.read_bits(4);
// Now read 32 bits (should use slow path)
int32_t value = bb.read_32bits();
EXPECT_EQ(0x23456789, value); // From remaining bits
// Read remaining 4 bits
int32_t remaining = bb.read_bits(4);
EXPECT_EQ(0xA, remaining);
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, ReadBitsUE_BasicValues)
{
srs_error_t err;
// Test ue(v) = 0: encoded as "1" (binary)
if (true) {
char data[1] = {(char)0x80}; // 10000000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(0, (int)value);
}
// Test ue(v) = 1: encoded as "010" (binary)
if (true) {
char data[1] = {0x40}; // 01000000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(1, (int)value);
}
// Test ue(v) = 2: encoded as "011" (binary)
if (true) {
char data[1] = {0x60}; // 01100000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(2, (int)value);
}
// Test ue(v) = 3: encoded as "00100" (binary)
if (true) {
char data[1] = {0x20}; // 00100000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(3, (int)value);
}
}
VOID TEST(KernelBitBufferTest, ReadBitsUE_LargerValues)
{
srs_error_t err;
// Test ue(v) = 6: encoded as "00111" (binary) - 0x38 = 00111000
if (true) {
char data[1] = {0x38}; // 00111000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(6, (int)value);
}
// Test ue(v) = 7: encoded as "00100" (binary) - 0x10 = 00010000
if (true) {
char data[1] = {0x10}; // 00010000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(7, (int)value);
}
// Test larger value that spans multiple bytes
if (true) {
char data[2] = {0x01, 0x12}; // 00000001 00010010
SrsBuffer buffer(data, 2);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
// From existing tests: 0x01, 0x12 should give 128 - 1 + 9 = 136
EXPECT_EQ(136, (int)value);
}
}
VOID TEST(KernelBitBufferTest, ReadBitsUE_ErrorCases)
{
srs_error_t err;
// Test empty buffer
if (true) {
SrsBuffer buffer(NULL, 0);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_FAILED(bb.read_bits_ue(value));
}
// Test overflow case (too many leading zeros)
if (true) {
char data[4] = {0x00, 0x00, 0x00, 0x01}; // 31+ leading zeros
SrsBuffer buffer(data, 4);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_FAILED(bb.read_bits_ue(value));
}
// Test insufficient data for leadingZeroBits
if (true) {
char data[1] = {0x01}; // 00000001 - needs more data
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_FAILED(bb.read_bits_ue(value));
}
}
VOID TEST(KernelBitBufferTest, ReadBitsSE_BasicValues)
{
srs_error_t err;
// Test se(v) = 0: same as ue(v) = 0, encoded as "1"
if (true) {
char data[1] = {(char)0x80}; // 10000000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(0, value);
}
// Test se(v) = 1: ue(v) = 1, encoded as "010"
if (true) {
char data[1] = {0x40}; // 01000000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(1, value);
}
// Test se(v) = -1: ue(v) = 2, encoded as "011"
if (true) {
char data[1] = {0x60}; // 01100000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(-1, value);
}
// Test se(v) = 2: ue(v) = 3, encoded as "00100"
if (true) {
char data[1] = {0x20}; // 00100000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(2, value);
}
// Test se(v) = -2: ue(v) = 4, encoded as "00101"
if (true) {
char data[1] = {0x28}; // 00101000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(-2, value);
}
}
VOID TEST(KernelBitBufferTest, ReadBitsSE_ErrorCases)
{
srs_error_t err;
// Test empty buffer
if (true) {
SrsBuffer buffer(NULL, 0);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_FAILED(bb.read_bits_se(value));
}
// Test error propagation from read_bits_ue
if (true) {
char data[4] = {0x00, 0x00, 0x00, 0x01}; // Will cause overflow in ue
SrsBuffer buffer(data, 4);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_FAILED(bb.read_bits_se(value));
}
}
VOID TEST(KernelBitBufferTest, EdgeCases)
{
// Test reading from single bit buffer
if (true) {
char data[1] = {(char)0x80}; // 10000000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
EXPECT_EQ(1, bb.read_bit());
EXPECT_EQ(7, bb.left_bits());
EXPECT_FALSE(bb.empty());
// Read remaining bits
for (int i = 0; i < 7; i++) {
EXPECT_EQ(0, bb.read_bit());
}
EXPECT_TRUE(bb.empty());
EXPECT_EQ(0, bb.left_bits());
}
// Test mixed operations
if (true) {
char data[4] = {0x12, 0x34, 0x56, 0x78};
SrsBuffer buffer(data, 4);
SrsBitBuffer bb(&buffer);
// Read some bits
int32_t bits = bb.read_bits(4);
EXPECT_EQ(1, bits); // First 4 bits of 0x12
// Skip some bits
bb.skip_bits(4);
// Read a byte (should use slow path since not aligned)
int8_t byte_val = bb.read_8bits();
EXPECT_EQ(0x34, byte_val);
// Read remaining bits
int32_t remaining = bb.read_bits(16);
EXPECT_EQ(0x5678, remaining);
EXPECT_TRUE(bb.empty());
}
}
VOID TEST(KernelBitBufferTest, LeftBitsCalculation)
{
char data[3] = {0x12, 0x34, 0x56};
SrsBuffer buffer(data, 3);
SrsBitBuffer bb(&buffer);
EXPECT_EQ(24, bb.left_bits());
// Read some bits and verify left_bits calculation
bb.read_bits(5);
EXPECT_EQ(19, bb.left_bits());
bb.read_bits(8);
EXPECT_EQ(11, bb.left_bits());
bb.read_bits(11);
EXPECT_EQ(0, bb.left_bits());
EXPECT_TRUE(bb.empty());
}
VOID TEST(KernelBitBufferTest, RequireBitsEdgeCases)
{
char data[2] = {0x12, 0x34};
SrsBuffer buffer(data, 2);
SrsBitBuffer bb(&buffer);
// Test boundary conditions
EXPECT_TRUE(bb.require_bits(0));
EXPECT_TRUE(bb.require_bits(16));
EXPECT_FALSE(bb.require_bits(17));
// After reading partial byte
bb.read_bits(3);
EXPECT_TRUE(bb.require_bits(13));
EXPECT_FALSE(bb.require_bits(14));
// Test negative input
EXPECT_FALSE(bb.require_bits(-1));
EXPECT_FALSE(bb.require_bits(-100));
}
VOID TEST(KernelBitBufferTest, ReadBitsUE_AlgorithmDefinition)
{
srs_error_t err;
// Test based on ITU-T H.265 algorithm definition:
// codeNum = (2^leadingZeroBits) - 1 + read_bits(leadingZeroBits)
// Test ue(v) = 0: leadingZeroBits = 0, codeNum = (2^0) - 1 + 0 = 0
// Binary: "1"
if (true) {
char data[1] = {(char)0x80}; // 10000000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(0, (int)value);
}
// Test ue(v) = 1: leadingZeroBits = 1, codeNum = (2^1) - 1 + 0 = 1
// Binary: "010"
if (true) {
char data[1] = {0x40}; // 01000000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(1, (int)value);
}
// Test ue(v) = 2: leadingZeroBits = 1, codeNum = (2^1) - 1 + 1 = 2
// Binary: "011"
if (true) {
char data[1] = {0x60}; // 01100000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(2, (int)value);
}
// Test ue(v) = 3: leadingZeroBits = 2, codeNum = (2^2) - 1 + 0 = 3
// Binary: "00100"
if (true) {
char data[1] = {0x20}; // 00100000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(3, (int)value);
}
// Test ue(v) = 4: leadingZeroBits = 2, codeNum = (2^2) - 1 + 1 = 4
// Binary: "00101"
if (true) {
char data[1] = {0x28}; // 00101000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(4, (int)value);
}
// Test ue(v) = 5: leadingZeroBits = 2, codeNum = (2^2) - 1 + 2 = 5
// Binary: "00110"
if (true) {
char data[1] = {0x30}; // 00110000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(5, (int)value);
}
// Test ue(v) = 6: leadingZeroBits = 2, codeNum = (2^2) - 1 + 3 = 6
// Binary: "00111"
if (true) {
char data[1] = {0x38}; // 00111000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(6, (int)value);
}
// Test ue(v) = 7: Use known working pattern from existing tests
// Binary: "00010000" = 0x10
if (true) {
char data[1] = {0x10}; // 00010000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(7, (int)value);
}
// Test ue(v) = 8: Use known working pattern from existing tests
// Binary: "00010010" = 0x12
if (true) {
char data[1] = {0x12}; // 00010010
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(8, (int)value);
}
// Test ue(v) = 9: Use known working pattern from existing tests
// Binary: "00010100" = 0x14
if (true) {
char data[1] = {0x14}; // 00010100
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(9, (int)value);
}
}
VOID TEST(KernelBitBufferTest, ReadBitsUE_LargeValues)
{
srs_error_t err;
// Test larger values using known working patterns from existing tests
// These tests verify the algorithm works for larger values without
// manually calculating the bit patterns
// Test a known working large value from existing tests
if (true) {
char data[2] = {0x01, 0x12}; // From existing tests: gives 136
SrsBuffer buffer(data, 2);
SrsBitBuffer bb(&buffer);
uint32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(value));
EXPECT_EQ(136, (int)value); // Known working value
}
}
VOID TEST(KernelBitBufferTest, ReadBitsSE_AlgorithmDefinition)
{
srs_error_t err;
// Test based on ITU-T H.265 algorithm definition:
// se(v) mapping: if (ue_val & 1) se_val = (ue_val + 1) / 2; else se_val = -(ue_val / 2);
// Test se(v) = 0: ue(v) = 0, se_val = -(0/2) = 0
// Binary: "1"
if (true) {
char data[1] = {(char)0x80}; // 10000000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(0, value);
}
// Test se(v) = 1: ue(v) = 1, se_val = (1+1)/2 = 1
// Binary: "010"
if (true) {
char data[1] = {0x40}; // 01000000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(1, value);
}
// Test se(v) = -1: ue(v) = 2, se_val = -(2/2) = -1
// Binary: "011"
if (true) {
char data[1] = {0x60}; // 01100000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(-1, value);
}
// Test se(v) = 2: ue(v) = 3, se_val = (3+1)/2 = 2
// Binary: "00100"
if (true) {
char data[1] = {0x20}; // 00100000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(2, value);
}
// Test se(v) = -2: ue(v) = 4, se_val = -(4/2) = -2
// Binary: "00101"
if (true) {
char data[1] = {0x28}; // 00101000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(-2, value);
}
// Test se(v) = 3: ue(v) = 5, se_val = (5+1)/2 = 3
// Binary: "00110"
if (true) {
char data[1] = {0x30}; // 00110000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(3, value);
}
// Test se(v) = -3: ue(v) = 6, se_val = -(6/2) = -3
// Binary: "00111"
if (true) {
char data[1] = {0x38}; // 00111000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(-3, value);
}
// Test se(v) = 4: ue(v) = 7, se_val = (7+1)/2 = 4
// Use known working pattern: 0x10 gives ue(7)
if (true) {
char data[1] = {0x10}; // 00010000
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(4, value);
}
// Test se(v) = -4: ue(v) = 8, se_val = -(8/2) = -4
// Use known working pattern: 0x12 gives ue(8)
if (true) {
char data[1] = {0x12}; // 00010010
SrsBuffer buffer(data, 1);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(-4, value);
}
}
VOID TEST(KernelBitBufferTest, ReadBitsSE_LargeValues)
{
srs_error_t err;
// Test larger signed values using known working patterns
// These tests verify the se() algorithm works for larger values
// Test a known working large positive value
// Using ue(136) from existing tests, se_val = (135+1)/2 = 68
if (true) {
char data[2] = {0x01, 0x11}; // Pattern that gives ue(135)
SrsBuffer buffer(data, 2);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(68, value); // (135+1)/2 = 68
}
// Test a known working large negative value
// Using ue(136) from existing tests, se_val = -(136/2) = -68
if (true) {
char data[2] = {0x01, 0x12}; // Pattern that gives ue(136)
SrsBuffer buffer(data, 2);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_SUCCESS(bb.read_bits_se(value));
EXPECT_EQ(-68, value); // -(136/2) = -68
}
}
VOID TEST(KernelBitBufferTest, ReadBitsUE_SE_ErrorPropagation)
{
srs_error_t err;
// Test that se() properly propagates errors from ue()
if (true) {
SrsBuffer buffer(NULL, 0);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_FAILED(bb.read_bits_se(value));
}
// Test overflow propagation from ue() to se()
if (true) {
char data[4] = {0x00, 0x00, 0x00, 0x01}; // Will cause overflow in ue
SrsBuffer buffer(data, 4);
SrsBitBuffer bb(&buffer);
int32_t value = 999;
HELPER_EXPECT_FAILED(bb.read_bits_se(value));
}
}
VOID TEST(KernelBitBufferTest, ReadBitsUE_SE_SequentialReading)
{
srs_error_t err;
// Test reading multiple ue/se values from the same buffer
// Data contains: ue(0)=1, ue(1)=010, ue(2)=011, se(1)=010, se(-1)=011
// Binary: "1" + "010" + "011" + "010" + "011" = "1010011010011"
// Padded: "1010011010011000" = 0xA6, 0x98
if (true) {
char data[2] = {(char)0xA6, (char)0x98}; // 10100110 10011000
SrsBuffer buffer(data, 2);
SrsBitBuffer bb(&buffer);
uint32_t ue_val = 999;
int32_t se_val = 999;
// Read ue(0)
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(ue_val));
EXPECT_EQ(0, (int)ue_val);
// Read ue(1)
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(ue_val));
EXPECT_EQ(1, (int)ue_val);
// Read ue(2)
HELPER_EXPECT_SUCCESS(bb.read_bits_ue(ue_val));
EXPECT_EQ(2, (int)ue_val);
// Read se(1)
HELPER_EXPECT_SUCCESS(bb.read_bits_se(se_val));
EXPECT_EQ(1, se_val);
// Read se(-1)
HELPER_EXPECT_SUCCESS(bb.read_bits_se(se_val));
EXPECT_EQ(-1, se_val);
}
}