file_stream_unittest.cc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  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/file_stream.h"
  5. #include <string>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/callback.h"
  9. #include "base/files/file.h"
  10. #include "base/files/file_util.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/path_service.h"
  13. #include "base/run_loop.h"
  14. #include "base/strings/string_util.h"
  15. #include "base/synchronization/waitable_event.h"
  16. #include "base/task/current_thread.h"
  17. #include "base/test/test_timeouts.h"
  18. #include "base/threading/thread.h"
  19. #include "base/threading/thread_restrictions.h"
  20. #include "base/threading/thread_task_runner_handle.h"
  21. #include "build/build_config.h"
  22. #include "net/base/io_buffer.h"
  23. #include "net/base/net_errors.h"
  24. #include "net/base/test_completion_callback.h"
  25. #include "net/log/test_net_log.h"
  26. #include "net/test/gtest_util.h"
  27. #include "net/test/test_with_task_environment.h"
  28. #include "testing/gmock/include/gmock/gmock.h"
  29. #include "testing/gtest/include/gtest/gtest.h"
  30. #include "testing/platform_test.h"
  31. using net::test::IsError;
  32. using net::test::IsOk;
  33. #if BUILDFLAG(IS_ANDROID)
  34. #include "base/test/test_file_util.h"
  35. #endif
  36. namespace net {
  37. namespace {
  38. constexpr char kTestData[] = "0123456789";
  39. constexpr int kTestDataSize = std::size(kTestData) - 1;
  40. // Creates an IOBufferWithSize that contains the kTestDataSize.
  41. scoped_refptr<IOBufferWithSize> CreateTestDataBuffer() {
  42. scoped_refptr<IOBufferWithSize> buf =
  43. base::MakeRefCounted<IOBufferWithSize>(kTestDataSize);
  44. memcpy(buf->data(), kTestData, kTestDataSize);
  45. return buf;
  46. }
  47. } // namespace
  48. class FileStreamTest : public PlatformTest, public WithTaskEnvironment {
  49. public:
  50. void SetUp() override {
  51. PlatformTest::SetUp();
  52. base::CreateTemporaryFile(&temp_file_path_);
  53. base::WriteFile(temp_file_path_, kTestData, kTestDataSize);
  54. }
  55. void TearDown() override {
  56. // FileStreamContexts must be asynchronously closed on the file task runner
  57. // before they can be deleted. Pump the RunLoop to avoid leaks.
  58. base::RunLoop().RunUntilIdle();
  59. EXPECT_TRUE(base::DeleteFile(temp_file_path_));
  60. PlatformTest::TearDown();
  61. }
  62. const base::FilePath temp_file_path() const { return temp_file_path_; }
  63. private:
  64. base::FilePath temp_file_path_;
  65. };
  66. namespace {
  67. TEST_F(FileStreamTest, OpenExplicitClose) {
  68. TestCompletionCallback callback;
  69. FileStream stream(base::ThreadTaskRunnerHandle::Get());
  70. int flags = base::File::FLAG_OPEN |
  71. base::File::FLAG_READ |
  72. base::File::FLAG_ASYNC;
  73. int rv = stream.Open(temp_file_path(), flags, callback.callback());
  74. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  75. EXPECT_THAT(callback.WaitForResult(), IsOk());
  76. EXPECT_TRUE(stream.IsOpen());
  77. EXPECT_THAT(stream.Close(callback.callback()), IsError(ERR_IO_PENDING));
  78. EXPECT_THAT(callback.WaitForResult(), IsOk());
  79. EXPECT_FALSE(stream.IsOpen());
  80. }
  81. TEST_F(FileStreamTest, OpenExplicitCloseOrphaned) {
  82. TestCompletionCallback callback;
  83. auto stream =
  84. std::make_unique<FileStream>(base::ThreadTaskRunnerHandle::Get());
  85. int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
  86. base::File::FLAG_ASYNC;
  87. int rv = stream->Open(temp_file_path(), flags, callback.callback());
  88. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  89. EXPECT_THAT(callback.WaitForResult(), IsOk());
  90. EXPECT_TRUE(stream->IsOpen());
  91. EXPECT_THAT(stream->Close(callback.callback()), IsError(ERR_IO_PENDING));
  92. stream.reset();
  93. // File isn't actually closed yet.
  94. base::RunLoop runloop;
  95. runloop.RunUntilIdle();
  96. // The file should now be closed, though the callback has not been called.
  97. }
  98. // Test the use of FileStream with a file handle provided at construction.
  99. TEST_F(FileStreamTest, UseFileHandle) {
  100. int rv = 0;
  101. TestCompletionCallback callback;
  102. TestInt64CompletionCallback callback64;
  103. // 1. Test reading with a file handle.
  104. ASSERT_EQ(kTestDataSize,
  105. base::WriteFile(temp_file_path(), kTestData, kTestDataSize));
  106. int flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
  107. base::File::FLAG_ASYNC;
  108. base::File file1(temp_file_path(), flags);
  109. // Seek to the beginning of the file and read.
  110. auto read_stream = std::make_unique<FileStream>(
  111. std::move(file1), base::ThreadTaskRunnerHandle::Get());
  112. ASSERT_THAT(read_stream->Seek(0, callback64.callback()),
  113. IsError(ERR_IO_PENDING));
  114. ASSERT_EQ(0, callback64.WaitForResult());
  115. // Read into buffer and compare.
  116. scoped_refptr<IOBufferWithSize> read_buffer =
  117. base::MakeRefCounted<IOBufferWithSize>(kTestDataSize);
  118. rv = read_stream->Read(read_buffer.get(), kTestDataSize, callback.callback());
  119. ASSERT_EQ(kTestDataSize, callback.GetResult(rv));
  120. ASSERT_EQ(0, memcmp(kTestData, read_buffer->data(), kTestDataSize));
  121. read_stream.reset();
  122. // 2. Test writing with a file handle.
  123. base::DeleteFile(temp_file_path());
  124. flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE |
  125. base::File::FLAG_ASYNC;
  126. base::File file2(temp_file_path(), flags);
  127. auto write_stream = std::make_unique<FileStream>(
  128. std::move(file2), base::ThreadTaskRunnerHandle::Get());
  129. ASSERT_THAT(write_stream->Seek(0, callback64.callback()),
  130. IsError(ERR_IO_PENDING));
  131. ASSERT_EQ(0, callback64.WaitForResult());
  132. scoped_refptr<IOBufferWithSize> write_buffer = CreateTestDataBuffer();
  133. rv = write_stream->Write(write_buffer.get(), kTestDataSize,
  134. callback.callback());
  135. ASSERT_EQ(kTestDataSize, callback.GetResult(rv));
  136. write_stream.reset();
  137. // Read into buffer and compare to make sure the handle worked fine.
  138. ASSERT_EQ(kTestDataSize,
  139. base::ReadFile(temp_file_path(), read_buffer->data(),
  140. kTestDataSize));
  141. ASSERT_EQ(0, memcmp(kTestData, read_buffer->data(), kTestDataSize));
  142. }
  143. TEST_F(FileStreamTest, UseClosedStream) {
  144. int rv = 0;
  145. TestCompletionCallback callback;
  146. TestInt64CompletionCallback callback64;
  147. FileStream stream(base::ThreadTaskRunnerHandle::Get());
  148. EXPECT_FALSE(stream.IsOpen());
  149. // Try seeking...
  150. rv = stream.Seek(5, callback64.callback());
  151. EXPECT_THAT(callback64.GetResult(rv), IsError(ERR_UNEXPECTED));
  152. // Try reading...
  153. scoped_refptr<IOBufferWithSize> buf =
  154. base::MakeRefCounted<IOBufferWithSize>(10);
  155. rv = stream.Read(buf.get(), buf->size(), callback.callback());
  156. EXPECT_THAT(callback.GetResult(rv), IsError(ERR_UNEXPECTED));
  157. }
  158. TEST_F(FileStreamTest, Read) {
  159. int64_t file_size;
  160. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  161. FileStream stream(base::ThreadTaskRunnerHandle::Get());
  162. int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
  163. base::File::FLAG_ASYNC;
  164. TestCompletionCallback callback;
  165. int rv = stream.Open(temp_file_path(), flags, callback.callback());
  166. EXPECT_THAT(callback.GetResult(rv), IsOk());
  167. int total_bytes_read = 0;
  168. std::string data_read;
  169. for (;;) {
  170. scoped_refptr<IOBufferWithSize> buf =
  171. base::MakeRefCounted<IOBufferWithSize>(4);
  172. rv = stream.Read(buf.get(), buf->size(), callback.callback());
  173. rv = callback.GetResult(rv);
  174. EXPECT_LE(0, rv);
  175. if (rv <= 0)
  176. break;
  177. total_bytes_read += rv;
  178. data_read.append(buf->data(), rv);
  179. }
  180. EXPECT_EQ(file_size, total_bytes_read);
  181. EXPECT_EQ(kTestData, data_read);
  182. }
  183. TEST_F(FileStreamTest, Read_EarlyDelete) {
  184. int64_t file_size;
  185. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  186. auto stream =
  187. std::make_unique<FileStream>(base::ThreadTaskRunnerHandle::Get());
  188. int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
  189. base::File::FLAG_ASYNC;
  190. TestCompletionCallback callback;
  191. int rv = stream->Open(temp_file_path(), flags, callback.callback());
  192. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  193. EXPECT_THAT(callback.WaitForResult(), IsOk());
  194. scoped_refptr<IOBufferWithSize> buf =
  195. base::MakeRefCounted<IOBufferWithSize>(4);
  196. rv = stream->Read(buf.get(), buf->size(), callback.callback());
  197. stream.reset(); // Delete instead of closing it.
  198. if (rv < 0) {
  199. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  200. // The callback should not be called if the request is cancelled.
  201. base::RunLoop().RunUntilIdle();
  202. EXPECT_FALSE(callback.have_result());
  203. } else {
  204. EXPECT_EQ(std::string(kTestData, rv), std::string(buf->data(), rv));
  205. }
  206. }
  207. TEST_F(FileStreamTest, Read_FromOffset) {
  208. int64_t file_size;
  209. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  210. FileStream stream(base::ThreadTaskRunnerHandle::Get());
  211. int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
  212. base::File::FLAG_ASYNC;
  213. TestCompletionCallback callback;
  214. int rv = stream.Open(temp_file_path(), flags, callback.callback());
  215. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  216. EXPECT_THAT(callback.WaitForResult(), IsOk());
  217. TestInt64CompletionCallback callback64;
  218. const int64_t kOffset = 3;
  219. rv = stream.Seek(kOffset, callback64.callback());
  220. ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
  221. int64_t new_offset = callback64.WaitForResult();
  222. EXPECT_EQ(kOffset, new_offset);
  223. int total_bytes_read = 0;
  224. std::string data_read;
  225. for (;;) {
  226. scoped_refptr<IOBufferWithSize> buf =
  227. base::MakeRefCounted<IOBufferWithSize>(4);
  228. rv = stream.Read(buf.get(), buf->size(), callback.callback());
  229. if (rv == ERR_IO_PENDING)
  230. rv = callback.WaitForResult();
  231. EXPECT_LE(0, rv);
  232. if (rv <= 0)
  233. break;
  234. total_bytes_read += rv;
  235. data_read.append(buf->data(), rv);
  236. }
  237. EXPECT_EQ(file_size - kOffset, total_bytes_read);
  238. EXPECT_EQ(kTestData + kOffset, data_read);
  239. }
  240. TEST_F(FileStreamTest, Write) {
  241. FileStream stream(base::ThreadTaskRunnerHandle::Get());
  242. int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
  243. base::File::FLAG_ASYNC;
  244. TestCompletionCallback callback;
  245. int rv = stream.Open(temp_file_path(), flags, callback.callback());
  246. EXPECT_THAT(callback.GetResult(rv), IsOk());
  247. int64_t file_size;
  248. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  249. EXPECT_EQ(0, file_size);
  250. scoped_refptr<IOBuffer> buf = CreateTestDataBuffer();
  251. rv = stream.Write(buf.get(), kTestDataSize, callback.callback());
  252. rv = callback.GetResult(rv);
  253. EXPECT_EQ(kTestDataSize, rv);
  254. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  255. EXPECT_EQ(kTestDataSize, file_size);
  256. std::string data_read;
  257. EXPECT_TRUE(base::ReadFileToString(temp_file_path(), &data_read));
  258. EXPECT_EQ(kTestData, data_read);
  259. }
  260. TEST_F(FileStreamTest, Write_EarlyDelete) {
  261. auto stream =
  262. std::make_unique<FileStream>(base::ThreadTaskRunnerHandle::Get());
  263. int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
  264. base::File::FLAG_ASYNC;
  265. TestCompletionCallback callback;
  266. int rv = stream->Open(temp_file_path(), flags, callback.callback());
  267. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  268. EXPECT_THAT(callback.WaitForResult(), IsOk());
  269. int64_t file_size;
  270. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  271. EXPECT_EQ(0, file_size);
  272. scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
  273. rv = stream->Write(buf.get(), buf->size(), callback.callback());
  274. stream.reset();
  275. if (rv < 0) {
  276. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  277. // The callback should not be called if the request is cancelled.
  278. base::RunLoop().RunUntilIdle();
  279. EXPECT_FALSE(callback.have_result());
  280. } else {
  281. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  282. EXPECT_EQ(file_size, rv);
  283. }
  284. }
  285. TEST_F(FileStreamTest, Write_FromOffset) {
  286. int64_t file_size;
  287. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  288. FileStream stream(base::ThreadTaskRunnerHandle::Get());
  289. int flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE |
  290. base::File::FLAG_ASYNC;
  291. TestCompletionCallback callback;
  292. int rv = stream.Open(temp_file_path(), flags, callback.callback());
  293. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  294. EXPECT_THAT(callback.WaitForResult(), IsOk());
  295. TestInt64CompletionCallback callback64;
  296. const int64_t kOffset = kTestDataSize;
  297. rv = stream.Seek(kOffset, callback64.callback());
  298. ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
  299. int64_t new_offset = callback64.WaitForResult();
  300. EXPECT_EQ(kTestDataSize, new_offset);
  301. int total_bytes_written = 0;
  302. scoped_refptr<IOBufferWithSize> buffer = CreateTestDataBuffer();
  303. int buffer_size = buffer->size();
  304. scoped_refptr<DrainableIOBuffer> drainable =
  305. base::MakeRefCounted<DrainableIOBuffer>(std::move(buffer), buffer_size);
  306. while (total_bytes_written != kTestDataSize) {
  307. rv = stream.Write(drainable.get(), drainable->BytesRemaining(),
  308. callback.callback());
  309. if (rv == ERR_IO_PENDING)
  310. rv = callback.WaitForResult();
  311. EXPECT_LT(0, rv);
  312. if (rv <= 0)
  313. break;
  314. drainable->DidConsume(rv);
  315. total_bytes_written += rv;
  316. }
  317. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  318. EXPECT_EQ(file_size, kTestDataSize * 2);
  319. }
  320. TEST_F(FileStreamTest, BasicReadWrite) {
  321. int64_t file_size;
  322. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  323. auto stream =
  324. std::make_unique<FileStream>(base::ThreadTaskRunnerHandle::Get());
  325. int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
  326. base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
  327. TestCompletionCallback callback;
  328. int rv = stream->Open(temp_file_path(), flags, callback.callback());
  329. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  330. EXPECT_THAT(callback.WaitForResult(), IsOk());
  331. int64_t total_bytes_read = 0;
  332. std::string data_read;
  333. for (;;) {
  334. scoped_refptr<IOBufferWithSize> buf =
  335. base::MakeRefCounted<IOBufferWithSize>(4);
  336. rv = stream->Read(buf.get(), buf->size(), callback.callback());
  337. if (rv == ERR_IO_PENDING)
  338. rv = callback.WaitForResult();
  339. EXPECT_LE(0, rv);
  340. if (rv <= 0)
  341. break;
  342. total_bytes_read += rv;
  343. data_read.append(buf->data(), rv);
  344. }
  345. EXPECT_EQ(file_size, total_bytes_read);
  346. EXPECT_TRUE(data_read == kTestData);
  347. int total_bytes_written = 0;
  348. scoped_refptr<IOBufferWithSize> buffer = CreateTestDataBuffer();
  349. int buffer_size = buffer->size();
  350. scoped_refptr<DrainableIOBuffer> drainable =
  351. base::MakeRefCounted<DrainableIOBuffer>(std::move(buffer), buffer_size);
  352. while (total_bytes_written != kTestDataSize) {
  353. rv = stream->Write(drainable.get(), drainable->BytesRemaining(),
  354. callback.callback());
  355. if (rv == ERR_IO_PENDING)
  356. rv = callback.WaitForResult();
  357. EXPECT_LT(0, rv);
  358. if (rv <= 0)
  359. break;
  360. drainable->DidConsume(rv);
  361. total_bytes_written += rv;
  362. }
  363. stream.reset();
  364. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  365. EXPECT_EQ(kTestDataSize * 2, file_size);
  366. }
  367. TEST_F(FileStreamTest, BasicWriteRead) {
  368. int64_t file_size;
  369. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  370. auto stream =
  371. std::make_unique<FileStream>(base::ThreadTaskRunnerHandle::Get());
  372. int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
  373. base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
  374. TestCompletionCallback callback;
  375. int rv = stream->Open(temp_file_path(), flags, callback.callback());
  376. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  377. EXPECT_THAT(callback.WaitForResult(), IsOk());
  378. TestInt64CompletionCallback callback64;
  379. rv = stream->Seek(file_size, callback64.callback());
  380. ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
  381. int64_t offset = callback64.WaitForResult();
  382. EXPECT_EQ(offset, file_size);
  383. int total_bytes_written = 0;
  384. scoped_refptr<IOBufferWithSize> buffer = CreateTestDataBuffer();
  385. int buffer_size = buffer->size();
  386. scoped_refptr<DrainableIOBuffer> drainable =
  387. base::MakeRefCounted<DrainableIOBuffer>(std::move(buffer), buffer_size);
  388. while (total_bytes_written != kTestDataSize) {
  389. rv = stream->Write(drainable.get(), drainable->BytesRemaining(),
  390. callback.callback());
  391. if (rv == ERR_IO_PENDING)
  392. rv = callback.WaitForResult();
  393. EXPECT_LT(0, rv);
  394. if (rv <= 0)
  395. break;
  396. drainable->DidConsume(rv);
  397. total_bytes_written += rv;
  398. }
  399. EXPECT_EQ(kTestDataSize, total_bytes_written);
  400. rv = stream->Seek(0, callback64.callback());
  401. ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
  402. offset = callback64.WaitForResult();
  403. EXPECT_EQ(0, offset);
  404. int total_bytes_read = 0;
  405. std::string data_read;
  406. for (;;) {
  407. scoped_refptr<IOBufferWithSize> buf =
  408. base::MakeRefCounted<IOBufferWithSize>(4);
  409. rv = stream->Read(buf.get(), buf->size(), callback.callback());
  410. if (rv == ERR_IO_PENDING)
  411. rv = callback.WaitForResult();
  412. EXPECT_LE(0, rv);
  413. if (rv <= 0)
  414. break;
  415. total_bytes_read += rv;
  416. data_read.append(buf->data(), rv);
  417. }
  418. stream.reset();
  419. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  420. EXPECT_EQ(kTestDataSize * 2, file_size);
  421. EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
  422. const std::string kExpectedFileData =
  423. std::string(kTestData) + std::string(kTestData);
  424. EXPECT_EQ(kExpectedFileData, data_read);
  425. }
  426. class TestWriteReadCompletionCallback {
  427. public:
  428. TestWriteReadCompletionCallback(FileStream* stream,
  429. int* total_bytes_written,
  430. int* total_bytes_read,
  431. std::string* data_read)
  432. : stream_(stream),
  433. total_bytes_written_(total_bytes_written),
  434. total_bytes_read_(total_bytes_read),
  435. data_read_(data_read),
  436. drainable_(
  437. base::MakeRefCounted<DrainableIOBuffer>(CreateTestDataBuffer(),
  438. kTestDataSize)) {}
  439. TestWriteReadCompletionCallback(const TestWriteReadCompletionCallback&) =
  440. delete;
  441. TestWriteReadCompletionCallback& operator=(
  442. const TestWriteReadCompletionCallback&) = delete;
  443. int WaitForResult() {
  444. DCHECK(!waiting_for_result_);
  445. while (!have_result_) {
  446. waiting_for_result_ = true;
  447. base::RunLoop().Run();
  448. waiting_for_result_ = false;
  449. }
  450. have_result_ = false; // auto-reset for next callback
  451. return result_;
  452. }
  453. CompletionOnceCallback callback() {
  454. return base::BindOnce(&TestWriteReadCompletionCallback::OnComplete,
  455. base::Unretained(this));
  456. }
  457. void ValidateWrittenData() {
  458. TestCompletionCallback callback;
  459. int rv = 0;
  460. for (;;) {
  461. scoped_refptr<IOBufferWithSize> buf =
  462. base::MakeRefCounted<IOBufferWithSize>(4);
  463. rv = stream_->Read(buf.get(), buf->size(), callback.callback());
  464. if (rv == ERR_IO_PENDING) {
  465. rv = callback.WaitForResult();
  466. }
  467. EXPECT_LE(0, rv);
  468. if (rv <= 0)
  469. break;
  470. *total_bytes_read_ += rv;
  471. data_read_->append(buf->data(), rv);
  472. }
  473. }
  474. private:
  475. void OnComplete(int result) {
  476. DCHECK_LT(0, result);
  477. *total_bytes_written_ += result;
  478. int rv;
  479. if (*total_bytes_written_ != kTestDataSize) {
  480. // Recurse to finish writing all data.
  481. int total_bytes_written = 0, total_bytes_read = 0;
  482. std::string data_read;
  483. TestWriteReadCompletionCallback callback(
  484. stream_, &total_bytes_written, &total_bytes_read, &data_read);
  485. rv = stream_->Write(
  486. drainable_.get(), drainable_->BytesRemaining(), callback.callback());
  487. DCHECK_EQ(ERR_IO_PENDING, rv);
  488. rv = callback.WaitForResult();
  489. drainable_->DidConsume(total_bytes_written);
  490. *total_bytes_written_ += total_bytes_written;
  491. *total_bytes_read_ += total_bytes_read;
  492. *data_read_ += data_read;
  493. } else { // We're done writing all data. Start reading the data.
  494. TestInt64CompletionCallback callback64;
  495. EXPECT_THAT(stream_->Seek(0, callback64.callback()),
  496. IsError(ERR_IO_PENDING));
  497. {
  498. EXPECT_LE(0, callback64.WaitForResult());
  499. }
  500. }
  501. result_ = *total_bytes_written_;
  502. have_result_ = true;
  503. if (waiting_for_result_)
  504. base::RunLoop::QuitCurrentWhenIdleDeprecated();
  505. }
  506. int result_ = 0;
  507. bool have_result_ = false;
  508. bool waiting_for_result_ = false;
  509. raw_ptr<FileStream> stream_;
  510. raw_ptr<int> total_bytes_written_;
  511. raw_ptr<int> total_bytes_read_;
  512. raw_ptr<std::string> data_read_;
  513. scoped_refptr<DrainableIOBuffer> drainable_;
  514. };
  515. TEST_F(FileStreamTest, WriteRead) {
  516. int64_t file_size;
  517. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  518. auto stream =
  519. std::make_unique<FileStream>(base::ThreadTaskRunnerHandle::Get());
  520. int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
  521. base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
  522. TestCompletionCallback open_callback;
  523. int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
  524. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  525. EXPECT_THAT(open_callback.WaitForResult(), IsOk());
  526. TestInt64CompletionCallback callback64;
  527. EXPECT_THAT(stream->Seek(file_size, callback64.callback()),
  528. IsError(ERR_IO_PENDING));
  529. EXPECT_EQ(file_size, callback64.WaitForResult());
  530. int total_bytes_written = 0;
  531. int total_bytes_read = 0;
  532. std::string data_read;
  533. TestWriteReadCompletionCallback callback(stream.get(), &total_bytes_written,
  534. &total_bytes_read, &data_read);
  535. scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
  536. rv = stream->Write(buf.get(), buf->size(), callback.callback());
  537. if (rv == ERR_IO_PENDING)
  538. rv = callback.WaitForResult();
  539. EXPECT_LT(0, rv);
  540. EXPECT_EQ(kTestDataSize, total_bytes_written);
  541. callback.ValidateWrittenData();
  542. stream.reset();
  543. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  544. EXPECT_EQ(kTestDataSize * 2, file_size);
  545. EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
  546. const std::string kExpectedFileData =
  547. std::string(kTestData) + std::string(kTestData);
  548. EXPECT_EQ(kExpectedFileData, data_read);
  549. }
  550. class TestWriteCloseCompletionCallback {
  551. public:
  552. TestWriteCloseCompletionCallback(FileStream* stream, int* total_bytes_written)
  553. : stream_(stream),
  554. total_bytes_written_(total_bytes_written),
  555. drainable_(
  556. base::MakeRefCounted<DrainableIOBuffer>(CreateTestDataBuffer(),
  557. kTestDataSize)) {}
  558. TestWriteCloseCompletionCallback(const TestWriteCloseCompletionCallback&) =
  559. delete;
  560. TestWriteCloseCompletionCallback& operator=(
  561. const TestWriteCloseCompletionCallback&) = delete;
  562. int WaitForResult() {
  563. DCHECK(!waiting_for_result_);
  564. while (!have_result_) {
  565. waiting_for_result_ = true;
  566. base::RunLoop().Run();
  567. waiting_for_result_ = false;
  568. }
  569. have_result_ = false; // auto-reset for next callback
  570. return result_;
  571. }
  572. CompletionOnceCallback callback() {
  573. return base::BindOnce(&TestWriteCloseCompletionCallback::OnComplete,
  574. base::Unretained(this));
  575. }
  576. private:
  577. void OnComplete(int result) {
  578. DCHECK_LT(0, result);
  579. *total_bytes_written_ += result;
  580. int rv;
  581. if (*total_bytes_written_ != kTestDataSize) {
  582. // Recurse to finish writing all data.
  583. int total_bytes_written = 0;
  584. TestWriteCloseCompletionCallback callback(stream_, &total_bytes_written);
  585. rv = stream_->Write(
  586. drainable_.get(), drainable_->BytesRemaining(), callback.callback());
  587. DCHECK_EQ(ERR_IO_PENDING, rv);
  588. rv = callback.WaitForResult();
  589. drainable_->DidConsume(total_bytes_written);
  590. *total_bytes_written_ += total_bytes_written;
  591. }
  592. result_ = *total_bytes_written_;
  593. have_result_ = true;
  594. if (waiting_for_result_)
  595. base::RunLoop::QuitCurrentWhenIdleDeprecated();
  596. }
  597. int result_ = 0;
  598. bool have_result_ = false;
  599. bool waiting_for_result_ = false;
  600. raw_ptr<FileStream> stream_;
  601. raw_ptr<int> total_bytes_written_;
  602. scoped_refptr<DrainableIOBuffer> drainable_;
  603. };
  604. TEST_F(FileStreamTest, WriteClose) {
  605. int64_t file_size;
  606. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  607. auto stream =
  608. std::make_unique<FileStream>(base::ThreadTaskRunnerHandle::Get());
  609. int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
  610. base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
  611. TestCompletionCallback open_callback;
  612. int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
  613. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  614. EXPECT_THAT(open_callback.WaitForResult(), IsOk());
  615. TestInt64CompletionCallback callback64;
  616. EXPECT_THAT(stream->Seek(file_size, callback64.callback()),
  617. IsError(ERR_IO_PENDING));
  618. EXPECT_EQ(file_size, callback64.WaitForResult());
  619. int total_bytes_written = 0;
  620. TestWriteCloseCompletionCallback callback(stream.get(), &total_bytes_written);
  621. scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
  622. rv = stream->Write(buf.get(), buf->size(), callback.callback());
  623. if (rv == ERR_IO_PENDING)
  624. total_bytes_written = callback.WaitForResult();
  625. EXPECT_LT(0, total_bytes_written);
  626. EXPECT_EQ(kTestDataSize, total_bytes_written);
  627. stream.reset();
  628. EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
  629. EXPECT_EQ(kTestDataSize * 2, file_size);
  630. }
  631. TEST_F(FileStreamTest, OpenAndDelete) {
  632. base::Thread worker_thread("StreamTest");
  633. ASSERT_TRUE(worker_thread.Start());
  634. base::ScopedDisallowBlocking disallow_blocking;
  635. auto stream = std::make_unique<FileStream>(worker_thread.task_runner());
  636. int flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE |
  637. base::File::FLAG_ASYNC;
  638. TestCompletionCallback open_callback;
  639. int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
  640. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  641. // Delete the stream without waiting for the open operation to be
  642. // complete. Should be safe.
  643. stream.reset();
  644. // Force an operation through the worker.
  645. auto stream2 = std::make_unique<FileStream>(worker_thread.task_runner());
  646. TestCompletionCallback open_callback2;
  647. rv = stream2->Open(temp_file_path(), flags, open_callback2.callback());
  648. EXPECT_THAT(open_callback2.GetResult(rv), IsOk());
  649. stream2.reset();
  650. // open_callback won't be called.
  651. base::RunLoop().RunUntilIdle();
  652. EXPECT_FALSE(open_callback.have_result());
  653. }
  654. // Verify that Write() errors are mapped correctly.
  655. TEST_F(FileStreamTest, WriteError) {
  656. // Try opening file as read-only and then writing to it using FileStream.
  657. uint32_t flags =
  658. base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_ASYNC;
  659. base::File file(temp_file_path(), flags);
  660. ASSERT_TRUE(file.IsValid());
  661. auto stream = std::make_unique<FileStream>(
  662. std::move(file), base::ThreadTaskRunnerHandle::Get());
  663. scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(1);
  664. buf->data()[0] = 0;
  665. TestCompletionCallback callback;
  666. int rv = stream->Write(buf.get(), 1, callback.callback());
  667. if (rv == ERR_IO_PENDING)
  668. rv = callback.WaitForResult();
  669. EXPECT_LT(rv, 0);
  670. stream.reset();
  671. base::RunLoop().RunUntilIdle();
  672. }
  673. // Verify that Read() errors are mapped correctly.
  674. TEST_F(FileStreamTest, ReadError) {
  675. // Try opening file for write and then reading from it using FileStream.
  676. uint32_t flags =
  677. base::File::FLAG_OPEN | base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
  678. base::File file(temp_file_path(), flags);
  679. ASSERT_TRUE(file.IsValid());
  680. auto stream = std::make_unique<FileStream>(
  681. std::move(file), base::ThreadTaskRunnerHandle::Get());
  682. scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(1);
  683. TestCompletionCallback callback;
  684. int rv = stream->Read(buf.get(), 1, callback.callback());
  685. if (rv == ERR_IO_PENDING)
  686. rv = callback.WaitForResult();
  687. EXPECT_LT(rv, 0);
  688. stream.reset();
  689. base::RunLoop().RunUntilIdle();
  690. }
  691. #if BUILDFLAG(IS_WIN)
  692. // Verifies that a FileStream will close itself if it receives a File whose
  693. // async flag doesn't match the async state of the underlying handle.
  694. TEST_F(FileStreamTest, AsyncFlagMismatch) {
  695. // Open the test file without async, then make a File with the same sync
  696. // handle but with the async flag set to true.
  697. uint32_t flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
  698. base::File file(temp_file_path(), flags);
  699. base::File lying_file(file.TakePlatformFile(), true);
  700. ASSERT_TRUE(lying_file.IsValid());
  701. FileStream stream(std::move(lying_file), base::ThreadTaskRunnerHandle::Get());
  702. ASSERT_FALSE(stream.IsOpen());
  703. TestCompletionCallback callback;
  704. scoped_refptr<IOBufferWithSize> buf =
  705. base::MakeRefCounted<IOBufferWithSize>(4);
  706. int rv = stream.Read(buf.get(), buf->size(), callback.callback());
  707. EXPECT_THAT(callback.GetResult(rv), IsError(ERR_UNEXPECTED));
  708. }
  709. #endif
  710. #if BUILDFLAG(IS_ANDROID)
  711. // TODO(https://crbug.com/894599): flaky on both android and cronet bots.
  712. TEST_F(FileStreamTest, DISABLED_ContentUriRead) {
  713. base::FilePath test_dir;
  714. base::PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
  715. test_dir = test_dir.AppendASCII("net");
  716. test_dir = test_dir.AppendASCII("data");
  717. test_dir = test_dir.AppendASCII("file_stream_unittest");
  718. ASSERT_TRUE(base::PathExists(test_dir));
  719. base::FilePath image_file = test_dir.Append(FILE_PATH_LITERAL("red.png"));
  720. // Insert the image into MediaStore. MediaStore will do some conversions, and
  721. // return the content URI.
  722. base::FilePath path = base::InsertImageIntoMediaStore(image_file);
  723. EXPECT_TRUE(path.IsContentUri());
  724. EXPECT_TRUE(base::PathExists(path));
  725. int64_t file_size;
  726. EXPECT_TRUE(base::GetFileSize(path, &file_size));
  727. EXPECT_LT(0, file_size);
  728. FileStream stream(base::ThreadTaskRunnerHandle::Get());
  729. int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
  730. base::File::FLAG_ASYNC;
  731. TestCompletionCallback callback;
  732. int rv = stream.Open(path, flags, callback.callback());
  733. EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  734. EXPECT_THAT(callback.WaitForResult(), IsOk());
  735. int total_bytes_read = 0;
  736. std::string data_read;
  737. for (;;) {
  738. scoped_refptr<IOBufferWithSize> buf =
  739. base::MakeRefCounted<IOBufferWithSize>(4);
  740. rv = stream.Read(buf.get(), buf->size(), callback.callback());
  741. if (rv == ERR_IO_PENDING)
  742. rv = callback.WaitForResult();
  743. EXPECT_LE(0, rv);
  744. if (rv <= 0)
  745. break;
  746. total_bytes_read += rv;
  747. data_read.append(buf->data(), rv);
  748. }
  749. EXPECT_EQ(file_size, total_bytes_read);
  750. }
  751. #endif
  752. } // namespace
  753. } // namespace net