srs/trunk/src/utest/srs_utest.cpp
Winlin 32dfed43ef
AI: Merge SRT and RTC servers into unified SrsServer. v7.0.68 (#4459)
This PR consolidates the SRT and RTC server functionality into the main
SrsServer class, eliminating the separate `SrsSrtServer` and
`SrsRtcServer` classes and their corresponding adapter classes. This
architectural change simplifies the codebase by removing the hybrid
server pattern and integrating all protocol handling directly into
`SrsServer`.

As unified connection manager (`_srs_conn_manager`) for all protocol
connections, all incoming connections are checked against the same
connection limit in `on_before_connection()`. This enables consistent
connection limits: `max_connections` now protects against resource
exhaustion from any protocol, not just RTMP.

Remove modules because it's not used now, so only keep the server
application module and main entry point. Remove the wait group to run
server, instead, directly run server and invoke the cycle method.

After this PR, the startup workflow and servers architecture should be
much easier to maintain.

---------

Co-authored-by: OSSRS-AI <winlinam@gmail.com>
2025-08-31 08:58:37 -04:00

262 lines
5.6 KiB
C++

//
// Copyright (c) 2013-2025 The SRS Authors
//
// SPDX-License-Identifier: MIT
//
#include <srs_utest.hpp>
#include <srs_app_config.hpp>
#include <srs_app_log.hpp>
#include <srs_app_rtc_dtls.hpp>
#include <srs_app_server.hpp>
#include <srs_kernel_error.hpp>
#include <srs_kernel_log.hpp>
#include <string>
using namespace std;
#include <sys/mman.h>
#include <sys/types.h>
#ifdef SRS_SRT
#include <srs_app_srt_server.hpp>
#include <srt/srt.h>
#endif
// Temporary disk config.
std::string _srs_tmp_file_prefix = "/tmp/srs-utest-";
// Temporary network config.
std::string _srs_tmp_host = "127.0.0.1";
int _srs_tmp_port = 11935;
srs_utime_t _srs_tmp_timeout = (100 * SRS_UTIME_MILLISECONDS);
// kernel module.
ISrsLog *_srs_log = NULL;
ISrsContext *_srs_context = NULL;
// app module.
SrsConfig *_srs_config = NULL;
bool _srs_in_docker = false;
bool _srs_config_by_env = false;
// The binary name of SRS.
const char *_srs_binary = NULL;
#include <srs_app_st.hpp>
#ifdef SRS_SRT
static void srs_srt_utest_null_log_handler(void *opaque, int level, const char *file, int line,
const char *area, const char *message)
{
// srt null log handler, do no print any log.
}
#endif
// Initialize global settings.
srs_error_t prepare_main()
{
srs_error_t err = srs_success;
if ((err = srs_global_initialize()) != srs_success) {
return srs_error_wrap(err, "init global");
}
_srs_server = new SrsServer();
srs_freep(_srs_log);
_srs_log = new MockEmptyLog(SrsLogLevelError);
if ((err = _srs_rtc_dtls_certificate->initialize()) != srs_success) {
return srs_error_wrap(err, "rtc dtls certificate initialize");
}
srs_freep(_srs_context);
_srs_context = new SrsThreadContext();
#ifdef SRS_SRT
if ((err = srs_srt_log_initialize()) != srs_success) {
return srs_error_wrap(err, "srt log initialize");
}
// Prevent the output of srt logs in utest.
srt_setloghandler(NULL, srs_srt_utest_null_log_handler);
_srt_eventloop = new SrsSrtEventLoop();
if ((err = _srt_eventloop->initialize()) != srs_success) {
return srs_error_wrap(err, "srt poller initialize");
}
if ((err = _srt_eventloop->start()) != srs_success) {
return srs_error_wrap(err, "srt poller start");
}
#endif
return err;
}
// We could do something in the main of utest.
// Copy from gtest-1.6.0/src/gtest_main.cc
GTEST_API_ int main(int argc, char **argv)
{
srs_error_t err = srs_success;
_srs_binary = argv[0];
if ((err = prepare_main()) != srs_success) {
fprintf(stderr, "Failed, %s\n", srs_error_desc(err).c_str());
int ret = srs_error_code(err);
srs_freep(err);
return ret;
}
testing::InitGoogleTest(&argc, argv);
int r0 = RUN_ALL_TESTS();
return r0;
}
MockEmptyLog::MockEmptyLog(SrsLogLevel l)
{
level_ = l;
}
MockEmptyLog::~MockEmptyLog()
{
}
void srs_bytes_print(char *pa, int size)
{
for (int i = 0; i < size; i++) {
char v = pa[i];
printf("%#x ", v);
}
printf("\n");
}
// basic test and samples.
VOID TEST(SampleTest, FastSampleInt64Test)
{
EXPECT_EQ(1, (int)sizeof(int8_t));
EXPECT_EQ(2, (int)sizeof(int16_t));
EXPECT_EQ(4, (int)sizeof(int32_t));
EXPECT_EQ(8, (int)sizeof(int64_t));
}
VOID TEST(SampleTest, FastSampleMacrosTest)
{
EXPECT_TRUE(1);
EXPECT_FALSE(0);
EXPECT_EQ(1, 1); // ==
EXPECT_NE(1, 2); // !=
EXPECT_LE(1, 2); // <=
EXPECT_LT(1, 2); // <
EXPECT_GE(2, 1); // >=
EXPECT_GT(2, 1); // >
EXPECT_STREQ("winlin", "winlin");
EXPECT_STRNE("winlin", "srs");
EXPECT_STRCASEEQ("winlin", "Winlin");
EXPECT_STRCASENE("winlin", "srs");
EXPECT_FLOAT_EQ(1.0, 1.000000000000001);
EXPECT_DOUBLE_EQ(1.0, 1.0000000000000001);
EXPECT_NEAR(10, 15, 5);
}
VOID TEST(SampleTest, StringEQTest)
{
string str = "100";
EXPECT_TRUE("100" == str);
EXPECT_EQ("100", str);
EXPECT_STREQ("100", str.c_str());
}
class MockSrsContextId
{
public:
MockSrsContextId()
{
bind_ = NULL;
}
MockSrsContextId(const MockSrsContextId &cp)
{
bind_ = NULL;
if (cp.bind_) {
bind_ = cp.bind_->copy();
}
}
MockSrsContextId &operator=(const MockSrsContextId &cp)
{
srs_freep(bind_);
if (cp.bind_) {
bind_ = cp.bind_->copy();
}
return *this;
}
virtual ~MockSrsContextId()
{
srs_freep(bind_);
}
public:
MockSrsContextId *copy() const
{
MockSrsContextId *cp = new MockSrsContextId();
if (bind_) {
cp->bind_ = bind_->copy();
}
return cp;
}
private:
MockSrsContextId *bind_;
};
VOID TEST(SampleTest, ContextTest)
{
MockSrsContextId cid;
cid.bind_ = new MockSrsContextId();
static std::map<int, MockSrsContextId> cache;
cache[0] = cid;
cache[0] = cid;
}
MockProtectedBuffer::MockProtectedBuffer() : raw_memory_(NULL), size_(0), data_(NULL)
{
}
MockProtectedBuffer::~MockProtectedBuffer()
{
if (size_ && raw_memory_) {
long page_size = sysconf(_SC_PAGESIZE);
munmap(raw_memory_, page_size * 2);
}
}
int MockProtectedBuffer::alloc(int size)
{
srs_assert(!raw_memory_);
long page_size = sysconf(_SC_PAGESIZE);
if (size >= page_size)
return -1;
char *data = (char *)mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (data == MAP_FAILED) {
return -1;
}
size_ = size;
raw_memory_ = data;
data_ = data + page_size - size;
int r0 = mprotect(data + page_size, page_size, PROT_NONE);
if (r0 < 0) {
return r0;
}
return 0;
}