file_stream_reader_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 <string>
6#include <vector>
7
8#include "base/files/file.h"
9#include "base/files/file_path.h"
10#include "base/files/scoped_temp_dir.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/memory/weak_ptr.h"
13#include "base/platform_file.h"
14#include "base/run_loop.h"
15#include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
16#include "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.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.
62fileapi::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(
68      GURL(origin),
69      fileapi::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(
100        kExtensionId, kFileSystemId, "Testing File System");
101    ASSERT_TRUE(result);
102    const ProvidedFileSystemInfo& file_system_info =
103        service->GetProvidedFileSystem(kExtensionId, kFileSystemId)
104            ->GetFileSystemInfo();
105    const std::string mount_point_name =
106        file_system_info.mount_path().BaseName().AsUTF8Unsafe();
107
108    file_url_ = CreateFileSystemURL(
109        mount_point_name, base::FilePath::FromUTF8Unsafe(kFakeFilePath + 1));
110    ASSERT_TRUE(file_url_.is_valid());
111    wrong_file_url_ = CreateFileSystemURL(
112        mount_point_name, base::FilePath::FromUTF8Unsafe("im-not-here.txt"));
113    ASSERT_TRUE(wrong_file_url_.is_valid());
114  }
115
116  virtual void TearDown() OVERRIDE {
117    // Setting the testing factory to NULL will destroy the created service
118    // associated with the testing profile.
119    ServiceFactory::GetInstance()->SetTestingFactory(profile_, NULL);
120  }
121
122  content::TestBrowserThreadBundle thread_bundle_;
123  base::ScopedTempDir data_dir_;
124  scoped_ptr<TestingProfileManager> profile_manager_;
125  TestingProfile* profile_;  // Owned by TestingProfileManager.
126  fileapi::FileSystemURL file_url_;
127  fileapi::FileSystemURL wrong_file_url_;
128};
129
130TEST_F(FileSystemProviderFileStreamReader, Read_AllAtOnce) {
131  EventLogger logger;
132
133  const int64 initial_offset = 0;
134  FileStreamReader reader(NULL,
135                          file_url_,
136                          initial_offset,
137                          base::Time::Now());  // Not used yet.
138  scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(kFakeFileSize));
139
140  const int result =
141      reader.Read(io_buffer.get(),
142                  kFakeFileSize,
143                  base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
144  EXPECT_EQ(net::ERR_IO_PENDING, result);
145  base::RunLoop().RunUntilIdle();
146
147  ASSERT_EQ(1u, logger.results().size());
148  EXPECT_LT(0, logger.results()[0]);
149  EXPECT_EQ(kFakeFileSize, static_cast<size_t>(logger.results()[0]));
150
151  std::string buffer_as_string(io_buffer->data(), kFakeFileSize);
152  EXPECT_EQ(kFakeFileText, buffer_as_string);
153}
154
155TEST_F(FileSystemProviderFileStreamReader, Read_WrongFile) {
156  EventLogger logger;
157
158  const int64 initial_offset = 0;
159  FileStreamReader reader(NULL,
160                          wrong_file_url_,
161                          initial_offset,
162                          base::Time::Now());  // Not used yet.
163  scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(kFakeFileSize));
164
165  const int result =
166      reader.Read(io_buffer.get(),
167                  kFakeFileSize,
168                  base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
169  EXPECT_EQ(net::ERR_IO_PENDING, result);
170  base::RunLoop().RunUntilIdle();
171
172  ASSERT_EQ(1u, logger.results().size());
173  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, logger.results()[0]);
174}
175
176TEST_F(FileSystemProviderFileStreamReader, Read_InChunks) {
177  EventLogger logger;
178
179  const int64 initial_offset = 0;
180  FileStreamReader reader(NULL,
181                          file_url_,
182                          initial_offset,
183                          base::Time::Now());  // Not used yet.
184
185  for (size_t offset = 0; offset < kFakeFileSize; ++offset) {
186    scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(1));
187    const int result =
188        reader.Read(io_buffer.get(),
189                    1,
190                    base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
191    EXPECT_EQ(net::ERR_IO_PENDING, result);
192    base::RunLoop().RunUntilIdle();
193    ASSERT_EQ(offset + 1u, logger.results().size());
194    EXPECT_EQ(1, logger.results()[offset]);
195    EXPECT_EQ(kFakeFileText[offset], io_buffer->data()[0]);
196  }
197}
198
199TEST_F(FileSystemProviderFileStreamReader, Read_Slice) {
200  EventLogger logger;
201
202  // Trim first 3 and last 3 characters.
203  const int64 initial_offset = 3;
204  const int length = static_cast<int>(kFakeFileSize) - initial_offset - 3;
205  ASSERT_GT(kFakeFileSize, static_cast<size_t>(initial_offset));
206  ASSERT_LT(0, length);
207
208  FileStreamReader reader(NULL,
209                          file_url_,
210                          initial_offset,
211                          base::Time::Now());  // Not used yet.
212  scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(length));
213
214  const int result =
215      reader.Read(io_buffer.get(),
216                  length,
217                  base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
218  EXPECT_EQ(net::ERR_IO_PENDING, result);
219  base::RunLoop().RunUntilIdle();
220
221  ASSERT_EQ(1u, logger.results().size());
222  EXPECT_EQ(length, logger.results()[0]);
223
224  std::string buffer_as_string(io_buffer->data(), length);
225  std::string expected_buffer(kFakeFileText + initial_offset, length);
226  EXPECT_EQ(expected_buffer, buffer_as_string);
227}
228
229TEST_F(FileSystemProviderFileStreamReader, Read_Beyond) {
230  EventLogger logger;
231
232  // Request reading 1KB more than available.
233  const int64 initial_offset = 0;
234  const int length = static_cast<int>(kFakeFileSize) + 1024;
235
236  FileStreamReader reader(NULL,
237                          file_url_,
238                          initial_offset,
239                          base::Time::Now());  // Not used yet.
240  scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(length));
241
242  const int result =
243      reader.Read(io_buffer.get(),
244                  length,
245                  base::Bind(&EventLogger::OnRead, logger.GetWeakPtr()));
246  EXPECT_EQ(net::ERR_IO_PENDING, result);
247  base::RunLoop().RunUntilIdle();
248
249  ASSERT_EQ(1u, logger.results().size());
250  EXPECT_LT(0, logger.results()[0]);
251  EXPECT_EQ(kFakeFileSize, static_cast<size_t>(logger.results()[0]));
252
253  std::string buffer_as_string(io_buffer->data(), kFakeFileSize);
254  EXPECT_EQ(kFakeFileText, buffer_as_string);
255}
256
257TEST_F(FileSystemProviderFileStreamReader, GetLength) {
258  EventLogger logger;
259
260  const int64 initial_offset = 0;
261  FileStreamReader reader(NULL,
262                          file_url_,
263                          initial_offset,
264                          base::Time::Now());  // Not used yet.
265
266  const int result = reader.GetLength(
267      base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
268  EXPECT_EQ(net::ERR_IO_PENDING, result);
269  base::RunLoop().RunUntilIdle();
270
271  ASSERT_EQ(1u, logger.results().size());
272  EXPECT_LT(0, logger.results()[0]);
273  EXPECT_EQ(kFakeFileSize, static_cast<size_t>(logger.results()[0]));
274}
275
276TEST_F(FileSystemProviderFileStreamReader, GetLength_WrongFile) {
277  EventLogger logger;
278
279  const int64 initial_offset = 0;
280  FileStreamReader reader(NULL,
281                          wrong_file_url_,
282                          initial_offset,
283                          base::Time::Now());  // Not used yet.
284
285  const int result = reader.GetLength(
286      base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr()));
287  EXPECT_EQ(net::ERR_IO_PENDING, result);
288  base::RunLoop().RunUntilIdle();
289
290  ASSERT_EQ(1u, logger.results().size());
291  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, logger.results()[0]);
292}
293
294}  // namespace file_system_provider
295}  // namespace chromeos
296