1 // Copyright 2014 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.
5 #include "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.h"
10 #include "base/files/file.h"
11 #include "base/files/file_path.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/run_loop.h"
16 #include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
17 #include "chrome/browser/chromeos/file_system_provider/service.h"
18 #include "chrome/browser/chromeos/file_system_provider/service_factory.h"
19 #include "chrome/test/base/testing_browser_process.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "chrome/test/base/testing_profile_manager.h"
22 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "content/public/test/test_file_system_context.h"
24 #include "extensions/browser/extension_registry.h"
25 #include "net/base/io_buffer.h"
26 #include "net/base/net_errors.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "webkit/browser/fileapi/async_file_util.h"
29 #include "webkit/browser/fileapi/external_mount_points.h"
30 #include "webkit/browser/fileapi/file_system_url.h"
33 namespace file_system_provider {
36 const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
37 const char kFileSystemId[] = "testing-file-system";
39 // Logs callbacks invocations on the file stream reader.
42 EventLogger() : weak_ptr_factory_(this) {}
43 virtual ~EventLogger() {}
45 void OnRead(int result) { results_.push_back(result); }
46 void OnGetLength(int64 result) { results_.push_back(result); }
48 base::WeakPtr<EventLogger> GetWeakPtr() {
49 return weak_ptr_factory_.GetWeakPtr();
52 const std::vector<int64>& results() const { return results_; }
55 std::vector<int64> results_;
56 base::WeakPtrFactory<EventLogger> weak_ptr_factory_;
58 DISALLOW_COPY_AND_ASSIGN(EventLogger);
61 // Creates a cracked FileSystemURL for tests.
62 fileapi::FileSystemURL CreateFileSystemURL(const std::string& mount_point_name,
63 const base::FilePath& file_path) {
64 const std::string origin = std::string("chrome-extension://") + kExtensionId;
65 const fileapi::ExternalMountPoints* const mount_points =
66 fileapi::ExternalMountPoints::GetSystemInstance();
67 return mount_points->CreateCrackedFileSystemURL(
69 fileapi::kFileSystemTypeExternal,
70 base::FilePath::FromUTF8Unsafe(mount_point_name).Append(file_path));
73 // Creates a Service instance. Used to be able to destroy the service in
75 KeyedService* CreateService(content::BrowserContext* context) {
76 return new Service(Profile::FromBrowserContext(context),
77 extensions::ExtensionRegistry::Get(context));
82 class FileSystemProviderFileStreamReader : public testing::Test {
84 FileSystemProviderFileStreamReader() {}
85 virtual ~FileSystemProviderFileStreamReader() {}
87 virtual void SetUp() OVERRIDE {
88 ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
89 profile_manager_.reset(
90 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
91 ASSERT_TRUE(profile_manager_->SetUp());
92 profile_ = profile_manager_->CreateTestingProfile("testing-profile");
94 ServiceFactory::GetInstance()->SetTestingFactory(profile_, &CreateService);
95 Service* service = Service::Get(profile_); // Owned by its factory.
96 service->SetFileSystemFactoryForTesting(
97 base::Bind(&FakeProvidedFileSystem::Create));
99 const bool result = service->MountFileSystem(kExtensionId,
101 "Testing File System",
102 false /* writable */);
104 FakeProvidedFileSystem* provided_file_system =
105 static_cast<FakeProvidedFileSystem*>(
106 service->GetProvidedFileSystem(kExtensionId, kFileSystemId));
107 ASSERT_TRUE(provided_file_system);
108 ASSERT_TRUE(provided_file_system->GetEntry(
109 base::FilePath::FromUTF8Unsafe(kFakeFilePath), &fake_file_));
110 const ProvidedFileSystemInfo& file_system_info =
111 service->GetProvidedFileSystem(kExtensionId, kFileSystemId)
112 ->GetFileSystemInfo();
113 const std::string mount_point_name =
114 file_system_info.mount_path().BaseName().AsUTF8Unsafe();
116 file_url_ = CreateFileSystemURL(
117 mount_point_name, base::FilePath::FromUTF8Unsafe(kFakeFilePath + 1));
118 ASSERT_TRUE(file_url_.is_valid());
119 wrong_file_url_ = CreateFileSystemURL(
120 mount_point_name, base::FilePath::FromUTF8Unsafe("im-not-here.txt"));
121 ASSERT_TRUE(wrong_file_url_.is_valid());
124 virtual void TearDown() OVERRIDE {
125 // Setting the testing factory to NULL will destroy the created service
126 // associated with the testing profile.
127 ServiceFactory::GetInstance()->SetTestingFactory(profile_, NULL);
130 content::TestBrowserThreadBundle thread_bundle_;
131 base::ScopedTempDir data_dir_;
132 scoped_ptr<TestingProfileManager> profile_manager_;
133 TestingProfile* profile_; // Owned by TestingProfileManager.
134 FakeEntry fake_file_;
135 fileapi::FileSystemURL file_url_;
136 fileapi::FileSystemURL wrong_file_url_;
139 TEST_F(FileSystemProviderFileStreamReader, Read_AllAtOnce) {
142 const int64 initial_offset = 0;
143 FileStreamReader reader(
144 NULL, file_url_, initial_offset, fake_file_.metadata.modification_time);
145 scoped_refptr<net::IOBuffer> io_buffer(
146 new net::IOBuffer(fake_file_.metadata.size));
149 reader.Read(io_buffer.get(),
150 fake_file_.metadata.size,
151 base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
152 EXPECT_EQ(net::ERR_IO_PENDING, result);
153 base::RunLoop().RunUntilIdle();
155 ASSERT_EQ(1u, logger.results().size());
156 EXPECT_LT(0, logger.results()[0]);
157 EXPECT_EQ(fake_file_.metadata.size, logger.results()[0]);
159 std::string buffer_as_string(io_buffer->data(), fake_file_.metadata.size);
160 EXPECT_EQ(fake_file_.contents, buffer_as_string);
163 TEST_F(FileSystemProviderFileStreamReader, Read_WrongFile) {
166 const int64 initial_offset = 0;
167 FileStreamReader reader(NULL,
170 fake_file_.metadata.modification_time);
171 scoped_refptr<net::IOBuffer> io_buffer(
172 new net::IOBuffer(fake_file_.metadata.size));
175 reader.Read(io_buffer.get(),
176 fake_file_.metadata.size,
177 base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
178 EXPECT_EQ(net::ERR_IO_PENDING, result);
179 base::RunLoop().RunUntilIdle();
181 ASSERT_EQ(1u, logger.results().size());
182 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, logger.results()[0]);
185 TEST_F(FileSystemProviderFileStreamReader, Read_InChunks) {
188 const int64 initial_offset = 0;
189 FileStreamReader reader(
190 NULL, file_url_, initial_offset, fake_file_.metadata.modification_time);
192 for (int64 offset = 0; offset < fake_file_.metadata.size; ++offset) {
193 scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(1));
195 reader.Read(io_buffer.get(),
197 base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
198 EXPECT_EQ(net::ERR_IO_PENDING, result);
199 base::RunLoop().RunUntilIdle();
200 ASSERT_EQ(offset + 1, static_cast<int64>(logger.results().size()));
201 EXPECT_EQ(1, logger.results()[offset]);
202 EXPECT_EQ(fake_file_.contents[offset], io_buffer->data()[0]);
206 TEST_F(FileSystemProviderFileStreamReader, Read_Slice) {
209 // Trim first 3 and last 3 characters.
210 const int64 initial_offset = 3;
211 const int length = fake_file_.metadata.size - initial_offset - 3;
212 ASSERT_GT(fake_file_.metadata.size, initial_offset);
213 ASSERT_LT(0, length);
215 FileStreamReader reader(
216 NULL, file_url_, initial_offset, fake_file_.metadata.modification_time);
217 scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(length));
220 reader.Read(io_buffer.get(),
222 base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
223 EXPECT_EQ(net::ERR_IO_PENDING, result);
224 base::RunLoop().RunUntilIdle();
226 ASSERT_EQ(1u, logger.results().size());
227 EXPECT_EQ(length, logger.results()[0]);
229 std::string buffer_as_string(io_buffer->data(), length);
230 std::string expected_buffer(fake_file_.contents.data() + initial_offset,
232 EXPECT_EQ(expected_buffer, buffer_as_string);
235 TEST_F(FileSystemProviderFileStreamReader, Read_Beyond) {
238 // Request reading 1KB more than available.
239 const int64 initial_offset = 0;
240 const int length = fake_file_.metadata.size + 1024;
242 FileStreamReader reader(
243 NULL, file_url_, initial_offset, fake_file_.metadata.modification_time);
244 scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(length));
247 reader.Read(io_buffer.get(),
249 base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
250 EXPECT_EQ(net::ERR_IO_PENDING, result);
251 base::RunLoop().RunUntilIdle();
253 ASSERT_EQ(1u, logger.results().size());
254 EXPECT_LT(0, logger.results()[0]);
255 EXPECT_EQ(fake_file_.metadata.size, logger.results()[0]);
257 std::string buffer_as_string(io_buffer->data(), fake_file_.metadata.size);
258 EXPECT_EQ(fake_file_.contents, buffer_as_string);
261 TEST_F(FileSystemProviderFileStreamReader, Read_ModifiedFile) {
264 const int64 initial_offset = 0;
265 FileStreamReader reader(NULL, file_url_, initial_offset, base::Time::Max());
267 scoped_refptr<net::IOBuffer> io_buffer(
268 new net::IOBuffer(fake_file_.metadata.size));
270 reader.Read(io_buffer.get(),
271 fake_file_.metadata.size,
272 base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
274 EXPECT_EQ(net::ERR_IO_PENDING, result);
275 base::RunLoop().RunUntilIdle();
277 ASSERT_EQ(1u, logger.results().size());
278 EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, logger.results()[0]);
281 TEST_F(FileSystemProviderFileStreamReader, Read_ExpectedModificationTimeNull) {
284 const int64 initial_offset = 0;
285 FileStreamReader reader(NULL, file_url_, initial_offset, base::Time());
287 scoped_refptr<net::IOBuffer> io_buffer(
288 new net::IOBuffer(fake_file_.metadata.size));
290 reader.Read(io_buffer.get(),
291 fake_file_.metadata.size,
292 base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
294 EXPECT_EQ(net::ERR_IO_PENDING, result);
295 base::RunLoop().RunUntilIdle();
297 ASSERT_EQ(1u, logger.results().size());
298 EXPECT_EQ(fake_file_.metadata.size, logger.results()[0]);
300 std::string buffer_as_string(io_buffer->data(), fake_file_.metadata.size);
301 EXPECT_EQ(fake_file_.contents, buffer_as_string);
304 TEST_F(FileSystemProviderFileStreamReader, GetLength) {
307 const int64 initial_offset = 0;
308 FileStreamReader reader(
309 NULL, file_url_, initial_offset, fake_file_.metadata.modification_time);
311 const int result = reader.GetLength(
312 base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
313 EXPECT_EQ(net::ERR_IO_PENDING, result);
314 base::RunLoop().RunUntilIdle();
316 ASSERT_EQ(1u, logger.results().size());
317 EXPECT_LT(0, logger.results()[0]);
318 EXPECT_EQ(fake_file_.metadata.size, logger.results()[0]);
321 TEST_F(FileSystemProviderFileStreamReader, GetLength_WrongFile) {
324 const int64 initial_offset = 0;
325 FileStreamReader reader(NULL,
328 fake_file_.metadata.modification_time);
330 const int result = reader.GetLength(
331 base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
332 EXPECT_EQ(net::ERR_IO_PENDING, result);
333 base::RunLoop().RunUntilIdle();
335 ASSERT_EQ(1u, logger.results().size());
336 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, logger.results()[0]);
339 TEST_F(FileSystemProviderFileStreamReader, GetLength_ModifiedFile) {
342 const int64 initial_offset = 0;
343 FileStreamReader reader(NULL, file_url_, initial_offset, base::Time::Max());
345 const int result = reader.GetLength(
346 base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
347 EXPECT_EQ(net::ERR_IO_PENDING, result);
348 base::RunLoop().RunUntilIdle();
350 ASSERT_EQ(1u, logger.results().size());
351 EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, logger.results()[0]);
354 TEST_F(FileSystemProviderFileStreamReader,
355 GetLength_ExpectedModificationTimeNull) {
358 const int64 initial_offset = 0;
359 FileStreamReader reader(NULL, file_url_, initial_offset, base::Time());
361 const int result = reader.GetLength(
362 base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
363 EXPECT_EQ(net::ERR_IO_PENDING, result);
364 base::RunLoop().RunUntilIdle();
366 ASSERT_EQ(1u, logger.results().size());
367 EXPECT_LT(0, logger.results()[0]);
368 EXPECT_EQ(fake_file_.metadata.size, logger.results()[0]);
371 } // namespace file_system_provider
372 } // namespace chromeos