| #include "quiche/http2/adapter/nghttp2_util.h" | |
| #include "quiche/http2/adapter/nghttp2_test_utils.h" | |
| #include "quiche/http2/adapter/test_utils.h" | |
| #include "quiche/common/platform/api/quiche_test.h" | |
| namespace http2 { | |
| namespace adapter { | |
| namespace test { | |
| namespace { | |
| // This send callback assumes |source|'s pointer is a TestDataSource, and | |
| // |user_data| is a std::string. | |
| int FakeSendCallback(nghttp2_session*, nghttp2_frame* /*frame*/, | |
| const uint8_t* framehd, size_t length, | |
| nghttp2_data_source* source, void* user_data) { | |
| auto* dest = static_cast<std::string*>(user_data); | |
| // Appends the frame header to the string. | |
| absl::StrAppend(dest, ToStringView(framehd, 9)); | |
| auto* test_source = static_cast<TestDataSource*>(source->ptr); | |
| absl::string_view payload = test_source->ReadNext(length); | |
| // Appends the frame payload to the string. | |
| absl::StrAppend(dest, payload); | |
| return 0; | |
| } | |
| TEST(MakeZeroCopyDataFrameSource, EmptyPayload) { | |
| std::string result; | |
| const absl::string_view kEmptyBody = ""; | |
| TestDataSource body1{kEmptyBody}; | |
| // The TestDataSource is wrapped in the nghttp2_data_provider data type. | |
| nghttp2_data_provider provider = body1.MakeDataProvider(); | |
| // This call transforms it back into a DataFrameSource, which is compatible | |
| // with the Http2Adapter API. | |
| std::unique_ptr<DataFrameSource> frame_source = | |
| MakeZeroCopyDataFrameSource(provider, &result, FakeSendCallback); | |
| auto [length, eof] = frame_source->SelectPayloadLength(100); | |
| EXPECT_EQ(length, 0); | |
| EXPECT_TRUE(eof); | |
| frame_source->Send("ninebytes", 0); | |
| EXPECT_EQ(result, "ninebytes"); | |
| } | |
| TEST(MakeZeroCopyDataFrameSource, ShortPayload) { | |
| std::string result; | |
| const absl::string_view kShortBody = | |
| "<html><head><title>Example Page!</title></head>" | |
| "<body><div><span><table><tr><th><blink>Wow!!" | |
| "</blink></th></tr></table></span></div></body>" | |
| "</html>"; | |
| TestDataSource body1{kShortBody}; | |
| // The TestDataSource is wrapped in the nghttp2_data_provider data type. | |
| nghttp2_data_provider provider = body1.MakeDataProvider(); | |
| // This call transforms it back into a DataFrameSource, which is compatible | |
| // with the Http2Adapter API. | |
| std::unique_ptr<DataFrameSource> frame_source = | |
| MakeZeroCopyDataFrameSource(provider, &result, FakeSendCallback); | |
| auto [length, eof] = frame_source->SelectPayloadLength(200); | |
| EXPECT_EQ(length, kShortBody.size()); | |
| EXPECT_TRUE(eof); | |
| frame_source->Send("ninebytes", length); | |
| EXPECT_EQ(result, absl::StrCat("ninebytes", kShortBody)); | |
| } | |
| TEST(MakeZeroCopyDataFrameSource, MultiFramePayload) { | |
| std::string result; | |
| const absl::string_view kShortBody = | |
| "<html><head><title>Example Page!</title></head>" | |
| "<body><div><span><table><tr><th><blink>Wow!!" | |
| "</blink></th></tr></table></span></div></body>" | |
| "</html>"; | |
| TestDataSource body1{kShortBody}; | |
| // The TestDataSource is wrapped in the nghttp2_data_provider data type. | |
| nghttp2_data_provider provider = body1.MakeDataProvider(); | |
| // This call transforms it back into a DataFrameSource, which is compatible | |
| // with the Http2Adapter API. | |
| std::unique_ptr<DataFrameSource> frame_source = | |
| MakeZeroCopyDataFrameSource(provider, &result, FakeSendCallback); | |
| auto ret = frame_source->SelectPayloadLength(50); | |
| EXPECT_EQ(ret.first, 50); | |
| EXPECT_FALSE(ret.second); | |
| frame_source->Send("ninebyte1", ret.first); | |
| ret = frame_source->SelectPayloadLength(50); | |
| EXPECT_EQ(ret.first, 50); | |
| EXPECT_FALSE(ret.second); | |
| frame_source->Send("ninebyte2", ret.first); | |
| ret = frame_source->SelectPayloadLength(50); | |
| EXPECT_EQ(ret.first, 44); | |
| EXPECT_TRUE(ret.second); | |
| frame_source->Send("ninebyte3", ret.first); | |
| EXPECT_EQ(result, | |
| "ninebyte1<html><head><title>Example Page!</title></head><bo" | |
| "ninebyte2dy><div><span><table><tr><th><blink>Wow!!</blink><" | |
| "ninebyte3/th></tr></table></span></div></body></html>"); | |
| } | |
| } // namespace | |
| } // namespace test | |
| } // namespace adapter | |
| } // namespace http2 |