file_stream_reader_unittest.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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. 4 5#include "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.h" 6 7#include <string> 8#include <vector> 9 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" 31 32namespace chromeos { 33namespace file_system_provider { 34namespace { 35 36const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj"; 37const char kFileSystemId[] = "testing-file-system"; 38 39// Logs callbacks invocations on the file stream reader. 40class EventLogger { 41 public: 42 EventLogger() : weak_ptr_factory_(this) {} 43 virtual ~EventLogger() {} 44 45 void OnRead(int result) { results_.push_back(result); } 46 void OnGetLength(int64 result) { results_.push_back(result); } 47 48 base::WeakPtr<EventLogger> GetWeakPtr() { 49 return weak_ptr_factory_.GetWeakPtr(); 50 } 51 52 const std::vector<int64>& results() const { return results_; } 53 54 private: 55 std::vector<int64> results_; 56 base::WeakPtrFactory<EventLogger> weak_ptr_factory_; 57 58 DISALLOW_COPY_AND_ASSIGN(EventLogger); 59}; 60 61// Creates a cracked FileSystemURL for tests. 62storage::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 storage::ExternalMountPoints* const mount_points = 66 storage::ExternalMountPoints::GetSystemInstance(); 67 return mount_points->CreateCrackedFileSystemURL( 68 GURL(origin), 69 storage::kFileSystemTypeExternal, 70 base::FilePath::FromUTF8Unsafe(mount_point_name).Append(file_path)); 71} 72 73// Creates a Service instance. Used to be able to destroy the service in 74// TearDown(). 75KeyedService* CreateService(content::BrowserContext* context) { 76 return new Service(Profile::FromBrowserContext(context), 77 extensions::ExtensionRegistry::Get(context)); 78} 79 80} // namespace 81 82class FileSystemProviderFileStreamReader : public testing::Test { 83 protected: 84 FileSystemProviderFileStreamReader() {} 85 virtual ~FileSystemProviderFileStreamReader() {} 86 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"); 93 94 ServiceFactory::GetInstance()->SetTestingFactory(profile_, &CreateService); 95 Service* service = Service::Get(profile_); // Owned by its factory. 96 service->SetFileSystemFactoryForTesting( 97 base::Bind(&FakeProvidedFileSystem::Create)); 98 99 const bool result = service->MountFileSystem(kExtensionId, 100 kFileSystemId, 101 "Testing File System", 102 false /* writable */); 103 ASSERT_TRUE(result); 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(); 115 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()); 122 } 123 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); 128 } 129 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 storage::FileSystemURL file_url_; 136 storage::FileSystemURL wrong_file_url_; 137}; 138 139TEST_F(FileSystemProviderFileStreamReader, Read_AllAtOnce) { 140 EventLogger logger; 141 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)); 147 148 const int result = 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(); 154 155 ASSERT_EQ(1u, logger.results().size()); 156 EXPECT_LT(0, logger.results()[0]); 157 EXPECT_EQ(fake_file_.metadata.size, logger.results()[0]); 158 159 std::string buffer_as_string(io_buffer->data(), fake_file_.metadata.size); 160 EXPECT_EQ(fake_file_.contents, buffer_as_string); 161} 162 163TEST_F(FileSystemProviderFileStreamReader, Read_WrongFile) { 164 EventLogger logger; 165 166 const int64 initial_offset = 0; 167 FileStreamReader reader(NULL, 168 wrong_file_url_, 169 initial_offset, 170 fake_file_.metadata.modification_time); 171 scoped_refptr<net::IOBuffer> io_buffer( 172 new net::IOBuffer(fake_file_.metadata.size)); 173 174 const int result = 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(); 180 181 ASSERT_EQ(1u, logger.results().size()); 182 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, logger.results()[0]); 183} 184 185TEST_F(FileSystemProviderFileStreamReader, Read_InChunks) { 186 EventLogger logger; 187 188 const int64 initial_offset = 0; 189 FileStreamReader reader( 190 NULL, file_url_, initial_offset, fake_file_.metadata.modification_time); 191 192 for (int64 offset = 0; offset < fake_file_.metadata.size; ++offset) { 193 scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(1)); 194 const int result = 195 reader.Read(io_buffer.get(), 196 1, 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]); 203 } 204} 205 206TEST_F(FileSystemProviderFileStreamReader, Read_Slice) { 207 EventLogger logger; 208 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); 214 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)); 218 219 const int result = 220 reader.Read(io_buffer.get(), 221 length, 222 base::Bind(&EventLogger::OnRead, logger.GetWeakPtr())); 223 EXPECT_EQ(net::ERR_IO_PENDING, result); 224 base::RunLoop().RunUntilIdle(); 225 226 ASSERT_EQ(1u, logger.results().size()); 227 EXPECT_EQ(length, logger.results()[0]); 228 229 std::string buffer_as_string(io_buffer->data(), length); 230 std::string expected_buffer(fake_file_.contents.data() + initial_offset, 231 length); 232 EXPECT_EQ(expected_buffer, buffer_as_string); 233} 234 235TEST_F(FileSystemProviderFileStreamReader, Read_Beyond) { 236 EventLogger logger; 237 238 // Request reading 1KB more than available. 239 const int64 initial_offset = 0; 240 const int length = fake_file_.metadata.size + 1024; 241 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)); 245 246 const int result = 247 reader.Read(io_buffer.get(), 248 length, 249 base::Bind(&EventLogger::OnRead, logger.GetWeakPtr())); 250 EXPECT_EQ(net::ERR_IO_PENDING, result); 251 base::RunLoop().RunUntilIdle(); 252 253 ASSERT_EQ(1u, logger.results().size()); 254 EXPECT_LT(0, logger.results()[0]); 255 EXPECT_EQ(fake_file_.metadata.size, logger.results()[0]); 256 257 std::string buffer_as_string(io_buffer->data(), fake_file_.metadata.size); 258 EXPECT_EQ(fake_file_.contents, buffer_as_string); 259} 260 261TEST_F(FileSystemProviderFileStreamReader, Read_ModifiedFile) { 262 EventLogger logger; 263 264 const int64 initial_offset = 0; 265 FileStreamReader reader(NULL, file_url_, initial_offset, base::Time::Max()); 266 267 scoped_refptr<net::IOBuffer> io_buffer( 268 new net::IOBuffer(fake_file_.metadata.size)); 269 const int result = 270 reader.Read(io_buffer.get(), 271 fake_file_.metadata.size, 272 base::Bind(&EventLogger::OnRead, logger.GetWeakPtr())); 273 274 EXPECT_EQ(net::ERR_IO_PENDING, result); 275 base::RunLoop().RunUntilIdle(); 276 277 ASSERT_EQ(1u, logger.results().size()); 278 EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, logger.results()[0]); 279} 280 281TEST_F(FileSystemProviderFileStreamReader, Read_ExpectedModificationTimeNull) { 282 EventLogger logger; 283 284 const int64 initial_offset = 0; 285 FileStreamReader reader(NULL, file_url_, initial_offset, base::Time()); 286 287 scoped_refptr<net::IOBuffer> io_buffer( 288 new net::IOBuffer(fake_file_.metadata.size)); 289 const int result = 290 reader.Read(io_buffer.get(), 291 fake_file_.metadata.size, 292 base::Bind(&EventLogger::OnRead, logger.GetWeakPtr())); 293 294 EXPECT_EQ(net::ERR_IO_PENDING, result); 295 base::RunLoop().RunUntilIdle(); 296 297 ASSERT_EQ(1u, logger.results().size()); 298 EXPECT_EQ(fake_file_.metadata.size, logger.results()[0]); 299 300 std::string buffer_as_string(io_buffer->data(), fake_file_.metadata.size); 301 EXPECT_EQ(fake_file_.contents, buffer_as_string); 302} 303 304TEST_F(FileSystemProviderFileStreamReader, GetLength) { 305 EventLogger logger; 306 307 const int64 initial_offset = 0; 308 FileStreamReader reader( 309 NULL, file_url_, initial_offset, fake_file_.metadata.modification_time); 310 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(); 315 316 ASSERT_EQ(1u, logger.results().size()); 317 EXPECT_LT(0, logger.results()[0]); 318 EXPECT_EQ(fake_file_.metadata.size, logger.results()[0]); 319} 320 321TEST_F(FileSystemProviderFileStreamReader, GetLength_WrongFile) { 322 EventLogger logger; 323 324 const int64 initial_offset = 0; 325 FileStreamReader reader(NULL, 326 wrong_file_url_, 327 initial_offset, 328 fake_file_.metadata.modification_time); 329 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(); 334 335 ASSERT_EQ(1u, logger.results().size()); 336 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, logger.results()[0]); 337} 338 339TEST_F(FileSystemProviderFileStreamReader, GetLength_ModifiedFile) { 340 EventLogger logger; 341 342 const int64 initial_offset = 0; 343 FileStreamReader reader(NULL, file_url_, initial_offset, base::Time::Max()); 344 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(); 349 350 ASSERT_EQ(1u, logger.results().size()); 351 EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, logger.results()[0]); 352} 353 354TEST_F(FileSystemProviderFileStreamReader, 355 GetLength_ExpectedModificationTimeNull) { 356 EventLogger logger; 357 358 const int64 initial_offset = 0; 359 FileStreamReader reader(NULL, file_url_, initial_offset, base::Time()); 360 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(); 365 366 ASSERT_EQ(1u, logger.results().size()); 367 EXPECT_LT(0, logger.results()[0]); 368 EXPECT_EQ(fake_file_.metadata.size, logger.results()[0]); 369} 370 371} // namespace file_system_provider 372} // namespace chromeos 373