mirror of
https://github.com/ossrs/srs.git
synced 2025-02-12 19:31:53 +00:00
Improve test coverage for http service.
This commit is contained in:
parent
6d0ac35db9
commit
9bd8b363b3
4 changed files with 244 additions and 55 deletions
|
@ -103,7 +103,7 @@ srs_error_t SrsHttpParser::parse_message(ISrsReader* reader, ISrsHttpMessage** p
|
|||
msg->set_header(header, http_should_keep_alive(&hp_header));
|
||||
if ((err = msg->set_url(url, jsonp)) != srs_success) {
|
||||
srs_freep(msg);
|
||||
return srs_error_wrap(err, "update message");
|
||||
return srs_error_wrap(err, "set url=%s, jsonp=%d", url.c_str(), jsonp);
|
||||
}
|
||||
|
||||
// parse ok, return the msg.
|
||||
|
@ -634,7 +634,7 @@ SrsRequest* SrsHttpMessage::to_request(string vhost)
|
|||
|
||||
std::string query = _uri->get_query();
|
||||
if (!query.empty()) {
|
||||
req->tcUrl = req->tcUrl + "?" + query;
|
||||
req->param = "?" + query;
|
||||
}
|
||||
|
||||
srs_discovery_tc_url(req->tcUrl, req->schema, req->host, req->vhost, req->app, req->stream, req->port, req->param);
|
||||
|
@ -788,9 +788,8 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t*
|
|||
if (!header_wrote || content_length != -1) {
|
||||
ssize_t nwrite = 0;
|
||||
for (int i = 0; i < iovcnt; i++) {
|
||||
const iovec* piovc = iov + i;
|
||||
nwrite += piovc->iov_len;
|
||||
if ((err = write((char*)piovc->iov_base, (int)piovc->iov_len)) != srs_success) {
|
||||
nwrite += iov[i].iov_len;
|
||||
if ((err = write((char*)iov[i].iov_base, (int)iov[i].iov_len)) != srs_success) {
|
||||
return srs_error_wrap(err, "writev");
|
||||
}
|
||||
}
|
||||
|
@ -807,6 +806,11 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t*
|
|||
return err;
|
||||
}
|
||||
|
||||
// whatever header is wrote, we should try to send header.
|
||||
if ((err = send_header(NULL, 0)) != srs_success) {
|
||||
return srs_error_wrap(err, "send header");
|
||||
}
|
||||
|
||||
// send in chunked encoding.
|
||||
int nb_iovss = 3 + iovcnt;
|
||||
iovec* iovss = iovss_cache;
|
||||
|
@ -816,9 +820,7 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t*
|
|||
iovss = iovss_cache = new iovec[nb_iovss];
|
||||
}
|
||||
|
||||
// send in chunked encoding.
|
||||
|
||||
// chunk size.
|
||||
// Send all iovs in one chunk, the size is the total size of iovs.
|
||||
int size = 0;
|
||||
for (int i = 0; i < iovcnt; i++) {
|
||||
const iovec* data_iov = iov + i;
|
||||
|
@ -828,28 +830,22 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t*
|
|||
|
||||
// chunk header
|
||||
int nb_size = snprintf(header_cache, SRS_HTTP_HEADER_CACHE_SIZE, "%x", size);
|
||||
iovec* iovs = iovss;
|
||||
iovs[0].iov_base = (char*)header_cache;
|
||||
iovs[0].iov_len = (int)nb_size;
|
||||
iovs++;
|
||||
iovss[0].iov_base = (char*)header_cache;
|
||||
iovss[0].iov_len = (int)nb_size;
|
||||
|
||||
// chunk header eof.
|
||||
iovs[0].iov_base = (char*)SRS_HTTP_CRLF;
|
||||
iovs[0].iov_len = 2;
|
||||
iovs++;
|
||||
iovss[1].iov_base = (char*)SRS_HTTP_CRLF;
|
||||
iovss[1].iov_len = 2;
|
||||
|
||||
// chunk body.
|
||||
for (int i = 0; i < iovcnt; i++) {
|
||||
const iovec* data_iov = iov + i;
|
||||
iovs[0].iov_base = (char*)data_iov->iov_base;
|
||||
iovs[0].iov_len = (int)data_iov->iov_len;
|
||||
iovs++;
|
||||
iovss[2+i].iov_base = (char*)iov[i].iov_base;
|
||||
iovss[2+i].iov_len = (int)iov[i].iov_len;
|
||||
}
|
||||
|
||||
// chunk body eof.
|
||||
iovs[0].iov_base = (char*)SRS_HTTP_CRLF;
|
||||
iovs[0].iov_len = 2;
|
||||
iovs++;
|
||||
iovss[2+iovcnt].iov_base = (char*)SRS_HTTP_CRLF;
|
||||
iovss[2+iovcnt].iov_len = 2;
|
||||
|
||||
// sendout all ioves.
|
||||
ssize_t nwrite;
|
||||
|
|
|
@ -89,24 +89,6 @@ srs_error_t MockMSegmentsReader::read(void* buf, size_t size, ssize_t* nread)
|
|||
return err;
|
||||
}
|
||||
|
||||
class MockResponseWriter : virtual public ISrsHttpResponseWriter, virtual public ISrsHttpHeaderFilter
|
||||
{
|
||||
public:
|
||||
SrsHttpResponseWriter* w;
|
||||
MockBufferIO io;
|
||||
public:
|
||||
MockResponseWriter();
|
||||
virtual ~MockResponseWriter();
|
||||
public:
|
||||
virtual srs_error_t final_request();
|
||||
virtual SrsHttpHeader* header();
|
||||
virtual srs_error_t write(char* data, int size);
|
||||
virtual srs_error_t writev(const iovec* iov, int iovcnt, ssize_t* pnwrite);
|
||||
virtual void write_header(int code);
|
||||
public:
|
||||
virtual srs_error_t filter(SrsHttpHeader* h);
|
||||
};
|
||||
|
||||
MockResponseWriter::MockResponseWriter()
|
||||
{
|
||||
w = new SrsHttpResponseWriter(&io);
|
||||
|
@ -221,12 +203,6 @@ bool _mock_srs_path_not_exists(std::string /*path*/)
|
|||
return false;
|
||||
}
|
||||
|
||||
#define __MOCK_HTTP_EXPECT_STREQ(status, text, w) \
|
||||
EXPECT_STREQ(mock_http_response(status, text).c_str(), HELPER_BUFFER2STR(&w.io.out_buffer).c_str())
|
||||
|
||||
#define __MOCK_HTTP_EXPECT_STREQ2(status, text, w) \
|
||||
EXPECT_STREQ(mock_http_response2(status, text).c_str(), HELPER_BUFFER2STR(&w.io.out_buffer).c_str())
|
||||
|
||||
VOID TEST(ProtocolHTTPTest, StatusCode2Text)
|
||||
{
|
||||
EXPECT_STREQ(SRS_CONSTS_HTTP_OK_str, srs_generate_http_status_text(SRS_CONSTS_HTTP_OK).c_str());
|
||||
|
|
|
@ -30,6 +30,38 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <srs_utest.hpp>
|
||||
|
||||
#include <srs_utest_protocol.hpp>
|
||||
#include <srs_http_stack.hpp>
|
||||
#include <srs_service_http_conn.hpp>
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class MockResponseWriter : virtual public ISrsHttpResponseWriter, virtual public ISrsHttpHeaderFilter
|
||||
{
|
||||
public:
|
||||
SrsHttpResponseWriter* w;
|
||||
MockBufferIO io;
|
||||
public:
|
||||
MockResponseWriter();
|
||||
virtual ~MockResponseWriter();
|
||||
public:
|
||||
virtual srs_error_t final_request();
|
||||
virtual SrsHttpHeader* header();
|
||||
virtual srs_error_t write(char* data, int size);
|
||||
virtual srs_error_t writev(const iovec* iov, int iovcnt, ssize_t* pnwrite);
|
||||
virtual void write_header(int code);
|
||||
public:
|
||||
virtual srs_error_t filter(SrsHttpHeader* h);
|
||||
};
|
||||
|
||||
string mock_http_response(int status, string content);
|
||||
string mock_http_response2(int status, string content);
|
||||
|
||||
#define __MOCK_HTTP_EXPECT_STREQ(status, text, w) \
|
||||
EXPECT_STREQ(mock_http_response(status, text).c_str(), HELPER_BUFFER2STR(&w.io.out_buffer).c_str())
|
||||
|
||||
#define __MOCK_HTTP_EXPECT_STREQ2(status, text, w) \
|
||||
EXPECT_STREQ(mock_http_response2(status, text).c_str(), HELPER_BUFFER2STR(&w.io.out_buffer).c_str())
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -31,6 +31,10 @@ using namespace std;
|
|||
|
||||
#include <srs_service_st.hpp>
|
||||
#include <srs_service_http_conn.hpp>
|
||||
#include <srs_rtmp_stack.hpp>
|
||||
#include <srs_core_autofree.hpp>
|
||||
#include <srs_utest_protocol.hpp>
|
||||
#include <srs_utest_http.hpp>
|
||||
|
||||
class MockSrsConnection : public ISrsConnection
|
||||
{
|
||||
|
@ -450,37 +454,37 @@ VOID TEST(TCPServerTest, MessageConnection)
|
|||
MockSrsConnection conn;
|
||||
SrsHttpMessage m;
|
||||
m.set_connection(&conn);
|
||||
EXPECT_TRUE(&conn == m.connection());
|
||||
EXPECT_TRUE(&conn == m.connection()); EXPECT_FALSE(m.is_jsonp());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=POST", true));
|
||||
EXPECT_TRUE(m.jsonp); EXPECT_STREQ("POST", m.jsonp_method.c_str());
|
||||
EXPECT_TRUE(m.jsonp); EXPECT_STREQ("POST", m.jsonp_method.c_str()); EXPECT_TRUE(m.is_jsonp());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=GET", true));
|
||||
EXPECT_EQ(SRS_CONSTS_HTTP_GET, m.method()); EXPECT_STREQ("GET", m.method_str().c_str());
|
||||
EXPECT_EQ(SRS_CONSTS_HTTP_GET, m.method()); EXPECT_STREQ("GET", m.method_str().c_str()); EXPECT_TRUE(m.is_jsonp());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=PUT", true));
|
||||
EXPECT_EQ(SRS_CONSTS_HTTP_PUT, m.method()); EXPECT_STREQ("PUT", m.method_str().c_str());
|
||||
EXPECT_EQ(SRS_CONSTS_HTTP_PUT, m.method()); EXPECT_STREQ("PUT", m.method_str().c_str()); EXPECT_TRUE(m.is_jsonp());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=POST", true));
|
||||
EXPECT_EQ(SRS_CONSTS_HTTP_POST, m.method()); EXPECT_STREQ("POST", m.method_str().c_str());
|
||||
EXPECT_EQ(SRS_CONSTS_HTTP_POST, m.method()); EXPECT_STREQ("POST", m.method_str().c_str()); EXPECT_TRUE(m.is_jsonp());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=DELETE", true));
|
||||
EXPECT_EQ(SRS_CONSTS_HTTP_DELETE, m.method()); EXPECT_STREQ("DELETE", m.method_str().c_str());
|
||||
EXPECT_EQ(SRS_CONSTS_HTTP_DELETE, m.method()); EXPECT_STREQ("DELETE", m.method_str().c_str()); EXPECT_TRUE(m.is_jsonp());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
|
@ -492,5 +496,186 @@ VOID TEST(TCPServerTest, MessageConnection)
|
|||
m.set_basic(SRS_CONSTS_HTTP_DELETE, 0, 0); EXPECT_EQ(SRS_CONSTS_HTTP_DELETE, m.method()); EXPECT_STREQ("DELETE", m.method_str().c_str());
|
||||
m.set_basic(SRS_CONSTS_HTTP_OPTIONS, 0, 0); EXPECT_EQ(SRS_CONSTS_HTTP_OPTIONS, m.method()); EXPECT_STREQ("OPTIONS", m.method_str().c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
EXPECT_TRUE(m.is_keep_alive());
|
||||
EXPECT_FALSE(m.is_infinite_chunked());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv", false));
|
||||
EXPECT_STREQ("http://127.0.0.1/live/livestream.flv", m.uri().c_str()); EXPECT_FALSE(m.is_jsonp());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?domain=ossrs.net", false));
|
||||
EXPECT_STREQ("ossrs.net", m.host().c_str()); EXPECT_FALSE(m.is_jsonp());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv", false));
|
||||
EXPECT_STREQ(".flv", m.ext().c_str()); EXPECT_FALSE(m.is_jsonp());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/v1/streams/100", false));
|
||||
EXPECT_EQ(100, m.parse_rest_id("/v1/streams/")); EXPECT_FALSE(m.is_jsonp());
|
||||
}
|
||||
}
|
||||
|
||||
VOID TEST(TCPServerTest, MessageInfinityChunked)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
EXPECT_FALSE(m.is_infinite_chunked());
|
||||
HELPER_EXPECT_SUCCESS(m.enter_infinite_chunked());
|
||||
EXPECT_TRUE(m.is_infinite_chunked());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_EXPECT_SUCCESS(m.enter_infinite_chunked());
|
||||
HELPER_EXPECT_SUCCESS(m.enter_infinite_chunked());
|
||||
EXPECT_TRUE(m.is_infinite_chunked());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
SrsHttpHeader hdr;
|
||||
hdr.set("Transfer-Encoding", "chunked");
|
||||
m.set_header(&hdr, false);
|
||||
HELPER_EXPECT_FAILED(m.enter_infinite_chunked());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
SrsHttpHeader hdr;
|
||||
hdr.set("Content-Length", "100");
|
||||
m.set_header(&hdr, false);
|
||||
HELPER_EXPECT_FAILED(m.enter_infinite_chunked());
|
||||
}
|
||||
}
|
||||
|
||||
VOID TEST(TCPServerTest, MessageTurnRequest)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_ASSERT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv", false));
|
||||
SrsRequest* r = m.to_request("ossrs.net");
|
||||
EXPECT_STREQ("live", r->app.c_str());
|
||||
EXPECT_STREQ("livestream", r->stream.c_str());
|
||||
EXPECT_STREQ("rtmp://ossrs.net/live", r->tcUrl.c_str());
|
||||
srs_freep(r);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage m;
|
||||
HELPER_ASSERT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?token=key", false));
|
||||
SrsRequest* r = m.to_request("ossrs.net");
|
||||
EXPECT_STREQ("rtmp://ossrs.net/live", r->tcUrl.c_str());
|
||||
EXPECT_STREQ("?token=key", r->param.c_str());
|
||||
srs_freep(r);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
MockSrsConnection conn;
|
||||
SrsHttpMessage m;
|
||||
m.set_connection(&conn);
|
||||
|
||||
SrsRequest* r = m.to_request("ossrs.net");
|
||||
EXPECT_STREQ("127.0.0.1", r->ip.c_str());
|
||||
srs_freep(r);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
MockSrsConnection conn;
|
||||
SrsHttpMessage m;
|
||||
m.set_connection(&conn);
|
||||
|
||||
SrsHttpHeader hdr;
|
||||
hdr.set("X-Real-IP", "10.11.12.13");
|
||||
m.set_header(&hdr, false);
|
||||
|
||||
SrsRequest* r = m.to_request("ossrs.net");
|
||||
EXPECT_STREQ("10.11.12.13", r->ip.c_str());
|
||||
srs_freep(r);
|
||||
}
|
||||
}
|
||||
|
||||
VOID TEST(TCPServerTest, MessageWritev)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
// For infinite chunked mode, all data is content.
|
||||
if (true) {
|
||||
MockBufferIO io;
|
||||
io.append("HTTP/1.1 200 OK\r\n\r\n");
|
||||
|
||||
SrsHttpParser hp; HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_RESPONSE, false));
|
||||
ISrsHttpMessage* msg = NULL; HELPER_ASSERT_SUCCESS(hp.parse_message(&io, &msg));
|
||||
|
||||
if (true) {
|
||||
SrsHttpMessage* hm = dynamic_cast<SrsHttpMessage*>(msg);
|
||||
ASSERT_TRUE(hm != NULL);
|
||||
hm->enter_infinite_chunked();
|
||||
}
|
||||
|
||||
char buf[32]; ssize_t nread = 0;
|
||||
ISrsHttpResponseReader* r = msg->body_reader();
|
||||
|
||||
io.append("Hello");
|
||||
HELPER_ARRAY_INIT(buf, sizeof(buf), 0);
|
||||
HELPER_ASSERT_SUCCESS(r->read(buf, 5, &nread));
|
||||
EXPECT_EQ(5, nread);
|
||||
EXPECT_STREQ("Hello", buf);
|
||||
|
||||
io.append("\r\nWorld!");
|
||||
HELPER_ARRAY_INIT(buf, sizeof(buf), 0);
|
||||
HELPER_ASSERT_SUCCESS(r->read(buf, 8, &nread));
|
||||
EXPECT_EQ(8, nread);
|
||||
EXPECT_STREQ("\r\nWorld!", buf);
|
||||
}
|
||||
|
||||
// Directly writev, merge to one chunk.
|
||||
if (true) {
|
||||
MockResponseWriter w;
|
||||
w.write_header(SRS_CONSTS_HTTP_OK);
|
||||
|
||||
iovec iovs[] = {
|
||||
{(char*)"Hello", 5},
|
||||
{(char*)"World", 5},
|
||||
{(char*)"!", 1},
|
||||
};
|
||||
HELPER_ASSERT_SUCCESS(w.writev(iovs, 3, NULL));
|
||||
|
||||
__MOCK_HTTP_EXPECT_STREQ2(200, "b\r\nHelloWorld!\r\n", w);
|
||||
}
|
||||
|
||||
// Use writev to send one iov, should also be ok.
|
||||
if (true) {
|
||||
MockResponseWriter w;
|
||||
|
||||
char data[] = "Hello, world!";
|
||||
iovec iovs[] = {{(char*)data, (int)(sizeof(data) - 1)}};
|
||||
HELPER_ASSERT_SUCCESS(w.writev(iovs, 1, NULL));
|
||||
|
||||
__MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w);
|
||||
}
|
||||
|
||||
// Write header multiple times, should be ok.
|
||||
if (true) {
|
||||
MockResponseWriter w;
|
||||
w.write_header(SRS_CONSTS_HTTP_OK);
|
||||
w.write_header(SRS_CONSTS_HTTP_OK);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue