| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/fileapi/copy_from_fd.h" |
| |
| #include <unistd.h> |
| |
| #include <memory> |
| |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_file.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "net/base/io_buffer.h" |
| #include "storage/browser/file_system/file_stream_writer.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| class FakeFileStreamWriter : public storage::FileStreamWriter { |
| public: |
| int Write(net::IOBuffer* buf, |
| int buf_len, |
| net::CompletionOnceCallback callback) override { |
| CHECK(::content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| data_.append(buf->data(), buf->size()); |
| return buf->size(); |
| } |
| |
| int Cancel(net::CompletionOnceCallback callback) override { |
| CHECK(::content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| return net::ERR_NOT_IMPLEMENTED; |
| } |
| |
| int Flush(storage::FlushMode flush_mode, |
| net::CompletionOnceCallback callback) override { |
| CHECK(::content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| flushed_ = true; |
| return net::OK; |
| } |
| |
| std::string data_; |
| bool flushed_ = false; |
| }; |
| |
| } // namespace |
| |
| TEST(CopyFromFileDescriptorTest, Basic) { |
| content::BrowserTaskEnvironment task_environment( |
| base::test::TaskEnvironment::MainThreadType::IO); |
| ASSERT_TRUE( |
| ::content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| |
| base::ScopedTempDir temp_dir; |
| ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| |
| base::FilePath temp_file_path; |
| base::ScopedFD scoped_fd = base::CreateAndOpenFdForTemporaryFileInDir( |
| temp_dir.GetPath(), &temp_file_path); |
| ASSERT_TRUE(scoped_fd.is_valid()); |
| ASSERT_EQ(write(scoped_fd.get(), "abcdefghij", 10), 10); |
| ASSERT_EQ(lseek(scoped_fd.get(), 3, SEEK_SET), 3); |
| |
| auto fs_writer = std::make_unique<FakeFileStreamWriter>(); |
| |
| auto callback = base::BindOnce( |
| [](int expected_fd, FakeFileStreamWriter* expected_fs_writer, |
| base::RepeatingClosure quit_closure, base::ScopedFD ret_scoped_fd, |
| std::unique_ptr<storage::FileStreamWriter> ret_fs_writer, |
| net::Error ret_error) { |
| ASSERT_TRUE( |
| ::content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| ASSERT_EQ(ret_scoped_fd.get(), expected_fd); |
| ASSERT_EQ(ret_fs_writer.get(), expected_fs_writer); |
| EXPECT_EQ(ret_error, net::OK); |
| EXPECT_EQ(expected_fs_writer->data_.size(), 10u - 3u); |
| EXPECT_EQ(expected_fs_writer->data_, "defghij"); |
| EXPECT_TRUE(expected_fs_writer->flushed_); |
| quit_closure.Run(); |
| }, |
| scoped_fd.get(), fs_writer.get(), task_environment.QuitClosure()); |
| |
| CopyFromFileDescriptor(std::move(scoped_fd), std::move(fs_writer), |
| storage::FlushPolicy::FLUSH_ON_COMPLETION, |
| std::move(callback)); |
| task_environment.RunUntilQuit(); |
| } |
| |
| } // namespace ash |