srs/trunk/src/utest/srs_utest_st2.cpp
Winlin b39aae1447 AI: Cover protocol HTTP/HTTPS/RTMP/RTC by utests. (#4493)
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
2025-09-16 22:21:07 -04:00

281 lines
6.9 KiB
C++

//
// Copyright (c) 2013-2025 The SRS Authors
//
// SPDX-License-Identifier: MIT
//
#include <srs_utest_st2.hpp>
#include <srs_app_st.hpp>
#include <srs_core_autofree.hpp>
#include <srs_kernel_error.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_protocol_st.hpp>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
using namespace std;
VOID TEST(StTest, AnonymouseSingleCoroutine)
{
SRS_COROUTINE_GO({
srs_usleep(1 * SRS_UTIME_MILLISECONDS);
});
// Wait for coroutine to terminate. Otherwise, it will be stopped
// and terminated, which cause some of the code not executed.
srs_usleep(50 * SRS_UTIME_MILLISECONDS);
}
VOID TEST(StTest, AnonymouseMultipleCoroutines)
{
SRS_COROUTINE_GO2(coroutine1, {
srs_usleep(1 * SRS_UTIME_MILLISECONDS);
});
// If multiple coroutines in the same scope, we should use different id.
SRS_COROUTINE_GO2(coroutine2, {
srs_usleep(1 * SRS_UTIME_MILLISECONDS);
});
// Wait for coroutine to terminate. Otherwise, it will be stopped
// and terminated, which cause some of the code not executed.
srs_usleep(50 * SRS_UTIME_MILLISECONDS);
}
VOID TEST(StTest, AnonymouseCoroutinePull)
{
int counter = 0;
if (true) {
SrsCoroutineChan ctx;
ctx.push(&counter);
SRS_COROUTINE_GO_CTX(&ctx, {
int *counter = (int *)ctx.pop();
srs_assert(ctx.trd_);
while (ctx.trd_->pull() == srs_success) {
srs_usleep(1 * SRS_UTIME_MILLISECONDS);
}
(*counter)++;
});
// Coroutine not terminated, so the counter is not increased.
EXPECT_TRUE(counter == 0);
// Wait for coroutine to run and terminated, or it will crash
// because the ctx.pop is called after coroutine terminated.
srs_usleep(50 * SRS_UTIME_MILLISECONDS);
}
EXPECT_TRUE(counter == 1);
}
VOID TEST(StTest, AnonymouseCoroutineWithContext)
{
int counter = 0;
SrsCoroutineChan ctx;
ctx.push(&counter);
SRS_COROUTINE_GO_CTX(&ctx, {
int *counter = (int *)ctx.pop();
(*counter)++;
});
// Coroutine not terminated, so the counter is not increased.
EXPECT_TRUE(counter == 0);
// Wait for coroutine to run and terminated, or it will crash
// because the ctx.pop is called after coroutine terminated.
srs_usleep(50 * SRS_UTIME_MILLISECONDS);
EXPECT_TRUE(counter == 1);
// Wait for coroutine to terminate. Otherwise, it will be stopped
// and terminated, which cause some of the code not executed.
srs_usleep(50 * SRS_UTIME_MILLISECONDS);
}
VOID TEST(StTest, AnonymouseCoroutineWithSync)
{
SrsUniquePtr<SrsCond> cond(new SrsCond());
int counter = 0;
SrsCoroutineChan ctx;
ctx.push(cond.get());
ctx.push(&counter);
SRS_COROUTINE_GO_CTX(&ctx, {
SrsCond *cond = (SrsCond *)ctx.pop();
int *counter = (int *)ctx.pop();
(*counter)++;
// Notify main thread the work is done.
cond->signal();
});
// The coroutine not terminated, so the counter is not increased.
EXPECT_TRUE(counter == 0);
// Wait for the coroutine to terminate. The counter is increased.
cond->wait();
EXPECT_TRUE(counter == 1);
}
VOID TEST(StTest, AnonymouseCoroutineWithWaitgroup)
{
SrsWaitGroup wg;
int counter = 0;
SrsCoroutineChan ctx;
ctx.push(&wg);
ctx.push(&counter);
wg.add(1);
SRS_COROUTINE_GO_CTX(&ctx, {
SrsWaitGroup *wg = (SrsWaitGroup *)ctx.pop();
int *counter = (int *)ctx.pop();
(*counter)++;
// Notify main thread the work is done.
wg->done();
});
// The coroutine not terminated, so the counter is not increased.
EXPECT_TRUE(counter == 0);
// Wait for the coroutine to terminate. The counter is increased.
wg.wait();
EXPECT_TRUE(counter == 1);
}
VOID TEST(StTest, AnonymouseCoroutineWithWaitgroups)
{
SrsWaitGroup wg;
int counter = 0;
SrsCoroutineChan ctx;
ctx.push(&wg);
ctx.push(&counter);
wg.add(1);
SRS_COROUTINE_GO_CTX2(&ctx, coroutine1, {
// The ctx is copied, so we can pop it again in different coroutines.
SrsWaitGroup *wg = (SrsWaitGroup *)ctx.pop();
int *counter = (int *)ctx.pop();
(*counter)++;
// Notify main thread the work is done.
wg->done();
});
wg.add(1);
SRS_COROUTINE_GO_CTX2(&ctx, coroutine2, {
// The ctx is copied, so we can pop it again in different coroutines.
SrsWaitGroup *wg = (SrsWaitGroup *)ctx.pop();
int *counter = (int *)ctx.pop();
(*counter)++;
// Notify main thread the work is done.
wg->done();
});
// The coroutine not terminated, so the counter is not increased.
EXPECT_TRUE(counter == 0);
// Wait for the coroutine to terminate. The counter is increased.
wg.wait();
EXPECT_TRUE(counter == 2);
}
VOID TEST(StTest, VerifyUsingRawCoroutine)
{
srs_error_t err;
class NormalThread : public ISrsCoroutineHandler
{
public:
virtual srs_error_t cycle()
{
srs_usleep(1 * SRS_UTIME_MILLISECONDS);
return srs_success;
}
};
NormalThread trd;
SrsSTCoroutine st("test", &trd);
HELPER_ASSERT_SUCCESS(st.start());
}
VOID TEST(StTest, VerifyMultipleAnonymousClasses)
{
do {
class AnonymousCoroutineHandler
{
};
} while (0);
do {
class AnonymousCoroutineHandler
{
};
} while (0);
SrsUniquePtr<SrsCond> cond(new SrsCond());
cond->signal();
SrsUniquePtr<SrsMutex> mutex(new SrsMutex());
SrsLocker(mutex->get());
}
// CAUTION: Badcase, you should not follow this style.
VOID TEST(StTest, AnonymouseBadcase)
{
// Generally we SHOULD NOT do this, unless you intend to.
if (true) {
SRS_COROUTINE_GO({
srs_usleep(1 * SRS_UTIME_MILLISECONDS);
});
}
// CAUTION: If multiple coroutines in the different scope, it's ok without id,
// but it's not recommended, becuase it will be stopped and your code
// maybe not executed.
// Generally we SHOULD NOT do this, unless you intend to.
if (true) {
SRS_COROUTINE_GO({
srs_usleep(1 * SRS_UTIME_MILLISECONDS);
});
}
}
// CAUTION: Badcase, you should not follow this style.
VOID TEST(StTest, AnonymouseBadcase2)
{
int counter = 0;
SrsCoroutineChan ctx;
ctx.push(&counter);
// Generally we SHOULD NOT do this, unless you intend to.
if (true) {
SRS_COROUTINE_GO_CTX(&ctx, {
int *counter = (int *)ctx.pop();
(*counter)++;
});
// Wait for coroutine to terminate. Otherwise, it will crash, for the
// coroutine is terminated while ctx.pop(), the lock is invalid.
srs_usleep(100 * SRS_UTIME_MILLISECONDS);
}
// Coroutine terminated, so the counter is increased.
EXPECT_TRUE(counter == 1);
}