1 #include "quiche/http2/adapter/nghttp2_util.h"
2
3 #include "quiche/http2/adapter/nghttp2_test_utils.h"
4 #include "quiche/http2/adapter/test_utils.h"
5 #include "quiche/common/platform/api/quiche_test.h"
6
7 namespace http2 {
8 namespace adapter {
9 namespace test {
10 namespace {
11
12 // This send callback assumes |source|'s pointer is a TestDataSource, and
13 // |user_data| is a std::string.
FakeSendCallback(nghttp2_session *,nghttp2_frame *,const uint8_t * framehd,size_t length,nghttp2_data_source * source,void * user_data)14 int FakeSendCallback(nghttp2_session*, nghttp2_frame* /*frame*/,
15 const uint8_t* framehd, size_t length,
16 nghttp2_data_source* source, void* user_data) {
17 auto* dest = static_cast<std::string*>(user_data);
18 // Appends the frame header to the string.
19 absl::StrAppend(dest, ToStringView(framehd, 9));
20 auto* test_source = static_cast<TestDataSource*>(source->ptr);
21 absl::string_view payload = test_source->ReadNext(length);
22 // Appends the frame payload to the string.
23 absl::StrAppend(dest, payload);
24 return 0;
25 }
26
TEST(MakeZeroCopyDataFrameSource,EmptyPayload)27 TEST(MakeZeroCopyDataFrameSource, EmptyPayload) {
28 std::string result;
29
30 const absl::string_view kEmptyBody = "";
31 TestDataSource body1{kEmptyBody};
32 // The TestDataSource is wrapped in the nghttp2_data_provider data type.
33 nghttp2_data_provider provider = body1.MakeDataProvider();
34
35 // This call transforms it back into a DataFrameSource, which is compatible
36 // with the Http2Adapter API.
37 std::unique_ptr<DataFrameSource> frame_source =
38 MakeZeroCopyDataFrameSource(provider, &result, FakeSendCallback);
39 auto [length, eof] = frame_source->SelectPayloadLength(100);
40 EXPECT_EQ(length, 0);
41 EXPECT_TRUE(eof);
42 frame_source->Send("ninebytes", 0);
43 EXPECT_EQ(result, "ninebytes");
44 }
45
TEST(MakeZeroCopyDataFrameSource,ShortPayload)46 TEST(MakeZeroCopyDataFrameSource, ShortPayload) {
47 std::string result;
48
49 const absl::string_view kShortBody =
50 "<html><head><title>Example Page!</title></head>"
51 "<body><div><span><table><tr><th><blink>Wow!!"
52 "</blink></th></tr></table></span></div></body>"
53 "</html>";
54 TestDataSource body1{kShortBody};
55 // The TestDataSource is wrapped in the nghttp2_data_provider data type.
56 nghttp2_data_provider provider = body1.MakeDataProvider();
57
58 // This call transforms it back into a DataFrameSource, which is compatible
59 // with the Http2Adapter API.
60 std::unique_ptr<DataFrameSource> frame_source =
61 MakeZeroCopyDataFrameSource(provider, &result, FakeSendCallback);
62 auto [length, eof] = frame_source->SelectPayloadLength(200);
63 EXPECT_EQ(length, kShortBody.size());
64 EXPECT_TRUE(eof);
65 frame_source->Send("ninebytes", length);
66 EXPECT_EQ(result, absl::StrCat("ninebytes", kShortBody));
67 }
68
TEST(MakeZeroCopyDataFrameSource,MultiFramePayload)69 TEST(MakeZeroCopyDataFrameSource, MultiFramePayload) {
70 std::string result;
71
72 const absl::string_view kShortBody =
73 "<html><head><title>Example Page!</title></head>"
74 "<body><div><span><table><tr><th><blink>Wow!!"
75 "</blink></th></tr></table></span></div></body>"
76 "</html>";
77 TestDataSource body1{kShortBody};
78 // The TestDataSource is wrapped in the nghttp2_data_provider data type.
79 nghttp2_data_provider provider = body1.MakeDataProvider();
80
81 // This call transforms it back into a DataFrameSource, which is compatible
82 // with the Http2Adapter API.
83 std::unique_ptr<DataFrameSource> frame_source =
84 MakeZeroCopyDataFrameSource(provider, &result, FakeSendCallback);
85 auto ret = frame_source->SelectPayloadLength(50);
86 EXPECT_EQ(ret.first, 50);
87 EXPECT_FALSE(ret.second);
88 frame_source->Send("ninebyte1", ret.first);
89
90 ret = frame_source->SelectPayloadLength(50);
91 EXPECT_EQ(ret.first, 50);
92 EXPECT_FALSE(ret.second);
93 frame_source->Send("ninebyte2", ret.first);
94
95 ret = frame_source->SelectPayloadLength(50);
96 EXPECT_EQ(ret.first, 44);
97 EXPECT_TRUE(ret.second);
98 frame_source->Send("ninebyte3", ret.first);
99
100 EXPECT_EQ(result,
101 "ninebyte1<html><head><title>Example Page!</title></head><bo"
102 "ninebyte2dy><div><span><table><tr><th><blink>Wow!!</blink><"
103 "ninebyte3/th></tr></table></span></div></body></html>");
104 }
105
106 } // namespace
107 } // namespace test
108 } // namespace adapter
109 } // namespace http2
110