blob: af8d98187f2866a6d2d1e5cc9408846bde996316 [file] [log] [blame]
#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