Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(297)

Side by Side Diff: webkit/fileapi/syncable/syncable_file_operation_runner_unittest.cc

Issue 15806012: Move webkit/fileapi/syncable/* code to webkit/browser/fileapi (final!) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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
7 #include "base/basictypes.h"
8 #include "base/file_util.h"
9 #include "base/location.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "webkit/blob/mock_blob_url_request_context.h"
14 #include "webkit/browser/fileapi/file_system_context.h"
15 #include "webkit/fileapi/syncable/canned_syncable_file_system.h"
16 #include "webkit/fileapi/syncable/local_file_change_tracker.h"
17 #include "webkit/fileapi/syncable/local_file_sync_context.h"
18 #include "webkit/fileapi/syncable/local_file_sync_status.h"
19 #include "webkit/fileapi/syncable/syncable_file_operation_runner.h"
20 #include "webkit/fileapi/syncable/syncable_file_system_operation.h"
21 #include "webkit/fileapi/syncable/syncable_file_system_util.h"
22
23 using fileapi::FileSystemOperation;
24 using fileapi::FileSystemURL;
25 using webkit_blob::MockBlobURLRequestContext;
26 using webkit_blob::ScopedTextBlob;
27 using base::PlatformFileError;
28
29 namespace sync_file_system {
30
31 namespace {
32 const std::string kServiceName = "test";
33 const std::string kParent = "foo";
34 const std::string kFile = "foo/file";
35 const std::string kDir = "foo/dir";
36 const std::string kChild = "foo/dir/bar";
37 const std::string kOther = "bar";
38 } // namespace
39
40 class SyncableFileOperationRunnerTest : public testing::Test {
41 protected:
42 typedef FileSystemOperation::StatusCallback StatusCallback;
43
44 // Use the current thread as IO thread so that we can directly call
45 // operations in the tests.
46 SyncableFileOperationRunnerTest()
47 : message_loop_(base::MessageLoop::TYPE_IO),
48 file_system_(GURL("http://example.com"), kServiceName,
49 base::MessageLoopProxy::current(),
50 base::MessageLoopProxy::current()),
51 callback_count_(0),
52 write_status_(base::PLATFORM_FILE_ERROR_FAILED),
53 write_bytes_(0),
54 write_complete_(false),
55 url_request_context_(file_system_.file_system_context()),
56 weak_factory_(this) {}
57
58 virtual void SetUp() OVERRIDE {
59 ASSERT_TRUE(dir_.CreateUniqueTempDir());
60 file_system_.SetUp();
61 sync_context_ = new LocalFileSyncContext(base::MessageLoopProxy::current(),
62 base::MessageLoopProxy::current());
63 ASSERT_EQ(SYNC_STATUS_OK,
64 file_system_.MaybeInitializeFileSystemContext(sync_context_));
65
66 ASSERT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem());
67 ASSERT_EQ(base::PLATFORM_FILE_OK,
68 file_system_.CreateDirectory(URL(kParent)));
69 }
70
71 virtual void TearDown() OVERRIDE {
72 if (sync_context_)
73 sync_context_->ShutdownOnUIThread();
74 sync_context_ = NULL;
75
76 file_system_.TearDown();
77 message_loop_.RunUntilIdle();
78 RevokeSyncableFileSystem(kServiceName);
79 }
80
81 FileSystemURL URL(const std::string& path) {
82 return file_system_.URL(path);
83 }
84
85 LocalFileSyncStatus* sync_status() {
86 return file_system_.file_system_context()->sync_context()->sync_status();
87 }
88
89 void ResetCallbackStatus() {
90 write_status_ = base::PLATFORM_FILE_ERROR_FAILED;
91 write_bytes_ = 0;
92 write_complete_ = false;
93 callback_count_ = 0;
94 }
95
96 StatusCallback ExpectStatus(const tracked_objects::Location& location,
97 PlatformFileError expect) {
98 return base::Bind(&SyncableFileOperationRunnerTest::DidFinish,
99 weak_factory_.GetWeakPtr(), location, expect);
100 }
101
102 FileSystemOperation::WriteCallback GetWriteCallback(
103 const tracked_objects::Location& location) {
104 return base::Bind(&SyncableFileOperationRunnerTest::DidWrite,
105 weak_factory_.GetWeakPtr(), location);
106 }
107
108 void DidWrite(const tracked_objects::Location& location,
109 PlatformFileError status, int64 bytes, bool complete) {
110 SCOPED_TRACE(testing::Message() << location.ToString());
111 write_status_ = status;
112 write_bytes_ += bytes;
113 write_complete_ = complete;
114 ++callback_count_;
115 }
116
117 void DidFinish(const tracked_objects::Location& location,
118 PlatformFileError expect, PlatformFileError status) {
119 SCOPED_TRACE(testing::Message() << location.ToString());
120 EXPECT_EQ(expect, status);
121 ++callback_count_;
122 }
123
124 bool CreateTempFile(base::FilePath* path) {
125 return file_util::CreateTemporaryFileInDir(dir_.path(), path);
126 }
127
128 base::ScopedTempDir dir_;
129
130 base::MessageLoop message_loop_;
131 CannedSyncableFileSystem file_system_;
132 scoped_refptr<LocalFileSyncContext> sync_context_;
133
134 int callback_count_;
135 PlatformFileError write_status_;
136 size_t write_bytes_;
137 bool write_complete_;
138
139 MockBlobURLRequestContext url_request_context_;
140
141 base::WeakPtrFactory<SyncableFileOperationRunnerTest> weak_factory_;
142
143 DISALLOW_COPY_AND_ASSIGN(SyncableFileOperationRunnerTest);
144 };
145
146 TEST_F(SyncableFileOperationRunnerTest, SimpleQueue) {
147 sync_status()->StartSyncing(URL(kFile));
148 ASSERT_FALSE(sync_status()->IsWritable(URL(kFile)));
149
150 // The URL is in syncing so the write operations won't run.
151 ResetCallbackStatus();
152 file_system_.NewOperation()->CreateFile(
153 URL(kFile), false /* exclusive */,
154 ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
155 file_system_.NewOperation()->Truncate(
156 URL(kFile), 1,
157 ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
158 base::MessageLoop::current()->RunUntilIdle();
159 EXPECT_EQ(0, callback_count_);
160
161 // Read operations are not blocked (and are executed before queued ones).
162 file_system_.NewOperation()->FileExists(
163 URL(kFile), ExpectStatus(FROM_HERE, base::PLATFORM_FILE_ERROR_NOT_FOUND));
164 base::MessageLoop::current()->RunUntilIdle();
165 EXPECT_EQ(1, callback_count_);
166
167 // End syncing (to enable write).
168 sync_status()->EndSyncing(URL(kFile));
169 ASSERT_TRUE(sync_status()->IsWritable(URL(kFile)));
170
171 ResetCallbackStatus();
172 base::MessageLoop::current()->RunUntilIdle();
173 EXPECT_EQ(2, callback_count_);
174
175 // Now the file must have been created and updated.
176 ResetCallbackStatus();
177 file_system_.NewOperation()->FileExists(
178 URL(kFile), ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
179 base::MessageLoop::current()->RunUntilIdle();
180 EXPECT_EQ(1, callback_count_);
181 }
182
183 TEST_F(SyncableFileOperationRunnerTest, WriteToParentAndChild) {
184 // First create the kDir directory and kChild in the dir.
185 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.CreateDirectory(URL(kDir)));
186 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.CreateFile(URL(kChild)));
187
188 // Start syncing the kDir directory.
189 sync_status()->StartSyncing(URL(kDir));
190 ASSERT_FALSE(sync_status()->IsWritable(URL(kDir)));
191
192 // Writes to kParent and kChild should be all queued up.
193 ResetCallbackStatus();
194 file_system_.NewOperation()->Truncate(
195 URL(kChild), 1, ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
196 file_system_.NewOperation()->Remove(
197 URL(kParent), true /* recursive */,
198 ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
199 base::MessageLoop::current()->RunUntilIdle();
200 EXPECT_EQ(0, callback_count_);
201
202 // Read operations are not blocked (and are executed before queued ones).
203 file_system_.NewOperation()->DirectoryExists(
204 URL(kDir), ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
205 base::MessageLoop::current()->RunUntilIdle();
206 EXPECT_EQ(1, callback_count_);
207
208 // Writes to unrelated files must succeed as well.
209 ResetCallbackStatus();
210 file_system_.NewOperation()->CreateDirectory(
211 URL(kOther), false /* exclusive */, false /* recursive */,
212 ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
213 base::MessageLoop::current()->RunUntilIdle();
214 EXPECT_EQ(1, callback_count_);
215
216 // End syncing (to enable write).
217 sync_status()->EndSyncing(URL(kDir));
218 ASSERT_TRUE(sync_status()->IsWritable(URL(kDir)));
219
220 ResetCallbackStatus();
221 base::MessageLoop::current()->RunUntilIdle();
222 EXPECT_EQ(2, callback_count_);
223 }
224
225 TEST_F(SyncableFileOperationRunnerTest, CopyAndMove) {
226 // First create the kDir directory and kChild in the dir.
227 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.CreateDirectory(URL(kDir)));
228 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.CreateFile(URL(kChild)));
229
230 // Start syncing the kParent directory.
231 sync_status()->StartSyncing(URL(kParent));
232
233 // Copying kDir to other directory should succeed, while moving would fail
234 // (since the source directory is in syncing).
235 ResetCallbackStatus();
236 file_system_.NewOperation()->Copy(
237 URL(kDir), URL("dest-copy"),
238 ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
239 file_system_.NewOperation()->Move(
240 URL(kDir), URL("dest-move"),
241 ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
242 base::MessageLoop::current()->RunUntilIdle();
243 EXPECT_EQ(1, callback_count_);
244
245 // Only "dest-copy1" should exist.
246 EXPECT_EQ(base::PLATFORM_FILE_OK,
247 file_system_.DirectoryExists(URL("dest-copy")));
248 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
249 file_system_.DirectoryExists(URL("dest-move")));
250
251 // Start syncing the "dest-copy2" directory.
252 sync_status()->StartSyncing(URL("dest-copy2"));
253
254 // Now the destination is also locked copying kDir should be queued.
255 ResetCallbackStatus();
256 file_system_.NewOperation()->Copy(
257 URL(kDir), URL("dest-copy2"),
258 ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
259 base::MessageLoop::current()->RunUntilIdle();
260 EXPECT_EQ(0, callback_count_);
261
262 // Finish syncing the "dest-copy2" directory to unlock Copy.
263 sync_status()->EndSyncing(URL("dest-copy2"));
264 ResetCallbackStatus();
265 base::MessageLoop::current()->RunUntilIdle();
266 EXPECT_EQ(1, callback_count_);
267
268 // Now we should have "dest-copy2".
269 EXPECT_EQ(base::PLATFORM_FILE_OK,
270 file_system_.DirectoryExists(URL("dest-copy2")));
271
272 // Finish syncing the kParent to unlock Move.
273 sync_status()->EndSyncing(URL(kParent));
274 ResetCallbackStatus();
275 base::MessageLoop::current()->RunUntilIdle();
276 EXPECT_EQ(1, callback_count_);
277
278 // Now we should have "dest-move".
279 EXPECT_EQ(base::PLATFORM_FILE_OK,
280 file_system_.DirectoryExists(URL("dest-move")));
281 }
282
283 TEST_F(SyncableFileOperationRunnerTest, Write) {
284 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.CreateFile(URL(kFile)));
285 const GURL kBlobURL("blob:foo");
286 const std::string kData("Lorem ipsum.");
287 ScopedTextBlob blob(url_request_context_, kBlobURL, kData);
288
289 sync_status()->StartSyncing(URL(kFile));
290
291 ResetCallbackStatus();
292 file_system_.NewOperation()->Write(
293 &url_request_context_,
294 URL(kFile), kBlobURL, 0, GetWriteCallback(FROM_HERE));
295 base::MessageLoop::current()->RunUntilIdle();
296 EXPECT_EQ(0, callback_count_);
297
298 sync_status()->EndSyncing(URL(kFile));
299 ResetCallbackStatus();
300
301 while (!write_complete_)
302 base::MessageLoop::current()->RunUntilIdle();
303
304 EXPECT_EQ(base::PLATFORM_FILE_OK, write_status_);
305 EXPECT_EQ(kData.size(), write_bytes_);
306 EXPECT_TRUE(write_complete_);
307 }
308
309 TEST_F(SyncableFileOperationRunnerTest, QueueAndCancel) {
310 sync_status()->StartSyncing(URL(kFile));
311 ASSERT_FALSE(sync_status()->IsWritable(URL(kFile)));
312
313 ResetCallbackStatus();
314 file_system_.NewOperation()->CreateFile(
315 URL(kFile), false /* exclusive */,
316 ExpectStatus(FROM_HERE, base::PLATFORM_FILE_ERROR_ABORT));
317 file_system_.NewOperation()->Truncate(
318 URL(kFile), 1,
319 ExpectStatus(FROM_HERE, base::PLATFORM_FILE_ERROR_ABORT));
320 base::MessageLoop::current()->RunUntilIdle();
321 EXPECT_EQ(0, callback_count_);
322
323 ResetCallbackStatus();
324
325 // This shouldn't crash nor leak memory.
326 sync_context_->ShutdownOnUIThread();
327 sync_context_ = NULL;
328 base::MessageLoop::current()->RunUntilIdle();
329 EXPECT_EQ(2, callback_count_);
330 }
331
332 // Test if CopyInForeignFile runs cooperatively with other Sync operations
333 // when it is called directly via AsLocalFileSystemOperation.
334 TEST_F(SyncableFileOperationRunnerTest, CopyInForeignFile) {
335 const std::string kTestData("test data");
336
337 base::FilePath temp_path;
338 ASSERT_TRUE(CreateTempFile(&temp_path));
339 ASSERT_EQ(static_cast<int>(kTestData.size()),
340 file_util::WriteFile(
341 temp_path, kTestData.data(), kTestData.size()));
342
343 sync_status()->StartSyncing(URL(kFile));
344 ASSERT_FALSE(sync_status()->IsWritable(URL(kFile)));
345
346 // The URL is in syncing so CopyIn (which is a write operation) won't run.
347 ResetCallbackStatus();
348 file_system_.NewOperation()->AsLocalFileSystemOperation()->CopyInForeignFile(
349 temp_path, URL(kFile),
350 ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
351 base::MessageLoop::current()->RunUntilIdle();
352 EXPECT_EQ(0, callback_count_);
353
354 // End syncing (to enable write).
355 sync_status()->EndSyncing(URL(kFile));
356 ASSERT_TRUE(sync_status()->IsWritable(URL(kFile)));
357
358 ResetCallbackStatus();
359 base::MessageLoop::current()->RunUntilIdle();
360 EXPECT_EQ(1, callback_count_);
361
362 // Now the file must have been created and have the same content as temp_path.
363 ResetCallbackStatus();
364 file_system_.DoVerifyFile(
365 URL(kFile), kTestData,
366 ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
367 base::MessageLoop::current()->RunUntilIdle();
368 EXPECT_EQ(1, callback_count_);
369 }
370
371 } // namespace sync_file_system
OLDNEW
« no previous file with comments | « webkit/fileapi/syncable/syncable_file_operation_runner.cc ('k') | webkit/fileapi/syncable/syncable_file_system_operation.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698