upload_file_element_reader_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. // Copyright (c) 2012 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/base/upload_file_element_reader.h"
  5. #include <stdint.h>
  6. #include <limits>
  7. #include "base/files/file_util.h"
  8. #include "base/files/scoped_temp_dir.h"
  9. #include "base/run_loop.h"
  10. #include "base/threading/thread_task_runner_handle.h"
  11. #include "build/build_config.h"
  12. #include "net/base/io_buffer.h"
  13. #include "net/base/net_errors.h"
  14. #include "net/base/test_completion_callback.h"
  15. #include "net/test/gtest_util.h"
  16. #include "net/test/test_with_task_environment.h"
  17. #include "testing/gmock/include/gmock/gmock.h"
  18. #include "testing/gtest/include/gtest/gtest.h"
  19. #if BUILDFLAG(IS_APPLE)
  20. #include "base/mac/scoped_nsautorelease_pool.h"
  21. #endif
  22. using net::test::IsError;
  23. using net::test::IsOk;
  24. namespace net {
  25. // When the parameter is false, the UploadFileElementReader is passed only a
  26. // FilePath and needs to open the file itself. When it's true, it's passed an
  27. // already open base::File.
  28. class UploadFileElementReaderTest : public testing::TestWithParam<bool>,
  29. public WithTaskEnvironment {
  30. protected:
  31. void SetUp() override {
  32. // Some tests (*.ReadPartially) rely on bytes_.size() being even.
  33. bytes_.assign({'1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c',
  34. 'd', 'e', 'f', 'g', 'h', 'i'});
  35. ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  36. ASSERT_TRUE(
  37. base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path_));
  38. ASSERT_EQ(
  39. static_cast<int>(bytes_.size()),
  40. base::WriteFile(temp_file_path_, &bytes_[0], bytes_.size()));
  41. reader_ =
  42. CreateReader(0, std::numeric_limits<uint64_t>::max(), base::Time());
  43. TestCompletionCallback callback;
  44. ASSERT_THAT(reader_->Init(callback.callback()), IsError(ERR_IO_PENDING));
  45. EXPECT_THAT(callback.WaitForResult(), IsOk());
  46. EXPECT_EQ(bytes_.size(), reader_->GetContentLength());
  47. EXPECT_EQ(bytes_.size(), reader_->BytesRemaining());
  48. EXPECT_FALSE(reader_->IsInMemory());
  49. }
  50. ~UploadFileElementReaderTest() override {
  51. reader_.reset();
  52. base::RunLoop().RunUntilIdle();
  53. }
  54. // Creates a UploadFileElementReader based on the value of GetParam().
  55. std::unique_ptr<UploadFileElementReader> CreateReader(
  56. int64_t offset,
  57. int64_t length,
  58. base::Time expected_modification_time) {
  59. if (GetParam()) {
  60. return std::make_unique<UploadFileElementReader>(
  61. base::ThreadTaskRunnerHandle::Get().get(), temp_file_path_, offset,
  62. length, expected_modification_time);
  63. }
  64. // The base::File::FLAG_WIN_SHARE_DELETE lets the file be deleted without
  65. // the test fixture waiting on it to be closed.
  66. int open_flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
  67. base::File::FLAG_WIN_SHARE_DELETE;
  68. #if BUILDFLAG(IS_WIN)
  69. // On Windows, file must be opened for asynchronous operation.
  70. open_flags |= base::File::FLAG_ASYNC;
  71. #endif // BUILDFLAG(IS_WIN)
  72. base::File file(temp_file_path_, open_flags);
  73. EXPECT_TRUE(file.IsValid());
  74. return std::make_unique<UploadFileElementReader>(
  75. base::ThreadTaskRunnerHandle::Get().get(), std::move(file),
  76. // Use an incorrect path, to make sure that the file is never re-opened.
  77. base::FilePath(FILE_PATH_LITERAL("this_should_be_ignored")), offset,
  78. length, expected_modification_time);
  79. }
  80. #if BUILDFLAG(IS_APPLE)
  81. // May be needed to avoid leaks on OSX.
  82. base::mac::ScopedNSAutoreleasePool scoped_pool_;
  83. #endif
  84. std::vector<char> bytes_;
  85. std::unique_ptr<UploadElementReader> reader_;
  86. base::ScopedTempDir temp_dir_;
  87. base::FilePath temp_file_path_;
  88. };
  89. TEST_P(UploadFileElementReaderTest, ReadPartially) {
  90. const size_t kHalfSize = bytes_.size() / 2;
  91. ASSERT_EQ(bytes_.size(), kHalfSize * 2);
  92. std::vector<char> buf(kHalfSize);
  93. scoped_refptr<IOBuffer> wrapped_buffer =
  94. base::MakeRefCounted<WrappedIOBuffer>(&buf[0]);
  95. TestCompletionCallback read_callback1;
  96. ASSERT_EQ(ERR_IO_PENDING,
  97. reader_->Read(
  98. wrapped_buffer.get(), buf.size(), read_callback1.callback()));
  99. EXPECT_EQ(static_cast<int>(buf.size()), read_callback1.WaitForResult());
  100. EXPECT_EQ(bytes_.size() - buf.size(), reader_->BytesRemaining());
  101. EXPECT_EQ(std::vector<char>(bytes_.begin(), bytes_.begin() + kHalfSize), buf);
  102. TestCompletionCallback read_callback2;
  103. EXPECT_EQ(ERR_IO_PENDING,
  104. reader_->Read(
  105. wrapped_buffer.get(), buf.size(), read_callback2.callback()));
  106. EXPECT_EQ(static_cast<int>(buf.size()), read_callback2.WaitForResult());
  107. EXPECT_EQ(0U, reader_->BytesRemaining());
  108. EXPECT_EQ(std::vector<char>(bytes_.begin() + kHalfSize, bytes_.end()), buf);
  109. }
  110. TEST_P(UploadFileElementReaderTest, ReadAll) {
  111. std::vector<char> buf(bytes_.size());
  112. scoped_refptr<IOBuffer> wrapped_buffer =
  113. base::MakeRefCounted<WrappedIOBuffer>(&buf[0]);
  114. TestCompletionCallback read_callback;
  115. ASSERT_EQ(ERR_IO_PENDING,
  116. reader_->Read(
  117. wrapped_buffer.get(), buf.size(), read_callback.callback()));
  118. EXPECT_EQ(static_cast<int>(buf.size()), read_callback.WaitForResult());
  119. EXPECT_EQ(0U, reader_->BytesRemaining());
  120. EXPECT_EQ(bytes_, buf);
  121. // Try to read again.
  122. EXPECT_EQ(0,
  123. reader_->Read(
  124. wrapped_buffer.get(), buf.size(), read_callback.callback()));
  125. }
  126. TEST_P(UploadFileElementReaderTest, ReadTooMuch) {
  127. const size_t kTooLargeSize = bytes_.size() * 2;
  128. std::vector<char> buf(kTooLargeSize);
  129. scoped_refptr<IOBuffer> wrapped_buffer =
  130. base::MakeRefCounted<WrappedIOBuffer>(&buf[0]);
  131. TestCompletionCallback read_callback;
  132. ASSERT_EQ(ERR_IO_PENDING,
  133. reader_->Read(
  134. wrapped_buffer.get(), buf.size(), read_callback.callback()));
  135. EXPECT_EQ(static_cast<int>(bytes_.size()), read_callback.WaitForResult());
  136. EXPECT_EQ(0U, reader_->BytesRemaining());
  137. buf.resize(bytes_.size()); // Resize to compare.
  138. EXPECT_EQ(bytes_, buf);
  139. }
  140. TEST_P(UploadFileElementReaderTest, MultipleInit) {
  141. std::vector<char> buf(bytes_.size());
  142. scoped_refptr<IOBuffer> wrapped_buffer =
  143. base::MakeRefCounted<WrappedIOBuffer>(&buf[0]);
  144. // Read all.
  145. TestCompletionCallback read_callback1;
  146. ASSERT_EQ(ERR_IO_PENDING,
  147. reader_->Read(
  148. wrapped_buffer.get(), buf.size(), read_callback1.callback()));
  149. EXPECT_EQ(static_cast<int>(buf.size()), read_callback1.WaitForResult());
  150. EXPECT_EQ(0U, reader_->BytesRemaining());
  151. EXPECT_EQ(bytes_, buf);
  152. // Call Init() again to reset the state.
  153. TestCompletionCallback init_callback;
  154. ASSERT_THAT(reader_->Init(init_callback.callback()), IsError(ERR_IO_PENDING));
  155. EXPECT_THAT(init_callback.WaitForResult(), IsOk());
  156. EXPECT_EQ(bytes_.size(), reader_->GetContentLength());
  157. EXPECT_EQ(bytes_.size(), reader_->BytesRemaining());
  158. // Read again.
  159. TestCompletionCallback read_callback2;
  160. ASSERT_EQ(ERR_IO_PENDING,
  161. reader_->Read(
  162. wrapped_buffer.get(), buf.size(), read_callback2.callback()));
  163. EXPECT_EQ(static_cast<int>(buf.size()), read_callback2.WaitForResult());
  164. EXPECT_EQ(0U, reader_->BytesRemaining());
  165. EXPECT_EQ(bytes_, buf);
  166. }
  167. TEST_P(UploadFileElementReaderTest, InitDuringAsyncOperation) {
  168. std::vector<char> buf(bytes_.size());
  169. scoped_refptr<IOBuffer> wrapped_buffer =
  170. base::MakeRefCounted<WrappedIOBuffer>(&buf[0]);
  171. // Start reading all.
  172. TestCompletionCallback read_callback1;
  173. EXPECT_EQ(ERR_IO_PENDING,
  174. reader_->Read(
  175. wrapped_buffer.get(), buf.size(), read_callback1.callback()));
  176. // Call Init to cancel the previous read.
  177. TestCompletionCallback init_callback1;
  178. EXPECT_THAT(reader_->Init(init_callback1.callback()),
  179. IsError(ERR_IO_PENDING));
  180. // Call Init again to cancel the previous init.
  181. TestCompletionCallback init_callback2;
  182. EXPECT_THAT(reader_->Init(init_callback2.callback()),
  183. IsError(ERR_IO_PENDING));
  184. EXPECT_THAT(init_callback2.WaitForResult(), IsOk());
  185. EXPECT_EQ(bytes_.size(), reader_->GetContentLength());
  186. EXPECT_EQ(bytes_.size(), reader_->BytesRemaining());
  187. // Read half.
  188. std::vector<char> buf2(bytes_.size() / 2);
  189. scoped_refptr<IOBuffer> wrapped_buffer2 =
  190. base::MakeRefCounted<WrappedIOBuffer>(&buf2[0]);
  191. TestCompletionCallback read_callback2;
  192. EXPECT_EQ(ERR_IO_PENDING,
  193. reader_->Read(
  194. wrapped_buffer2.get(), buf2.size(), read_callback2.callback()));
  195. EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult());
  196. EXPECT_EQ(bytes_.size() - buf2.size(), reader_->BytesRemaining());
  197. EXPECT_EQ(std::vector<char>(bytes_.begin(), bytes_.begin() + buf2.size()),
  198. buf2);
  199. // Make sure callbacks are not called for cancelled operations.
  200. EXPECT_FALSE(read_callback1.have_result());
  201. EXPECT_FALSE(init_callback1.have_result());
  202. }
  203. TEST_P(UploadFileElementReaderTest, RepeatedInitDuringInit) {
  204. std::vector<char> buf(bytes_.size());
  205. scoped_refptr<IOBuffer> wrapped_buffer =
  206. base::MakeRefCounted<WrappedIOBuffer>(&buf[0]);
  207. TestCompletionCallback init_callback1;
  208. EXPECT_THAT(reader_->Init(init_callback1.callback()),
  209. IsError(ERR_IO_PENDING));
  210. // Call Init again to cancel the previous init.
  211. TestCompletionCallback init_callback2;
  212. EXPECT_THAT(reader_->Init(init_callback2.callback()),
  213. IsError(ERR_IO_PENDING));
  214. // Call Init yet again to cancel the previous init.
  215. TestCompletionCallback init_callback3;
  216. EXPECT_THAT(reader_->Init(init_callback3.callback()),
  217. IsError(ERR_IO_PENDING));
  218. EXPECT_THAT(init_callback3.WaitForResult(), IsOk());
  219. EXPECT_EQ(bytes_.size(), reader_->GetContentLength());
  220. EXPECT_EQ(bytes_.size(), reader_->BytesRemaining());
  221. // Read all.
  222. TestCompletionCallback read_callback;
  223. int result =
  224. reader_->Read(wrapped_buffer.get(), buf.size(), read_callback.callback());
  225. EXPECT_EQ(static_cast<int>(buf.size()), read_callback.GetResult(result));
  226. EXPECT_EQ(0U, reader_->BytesRemaining());
  227. EXPECT_EQ(bytes_, buf);
  228. EXPECT_FALSE(init_callback1.have_result());
  229. EXPECT_FALSE(init_callback2.have_result());
  230. }
  231. TEST_P(UploadFileElementReaderTest, Range) {
  232. const uint64_t kOffset = 2;
  233. const uint64_t kLength = bytes_.size() - kOffset * 3;
  234. reader_ = CreateReader(kOffset, kLength, base::Time());
  235. TestCompletionCallback init_callback;
  236. ASSERT_THAT(reader_->Init(init_callback.callback()), IsError(ERR_IO_PENDING));
  237. EXPECT_THAT(init_callback.WaitForResult(), IsOk());
  238. EXPECT_EQ(kLength, reader_->GetContentLength());
  239. EXPECT_EQ(kLength, reader_->BytesRemaining());
  240. std::vector<char> buf(kLength);
  241. scoped_refptr<IOBuffer> wrapped_buffer =
  242. base::MakeRefCounted<WrappedIOBuffer>(&buf[0]);
  243. TestCompletionCallback read_callback;
  244. ASSERT_EQ(
  245. ERR_IO_PENDING,
  246. reader_->Read(wrapped_buffer.get(), kLength, read_callback.callback()));
  247. EXPECT_EQ(static_cast<int>(kLength), read_callback.WaitForResult());
  248. const std::vector<char> expected(bytes_.begin() + kOffset,
  249. bytes_.begin() + kOffset + kLength);
  250. EXPECT_EQ(expected, buf);
  251. }
  252. TEST_P(UploadFileElementReaderTest, FileChanged) {
  253. base::File::Info info;
  254. ASSERT_TRUE(base::GetFileInfo(temp_file_path_, &info));
  255. // Expect one second before the actual modification time to simulate change.
  256. const base::Time expected_modification_time =
  257. info.last_modified - base::Seconds(1);
  258. reader_ = CreateReader(0, std::numeric_limits<uint64_t>::max(),
  259. expected_modification_time);
  260. TestCompletionCallback init_callback;
  261. ASSERT_THAT(reader_->Init(init_callback.callback()), IsError(ERR_IO_PENDING));
  262. EXPECT_THAT(init_callback.WaitForResult(), IsError(ERR_UPLOAD_FILE_CHANGED));
  263. }
  264. TEST_P(UploadFileElementReaderTest, InexactExpectedTimeStamp) {
  265. base::File::Info info;
  266. ASSERT_TRUE(base::GetFileInfo(temp_file_path_, &info));
  267. const base::Time expected_modification_time =
  268. info.last_modified - base::Milliseconds(900);
  269. reader_ = CreateReader(0, std::numeric_limits<uint64_t>::max(),
  270. expected_modification_time);
  271. TestCompletionCallback init_callback;
  272. ASSERT_THAT(reader_->Init(init_callback.callback()), IsError(ERR_IO_PENDING));
  273. EXPECT_THAT(init_callback.WaitForResult(), IsOk());
  274. }
  275. TEST_P(UploadFileElementReaderTest, WrongPath) {
  276. const base::FilePath wrong_path(FILE_PATH_LITERAL("wrong_path"));
  277. reader_ = std::make_unique<UploadFileElementReader>(
  278. base::ThreadTaskRunnerHandle::Get().get(), wrong_path, 0,
  279. std::numeric_limits<uint64_t>::max(), base::Time());
  280. TestCompletionCallback init_callback;
  281. ASSERT_THAT(reader_->Init(init_callback.callback()), IsError(ERR_IO_PENDING));
  282. EXPECT_THAT(init_callback.WaitForResult(), IsError(ERR_FILE_NOT_FOUND));
  283. }
  284. INSTANTIATE_TEST_SUITE_P(All,
  285. UploadFileElementReaderTest,
  286. testing::ValuesIn({false, true}));
  287. } // namespace net