| #include "http2/adapter/nghttp2_data_provider.h" | 
 |  | 
 | #include "http2/adapter/test_utils.h" | 
 | #include "common/platform/api/quiche_test.h" | 
 |  | 
 | namespace http2 { | 
 | namespace adapter { | 
 | namespace test { | 
 |  | 
 | const size_t kFrameHeaderSize = 9; | 
 |  | 
 | // Verifies that a nghttp2_data_provider derived from a DataFrameSource works | 
 | // correctly with nghttp2-style callbacks when the amount of data read is less | 
 | // than what the source provides. | 
 | TEST(DataProviderTest, ReadLessThanSourceProvides) { | 
 |   DataSavingVisitor visitor; | 
 |   TestDataFrameSource source(visitor, true); | 
 |   source.AppendPayload("Example payload"); | 
 |   source.EndData(); | 
 |   auto provider = MakeDataProvider(&source); | 
 |   uint32_t data_flags = 0; | 
 |   const int32_t kStreamId = 1; | 
 |   const size_t kReadLength = 10; | 
 |   // Read callback selects a payload length given an upper bound. | 
 |   ssize_t result = | 
 |       provider->read_callback(nullptr, kStreamId, nullptr, kReadLength, | 
 |                               &data_flags, &provider->source, nullptr); | 
 |   ASSERT_EQ(kReadLength, result); | 
 |   EXPECT_EQ(NGHTTP2_DATA_FLAG_NO_COPY, data_flags); | 
 |  | 
 |   const uint8_t framehd[kFrameHeaderSize] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; | 
 |   // Sends the frame header and some payload bytes. | 
 |   int send_result = callbacks::DataFrameSourceSendCallback( | 
 |       nullptr, nullptr, framehd, result, &provider->source, nullptr); | 
 |   EXPECT_EQ(0, send_result); | 
 |   // Data accepted by the visitor includes a frame header and kReadLength bytes | 
 |   // of payload. | 
 |   EXPECT_EQ(visitor.data().size(), kFrameHeaderSize + kReadLength); | 
 | } | 
 |  | 
 | // Verifies that a nghttp2_data_provider derived from a DataFrameSource works | 
 | // correctly with nghttp2-style callbacks when the amount of data read is more | 
 | // than what the source provides. | 
 | TEST(DataProviderTest, ReadMoreThanSourceProvides) { | 
 |   DataSavingVisitor visitor; | 
 |   const absl::string_view kPayload = "Example payload"; | 
 |   TestDataFrameSource source(visitor, true); | 
 |   source.AppendPayload(kPayload); | 
 |   source.EndData(); | 
 |   auto provider = MakeDataProvider(&source); | 
 |   uint32_t data_flags = 0; | 
 |   const int32_t kStreamId = 1; | 
 |   const size_t kReadLength = 30; | 
 |   // Read callback selects a payload length given an upper bound. | 
 |   ssize_t result = | 
 |       provider->read_callback(nullptr, kStreamId, nullptr, kReadLength, | 
 |                               &data_flags, &provider->source, nullptr); | 
 |   ASSERT_EQ(kPayload.size(), result); | 
 |   EXPECT_EQ(NGHTTP2_DATA_FLAG_NO_COPY | NGHTTP2_DATA_FLAG_EOF, data_flags); | 
 |  | 
 |   const uint8_t framehd[kFrameHeaderSize] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; | 
 |   // Sends the frame header and some payload bytes. | 
 |   int send_result = callbacks::DataFrameSourceSendCallback( | 
 |       nullptr, nullptr, framehd, result, &provider->source, nullptr); | 
 |   EXPECT_EQ(0, send_result); | 
 |   // Data accepted by the visitor includes a frame header and the entire | 
 |   // payload. | 
 |   EXPECT_EQ(visitor.data().size(), kFrameHeaderSize + kPayload.size()); | 
 | } | 
 |  | 
 | // Verifies that a nghttp2_data_provider derived from a DataFrameSource works | 
 | // correctly with nghttp2-style callbacks when the source is blocked. | 
 | TEST(DataProviderTest, ReadFromBlockedSource) { | 
 |   DataSavingVisitor visitor; | 
 |   // Source has no payload, but also no fin, so it's blocked. | 
 |   TestDataFrameSource source(visitor, false); | 
 |   auto provider = MakeDataProvider(&source); | 
 |   uint32_t data_flags = 0; | 
 |   const int32_t kStreamId = 1; | 
 |   const size_t kReadLength = 10; | 
 |   ssize_t result = | 
 |       provider->read_callback(nullptr, kStreamId, nullptr, kReadLength, | 
 |                               &data_flags, &provider->source, nullptr); | 
 |   // Read operation is deferred, since the source is blocked. | 
 |   EXPECT_EQ(NGHTTP2_ERR_DEFERRED, result); | 
 | } | 
 |  | 
 | // Verifies that a nghttp2_data_provider derived from a DataFrameSource works | 
 | // correctly with nghttp2-style callbacks when the source provides only fin and | 
 | // no data. | 
 | TEST(DataProviderTest, ReadFromZeroLengthSource) { | 
 |   DataSavingVisitor visitor; | 
 |   // Empty payload and fin=true indicates the source is done. | 
 |   TestDataFrameSource source(visitor, true); | 
 |   source.EndData(); | 
 |   auto provider = MakeDataProvider(&source); | 
 |   uint32_t data_flags = 0; | 
 |   const int32_t kStreamId = 1; | 
 |   const size_t kReadLength = 10; | 
 |   ssize_t result = | 
 |       provider->read_callback(nullptr, kStreamId, nullptr, kReadLength, | 
 |                               &data_flags, &provider->source, nullptr); | 
 |   ASSERT_EQ(0, result); | 
 |   EXPECT_EQ(NGHTTP2_DATA_FLAG_NO_COPY | NGHTTP2_DATA_FLAG_EOF, data_flags); | 
 |  | 
 |   const uint8_t framehd[kFrameHeaderSize] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; | 
 |   int send_result = callbacks::DataFrameSourceSendCallback( | 
 |       nullptr, nullptr, framehd, result, &provider->source, nullptr); | 
 |   EXPECT_EQ(0, send_result); | 
 |   // Data accepted by the visitor includes a frame header with fin and zero | 
 |   // bytes of payload. | 
 |   EXPECT_EQ(visitor.data().size(), kFrameHeaderSize); | 
 | } | 
 |  | 
 | }  // namespace test | 
 | }  // namespace adapter | 
 | }  // namespace http2 |