1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00
srs/trunk/src/utest/srs_utest_app.cpp
Winlin c8a1e0f3da
Refine AUTHORS.txt to AUTHORS.md, etc. 5.0.8 (#2464)
* Refine AUTHORS.txt to AUTHORS.md, etc. 5.0.8

* Update README.md

* Update README.md

* Refine format for AUTHORS.md
2021-07-08 14:30:47 +08:00

660 lines
21 KiB
C++

//
// Copyright (c) 2013-2021 The SRS Authors
//
// SPDX-License-Identifier: MIT
//
#include <srs_utest_app.hpp>
using namespace std;
#include <srs_kernel_error.hpp>
#include <srs_app_fragment.hpp>
#include <srs_app_security.hpp>
#include <srs_app_config.hpp>
#include <srs_app_st.hpp>
#include <srs_service_conn.hpp>
#include <srs_app_conn.hpp>
class MockIDResource : public ISrsResource
{
public:
int id;
MockIDResource(int v) {
id = v;
}
virtual ~MockIDResource() {
}
virtual const SrsContextId& get_id() {
return _srs_context->get_id();
}
virtual std::string desc() {
return "";
}
};
VOID TEST(AppResourceManagerTest, FindByFastID)
{
srs_error_t err = srs_success;
if (true) {
SrsResourceManager m("test");
HELPER_EXPECT_SUCCESS(m.start());
m.add_with_fast_id(101, new MockIDResource(1));
m.add_with_fast_id(102, new MockIDResource(2));
m.add_with_fast_id(103, new MockIDResource(3));
EXPECT_EQ(1, ((MockIDResource*)m.find_by_fast_id(101))->id);
EXPECT_EQ(2, ((MockIDResource*)m.find_by_fast_id(102))->id);
EXPECT_EQ(3, ((MockIDResource*)m.find_by_fast_id(103))->id);
}
if (true) {
SrsResourceManager m("test");
HELPER_EXPECT_SUCCESS(m.start());
MockIDResource* r1 = new MockIDResource(1);
MockIDResource* r2 = new MockIDResource(2);
MockIDResource* r3 = new MockIDResource(3);
m.add_with_fast_id(101, r1);
m.add_with_fast_id(102, r2);
m.add_with_fast_id(103, r3);
EXPECT_EQ(1, ((MockIDResource*)m.find_by_fast_id(101))->id);
EXPECT_EQ(2, ((MockIDResource*)m.find_by_fast_id(102))->id);
EXPECT_EQ(3, ((MockIDResource*)m.find_by_fast_id(103))->id);
m.remove(r2); srs_usleep(0);
EXPECT_TRUE(m.find_by_fast_id(102) == NULL);
}
if (true) {
SrsResourceManager m("test");
HELPER_EXPECT_SUCCESS(m.start());
MockIDResource* r1 = new MockIDResource(1);
MockIDResource* r2 = new MockIDResource(2);
MockIDResource* r3 = new MockIDResource(3);
m.add_with_fast_id(1, r1);
m.add_with_fast_id(100001, r2);
m.add_with_fast_id(1000001, r3);
EXPECT_EQ(1, ((MockIDResource*)m.find_by_fast_id(1))->id);
EXPECT_EQ(2, ((MockIDResource*)m.find_by_fast_id(100001))->id);
EXPECT_EQ(3, ((MockIDResource*)m.find_by_fast_id(1000001))->id);
m.remove(r2); srs_usleep(0);
EXPECT_TRUE(m.find_by_fast_id(100001) == NULL);
m.remove(r3); srs_usleep(0);
EXPECT_TRUE(m.find_by_fast_id(1000001) == NULL);
m.remove(r1); srs_usleep(0);
EXPECT_TRUE(m.find_by_fast_id(1) == NULL);
}
if (true) {
SrsResourceManager m("test");
HELPER_EXPECT_SUCCESS(m.start());
m.add_with_fast_id(101, new MockIDResource(1));
m.add_with_fast_id(10101, new MockIDResource(2));
m.add_with_fast_id(1010101, new MockIDResource(3));
m.add_with_fast_id(101010101, new MockIDResource(4));
m.add_with_fast_id(10101010101LL, new MockIDResource(5));
m.add_with_fast_id(1010101010101LL, new MockIDResource(6));
m.add_with_fast_id(101010101010101LL, new MockIDResource(7));
m.add_with_fast_id(10101010101010101LL, new MockIDResource(8));
m.add_with_fast_id(1010101010101010101ULL, new MockIDResource(9));
m.add_with_fast_id(11010101010101010101ULL, new MockIDResource(10));
EXPECT_EQ(1, ((MockIDResource*)m.find_by_fast_id(101))->id);
EXPECT_EQ(2, ((MockIDResource*)m.find_by_fast_id(10101))->id);
EXPECT_EQ(3, ((MockIDResource*)m.find_by_fast_id(1010101))->id);
EXPECT_EQ(4, ((MockIDResource*)m.find_by_fast_id(101010101))->id);
EXPECT_EQ(5, ((MockIDResource*)m.find_by_fast_id(10101010101LL))->id);
EXPECT_EQ(6, ((MockIDResource*)m.find_by_fast_id(1010101010101LL))->id);
EXPECT_EQ(7, ((MockIDResource*)m.find_by_fast_id(101010101010101LL))->id);
EXPECT_EQ(8, ((MockIDResource*)m.find_by_fast_id(10101010101010101LL))->id);
EXPECT_EQ(9, ((MockIDResource*)m.find_by_fast_id(1010101010101010101ULL))->id);
EXPECT_EQ(10, ((MockIDResource*)m.find_by_fast_id(11010101010101010101ULL))->id);
}
if (true) {
SrsResourceManager m("test");
HELPER_EXPECT_SUCCESS(m.start());
m.add_with_fast_id(101, new MockIDResource(1));
m.add_with_fast_id(101, new MockIDResource(4));
EXPECT_EQ(1, ((MockIDResource*)m.find_by_fast_id(101))->id);
}
}
VOID TEST(AppCoroutineTest, Dummy)
{
SrsDummyCoroutine dc;
if (true) {
SrsContextId v = dc.cid();
EXPECT_FALSE(v.empty());
srs_error_t err = dc.pull();
EXPECT_TRUE(err != srs_success);
EXPECT_TRUE(ERROR_THREAD_DUMMY == srs_error_code(err));
srs_freep(err);
err = dc.start();
EXPECT_TRUE(err != srs_success);
EXPECT_TRUE(ERROR_THREAD_DUMMY == srs_error_code(err));
srs_freep(err);
}
if (true) {
dc.stop();
SrsContextId v = dc.cid();
EXPECT_FALSE(v.empty());
srs_error_t err = dc.pull();
EXPECT_TRUE(err != srs_success);
EXPECT_TRUE(ERROR_THREAD_DUMMY == srs_error_code(err));
srs_freep(err);
err = dc.start();
EXPECT_TRUE(err != srs_success);
EXPECT_TRUE(ERROR_THREAD_DUMMY == srs_error_code(err));
srs_freep(err);
}
if (true) {
dc.interrupt();
SrsContextId v = dc.cid();
EXPECT_FALSE(v.empty());
srs_error_t err = dc.pull();
EXPECT_TRUE(err != srs_success);
EXPECT_TRUE(ERROR_THREAD_DUMMY == srs_error_code(err));
srs_freep(err);
err = dc.start();
EXPECT_TRUE(err != srs_success);
EXPECT_TRUE(ERROR_THREAD_DUMMY == srs_error_code(err));
srs_freep(err);
}
}
class MockCoroutineHandler : public ISrsCoroutineHandler {
public:
SrsSTCoroutine* trd;
srs_error_t err;
srs_cond_t running;
srs_cond_t exited;
SrsContextId cid;
// Quit without error.
bool quit;
public:
MockCoroutineHandler() : trd(NULL), err(srs_success), quit(false) {
cid.set_value("0");
running = srs_cond_new();
exited = srs_cond_new();
}
virtual ~MockCoroutineHandler() {
srs_cond_destroy(running);
srs_cond_destroy(exited);
}
public:
virtual srs_error_t cycle() {
srs_error_t r0 = srs_success;
srs_cond_signal(running);
cid = _srs_context->get_id();
while (!quit && (r0 = trd->pull()) == srs_success && err == srs_success) {
srs_usleep(10 * SRS_UTIME_MILLISECONDS);
}
srs_cond_signal(exited);
if (err != srs_success) {
srs_freep(r0);
return err;
}
return r0;
}
};
VOID TEST(AppCoroutineTest, StartStop)
{
if (true) {
MockCoroutineHandler ch;
SrsSTCoroutine sc("test", &ch);
ch.trd = &sc;
EXPECT_TRUE(sc.cid().empty());
// Thread stop after created.
sc.stop();
EXPECT_TRUE(sc.cid().empty());
srs_error_t err = sc.pull();
EXPECT_TRUE(srs_success != err);
EXPECT_TRUE(ERROR_THREAD_TERMINATED == srs_error_code(err));
srs_freep(err);
// Should never reuse a disposed thread.
err = sc.start();
EXPECT_TRUE(srs_success != err);
EXPECT_TRUE(ERROR_THREAD_DISPOSED == srs_error_code(err));
srs_freep(err);
}
if (true) {
MockCoroutineHandler ch;
SrsSTCoroutine sc("test", &ch);
ch.trd = &sc;
EXPECT_TRUE(sc.cid().empty());
EXPECT_TRUE(srs_success == sc.start());
EXPECT_TRUE(srs_success == sc.pull());
srs_cond_timedwait(ch.running, 100 * SRS_UTIME_MILLISECONDS);
EXPECT_TRUE(!sc.cid().empty());
// Thread stop after started.
sc.stop();
srs_error_t err = sc.pull();
EXPECT_TRUE(srs_success != err);
EXPECT_TRUE(ERROR_THREAD_INTERRUPED == srs_error_code(err));
srs_freep(err);
// Should never reuse a disposed thread.
err = sc.start();
EXPECT_TRUE(srs_success != err);
EXPECT_TRUE(ERROR_THREAD_DISPOSED == srs_error_code(err));
srs_freep(err);
}
if (true) {
MockCoroutineHandler ch;
SrsSTCoroutine sc("test", &ch);
ch.trd = &sc;
EXPECT_TRUE(sc.cid().empty());
EXPECT_TRUE(srs_success == sc.start());
EXPECT_TRUE(srs_success == sc.pull());
// Error when start multiple times.
srs_error_t err = sc.start();
EXPECT_TRUE(srs_success != err);
EXPECT_TRUE(ERROR_THREAD_STARTED == srs_error_code(err));
srs_freep(err);
err = sc.pull();
EXPECT_TRUE(srs_success != err);
EXPECT_TRUE(ERROR_THREAD_STARTED == srs_error_code(err));
srs_freep(err);
}
}
VOID TEST(AppCoroutineTest, Cycle)
{
if (true) {
MockCoroutineHandler ch;
SrsSTCoroutine sc("test", &ch);
ch.trd = &sc;
EXPECT_TRUE(srs_success == sc.start());
EXPECT_TRUE(srs_success == sc.pull());
// Set cycle to error.
ch.err = srs_error_new(-1, "cycle");
srs_cond_timedwait(ch.running, 100 * SRS_UTIME_MILLISECONDS);
// The cycle error should be pulled.
srs_error_t err = sc.pull();
EXPECT_TRUE(srs_success != err);
EXPECT_TRUE(-1 == srs_error_code(err));
srs_freep(err);
}
if (true) {
MockCoroutineHandler ch;
SrsContextId cid;
SrsSTCoroutine sc("test", &ch, cid.set_value("250"));
ch.trd = &sc;
EXPECT_TRUE(!sc.cid().compare(cid));
EXPECT_TRUE(srs_success == sc.start());
EXPECT_TRUE(srs_success == sc.pull());
// After running, the cid in cycle should equal to the thread.
srs_cond_timedwait(ch.running, 100 * SRS_UTIME_MILLISECONDS);
EXPECT_TRUE(!ch.cid.compare(cid));
}
if (true) {
MockCoroutineHandler ch;
SrsSTCoroutine sc("test", &ch);
ch.trd = &sc;
EXPECT_TRUE(srs_success == sc.start());
EXPECT_TRUE(srs_success == sc.pull());
srs_cond_timedwait(ch.running, 100 * SRS_UTIME_MILLISECONDS);
// Interrupt thread, set err to interrupted.
sc.interrupt();
// Set cycle to error.
ch.err = srs_error_new(-1, "cycle");
// When thread terminated, thread will get its error.
srs_cond_timedwait(ch.exited, 100 * SRS_UTIME_MILLISECONDS);
// Override the error by cycle error.
sc.stop();
// Should be cycle error.
srs_error_t err = sc.pull();
EXPECT_TRUE(srs_success != err);
EXPECT_TRUE(-1 == srs_error_code(err));
srs_freep(err);
}
if (true) {
MockCoroutineHandler ch;
SrsSTCoroutine sc("test", &ch);
ch.trd = &sc;
EXPECT_TRUE(srs_success == sc.start());
EXPECT_TRUE(srs_success == sc.pull());
// Quit without error.
ch.quit = true;
// Wait for thread to done.
srs_cond_timedwait(ch.exited, 100 * SRS_UTIME_MILLISECONDS);
// Override the error by cycle error.
sc.stop();
// Should be cycle error.
srs_error_t err = sc.pull();
EXPECT_TRUE(srs_success == err);
srs_freep(err);
}
}
void* mock_st_thread_create(void *(*/*start*/)(void *arg), void */*arg*/, int /*joinable*/, int /*stack_size*/) {
return NULL;
}
VOID TEST(AppCoroutineTest, StartThread)
{
MockCoroutineHandler ch;
SrsSTCoroutine sc("test", &ch);
ch.trd = &sc;
_ST_THREAD_CREATE_PFN ov = _pfn_st_thread_create;
_pfn_st_thread_create = (_ST_THREAD_CREATE_PFN)mock_st_thread_create;
srs_error_t err = sc.start();
_pfn_st_thread_create = ov;
EXPECT_TRUE(srs_success != err);
EXPECT_TRUE(ERROR_ST_CREATE_CYCLE_THREAD == srs_error_code(err));
srs_freep(err);
}
VOID TEST(AppFragmentTest, CheckDuration)
{
if (true) {
SrsFragment frg;
EXPECT_EQ(-1, frg.start_dts);
EXPECT_EQ(0, frg.dur);
EXPECT_FALSE(frg.sequence_header);
}
if (true) {
SrsFragment frg;
frg.append(0);
EXPECT_EQ(0, frg.duration());
frg.append(10);
EXPECT_EQ(10 * SRS_UTIME_MILLISECONDS, frg.duration());
frg.append(99);
EXPECT_EQ(99 * SRS_UTIME_MILLISECONDS, frg.duration());
frg.append(0x7fffffffLL);
EXPECT_EQ(0x7fffffffLL * SRS_UTIME_MILLISECONDS, frg.duration());
frg.append(0xffffffffLL);
EXPECT_EQ(0xffffffffLL * SRS_UTIME_MILLISECONDS, frg.duration());
frg.append(0x20c49ba5e353f7LL);
EXPECT_EQ(0x20c49ba5e353f7LL * SRS_UTIME_MILLISECONDS, frg.duration());
}
if (true) {
SrsFragment frg;
frg.append(0);
EXPECT_EQ(0, frg.duration());
frg.append(0x7fffffffffffffffLL);
EXPECT_EQ(0, frg.duration());
}
if (true) {
SrsFragment frg;
frg.append(100);
EXPECT_EQ(0, frg.duration());
frg.append(10);
EXPECT_EQ(0, frg.duration());
frg.append(100);
EXPECT_EQ(90 * SRS_UTIME_MILLISECONDS, frg.duration());
}
if (true) {
SrsFragment frg;
frg.append(-10);
EXPECT_EQ(0, frg.duration());
frg.append(-5);
EXPECT_EQ(0, frg.duration());
frg.append(10);
EXPECT_EQ(10 * SRS_UTIME_MILLISECONDS, frg.duration());
}
}
VOID TEST(AppSecurity, CheckSecurity)
{
srs_error_t err;
// Deny if no rules.
if (true) {
SrsSecurity sec; SrsRequest rr;
HELPER_EXPECT_FAILED(sec.do_check(NULL, SrsRtmpConnUnknown, "", &rr));
}
// Deny if not allowed.
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnUnknown, "", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("others"); rules.get_or_create("any");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnUnknown, "", &rr));
}
// Deny by rule.
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "play", "all");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnPlay, "", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "play", "12.13.14.15");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnPlay, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "play", "11.12.13.14");
if (true) {
SrsConfDirective* d = new SrsConfDirective();
d->name = "deny";
d->args.push_back("play");
d->args.push_back("12.13.14.15");
rules.directives.push_back(d);
}
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnPlay, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "publish", "12.13.14.15");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnFMLEPublish, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "publish", "12.13.14.15");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnFlashPublish, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "publish", "all");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnFlashPublish, "11.12.13.14", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "publish", "12.13.14.15");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnHaivisionPublish, "12.13.14.15", &rr));
}
// Allowed if not denied.
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "play", "all");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnFMLEPublish, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "play", "12.13.14.15");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnFMLEPublish, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "play", "12.13.14.15");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnPlay, "11.12.13.14", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "publish", "12.13.14.15");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnPlay, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "publish", "12.13.14.15");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnUnknown, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "publish", "12.13.14.15");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnFlashPublish, "11.12.13.14", &rr));
}
// Allowed by rule.
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "play", "12.13.14.15");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnPlay, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "play", "all");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnPlay, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "publish", "all");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnFMLEPublish, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "publish", "all");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnFlashPublish, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "publish", "all");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnHaivisionPublish, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "publish", "12.13.14.15");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnHaivisionPublish, "12.13.14.15", &rr));
}
// Allowed if not denied.
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "play", "12.13.14.15");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnFMLEPublish, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("deny", "play", "all");
HELPER_EXPECT_SUCCESS(sec.do_check(&rules, SrsRtmpConnFMLEPublish, "12.13.14.15", &rr));
}
// Denied if not allowd.
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "play", "11.12.13.14");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnFMLEPublish, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "play", "11.12.13.14");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnPlay, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "publish", "12.13.14.15");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnPlay, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "publish", "11.12.13.14");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnHaivisionPublish, "12.13.14.15", &rr));
}
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "publish", "11.12.13.14");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnUnknown, "11.12.13.14", &rr));
}
// Denied if dup.
if (true) {
SrsSecurity sec; SrsRequest rr; SrsConfDirective rules;
rules.get_or_create("allow", "play", "11.12.13.14");
rules.get_or_create("deny", "play", "11.12.13.14");
HELPER_EXPECT_FAILED(sec.do_check(&rules, SrsRtmpConnPlay, "11.12.13.14", &rr));
}
// SRS apply the following simple strategies one by one:
// 1. allow all if security disabled.
// 2. default to deny all when security enabled.
// 3. allow if matches allow strategy.
// 4. deny if matches deny strategy.
}