spdy_read_queue_unittest.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright (c) 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/spdy/spdy_read_queue.h"
  5. #include <algorithm>
  6. #include <cstddef>
  7. #include <memory>
  8. #include <string>
  9. #include <utility>
  10. #include "base/bind.h"
  11. #include "base/callback.h"
  12. #include "net/spdy/spdy_buffer.h"
  13. #include "testing/gtest/include/gtest/gtest.h"
  14. namespace net::test {
  15. namespace {
  16. const char kData[] = "SPDY read queue test data.\0Some more data.";
  17. const size_t kDataSize = std::size(kData);
  18. // Enqueues |data| onto |queue| in chunks of at most |max_buffer_size|
  19. // bytes.
  20. void EnqueueString(const std::string& data,
  21. size_t max_buffer_size,
  22. SpdyReadQueue* queue) {
  23. ASSERT_GT(data.size(), 0u);
  24. ASSERT_GT(max_buffer_size, 0u);
  25. size_t old_total_size = queue->GetTotalSize();
  26. for (size_t i = 0; i < data.size();) {
  27. size_t buffer_size = std::min(data.size() - i, max_buffer_size);
  28. queue->Enqueue(std::make_unique<SpdyBuffer>(data.data() + i, buffer_size));
  29. i += buffer_size;
  30. EXPECT_FALSE(queue->IsEmpty());
  31. EXPECT_EQ(old_total_size + i, queue->GetTotalSize());
  32. }
  33. }
  34. // Dequeues all bytes in |queue| in chunks of at most
  35. // |max_buffer_size| bytes and returns the data as a string.
  36. std::string DrainToString(size_t max_buffer_size, SpdyReadQueue* queue) {
  37. std::string data;
  38. // Pad the buffer so we can detect out-of-bound writes.
  39. size_t padding = std::max(static_cast<size_t>(4096), queue->GetTotalSize());
  40. size_t buffer_size_with_padding = padding + max_buffer_size + padding;
  41. auto buffer = std::make_unique<char[]>(buffer_size_with_padding);
  42. std::memset(buffer.get(), 0, buffer_size_with_padding);
  43. char* buffer_data = buffer.get() + padding;
  44. while (!queue->IsEmpty()) {
  45. size_t old_total_size = queue->GetTotalSize();
  46. EXPECT_GT(old_total_size, 0u);
  47. size_t dequeued_bytes = queue->Dequeue(buffer_data, max_buffer_size);
  48. // Make sure |queue| doesn't write past either end of its given
  49. // boundaries.
  50. for (int i = 1; i <= static_cast<int>(padding); ++i) {
  51. EXPECT_EQ('\0', buffer_data[-i]) << -i;
  52. }
  53. for (size_t i = 0; i < padding; ++i) {
  54. EXPECT_EQ('\0', buffer_data[max_buffer_size + i]) << i;
  55. }
  56. data.append(buffer_data, dequeued_bytes);
  57. EXPECT_EQ(dequeued_bytes, std::min(max_buffer_size, dequeued_bytes));
  58. EXPECT_EQ(queue->GetTotalSize(), old_total_size - dequeued_bytes);
  59. }
  60. EXPECT_TRUE(queue->IsEmpty());
  61. return data;
  62. }
  63. // Enqueue a test string with the given enqueue/dequeue max buffer
  64. // sizes.
  65. void RunEnqueueDequeueTest(size_t enqueue_max_buffer_size,
  66. size_t dequeue_max_buffer_size) {
  67. std::string data(kData, kDataSize);
  68. SpdyReadQueue read_queue;
  69. EnqueueString(data, enqueue_max_buffer_size, &read_queue);
  70. const std::string& drained_data =
  71. DrainToString(dequeue_max_buffer_size, &read_queue);
  72. EXPECT_EQ(data, drained_data);
  73. }
  74. void OnBufferDiscarded(bool* discarded,
  75. size_t* discarded_bytes,
  76. size_t delta,
  77. SpdyBuffer::ConsumeSource consume_source) {
  78. EXPECT_EQ(SpdyBuffer::DISCARD, consume_source);
  79. *discarded = true;
  80. *discarded_bytes = delta;
  81. }
  82. } // namespace
  83. class SpdyReadQueueTest : public ::testing::Test {};
  84. // Call RunEnqueueDequeueTest() with various buffer size combinatinos.
  85. TEST_F(SpdyReadQueueTest, LargeEnqueueAndDequeueBuffers) {
  86. RunEnqueueDequeueTest(2 * kDataSize, 2 * kDataSize);
  87. }
  88. TEST_F(SpdyReadQueueTest, OneByteEnqueueAndDequeueBuffers) {
  89. RunEnqueueDequeueTest(1, 1);
  90. }
  91. TEST_F(SpdyReadQueueTest, CoprimeBufferSizes) {
  92. RunEnqueueDequeueTest(2, 3);
  93. RunEnqueueDequeueTest(3, 2);
  94. }
  95. TEST_F(SpdyReadQueueTest, Clear) {
  96. auto buffer = std::make_unique<SpdyBuffer>(kData, kDataSize);
  97. bool discarded = false;
  98. size_t discarded_bytes = 0;
  99. buffer->AddConsumeCallback(
  100. base::BindRepeating(&OnBufferDiscarded, &discarded, &discarded_bytes));
  101. SpdyReadQueue read_queue;
  102. read_queue.Enqueue(std::move(buffer));
  103. EXPECT_FALSE(discarded);
  104. EXPECT_EQ(0u, discarded_bytes);
  105. EXPECT_FALSE(read_queue.IsEmpty());
  106. read_queue.Clear();
  107. EXPECT_TRUE(discarded);
  108. EXPECT_EQ(kDataSize, discarded_bytes);
  109. EXPECT_TRUE(read_queue.IsEmpty());
  110. }
  111. } // namespace net::test