1 #include "quiche/http2/adapter/nghttp2_data_provider.h"
2
3 #include "quiche/http2/adapter/test_utils.h"
4 #include "quiche/common/platform/api/quiche_test.h"
5
6 namespace http2 {
7 namespace adapter {
8 namespace test {
9
10 const size_t kFrameHeaderSize = 9;
11
12 // Verifies that a nghttp2_data_provider derived from a DataFrameSource works
13 // correctly with nghttp2-style callbacks when the amount of data read is less
14 // than what the source provides.
TEST(DataProviderTest,ReadLessThanSourceProvides)15 TEST(DataProviderTest, ReadLessThanSourceProvides) {
16 DataSavingVisitor visitor;
17 TestDataFrameSource source(visitor, true);
18 source.AppendPayload("Example payload");
19 source.EndData();
20 auto provider = MakeDataProvider(&source);
21 uint32_t data_flags = 0;
22 const int32_t kStreamId = 1;
23 const size_t kReadLength = 10;
24 // Read callback selects a payload length given an upper bound.
25 ssize_t result =
26 provider->read_callback(nullptr, kStreamId, nullptr, kReadLength,
27 &data_flags, &provider->source, nullptr);
28 ASSERT_EQ(kReadLength, result);
29 EXPECT_EQ(NGHTTP2_DATA_FLAG_NO_COPY, data_flags);
30
31 const uint8_t framehd[kFrameHeaderSize] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
32 // Sends the frame header and some payload bytes.
33 int send_result = callbacks::DataFrameSourceSendCallback(
34 nullptr, nullptr, framehd, result, &provider->source, nullptr);
35 EXPECT_EQ(0, send_result);
36 // Data accepted by the visitor includes a frame header and kReadLength bytes
37 // of payload.
38 EXPECT_EQ(visitor.data().size(), kFrameHeaderSize + kReadLength);
39 }
40
41 // Verifies that a nghttp2_data_provider derived from a DataFrameSource works
42 // correctly with nghttp2-style callbacks when the amount of data read is more
43 // than what the source provides.
TEST(DataProviderTest,ReadMoreThanSourceProvides)44 TEST(DataProviderTest, ReadMoreThanSourceProvides) {
45 DataSavingVisitor visitor;
46 const absl::string_view kPayload = "Example payload";
47 TestDataFrameSource source(visitor, true);
48 source.AppendPayload(kPayload);
49 source.EndData();
50 auto provider = MakeDataProvider(&source);
51 uint32_t data_flags = 0;
52 const int32_t kStreamId = 1;
53 const size_t kReadLength = 30;
54 // Read callback selects a payload length given an upper bound.
55 ssize_t result =
56 provider->read_callback(nullptr, kStreamId, nullptr, kReadLength,
57 &data_flags, &provider->source, nullptr);
58 ASSERT_EQ(kPayload.size(), result);
59 EXPECT_EQ(NGHTTP2_DATA_FLAG_NO_COPY | NGHTTP2_DATA_FLAG_EOF, data_flags);
60
61 const uint8_t framehd[kFrameHeaderSize] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
62 // Sends the frame header and some payload bytes.
63 int send_result = callbacks::DataFrameSourceSendCallback(
64 nullptr, nullptr, framehd, result, &provider->source, nullptr);
65 EXPECT_EQ(0, send_result);
66 // Data accepted by the visitor includes a frame header and the entire
67 // payload.
68 EXPECT_EQ(visitor.data().size(), kFrameHeaderSize + kPayload.size());
69 }
70
71 // Verifies that a nghttp2_data_provider derived from a DataFrameSource works
72 // correctly with nghttp2-style callbacks when the source is blocked.
TEST(DataProviderTest,ReadFromBlockedSource)73 TEST(DataProviderTest, ReadFromBlockedSource) {
74 DataSavingVisitor visitor;
75 // Source has no payload, but also no fin, so it's blocked.
76 TestDataFrameSource source(visitor, false);
77 auto provider = MakeDataProvider(&source);
78 uint32_t data_flags = 0;
79 const int32_t kStreamId = 1;
80 const size_t kReadLength = 10;
81 ssize_t result =
82 provider->read_callback(nullptr, kStreamId, nullptr, kReadLength,
83 &data_flags, &provider->source, nullptr);
84 // Read operation is deferred, since the source is blocked.
85 EXPECT_EQ(NGHTTP2_ERR_DEFERRED, result);
86 }
87
88 // Verifies that a nghttp2_data_provider derived from a DataFrameSource works
89 // correctly with nghttp2-style callbacks when the source provides only fin and
90 // no data.
TEST(DataProviderTest,ReadFromZeroLengthSource)91 TEST(DataProviderTest, ReadFromZeroLengthSource) {
92 DataSavingVisitor visitor;
93 // Empty payload and fin=true indicates the source is done.
94 TestDataFrameSource source(visitor, true);
95 source.EndData();
96 auto provider = MakeDataProvider(&source);
97 uint32_t data_flags = 0;
98 const int32_t kStreamId = 1;
99 const size_t kReadLength = 10;
100 ssize_t result =
101 provider->read_callback(nullptr, kStreamId, nullptr, kReadLength,
102 &data_flags, &provider->source, nullptr);
103 ASSERT_EQ(0, result);
104 EXPECT_EQ(NGHTTP2_DATA_FLAG_NO_COPY | NGHTTP2_DATA_FLAG_EOF, data_flags);
105
106 const uint8_t framehd[kFrameHeaderSize] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
107 int send_result = callbacks::DataFrameSourceSendCallback(
108 nullptr, nullptr, framehd, result, &provider->source, nullptr);
109 EXPECT_EQ(0, send_result);
110 // Data accepted by the visitor includes a frame header with fin and zero
111 // bytes of payload.
112 EXPECT_EQ(visitor.data().size(), kFrameHeaderSize);
113 }
114
115 } // namespace test
116 } // namespace adapter
117 } // namespace http2
118