hessian2/basic_codec/string_codec_unittests.cc (325 lines of code) (raw):

#include <iostream> #include <type_traits> #include "common/common.h" #include "gtest/gtest.h" #include "hessian2/basic_codec/string_codec.hpp" #include "hessian2/test_framework/decoder_test_framework.h" #include "hessian2/test_framework/encoder_test_framework.h" namespace { std::string GenerateString1023() { std::string expect; for (int i = 0; i < 16; ++i) { expect.append(absl::StrFormat( "%d%d 456789012345678901234567890123456789012345678901234567890123\n", i / 10, i % 10)); } expect.resize(1023); return expect; } std::string GenerateString1024() { std::string expect; for (int i = 0; i < 16; ++i) { expect.append(absl::StrFormat( "%d%d 456789012345678901234567890123456789012345678901234567890123\n", i / 10, i % 10)); } expect.resize(1024); return expect; } std::string GenerateString65536() { std::string expect; for (int i = 0; i < 1024; ++i) { expect.append(absl::StrFormat( "%d%d%d 56789012345678901234567890123456789012345678901234567890123\n", i / 100, i / 10 % 10, i % 10)); } expect.resize(65536); return expect; } std::string GenerateString131072() { std::string expect; for (int i = 0; i < 3072; ++i) { expect.append(absl::StrFormat( "%d%d%d 56789012345678901234567890123456789012345678901234567890123\n", i / 100, i / 10 % 10, i % 10)); } expect.resize(131072); return expect; } std::string GenerateEmojiString() { uint32_t emoji = 0x0001f923; uint32_t max_unicode = 0x0010ffff; std::string s; // Write the first emoji codepoint as a UTF-8 string. s.push_back(0xf0 | (emoji >> 18)); s.push_back(0x80 | ((emoji >> 12) & 0x3f)); s.push_back(0x80 | ((emoji >> 6) & 0x3f)); s.push_back(0x80 | (emoji & 0x3f)); s += ",max"; // Write the max unicode codepoint as a UTF-8 string. s.push_back(0xf0 | (max_unicode >> 18)); s.push_back(0x80 | ((max_unicode >> 12) & 0x3f)); s.push_back(0x80 | ((max_unicode >> 6) & 0x3f)); s.push_back(0x80 | (max_unicode & 0x3f)); return s; } std::string GenerateComplexString() { return "킐\u0088中国你好!\u0088\u0088\u0088\u0088\u0088\u0088"; } std::string GenerateSuperComplexString() { return "킐\u0088中国你好!" "\u0088\u0088\u0088\u0088\u0088\u0088✅❓☑️😊🤔👀🫅🔒🗝️🧫🛹🚅" "🧻🪞🪞🪞🪞" "🪞🪞🪞🪞🪞🕟🕟🕟🕟🕟🕟🕟🔅🔅🔅🔅🔅🔅🤍🤍🤍🤍🤍🤍🌈🌈🌈🌈🌈🌈🏦🏦🏦" "🏦" "🏦🏦🚎🚎🚎🚎🚎🚎🚎⏰⏰⏰⏰⏰⏲️⏲️⏲️🗄️abcdefghijklmnopqrstuvwxyz1234567@#" "$" "%^&*()_+⏲️⏲️⏲️⏲️🐪🐫c⏰"; } } // namespace namespace Hessian2 { class StringCodecTest : public testing::Test { public: void decodeSucc(absl::string_view data, std::string out, size_t size) { Hessian2::Decoder decoder(data); auto output = decoder.decode<std::string>(); EXPECT_EQ(out, *output); EXPECT_EQ(size, decoder.offset()); } void decodeFail(absl::string_view data) { Hessian2::Decoder decoder(data); auto output = decoder.decode<std::string>(); EXPECT_EQ(nullptr, output); } void encodeSucc(std::string data, size_t size, std::string expected_data = "") { std::string res; Hessian2::Encoder encoder(res); encoder.encode<std::string>(data); if (!expected_data.empty()) { EXPECT_EQ(expected_data, res); } decodeSucc(res, data, size); } }; TEST(SimpleDecodingAndEncodingTest, SimpleDecodingAndEncodingTest) { { std::string buffer; std::string value = GenerateString131072(); Hessian2::Encoder encoder(buffer); encoder.encode(value); Hessian2::Decoder decoder(buffer); EXPECT_EQ(*decoder.decode<std::string>(), value); } } TEST(EmojiDecodingAndEncodingTest, EmojiDecodingAndEncodingTest) { { std::string buffer; std::string value = GenerateEmojiString(); Hessian2::Encoder encoder(buffer); encoder.encode(value); Hessian2::Decoder decoder(buffer); EXPECT_EQ(*decoder.decode<std::string>(), value); } } TEST(ComplexDecodingAndEncodingTest, ComplexDecodingAndEncodingTest) { { std::string buffer; std::string value = GenerateComplexString() + GenerateSuperComplexString() + GenerateString131072() + GenerateSuperComplexString() + GenerateComplexString() + GenerateSuperComplexString(); Hessian2::Encoder encoder(buffer); encoder.encode(value); Hessian2::Decoder decoder(buffer); EXPECT_EQ(*decoder.decode<std::string>(), value); } } TEST_F(TestDecoderFramework, DecoderJavaTestCaseForString) { { EXPECT_TRUE(Decode<std::string>("replyString_0", std::string())); } { EXPECT_TRUE(Decode<std::string>("replyString_1", std::string({'0'}))); } { EXPECT_TRUE(Decode<std::string>( "replyString_31", std::string("0123456789012345678901234567890"))); } { EXPECT_TRUE(Decode<std::string>( "replyString_32", std::string("01234567890123456789012345678901"))); } { EXPECT_TRUE(Decode<std::string>("replyString_1023", GenerateString1023())); } { EXPECT_TRUE(Decode<std::string>("replyString_1024", GenerateString1024())); } { EXPECT_TRUE( Decode<std::string>("replyString_65536", GenerateString65536())); } { EXPECT_TRUE(Decode<std::string>("customReplyComplexString", GenerateComplexString())); } { #ifdef COMPATIBLE_WITH_JAVA_HESSIAN_LITE EXPECT_TRUE(Decode<std::string>("customReplySuperComplexString", GenerateSuperComplexString())); #endif } { #ifdef COMPATIBLE_WITH_JAVA_HESSIAN_LITE EXPECT_TRUE( Decode<std::string>("customReplyStringEmoji", GenerateEmojiString())); #endif } } TEST_F(TestEncoderFramework, EncoderJavaTestCaseForString) { { EXPECT_TRUE(Encode<std::string>("argString_0", std::string())); } { EXPECT_TRUE(Encode<std::string>("argString_1", std::string({'0'}))); } { EXPECT_TRUE(Encode<std::string>( "argString_31", std::string("0123456789012345678901234567890"))); } { EXPECT_TRUE(Encode<std::string>( "argString_32", std::string("01234567890123456789012345678901"))); } { EXPECT_TRUE(Encode<std::string>("argString_1023", GenerateString1023())); } { EXPECT_TRUE(Encode<std::string>("argString_1024", GenerateString1024())); } { EXPECT_TRUE(Encode<std::string>("argString_65536", GenerateString65536())); } { EXPECT_TRUE( Encode<std::string>("customArgComplexString", GenerateComplexString())); } } TEST_F(StringCodecTest, Decode) { // Insufficient data { std::string data{0x01}; decodeFail(data); } { std::string data{0x30}; decodeFail(data); } { std::string data{0x30, 't'}; decodeFail(data); } { std::string data{0x53, 't'}; decodeFail(data); } { std::string data{0x53, 't', 'e'}; decodeFail(data); } { std::string data{0x52, 't'}; decodeFail(data); } // Incorrect type { std::string data{0x20, 't'}; decodeFail(data); } { std::string data{0x01, 't'}; decodeSucc(data, "t", 2); } // empty string { std::string data{0x00}; decodeSucc(data, "", 1); } { std::string data{0x01, 0x00}; std::string str; str.push_back('\0'); decodeSucc(data, str, 2); } { unsigned char buf[] = {0x01, 0xc3, 0x83}; std::string data(reinterpret_cast<char *>(buf), 3); decodeSucc(data, "Ã", 3); } { // utf-8 encode character "中文" unsigned char buf[] = {0x02, 0xe4, 0xb8, 0xad, 0xe6, 0x96, 0x87}; std::string data(reinterpret_cast<char *>(buf), 7); decodeSucc(data, "中文", 7); } { std::string data{0x53, 0x00, 0x05, 'h', 'e', 'l', 'l', 'o'}; decodeSucc(data, "hello", 8); } { std::string data{0x05, 'h', 'e', 'l', 'l', 'o'}; decodeSucc(data, "hello", 6); } { std::string data{0x52, 0x00, 0x07, 'h', 'e', 'l', 'l', 'o', ',', ' ', 0x05, 'w', 'o', 'r', 'l', 'd'}; decodeSucc(data, "hello, world", 16); } { std::string expect_string(257, 't'); std::string prefix{0x31, 0x01}; std::string data = prefix.append(expect_string); decodeSucc(data, expect_string, 259); } } TEST_F(StringCodecTest, Encode) { // empty string { std::string input; encodeSucc(input, 1); } { std::string input{0x00}; encodeSucc(input, 2); } { // utf-8 encode character "中文" std::string input(u8"中文"); unsigned char buf[] = {0x02, 0xe4, 0xb8, 0xad, 0xe6, 0x96, 0x87}; std::string expect(reinterpret_cast<char *>(buf), sizeof(buf)); encodeSucc(input, 7, expect); } { std::string input("hello"); encodeSucc(input, 6); } { std::string input("hello, world"); encodeSucc(input, 13); } { std::string input(257, 't'); encodeSucc(input, 259); } { std::string test_str(32, 't'); std::string expect_str = "\x30\x20" + test_str; encodeSucc(test_str, 34, expect_str); } { std::string input(256, 't'); std::string expect_str = std::string{0x31, 0x00} + input; encodeSucc(input, 258, expect_str); } { std::string input(1024, 't'); std::string expect_str = std::string{'S', 0x04, 0x00} + input; encodeSucc(input, 1027, expect_str); } { std::string input(65536, 't'); std::string expect_str = "\x52\x80" + std::string(1, '\0') + std::string(32768, 't') + "\x53\x80" + std::string(1, '\0') + std::string(32768, 't'); encodeSucc(input, 65542, expect_str); } { std::string input(u8"🤣🤣🤣"); #ifdef COMPATIBLE_WITH_JAVA_HESSIAN_LITE encodeSucc(input, 19); // 1 byte for length, 18 bytes for data. #else encodeSucc(input, 13); // 1 byte for length, 12 bytes for data. #endif } } } // namespace Hessian2