From 94cf0c10696125d5710c6612d5acd23dbf2c5a83 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 7 Jun 2014 22:23:17 +0800 Subject: [PATCH] refine kernel buffer. complete the utest for buffer. --- trunk/configure | 2 +- trunk/src/app/srs_app_http.cpp | 2 +- trunk/src/app/srs_app_http_client.cpp | 2 +- trunk/src/app/srs_app_socket.cpp | 12 +-- trunk/src/app/srs_app_socket.hpp | 6 +- trunk/src/kernel/srs_kernel_buffer.cpp | 2 +- trunk/src/kernel/srs_kernel_buffer.hpp | 21 +++-- trunk/src/libs/srs_lib_simple_socket.cpp | 8 +- trunk/src/libs/srs_lib_simple_socket.hpp | 6 +- trunk/src/rtmp/srs_protocol_io.hpp | 4 +- trunk/src/srs/srs.upp | 2 + trunk/src/utest/srs_utest.cpp | 6 +- trunk/src/utest/srs_utest.hpp | 21 ++++- trunk/src/utest/srs_utest_buffer.cpp | 115 +++++++++++++++++++++++ trunk/src/utest/srs_utest_buffer.hpp | 46 +++++++++ 15 files changed, 218 insertions(+), 37 deletions(-) create mode 100644 trunk/src/utest/srs_utest_buffer.cpp create mode 100644 trunk/src/utest/srs_utest_buffer.hpp diff --git a/trunk/configure b/trunk/configure index 838e070f5..3ee86171d 100755 --- a/trunk/configure +++ b/trunk/configure @@ -516,7 +516,7 @@ if [ $SRS_LIBRTMP = YES ]; then fi # # utest, the unit-test cases of srs, base on gtest1.6 -MODULE_FILES=("srs_utest" "srs_utest_amf0" "srs_utest_handshake") +MODULE_FILES=("srs_utest" "srs_utest_amf0" "srs_utest_handshake" "srs_utest_buffer") ModuleLibIncs=(${SRS_OBJS} ${LibSTRoot}) ModuleLibFiles=(${LibSTfile} ${LibHttpParserfile} ${LibSSLfile}) MODULE_DEPENDS=("CORE" "KERNEL" "RTMP" "APP") diff --git a/trunk/src/app/srs_app_http.cpp b/trunk/src/app/srs_app_http.cpp index 3d5324a6b..76909b982 100644 --- a/trunk/src/app/srs_app_http.cpp +++ b/trunk/src/app/srs_app_http.cpp @@ -328,7 +328,7 @@ SrsHttpHandler* SrsHttpHandler::res_body(stringstream& ss, string body) int SrsHttpHandler::res_flush(SrsSocket* skt, stringstream& ss) { - return skt->write(ss.str().c_str(), ss.str().length(), NULL); + return skt->write((void*)ss.str().c_str(), ss.str().length(), NULL); } int SrsHttpHandler::res_options(SrsSocket* skt) diff --git a/trunk/src/app/srs_app_http_client.cpp b/trunk/src/app/srs_app_http_client.cpp index f3250dd1f..2c197dea0 100644 --- a/trunk/src/app/srs_app_http_client.cpp +++ b/trunk/src/app/srs_app_http_client.cpp @@ -83,7 +83,7 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, string& res) SrsSocket skt(stfd); std::string data = ss.str(); - if ((ret = skt.write(data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) { + if ((ret = skt.write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) { // disconnect when error. disconnect(); diff --git a/trunk/src/app/srs_app_socket.cpp b/trunk/src/app/srs_app_socket.cpp index 139ef10a9..51ea2b95f 100644 --- a/trunk/src/app/srs_app_socket.cpp +++ b/trunk/src/app/srs_app_socket.cpp @@ -72,11 +72,11 @@ int64_t SrsSocket::get_send_bytes() return send_bytes; } -int SrsSocket::read(const void* buf, size_t size, ssize_t* nread) +int SrsSocket::read(void* buf, size_t size, ssize_t* nread) { int ret = ERROR_SUCCESS; - ssize_t nb_read = st_read(stfd, (void*)buf, size, recv_timeout); + ssize_t nb_read = st_read(stfd, buf, size, recv_timeout); if (nread) { *nread = nb_read; } @@ -100,11 +100,11 @@ int SrsSocket::read(const void* buf, size_t size, ssize_t* nread) return ret; } -int SrsSocket::read_fully(const void* buf, size_t size, ssize_t* nread) +int SrsSocket::read_fully(void* buf, size_t size, ssize_t* nread) { int ret = ERROR_SUCCESS; - ssize_t nb_read = st_read_fully(stfd, (void*)buf, size, recv_timeout); + ssize_t nb_read = st_read_fully(stfd, buf, size, recv_timeout); if (nread) { *nread = nb_read; } @@ -128,11 +128,11 @@ int SrsSocket::read_fully(const void* buf, size_t size, ssize_t* nread) return ret; } -int SrsSocket::write(const void* buf, size_t size, ssize_t* nwrite) +int SrsSocket::write(void* buf, size_t size, ssize_t* nwrite) { int ret = ERROR_SUCCESS; - ssize_t nb_write = st_write(stfd, (void*)buf, size, send_timeout); + ssize_t nb_write = st_write(stfd, buf, size, send_timeout); if (nwrite) { *nwrite = nb_write; } diff --git a/trunk/src/app/srs_app_socket.hpp b/trunk/src/app/srs_app_socket.hpp index a293b12ed..393daa454 100644 --- a/trunk/src/app/srs_app_socket.hpp +++ b/trunk/src/app/srs_app_socket.hpp @@ -60,12 +60,12 @@ public: /** * @param nread, the actual read bytes, ignore if NULL. */ - virtual int read(const void* buf, size_t size, ssize_t* nread); - virtual int read_fully(const void* buf, size_t size, ssize_t* nread); + virtual int read(void* buf, size_t size, ssize_t* nread); + virtual int read_fully(void* buf, size_t size, ssize_t* nread); /** * @param nwrite, the actual write bytes, ignore if NULL. */ - virtual int write(const void* buf, size_t size, ssize_t* nwrite); + virtual int write(void* buf, size_t size, ssize_t* nwrite); virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite); }; diff --git a/trunk/src/kernel/srs_kernel_buffer.cpp b/trunk/src/kernel/srs_kernel_buffer.cpp index b96915742..b5e7440f2 100644 --- a/trunk/src/kernel/srs_kernel_buffer.cpp +++ b/trunk/src/kernel/srs_kernel_buffer.cpp @@ -60,7 +60,7 @@ void SrsBuffer::erase(int size) { srs_assert(size > 0); - if (size == length()) { + if (size >= length()) { data.clear(); return; } diff --git a/trunk/src/kernel/srs_kernel_buffer.hpp b/trunk/src/kernel/srs_kernel_buffer.hpp index 147136210..5942d0f12 100644 --- a/trunk/src/kernel/srs_kernel_buffer.hpp +++ b/trunk/src/kernel/srs_kernel_buffer.hpp @@ -42,15 +42,14 @@ public: virtual ~ISrsBufferReader(); // for protocol/amf0/msg-codec public: - virtual int read(const void* buf, size_t size, ssize_t* nread) = 0; + virtual int read(void* buf, size_t size, ssize_t* nread) = 0; }; /** * the buffer provices bytes cache for protocol. generally, * protocol recv data from socket, put into buffer, decode to RTMP message. -* protocol encode RTMP message to bytes, put into buffer, send to socket. */ - class SrsBuffer +class SrsBuffer { private: std::vector data; @@ -59,8 +58,8 @@ public: virtual ~SrsBuffer(); public: /** - * get the length of buffer. - * never negative, empty if zero. + * get the length of buffer. empty if zero. + * @remark assert length() is not negative. */ virtual int length(); /** @@ -70,20 +69,24 @@ public: virtual char* bytes(); /** * erase size of bytes from begin. - * if size equals to length(), clear buffer. - * @param size + * @param size to erase size of bytes. + * clear if size greater than or equals to length() + * @remark assert size is positive. */ virtual void erase(int size); /** * append specified bytes to buffer. - * @param size the size of bytes, assert positive. + * @param size the size of bytes + * @remark assert size is positive. */ virtual void append(const char* bytes, int size); public: /** * grow buffer to the required size, loop to read from skt to fill. * @param reader, read more bytes from reader to fill the buffer to required size. - * @param required_size, loop to fill to ensure buffer size to required. + * @param required_size, loop to fill to ensure buffer size to required. + * @return an int error code, error if required_size negative. + * @remark, we actually maybe read more than required_size, maybe 4k for example. */ virtual int grow(ISrsBufferReader* reader, int required_size); }; diff --git a/trunk/src/libs/srs_lib_simple_socket.cpp b/trunk/src/libs/srs_lib_simple_socket.cpp index af75371e3..d212a6f01 100644 --- a/trunk/src/libs/srs_lib_simple_socket.cpp +++ b/trunk/src/libs/srs_lib_simple_socket.cpp @@ -78,11 +78,11 @@ int SimpleSocketStream::connect(const char* server_ip, int port) } // ISrsBufferReader -int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread) +int SimpleSocketStream::read(void* buf, size_t size, ssize_t* nread) { int ret = ERROR_SUCCESS; - *nread = ::recv(fd, (void*)buf, size, 0); + *nread = ::recv(fd, buf, size, 0); // On success a non-negative integer indicating the number of bytes actually read is returned // (a value of 0 means the network connection is closed or end of file is reached). @@ -160,7 +160,7 @@ bool SimpleSocketStream::is_never_timeout(int64_t timeout_us) return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT; } -int SimpleSocketStream::read_fully(const void* buf, size_t size, ssize_t* nread) +int SimpleSocketStream::read_fully(void* buf, size_t size, ssize_t* nread) { int ret = ERROR_SUCCESS; @@ -184,7 +184,7 @@ int SimpleSocketStream::read_fully(const void* buf, size_t size, ssize_t* nread) return ret; } -int SimpleSocketStream::write(const void* buf, size_t size, ssize_t* nwrite) +int SimpleSocketStream::write(void* buf, size_t size, ssize_t* nwrite) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/libs/srs_lib_simple_socket.hpp b/trunk/src/libs/srs_lib_simple_socket.hpp index 835964b37..452d25cf3 100644 --- a/trunk/src/libs/srs_lib_simple_socket.hpp +++ b/trunk/src/libs/srs_lib_simple_socket.hpp @@ -52,7 +52,7 @@ public: virtual int connect(const char* server, int port); // ISrsBufferReader public: - virtual int read(const void* buf, size_t size, ssize_t* nread); + virtual int read(void* buf, size_t size, ssize_t* nread); // ISrsProtocolReader public: virtual void set_recv_timeout(int64_t timeout_us); @@ -67,8 +67,8 @@ public: // ISrsProtocolReaderWriter public: virtual bool is_never_timeout(int64_t timeout_us); - virtual int read_fully(const void* buf, size_t size, ssize_t* nread); - virtual int write(const void* buf, size_t size, ssize_t* nwrite); + virtual int read_fully(void* buf, size_t size, ssize_t* nread); + virtual int write(void* buf, size_t size, ssize_t* nwrite); }; #endif diff --git a/trunk/src/rtmp/srs_protocol_io.hpp b/trunk/src/rtmp/srs_protocol_io.hpp index 9020655b3..b993a2a49 100644 --- a/trunk/src/rtmp/srs_protocol_io.hpp +++ b/trunk/src/rtmp/srs_protocol_io.hpp @@ -78,8 +78,8 @@ public: virtual bool is_never_timeout(int64_t timeout_us) = 0; // for handshake. public: - virtual int read_fully(const void* buf, size_t size, ssize_t* nread) = 0; - virtual int write(const void* buf, size_t size, ssize_t* nwrite) = 0; + virtual int read_fully(void* buf, size_t size, ssize_t* nread) = 0; + virtual int write(void* buf, size_t size, ssize_t* nwrite) = 0; }; #endif diff --git a/trunk/src/srs/srs.upp b/trunk/src/srs/srs.upp index 76ec7b67d..cf6e2c437 100755 --- a/trunk/src/srs/srs.upp +++ b/trunk/src/srs/srs.upp @@ -108,6 +108,8 @@ file ..\utest\srs_utest.cpp, ..\utest\srs_utest_amf0.hpp, ..\utest\srs_utest_amf0.cpp, + ..\utest\srs_utest_buffer.hpp, + ..\utest\srs_utest_buffer.cpp, ..\utest\srs_utest_handshake.hpp, ..\utest\srs_utest_handshake.cpp, research readonly separator, diff --git a/trunk/src/utest/srs_utest.cpp b/trunk/src/utest/srs_utest.cpp index df4683dd5..a58e5814c 100644 --- a/trunk/src/utest/srs_utest.cpp +++ b/trunk/src/utest/srs_utest.cpp @@ -49,12 +49,12 @@ bool MockEmptyIO::is_never_timeout(int64_t /*timeout_us*/) return true; } -int MockEmptyIO::read_fully(const void* /*buf*/, size_t /*size*/, ssize_t* /*nread*/) +int MockEmptyIO::read_fully(void* /*buf*/, size_t /*size*/, ssize_t* /*nread*/) { return ERROR_SUCCESS; } -int MockEmptyIO::write(const void* /*buf*/, size_t /*size*/, ssize_t* /*nwrite*/) +int MockEmptyIO::write(void* /*buf*/, size_t /*size*/, ssize_t* /*nwrite*/) { return ERROR_SUCCESS; } @@ -92,7 +92,7 @@ int MockEmptyIO::writev(const iovec */*iov*/, int /*iov_size*/, ssize_t* /*nwrit return ERROR_SUCCESS; } -int MockEmptyIO::read(const void* /*buf*/, size_t /*size*/, ssize_t* /*nread*/) +int MockEmptyIO::read(void* /*buf*/, size_t /*size*/, ssize_t* /*nread*/) { return ERROR_SUCCESS; } diff --git a/trunk/src/utest/srs_utest.hpp b/trunk/src/utest/srs_utest.hpp index 54e4ac899..c0fdfaa7d 100644 --- a/trunk/src/utest/srs_utest.hpp +++ b/trunk/src/utest/srs_utest.hpp @@ -34,6 +34,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // we add an empty macro for upp to show the smart tips. #define VOID +// the asserts of gtest: +// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual +// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2 +// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2 +// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2 +// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2 +// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2 +// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2 +// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2 +// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case +// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case +// * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual): Tests that two float values are almost equal. +// * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual): Tests that two double values are almost equal. +// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error): Tests that v1 and v2 are within the given distance to each other. + #include class MockEmptyIO : public ISrsProtocolReaderWriter @@ -46,8 +61,8 @@ public: virtual bool is_never_timeout(int64_t timeout_us); // for handshake. public: - virtual int read_fully(const void* buf, size_t size, ssize_t* nread); - virtual int write(const void* buf, size_t size, ssize_t* nwrite); + virtual int read_fully(void* buf, size_t size, ssize_t* nread); + virtual int write(void* buf, size_t size, ssize_t* nwrite); // for protocol public: virtual void set_recv_timeout(int64_t timeout_us); @@ -61,7 +76,7 @@ public: virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite); // for protocol/amf0/msg-codec public: - virtual int read(const void* buf, size_t size, ssize_t* nread); + virtual int read(void* buf, size_t size, ssize_t* nread); }; #endif diff --git a/trunk/src/utest/srs_utest_buffer.cpp b/trunk/src/utest/srs_utest_buffer.cpp new file mode 100644 index 000000000..5f07ebb04 --- /dev/null +++ b/trunk/src/utest/srs_utest_buffer.cpp @@ -0,0 +1,115 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013-2014 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include + +#include + +MockBufferReader::MockBufferReader(const char* data) +{ + str = data; +} + +MockBufferReader::~MockBufferReader() +{ +} + +int MockBufferReader::read(void* buf, size_t size, ssize_t* nread) +{ + int len = srs_min(str.length(), size); + + memcpy(buf, str.data(), len); + + if (nread) { + *nread = len; + } + + return ERROR_SUCCESS; +} + +VOID TEST(BufferTest, DefaultObject) +{ + SrsBuffer b; + + EXPECT_EQ(0, b.length()); + EXPECT_EQ(NULL, b.bytes()); +} + +VOID TEST(BufferTest, AppendBytes) +{ + SrsBuffer b; + + char winlin[] = "winlin"; + b.append(winlin, strlen(winlin)); + EXPECT_EQ((int)strlen(winlin), b.length()); + ASSERT_TRUE(NULL != b.bytes()); + EXPECT_EQ('w', b.bytes()[0]); + EXPECT_EQ('n', b.bytes()[5]); + + b.append(winlin, strlen(winlin)); + EXPECT_EQ(2 * (int)strlen(winlin), b.length()); + ASSERT_TRUE(NULL != b.bytes()); + EXPECT_EQ('w', b.bytes()[0]); + EXPECT_EQ('n', b.bytes()[5]); + EXPECT_EQ('w', b.bytes()[6]); + EXPECT_EQ('n', b.bytes()[11]); +} + +VOID TEST(BufferTest, EraseBytes) +{ + SrsBuffer b; + + char winlin[] = "winlin"; + b.append(winlin, strlen(winlin)); + b.erase(b.length()); + EXPECT_EQ(0, b.length()); + + b.append(winlin, strlen(winlin)); + b.erase(1); + EXPECT_EQ(5, b.length()); + EXPECT_EQ('i', b.bytes()[0]); + EXPECT_EQ('n', b.bytes()[4]); + b.erase(2); + EXPECT_EQ(3, b.length()); + EXPECT_EQ('l', b.bytes()[0]); + EXPECT_EQ('n', b.bytes()[2]); + b.erase(3); + EXPECT_EQ(0, b.length()); +} + +VOID TEST(BufferTest, Grow) +{ + SrsBuffer b; + MockBufferReader r("winlin"); + + b.grow(&r, 1); + EXPECT_EQ(6, b.length()); + EXPECT_EQ('w', b.bytes()[0]); + + b.grow(&r, 3); + EXPECT_EQ(6, b.length()); + EXPECT_EQ('n', b.bytes()[2]); + + b.grow(&r, 100); + EXPECT_EQ(102, b.length()); + EXPECT_EQ('l', b.bytes()[99]); +} diff --git a/trunk/src/utest/srs_utest_buffer.hpp b/trunk/src/utest/srs_utest_buffer.hpp new file mode 100644 index 000000000..6281d0f4b --- /dev/null +++ b/trunk/src/utest/srs_utest_buffer.hpp @@ -0,0 +1,46 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013-2014 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef SRS_UTEST_BUFFER_HPP +#define SRS_UTEST_BUFFER_HPP + +/* +#include +*/ +#include + +#include +#include + +class MockBufferReader: public ISrsBufferReader +{ +private: + std::string str; +public: + MockBufferReader(const char* data); + virtual ~MockBufferReader(); +public: + virtual int read(void* buf, size_t size, ssize_t* nread); +}; + +#endif