[go: nahoru, domu]

blob: 2ff4ee5e2748b9be04532906a1c37cb78aad3578 [file] [log] [blame]
Nigel Tao9a4532c2024-01-31 05:46:151// Copyright 2024 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ash/fileapi/diversion_file_manager.h"
6
7#include "base/files/file_util.h"
8#include "content/public/browser/browser_thread.h"
9#include "content/public/test/browser_task_environment.h"
10#include "net/base/io_buffer.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace ash {
14
15using FinishDivertingResult = DiversionFileManager::FinishDivertingResult;
16using StartDivertingResult = DiversionFileManager::StartDivertingResult;
17using StoppedReason = DiversionFileManager::StoppedReason;
18
19namespace {
20
21DiversionFileManager::Callback IncrementCounterCallback(
22 StoppedReason expected_stopped_reason,
23 const storage::FileSystemURL& expected_url,
24 int* counter,
25 int delta) {
26 return base::BindOnce(
27 [](StoppedReason expected_stopped_reason,
28 const storage::FileSystemURL& expected_url, int* counter, int delta,
29 StoppedReason stopped_reason, const storage::FileSystemURL& url,
30 base::ScopedFD scoped_fd, int64_t file_size, base::File::Error error) {
31 EXPECT_EQ(expected_stopped_reason, stopped_reason);
32 EXPECT_EQ(expected_url, url);
33 *counter += delta;
34 },
35 expected_stopped_reason, expected_url, counter, delta);
36}
37
38} // namespace
39
40class DiversionFileManagerTest : public testing::Test {
41 public:
42 DiversionFileManagerTest()
43 : task_environment_(base::test::TaskEnvironment::MainThreadType::IO,
44 base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
45
46 protected:
47 void SynchronousWrite(storage::FileStreamWriter& writer, std::string s) {
48 scoped_refptr<net::StringIOBuffer> buffer =
49 base::MakeRefCounted<net::StringIOBuffer>(s);
50 writer.Write(
51 buffer.get(), buffer->size(),
52 base::BindOnce([](base::RepeatingClosure quit_closure,
53 int byte_count_or_error_code) { quit_closure.Run(); },
54 task_environment_.QuitClosure()));
55 task_environment_.RunUntilQuit();
56 }
57
58 content::BrowserTaskEnvironment task_environment_;
59};
60
61TEST_F(DiversionFileManagerTest, ImplicitExplicitFinish) {
62 ASSERT_TRUE(
63 ::content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
64
65 scoped_refptr<DiversionFileManager> dfm =
66 base::MakeRefCounted<DiversionFileManager>();
67 storage::FileSystemURL bar_url = storage::FileSystemURL::CreateForTest(
68 GURL("filesystem:chrome-extension://abc/external/p/q/bar"));
69 storage::FileSystemURL foo_url = storage::FileSystemURL::CreateForTest(
70 GURL("filesystem:chrome-extension://abc/external/p/q/foo"));
71 EXPECT_FALSE(dfm->IsDiverting(bar_url));
72 EXPECT_FALSE(dfm->IsDiverting(foo_url));
73
74 int bar_counter = 0;
75 int foo_counter = 0;
76
77 ASSERT_EQ(
78 StartDivertingResult::kOK,
79 dfm->StartDiverting(bar_url, base::Seconds(28),
80 IncrementCounterCallback(StoppedReason::kImplicitIdle,
81 bar_url, &bar_counter, 1)));
82 ASSERT_EQ(
83 StartDivertingResult::kOK,
84 dfm->StartDiverting(foo_url, base::Seconds(32),
85 IncrementCounterCallback(StoppedReason::kImplicitIdle,
86 foo_url, &foo_counter, 10)));
87 EXPECT_TRUE(dfm->IsDiverting(bar_url));
88 EXPECT_TRUE(dfm->IsDiverting(foo_url));
89
90 task_environment_.FastForwardBy(base::Seconds(30));
91 EXPECT_FALSE(dfm->IsDiverting(bar_url));
92 EXPECT_TRUE(dfm->IsDiverting(foo_url));
93
94 ASSERT_EQ(FinishDivertingResult::kWasNotDiverting,
95 dfm->FinishDiverting(bar_url, IncrementCounterCallback(
96 StoppedReason::kExplicitFinish,
97 bar_url, &bar_counter, 100)));
98 ASSERT_EQ(FinishDivertingResult::kOK,
99 dfm->FinishDiverting(foo_url, IncrementCounterCallback(
100 StoppedReason::kExplicitFinish,
101 foo_url, &foo_counter, 1000)));
102 EXPECT_FALSE(dfm->IsDiverting(bar_url));
103 EXPECT_FALSE(dfm->IsDiverting(foo_url));
104
105 EXPECT_EQ(bar_counter, 1);
106 EXPECT_EQ(foo_counter, 1000);
107}
108
109TEST_F(DiversionFileManagerTest, ReaderKeepsDiversionAlive) {
110 ASSERT_TRUE(
111 ::content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
112
113 scoped_refptr<DiversionFileManager> dfm =
114 base::MakeRefCounted<DiversionFileManager>();
115 storage::FileSystemURL foo_url = storage::FileSystemURL::CreateForTest(
116 GURL("filesystem:chrome-extension://abc/external/p/q/foo"));
117
118 int foo_counter = 0;
119
120 ASSERT_EQ(
121 StartDivertingResult::kOK,
122 dfm->StartDiverting(foo_url, base::Seconds(15),
123 IncrementCounterCallback(StoppedReason::kImplicitIdle,
124 foo_url, &foo_counter, 1)));
125
126 task_environment_.FastForwardBy(base::Seconds(10));
127 EXPECT_TRUE(dfm->IsDiverting(foo_url));
128
129 std::unique_ptr<storage::FileStreamReader> reader =
130 dfm->CreateDivertedFileStreamReader(foo_url, 0);
131
132 task_environment_.FastForwardBy(base::Seconds(10));
133 EXPECT_TRUE(dfm->IsDiverting(foo_url));
134 EXPECT_EQ(foo_counter, 0);
135
136 task_environment_.FastForwardBy(base::Seconds(10));
137 EXPECT_TRUE(dfm->IsDiverting(foo_url));
138 EXPECT_EQ(foo_counter, 0);
139
140 reader.reset();
141
142 task_environment_.FastForwardBy(base::Seconds(10));
143 EXPECT_TRUE(dfm->IsDiverting(foo_url));
144 EXPECT_EQ(foo_counter, 0);
145
146 task_environment_.FastForwardBy(base::Seconds(10));
147 EXPECT_FALSE(dfm->IsDiverting(foo_url));
148 EXPECT_EQ(foo_counter, 1);
149}
150
151TEST_F(DiversionFileManagerTest, Writes) {
152 ASSERT_TRUE(
153 ::content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
154
155 scoped_refptr<DiversionFileManager> dfm =
156 base::MakeRefCounted<DiversionFileManager>();
157 storage::FileSystemURL foo_url = storage::FileSystemURL::CreateForTest(
158 GURL("filesystem:chrome-extension://abc/external/p/q/foo"));
159
160 base::FilePath temp_dir;
161 ASSERT_TRUE(base::GetTempDir(&temp_dir));
162 dfm->OverrideTmpfileDirForTesting(temp_dir);
163
164 static constexpr auto on_implicit_idle =
165 [](StoppedReason stopped_reason, const storage::FileSystemURL& url,
166 base::ScopedFD scoped_fd, int64_t file_size, base::File::Error error) {
167 // We shouldn't get here. We should get to on_explicit_finish instead.
Peter Boström01ab59a2024-08-15 02:39:49168 NOTREACHED();
Nigel Tao9a4532c2024-01-31 05:46:15169 };
170 ASSERT_EQ(StartDivertingResult::kOK,
171 dfm->StartDiverting(foo_url, base::Seconds(15),
172 base::BindOnce(on_implicit_idle)));
173
174 dfm->TruncateDivertedFile(foo_url, 0,
175 base::BindOnce([](base::File::Error result) {
176 EXPECT_EQ(base::File::FILE_OK, result);
177 }));
178
179 std::unique_ptr<storage::FileStreamWriter> writer =
180 dfm->CreateDivertedFileStreamWriter(foo_url, 0);
181
182 SynchronousWrite(*writer, "hi ");
183 dfm->GetDivertedFileInfo(
184 foo_url, {storage::FileSystemOperation::GetMetadataField::kSize},
185 base::BindOnce(
186 [](base::File::Error result, const base::File::Info& file_info) {
187 EXPECT_EQ(base::File::FILE_OK, result);
188 EXPECT_EQ(3, file_info.size);
189 }));
190
191 task_environment_.FastForwardBy(base::Seconds(20));
192 EXPECT_TRUE(dfm->IsDiverting(foo_url));
193
194 SynchronousWrite(*writer, "there.");
195 dfm->GetDivertedFileInfo(
196 foo_url, {storage::FileSystemOperation::GetMetadataField::kSize},
197 base::BindOnce(
198 [](base::File::Error result, const base::File::Info& file_info) {
199 EXPECT_EQ(base::File::FILE_OK, result);
200 EXPECT_EQ(9, file_info.size);
201 }));
202
203 task_environment_.FastForwardBy(base::Seconds(20));
204 EXPECT_TRUE(dfm->IsDiverting(foo_url));
205
206 bool on_explicit_finish_called = false;
207 static constexpr auto on_explicit_finish =
208 [](bool* called, StoppedReason stopped_reason,
209 const storage::FileSystemURL& url, base::ScopedFD scoped_fd,
210 int64_t file_size, base::File::Error error) {
211 ASSERT_TRUE(scoped_fd.is_valid());
danakj5807186462024-06-06 20:10:37212 EXPECT_EQ(file_size, 9u);
Nigel Tao9a4532c2024-01-31 05:46:15213 EXPECT_EQ(base::File::FILE_OK, error);
214 char buf[9] = {0};
danakj5807186462024-06-06 20:10:37215 EXPECT_TRUE(base::ReadFromFD(scoped_fd.get(), buf));
216 EXPECT_EQ(buf, base::span_from_cstring("hi there."));
Nigel Tao9a4532c2024-01-31 05:46:15217 *called = true;
218 };
219 ASSERT_EQ(FinishDivertingResult::kOK,
220 dfm->FinishDiverting(foo_url,
221 base::BindOnce(on_explicit_finish,
222 &on_explicit_finish_called)));
223
224 task_environment_.FastForwardBy(base::Seconds(20));
225 EXPECT_FALSE(dfm->IsDiverting(foo_url));
226 EXPECT_FALSE(on_explicit_finish_called);
227
228 writer.reset();
229 EXPECT_FALSE(dfm->IsDiverting(foo_url));
230 EXPECT_TRUE(on_explicit_finish_called);
231}
232
233} // namespace ash