data_pipe_element_reader_unittest.cc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // Copyright 2017 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 "services/network/data_pipe_element_reader.h"
  5. #include <stdint.h>
  6. #include <limits>
  7. #include <memory>
  8. #include "base/memory/ref_counted.h"
  9. #include "base/run_loop.h"
  10. #include "base/strings/string_number_conversions.h"
  11. #include "base/test/task_environment.h"
  12. #include "mojo/public/cpp/bindings/pending_remote.h"
  13. #include "mojo/public/cpp/bindings/receiver.h"
  14. #include "mojo/public/cpp/system/data_pipe.h"
  15. #include "mojo/public/cpp/system/data_pipe_utils.h"
  16. #include "net/base/io_buffer.h"
  17. #include "net/base/test_completion_callback.h"
  18. #include "services/network/public/mojom/data_pipe_getter.mojom.h"
  19. #include "testing/gtest/include/gtest/gtest.h"
  20. // Most tests of this class are at the URLLoader layer. These tests focus on
  21. // things too difficult to cover with integration tests.
  22. namespace network {
  23. namespace {
  24. class PassThroughDataPipeGetter : public mojom::DataPipeGetter {
  25. public:
  26. explicit PassThroughDataPipeGetter() = default;
  27. PassThroughDataPipeGetter(const PassThroughDataPipeGetter&) = delete;
  28. PassThroughDataPipeGetter& operator=(const PassThroughDataPipeGetter&) =
  29. delete;
  30. mojo::PendingRemote<network::mojom::DataPipeGetter>
  31. GetDataPipeGetterRemote() {
  32. EXPECT_FALSE(receiver_.is_bound());
  33. return receiver_.BindNewPipeAndPassRemote();
  34. }
  35. void WaitForRead(mojo::ScopedDataPipeProducerHandle* write_pipe,
  36. ReadCallback* read_callback) {
  37. DCHECK(!run_loop_);
  38. if (!write_pipe_.is_valid()) {
  39. run_loop_ = std::make_unique<base::RunLoop>();
  40. run_loop_->Run();
  41. run_loop_.reset();
  42. }
  43. EXPECT_TRUE(write_pipe_.is_valid());
  44. EXPECT_TRUE(read_callback_);
  45. *write_pipe = std::move(write_pipe_);
  46. *read_callback = std::move(read_callback_);
  47. }
  48. private:
  49. // network::mojom::DataPipeGetter implementation:
  50. void Read(mojo::ScopedDataPipeProducerHandle pipe,
  51. ReadCallback callback) override {
  52. EXPECT_FALSE(write_pipe_.is_valid());
  53. EXPECT_FALSE(read_callback_);
  54. write_pipe_ = std::move(pipe);
  55. read_callback_ = std::move(callback);
  56. if (run_loop_)
  57. run_loop_->Quit();
  58. }
  59. void Clone(
  60. mojo::PendingReceiver<network::mojom::DataPipeGetter> receiver) override {
  61. NOTIMPLEMENTED();
  62. }
  63. std::unique_ptr<base::RunLoop> run_loop_;
  64. mojo::Receiver<network::mojom::DataPipeGetter> receiver_{this};
  65. mojo::ScopedDataPipeProducerHandle write_pipe_;
  66. ReadCallback read_callback_;
  67. };
  68. class DataPipeElementReaderTest : public testing::Test {
  69. public:
  70. DataPipeElementReaderTest()
  71. : element_reader_(nullptr, data_pipe_getter_.GetDataPipeGetterRemote()) {}
  72. protected:
  73. base::test::SingleThreadTaskEnvironment task_environment_{
  74. base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
  75. PassThroughDataPipeGetter data_pipe_getter_;
  76. DataPipeElementReader element_reader_;
  77. };
  78. // Test the case where a second Init() call occurs when there's a pending Init()
  79. // call in progress. The first call should be dropped, in favor of the second
  80. // one.
  81. TEST_F(DataPipeElementReaderTest, InitInterruptsInit) {
  82. // Value deliberately outside of the range of an uint32_t, to catch any
  83. // accidental conversions to an int.
  84. const uint64_t kResponseBodySize = std::numeric_limits<uint32_t>::max();
  85. // The network stack calls Init.
  86. net::TestCompletionCallback first_init_callback;
  87. EXPECT_EQ(net::ERR_IO_PENDING,
  88. element_reader_.Init(first_init_callback.callback()));
  89. // Wait for DataPipeGetter::Read() to be called.
  90. mojo::ScopedDataPipeProducerHandle first_write_pipe;
  91. network::mojom::DataPipeGetter::ReadCallback first_read_pipe_callback;
  92. data_pipe_getter_.WaitForRead(&first_write_pipe, &first_read_pipe_callback);
  93. // The network stack calls Init again, interrupting the previous call.
  94. net::TestCompletionCallback second_init_callback;
  95. EXPECT_EQ(net::ERR_IO_PENDING,
  96. element_reader_.Init(second_init_callback.callback()));
  97. // Wait for DataPipeGetter::Read() to be called again.
  98. mojo::ScopedDataPipeProducerHandle second_write_pipe;
  99. network::mojom::DataPipeGetter::ReadCallback second_read_pipe_callback;
  100. data_pipe_getter_.WaitForRead(&second_write_pipe, &second_read_pipe_callback);
  101. // Sending data on the first read pipe should do nothing.
  102. std::move(first_read_pipe_callback)
  103. .Run(net::ERR_FAILED, kResponseBodySize - 1);
  104. // Run any pending tasks, to make sure nothing unexpected is queued.
  105. base::RunLoop().RunUntilIdle();
  106. EXPECT_FALSE(first_init_callback.have_result());
  107. EXPECT_FALSE(second_init_callback.have_result());
  108. // Sending data on the second pipe should result in the second init callback
  109. // being invoked.
  110. std::move(second_read_pipe_callback).Run(net::OK, kResponseBodySize);
  111. EXPECT_EQ(net::OK, second_init_callback.WaitForResult());
  112. EXPECT_FALSE(first_init_callback.have_result());
  113. EXPECT_EQ(kResponseBodySize, element_reader_.GetContentLength());
  114. EXPECT_EQ(kResponseBodySize, element_reader_.BytesRemaining());
  115. EXPECT_FALSE(element_reader_.IsInMemory());
  116. // Try to read from the body.
  117. auto io_buffer = base::MakeRefCounted<net::IOBufferWithSize>(10);
  118. net::TestCompletionCallback read_callback;
  119. EXPECT_EQ(net::ERR_IO_PENDING,
  120. element_reader_.Read(io_buffer.get(), io_buffer->size(),
  121. read_callback.callback()));
  122. // Writes to the first write pipe should either fail, or succeed but be
  123. // ignored.
  124. mojo::BlockingCopyFromString("foo", first_write_pipe);
  125. base::RunLoop().RunUntilIdle();
  126. EXPECT_FALSE(read_callback.have_result());
  127. }
  128. // Test the case where a second Init() call occurs when there's a pending Read()
  129. // call in progress. The old Read() should be dropped, in favor of the new
  130. // Init().
  131. TEST_F(DataPipeElementReaderTest, InitInterruptsRead) {
  132. // Value deliberately outside of the range of an uint32_t, to catch any
  133. // accidental conversions to an int.
  134. const uint64_t kResponseBodySize = std::numeric_limits<uint32_t>::max();
  135. // The network stack calls Init.
  136. net::TestCompletionCallback first_init_callback;
  137. EXPECT_EQ(net::ERR_IO_PENDING,
  138. element_reader_.Init(first_init_callback.callback()));
  139. // Wait for DataPipeGetter::Read() to be called.
  140. mojo::ScopedDataPipeProducerHandle first_write_pipe;
  141. network::mojom::DataPipeGetter::ReadCallback first_read_pipe_callback;
  142. data_pipe_getter_.WaitForRead(&first_write_pipe, &first_read_pipe_callback);
  143. std::move(first_read_pipe_callback).Run(net::OK, kResponseBodySize);
  144. ASSERT_EQ(net::OK, first_init_callback.WaitForResult());
  145. auto first_io_buffer = base::MakeRefCounted<net::IOBufferWithSize>(10);
  146. net::TestCompletionCallback first_read_callback;
  147. EXPECT_EQ(net::ERR_IO_PENDING,
  148. element_reader_.Read(first_io_buffer.get(), first_io_buffer->size(),
  149. first_read_callback.callback()));
  150. // The network stack calls Init again, interrupting the previous read.
  151. net::TestCompletionCallback second_init_callback;
  152. EXPECT_EQ(net::ERR_IO_PENDING,
  153. element_reader_.Init(second_init_callback.callback()));
  154. // Wait for DataPipeGetter::Read() to be called again.
  155. mojo::ScopedDataPipeProducerHandle second_write_pipe;
  156. network::mojom::DataPipeGetter::ReadCallback second_read_pipe_callback;
  157. data_pipe_getter_.WaitForRead(&second_write_pipe, &second_read_pipe_callback);
  158. // Run any pending tasks, to make sure nothing unexpected is queued.
  159. base::RunLoop().RunUntilIdle();
  160. EXPECT_FALSE(first_read_callback.have_result());
  161. EXPECT_FALSE(second_init_callback.have_result());
  162. // Sending data on the second pipe should result in the second init callback
  163. // being invoked.
  164. std::move(second_read_pipe_callback).Run(net::OK, kResponseBodySize);
  165. EXPECT_EQ(net::OK, second_init_callback.WaitForResult());
  166. EXPECT_EQ(kResponseBodySize, element_reader_.GetContentLength());
  167. EXPECT_EQ(kResponseBodySize, element_reader_.BytesRemaining());
  168. EXPECT_FALSE(element_reader_.IsInMemory());
  169. // Try to read from the body.
  170. auto io_buffer = base::MakeRefCounted<net::IOBufferWithSize>(10);
  171. net::TestCompletionCallback second_read_callback;
  172. EXPECT_EQ(net::ERR_IO_PENDING,
  173. element_reader_.Read(io_buffer.get(), io_buffer->size(),
  174. second_read_callback.callback()));
  175. // Writes to the first write pipe should either fail, or succeed but be
  176. // ignored.
  177. mojo::BlockingCopyFromString("foo", first_write_pipe);
  178. base::RunLoop().RunUntilIdle();
  179. EXPECT_FALSE(second_read_callback.have_result());
  180. }
  181. } // namespace
  182. } // namespace network