Skip to content

Commit

Permalink
For #2369, #1708, #1941: Add utest to cover fail for close or stop
Browse files Browse the repository at this point in the history
  • Loading branch information
winlinvip committed Nov 4, 2021
1 parent 2708343 commit df7faa1
Showing 1 changed file with 89 additions and 22 deletions.
111 changes: 89 additions & 22 deletions trunk/src/utest/srs_utest_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,28 +69,19 @@ class MockTcpHandler : public ISrsTcpHandler
private:
srs_netfd_t fd;
public:
MockTcpHandler();
virtual ~MockTcpHandler();
MockTcpHandler() {
fd = NULL;
}
virtual ~MockTcpHandler() {
srs_close_stfd(fd);
}
public:
virtual srs_error_t on_tcp_client(srs_netfd_t stfd);
virtual srs_error_t on_tcp_client(srs_netfd_t stfd) {
fd = stfd;
return srs_success;
}
};

MockTcpHandler::MockTcpHandler()
{
fd = NULL;
}

MockTcpHandler::~MockTcpHandler()
{
srs_close_stfd(fd);
}

srs_error_t MockTcpHandler::on_tcp_client(srs_netfd_t stfd)
{
fd = stfd;
return srs_success;
}

VOID TEST(TCPServerTest, PingPong)
{
srs_error_t err;
Expand Down Expand Up @@ -1459,7 +1450,7 @@ class MockStopSelfThread : public ISrsCoroutineHandler
int r0;
int r1;
SrsFastCoroutine trd;
MockStopSelfThread() : trd("mock", this), r0(0), r1(0) {
MockStopSelfThread() : r0(0), r1(0), trd("mock", this) {
}
virtual ~MockStopSelfThread() {
}
Expand All @@ -1476,12 +1467,88 @@ class MockStopSelfThread : public ISrsCoroutineHandler
}
};

VOID TEST(StopSelfThreadTest, ShouldFailWhenStopSelf)
VOID TEST(ThreadCriticalTest, ShouldFailWhenStopSelf)
{
srs_error_t err;
MockStopSelfThread trd;
trd.start();
HELPER_EXPECT_SUCCESS(trd.start());

// Switch to thread cycle, should fail.
srs_usleep(0);
EXPECT_EQ(-1, trd.r0);
EXPECT_EQ(EDEADLK, trd.r1);
}

class MockAsyncReaderThread : public ISrsCoroutineHandler
{
public:
SrsFastCoroutine trd;
srs_netfd_t fd;
MockAsyncReaderThread(srs_netfd_t v) : trd("mock", this), fd(v) {
}
virtual ~MockAsyncReaderThread() {
}
srs_error_t start() {
return trd.start();
}
void stop() {
trd.stop();
}
virtual srs_error_t cycle() {
srs_error_t err = srs_success;
while (true) {
if ((err = trd.pull()) != srs_success) {
return err;
}
char buf[16] = {0};
if (st_read((st_netfd_t)fd, buf, sizeof(buf), SRS_UTIME_NO_TIMEOUT) <= 0) {
break;
}
}
return err;
}
};

VOID TEST(ThreadCriticalTest, FailIfCloseActiveFD)
{
srs_error_t err;

MockTcpHandler h;
SrsTcpListener l(&h, _srs_tmp_host, _srs_tmp_port);
HELPER_EXPECT_SUCCESS(l.listen());

SrsTcpClient c0(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout);
HELPER_EXPECT_SUCCESS(c0.connect());

srs_usleep(30 * SRS_UTIME_MILLISECONDS);
EXPECT_TRUE(h.fd != NULL);

MockAsyncReaderThread trd0(h.fd);
HELPER_EXPECT_SUCCESS(trd0.start());

MockAsyncReaderThread trd1(h.fd);
HELPER_EXPECT_SUCCESS(trd1.start());

// Wait for all threads to run.
srs_usleep(10 * SRS_UTIME_MILLISECONDS);

// Should fail when close, because there is 2 threads reading fd.
int r0 = st_netfd_close((st_netfd_t)h.fd);
EXPECT_EQ(-1, r0);
EXPECT_EQ(EBUSY, errno);

// Stop thread1, still fail because thread0 is reading fd.
trd1.stop();
r0 = st_netfd_close((st_netfd_t)h.fd);
EXPECT_EQ(-1, r0);
EXPECT_EQ(EBUSY, errno);

// Stop thread0, should success, no threads is reading fd.
trd0.stop();
r0 = st_netfd_close((st_netfd_t)h.fd);
EXPECT_EQ(0, r0);

// Set fd to NULL to avoid close fail for EBADF.
h.fd = NULL;
}

0 comments on commit df7faa1

Please sign in to comment.