Fix a bug in compressing by zlib (#308)

This commit is contained in:
An Tao 2019-12-07 01:26:12 +08:00 committed by GitHub
parent d85d8f7821
commit 5bb54cd4cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 245 additions and 13 deletions

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "trantor"]
path = trantor
url = https://github.com/an-tao/trantor.git
[submodule "third_party/googletest"]
path = third_party/googletest
url = https://github.com/google/googletest

View File

@ -332,7 +332,7 @@ set(INCLUDING_DIRS ${INS_STRING})
configure_file(${PROJECT_SOURCE_DIR}/cmake/templates/config.h.in
${PROJECT_BINARY_DIR}/drogon/config.h @ONLY)
if(MAKETEST STREQUAL YES)
if(MAKE_TESTING)
add_subdirectory(lib/tests)
if(PostgreSQL_FOUND)
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/postgresql_impl/test)
@ -344,6 +344,9 @@ if(MAKETEST STREQUAL YES)
if(SQLITE3_FOUND)
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/sqlite3_impl/test)
endif()
enable_testing()
add_subdirectory(third_party/googletest)
add_subdirectory(unittest)
endif()
# Installation

View File

@ -28,7 +28,7 @@ function build_drogon() {
echo "Start building drogon ..."
if [ $1 -eq 1 ]; then
cmake .. -DMAKETEST=YES
cmake .. -DMAKE_TESTING=YES
else
cmake ..
fi

View File

@ -715,19 +715,28 @@ std::string gzipCompress(const char *data, const size_t ndata)
outstr.resize(compressBound(ndata));
strm.next_in = (Bytef *)data;
strm.avail_in = ndata;
strm.next_out = (Bytef *)outstr.data();
strm.avail_out = outstr.length();
if (deflate(&strm, Z_FINISH) != Z_STREAM_END)
int ret;
do
{
LOG_ERROR << "deflate error!";
return std::string{};
}
if (deflateEnd(&strm) != Z_OK)
{
LOG_ERROR << "deflateEnd error!";
return std::string{};
}
if (strm.total_out >= outstr.size())
{
outstr.resize(strm.total_out * 2);
}
assert(outstr.size() >= strm.total_out);
strm.avail_out = outstr.size() - strm.total_out;
strm.next_out = (Bytef *)outstr.data() + strm.total_out;
ret = deflate(&strm, Z_FINISH); /* no bad return value */
if (ret == Z_STREAM_ERROR)
{
(void)deflateEnd(&strm);
return std::string{};
}
} while (strm.avail_out == 0);
assert(strm.avail_in == 0);
assert(ret == Z_STREAM_END); /* stream will be complete */
outstr.resize(strm.total_out);
/* clean up and return */
(void)deflateEnd(&strm);
return outstr;
}
return std::string{};

1
third_party/googletest vendored Submodule

@ -0,0 +1 @@
Subproject commit 2002f267f05be6f41a3d458954414ba2bfa3ff1d

20
unittest/CMakeLists.txt Normal file
View File

@ -0,0 +1,20 @@
add_executable(msgbuffer_unittest MsgBufferUnittest.cpp)
add_executable(timer_unittest TimerUnittest.cpp)
add_executable(drobject_unittest DrObjectUnittest.cpp)
add_executable(gzip_unittest GzipUnittest.cpp)
set(UNITTEST_TARGETS
msgbuffer_unittest
timer_unittest
drobject_unittest
gzip_unittest)
set_property(TARGET ${UNITTEST_TARGETS}
PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD})
set_property(TARGET ${UNITTEST_TARGETS} PROPERTY CXX_STANDARD_REQUIRED ON)
set_property(TARGET ${UNITTEST_TARGETS} PROPERTY CXX_EXTENSIONS OFF)
include(GoogleTest)
foreach(T ${UNITTEST_TARGETS})
target_link_libraries(${T} PRIVATE drogon gtest)
gtest_discover_tests(${T})
endforeach()

View File

@ -0,0 +1,46 @@
#include <drogon/DrObject.h>
#include <gtest/gtest.h>
#include <string>
#include <iostream>
using namespace drogon;
class TestA : public DrObject<TestA>
{
};
namespace test
{
class TestB : public DrObject<TestB>
{
};
} // namespace test
TEST(DrObjectTest, creationTest)
{
auto obj = DrClassMap::newObject("TestA");
EXPECT_NE(obj, nullptr);
auto objPtr = DrClassMap::getSingleInstance("TestA");
EXPECT_NE(objPtr.get(), nullptr);
auto objPtr2 = DrClassMap::getSingleInstance<TestA>();
EXPECT_NE(objPtr2.get(), nullptr);
EXPECT_EQ(objPtr, objPtr2);
}
TEST(DrObjectTest, namespaceTest)
{
auto obj = DrClassMap::newObject("test::TestB");
EXPECT_NE(obj, nullptr);
auto objPtr = DrClassMap::getSingleInstance("test::TestB");
EXPECT_NE(objPtr.get(), nullptr);
auto objPtr2 = DrClassMap::getSingleInstance<test::TestB>();
EXPECT_NE(objPtr2.get(), nullptr);
EXPECT_EQ(objPtr, objPtr2);
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

30
unittest/GzipUnittest.cpp Normal file
View File

@ -0,0 +1,30 @@
#include <drogon/utils/Utilities.h>
#include <gtest/gtest.h>
#include <string>
#include <iostream>
using namespace drogon::utils;
TEST(GzipTest, shortText)
{
std::string source{"123中文顶替要枯械"};
auto compressed = gzipCompress(source.data(), source.length());
auto decompressed = gzipDecompress(compressed.data(), compressed.length());
EXPECT_EQ(source, decompressed);
}
TEST(GzipTest, longText)
{
std::string source;
for (size_t i = 0; i < 100000; i++)
{
source.append(std::to_string(i));
}
auto compressed = gzipCompress(source.data(), source.length());
auto decompressed = gzipDecompress(compressed.data(), compressed.length());
EXPECT_EQ(source, decompressed);
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,78 @@
#include <trantor/utils/MsgBuffer.h>
#include <gtest/gtest.h>
#include <string>
#include <iostream>
using namespace trantor;
TEST(MsgBufferTest, readableTest)
{
MsgBuffer buffer;
EXPECT_EQ(0, buffer.readableBytes());
buffer.append(std::string(128, 'a'));
EXPECT_EQ(128, buffer.readableBytes());
buffer.retrieve(100);
EXPECT_EQ(28, buffer.readableBytes());
EXPECT_EQ('a', buffer.peekInt8());
buffer.retrieveAll();
EXPECT_EQ(0, buffer.readableBytes());
}
TEST(MsgBufferTest, writableTest)
{
MsgBuffer buffer(100);
EXPECT_EQ(100, buffer.writableBytes());
buffer.append("abcde");
EXPECT_EQ(95, buffer.writableBytes());
buffer.append(std::string(100, 'x'));
EXPECT_EQ(111, buffer.writableBytes());
buffer.retrieve(100);
EXPECT_EQ(111, buffer.writableBytes());
buffer.append(std::string(112, 'c'));
EXPECT_EQ(99, buffer.writableBytes());
buffer.retrieveAll();
EXPECT_EQ(216, buffer.writableBytes());
}
TEST(MsgBufferTest, addInFrontTest)
{
MsgBuffer buffer(100);
EXPECT_EQ(100, buffer.writableBytes());
buffer.addInFrontInt8('a');
EXPECT_EQ(100, buffer.writableBytes());
buffer.addInFrontInt64(123);
EXPECT_EQ(92, buffer.writableBytes());
buffer.addInFrontInt64(100);
EXPECT_EQ(84, buffer.writableBytes());
buffer.addInFrontInt8(1);
EXPECT_EQ(84, buffer.writableBytes());
}
TEST(MsgBuffer, MoveContrustor)
{
MsgBuffer buf1(100);
const char *bufptr1 = buf1.peek();
MsgBuffer buffnew1 = std::move(buf1);
EXPECT_EQ(bufptr1, buffnew1.peek());
MsgBuffer buf2(100);
const char *bufptr2 = buf2.peek();
MsgBuffer buffnew2(std::move(buf2));
EXPECT_EQ(bufptr2, buffnew2.peek());
}
TEST(Msgbuffer, MoveAssignmentOperator)
{
MsgBuffer buf(100);
const char *bufptr = buf.peek();
size_t writable = buf.writableBytes();
MsgBuffer buffnew(1000);
buffnew = std::move(buf);
EXPECT_EQ(bufptr, buffnew.peek());
EXPECT_EQ(writable, buffnew.writableBytes());
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,42 @@
#include <trantor/net/EventLoop.h>
#include <gtest/gtest.h>
#include <string>
#include <iostream>
using namespace trantor;
using namespace std::literals;
EventLoop loop;
TEST(TimerTest, RunEvery)
{
size_t count{0};
std::chrono::steady_clock::time_point tp{std::chrono::steady_clock::now()};
loop.runEvery(0.1s, [&count, tp] {
++count;
if (count == 10)
{
auto d = std::chrono::steady_clock::now() - tp;
auto err = d > 1s ? d - 1s : 1s - d;
auto msErr =
std::chrono::duration_cast<std::chrono::milliseconds>(err)
.count();
EXPECT_LT(msErr, 100LL);
loop.quit();
return;
}
std::this_thread::sleep_for(0.02s);
});
loop.runAfter(0.35s, [tp] {
auto d = std::chrono::steady_clock::now() - tp;
auto err = d > 0.35s ? d - 0.35s : 0.35s - d;
auto msErr =
std::chrono::duration_cast<std::chrono::milliseconds>(err).count();
EXPECT_LT(msErr, 30LL);
});
loop.loop();
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}