1 // Copyright 2013 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/sync_file_system/drive_backend_v1/drive_file_sync_service.h"
9 #include "base/file_util.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/stl_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/threading/sequenced_worker_pool.h"
16 #include "chrome/browser/drive/drive_uploader.h"
17 #include "chrome/browser/drive/fake_drive_service.h"
18 #include "chrome/browser/drive/test_util.h"
19 #include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
20 #include "chrome/browser/sync_file_system/drive_backend_v1/api_util.h"
21 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_util.h"
22 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.h"
23 #include "chrome/browser/sync_file_system/local/canned_syncable_file_system.h"
24 #include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
25 #include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
26 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
27 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
28 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
29 #include "chrome/test/base/testing_browser_process.h"
30 #include "chrome/test/base/testing_profile.h"
31 #include "chrome/test/base/testing_profile_manager.h"
32 #include "content/public/test/test_browser_thread.h"
33 #include "content/public/test/test_browser_thread_bundle.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
36 #include "third_party/leveldatabase/src/include/leveldb/env.h"
37 #include "webkit/browser/fileapi/file_system_context.h"
39 #define FPL(path) FILE_PATH_LITERAL(path)
41 using content::BrowserThread;
43 using google_apis::GDataErrorCode;
44 using google_apis::ResourceEntry;
46 namespace sync_file_system {
49 const char kTestProfileName[] = "test-profile";
52 using drive_backend::APIUtil;
53 using drive_backend::APIUtilInterface;
54 using drive_backend::FakeDriveServiceHelper;
56 class DriveFileSyncServiceSyncTest : public testing::Test {
58 DriveFileSyncServiceSyncTest()
59 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
60 profile_manager_(TestingBrowserProcess::GetGlobal()) {}
62 virtual ~DriveFileSyncServiceSyncTest() {
65 virtual void SetUp() OVERRIDE {
66 // TODO(tzik): Set up TestExtensionSystem to support simulated relaunch.
67 in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
69 ASSERT_TRUE(profile_manager_.SetUp());
70 TestingProfile* profile =
71 profile_manager_.CreateTestingProfile(kTestProfileName);
73 RegisterSyncableFileSystem();
74 local_sync_service_ = LocalFileSyncService::CreateForTesting(
75 profile, in_memory_env_.get());
77 fake_drive_service_ = new drive::FakeDriveService();
78 fake_drive_service_->Initialize("test_user@gmail.com");
79 ASSERT_TRUE(drive::test_util::SetUpTestEntries(fake_drive_service_));
81 drive_uploader_ = new drive::DriveUploader(
82 fake_drive_service_, base::ThreadTaskRunnerHandle::Get().get());
84 fake_drive_helper_.reset(new FakeDriveServiceHelper(
85 fake_drive_service_, drive_uploader_,
86 APIUtil::GetSyncRootDirectoryName()));
88 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
90 scoped_ptr<DriveMetadataStore> metadata_store(
91 new DriveMetadataStore(fake_drive_helper_->base_dir_path(),
92 base::ThreadTaskRunnerHandle::Get().get()));
93 metadata_store->Initialize(CreateResultReceiver(&status, &created));
95 EXPECT_EQ(SYNC_STATUS_OK, status);
98 scoped_ptr<APIUtil> api_util(APIUtil::CreateForTesting(
99 fake_drive_helper_->base_dir_path().AppendASCII("tmp"),
100 scoped_ptr<drive::DriveServiceInterface>(fake_drive_service_),
101 scoped_ptr<drive::DriveUploaderInterface>(drive_uploader_)));
103 remote_sync_service_ = DriveFileSyncService::CreateForTesting(
105 fake_drive_helper_->base_dir_path(),
106 api_util.PassAs<APIUtilInterface>(),
107 metadata_store.Pass());
109 local_sync_service_->SetLocalChangeProcessor(remote_sync_service_.get());
110 remote_sync_service_->SetRemoteChangeProcessor(local_sync_service_.get());
113 virtual void TearDown() OVERRIDE {
114 drive_uploader_ = NULL;
115 fake_drive_service_ = NULL;
116 remote_sync_service_.reset();
117 local_sync_service_.reset();
120 typedef std::map<GURL, CannedSyncableFileSystem*>::iterator iterator;
121 for (iterator itr = file_systems_.begin();
122 itr != file_systems_.end(); ++itr) {
123 itr->second->TearDown();
126 file_systems_.clear();
129 RevokeSyncableFileSystem();
133 void RegisterOrigin(const GURL& origin) {
134 if (!ContainsKey(file_systems_, origin)) {
135 CannedSyncableFileSystem* file_system = new CannedSyncableFileSystem(
137 in_memory_env_.get(),
138 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(),
139 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
142 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
143 file_system->SetUp(CannedSyncableFileSystem::QUOTA_ENABLED);
144 local_sync_service_->MaybeInitializeFileSystemContext(
145 origin, file_system->file_system_context(),
146 CreateResultReceiver(&status));
148 EXPECT_EQ(SYNC_STATUS_OK, status);
150 file_system->backend()->sync_context()->
151 set_mock_notify_changes_duration_in_sec(0);
153 EXPECT_EQ(base::File::FILE_OK, file_system->OpenFileSystem());
154 file_systems_[origin] = file_system;
157 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
158 remote_sync_service_->RegisterOrigin(
159 origin, CreateResultReceiver(&status));
161 EXPECT_EQ(SYNC_STATUS_OK, status);
164 void AddOrUpdateLocalFile(const GURL& origin,
165 const base::FilePath& path,
166 const std::string& content) {
167 fileapi::FileSystemURL url(CreateSyncableFileSystemURL(origin, path));
168 ASSERT_TRUE(ContainsKey(file_systems_, origin));
169 EXPECT_EQ(base::File::FILE_OK, file_systems_[origin]->CreateFile(url));
170 int64 bytes_written = file_systems_[origin]->WriteString(url, content);
171 EXPECT_EQ(static_cast<int64>(content.size()), bytes_written);
175 void UpdateLocalFile(const GURL& origin,
176 const base::FilePath& path,
177 const std::string& content) {
178 ASSERT_TRUE(ContainsKey(file_systems_, origin));
179 int64 bytes_written = file_systems_[origin]->WriteString(
180 CreateSyncableFileSystemURL(origin, path), content);
181 EXPECT_EQ(static_cast<int64>(content.size()), bytes_written);
185 void RemoveLocal(const GURL& origin, const base::FilePath& path) {
186 ASSERT_TRUE(ContainsKey(file_systems_, origin));
187 EXPECT_EQ(base::File::FILE_OK,
188 file_systems_[origin]->Remove(
189 CreateSyncableFileSystemURL(origin, path),
190 true /* recursive */));
194 SyncStatusCode ProcessLocalChange() {
195 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
196 fileapi::FileSystemURL url;
197 local_sync_service_->ProcessLocalChange(
198 CreateResultReceiver(&status, &url));
203 SyncStatusCode ProcessRemoteChange() {
204 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
205 fileapi::FileSystemURL url;
206 remote_sync_service_->ProcessRemoteChange(
207 CreateResultReceiver(&status, &url));
212 SyncStatusCode ProcessChangesUntilDone() {
213 remote_sync_service_->OnNotificationReceived();
216 SyncStatusCode local_sync_status;
217 SyncStatusCode remote_sync_status;
219 local_sync_status = ProcessLocalChange();
220 if (local_sync_status != SYNC_STATUS_OK &&
221 local_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC)
222 return local_sync_status;
224 remote_sync_status = ProcessRemoteChange();
225 if (remote_sync_status != SYNC_STATUS_OK &&
226 remote_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC)
227 return remote_sync_status;
228 } while (local_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC &&
229 remote_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC);
230 return SYNC_STATUS_OK;
233 // Verifies local and remote files/folders are consistent.
234 // This function checks:
235 // - Each registered origin has corresponding remote folder.
236 // - Each local file/folder has corresponding remote one.
237 // - Each remote file/folder has corresponding local one.
238 // TODO(tzik): Handle conflict case. i.e. allow remote file has different
239 // file content if the corresponding local file conflicts to it.
240 void VerifyConsistency() {
241 std::string sync_root_folder_id;
242 GDataErrorCode error =
243 fake_drive_helper_->GetSyncRootFolderID(&sync_root_folder_id);
244 if (sync_root_folder_id.empty()) {
245 EXPECT_EQ(google_apis::HTTP_NOT_FOUND, error);
246 EXPECT_TRUE(file_systems_.empty());
249 EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
251 ScopedVector<ResourceEntry> remote_entries;
252 EXPECT_EQ(google_apis::HTTP_SUCCESS,
253 fake_drive_helper_->ListFilesInFolder(
254 sync_root_folder_id, &remote_entries));
255 std::map<std::string, const ResourceEntry*> origin_root_by_title;
256 for (ScopedVector<ResourceEntry>::iterator itr = remote_entries.begin();
257 itr != remote_entries.end();
259 const ResourceEntry& remote_entry = **itr;
260 EXPECT_FALSE(ContainsKey(origin_root_by_title, remote_entry.title()));
261 origin_root_by_title[remote_entry.title()] = *itr;
264 for (std::map<GURL, CannedSyncableFileSystem*>::const_iterator itr =
265 file_systems_.begin();
266 itr != file_systems_.end(); ++itr) {
267 const GURL& origin = itr->first;
268 SCOPED_TRACE(testing::Message() << "Verifying origin: " << origin);
269 CannedSyncableFileSystem* file_system = itr->second;
270 ASSERT_TRUE(ContainsKey(origin_root_by_title, origin.host()));
271 VerifyConsistencyForFolder(
272 origin, base::FilePath(),
273 origin_root_by_title[origin.host()]->resource_id(),
278 void VerifyConsistencyForOrigin(const GURL& origin) {
279 std::string sync_root_folder_id;
280 ASSERT_EQ(google_apis::HTTP_SUCCESS,
281 fake_drive_helper_->GetSyncRootFolderID(&sync_root_folder_id));
282 ASSERT_FALSE(sync_root_folder_id.empty());
284 ScopedVector<ResourceEntry> origin_folder;
285 EXPECT_EQ(google_apis::HTTP_SUCCESS,
286 fake_drive_helper_->SearchByTitle(
287 sync_root_folder_id, origin.host(), &origin_folder));
288 ASSERT_EQ(1u, origin_folder.size());
290 ASSERT_TRUE(ContainsKey(file_systems_, origin));
291 VerifyConsistencyForFolder(
292 origin, base::FilePath(),
293 origin_folder[0]->resource_id(),
294 file_systems_[origin]);
297 void VerifyConsistencyForFolder(const GURL& origin,
298 const base::FilePath& path,
299 const std::string& folder_id,
300 CannedSyncableFileSystem* file_system) {
301 SCOPED_TRACE(testing::Message() << "Verifying path: " << path.value());
303 ScopedVector<ResourceEntry> remote_entries;
304 EXPECT_EQ(google_apis::HTTP_SUCCESS,
305 fake_drive_helper_->ListFilesInFolder(
306 folder_id, &remote_entries));
307 std::map<std::string, const ResourceEntry*> remote_entry_by_title;
308 for (ScopedVector<ResourceEntry>::iterator itr = remote_entries.begin();
309 itr != remote_entries.end();
311 const ResourceEntry& remote_entry = **itr;
312 EXPECT_FALSE(ContainsKey(remote_entry_by_title, remote_entry.title()));
313 remote_entry_by_title[remote_entry.title()] = *itr;
316 fileapi::FileSystemURL url(CreateSyncableFileSystemURL(origin, path));
317 CannedSyncableFileSystem::FileEntryList local_entries;
318 EXPECT_EQ(base::File::FILE_OK,
319 file_system->ReadDirectory(url, &local_entries));
320 for (CannedSyncableFileSystem::FileEntryList::iterator itr =
321 local_entries.begin();
322 itr != local_entries.end();
324 const fileapi::DirectoryEntry& local_entry = *itr;
325 fileapi::FileSystemURL entry_url(
326 CreateSyncableFileSystemURL(origin, path.Append(local_entry.name)));
327 std::string title = DriveFileSyncService::PathToTitle(entry_url.path());
328 ASSERT_TRUE(ContainsKey(remote_entry_by_title, title));
329 const ResourceEntry& remote_entry = *remote_entry_by_title[title];
330 if (local_entry.is_directory) {
331 ASSERT_TRUE(remote_entry.is_folder());
332 VerifyConsistencyForFolder(origin, entry_url.path(),
333 remote_entry.resource_id(),
336 ASSERT_TRUE(remote_entry.is_file());
337 VerifyConsistencyForFile(origin, entry_url.path(),
338 remote_entry.resource_id(),
341 remote_entry_by_title.erase(title);
344 EXPECT_TRUE(remote_entry_by_title.empty());
347 void VerifyConsistencyForFile(const GURL& origin,
348 const base::FilePath& path,
349 const std::string& file_id,
350 CannedSyncableFileSystem* file_system) {
351 fileapi::FileSystemURL url(CreateSyncableFileSystemURL(origin, path));
352 std::string file_content;
353 EXPECT_EQ(google_apis::HTTP_SUCCESS,
354 fake_drive_helper_->ReadFile(file_id, &file_content));
355 EXPECT_EQ(base::File::FILE_OK,
356 file_system->VerifyFile(url, file_content));
359 void FlushMessageLoop() {
360 base::MessageLoop::current()->RunUntilIdle();
361 BrowserThread::GetBlockingPool()->FlushForTesting();
362 base::MessageLoop::current()->RunUntilIdle();
365 void TestInitialization();
366 void TestLocalToRemoteBasic();
367 void TestRemoteToLocalBasic();
368 void TestLocalFileUpdate();
369 void TestRemoteFileUpdate();
370 void TestLocalFileDeletion();
371 void TestRemoteFileDeletion();
373 ScopedDisableSyncFSV2 scoped_disable_v2_;
374 content::TestBrowserThreadBundle thread_bundle_;
376 scoped_ptr<leveldb::Env> in_memory_env_;
377 TestingProfileManager profile_manager_;
379 drive::FakeDriveService* fake_drive_service_;
380 drive::DriveUploader* drive_uploader_;
381 scoped_ptr<FakeDriveServiceHelper> fake_drive_helper_;
382 std::map<GURL, CannedSyncableFileSystem*> file_systems_;
384 scoped_ptr<DriveFileSyncService> remote_sync_service_;
385 scoped_ptr<LocalFileSyncService> local_sync_service_;
388 DISALLOW_COPY_AND_ASSIGN(DriveFileSyncServiceSyncTest);
391 void DriveFileSyncServiceSyncTest::TestInitialization() {
392 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
396 void DriveFileSyncServiceSyncTest::TestLocalToRemoteBasic() {
397 const GURL kOrigin("chrome-extension://example");
399 RegisterOrigin(kOrigin);
400 AddOrUpdateLocalFile(kOrigin, base::FilePath(FPL("file")), "abcde");
402 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
406 void DriveFileSyncServiceSyncTest::TestRemoteToLocalBasic() {
407 const GURL kOrigin("chrome-extension://example");
409 std::string sync_root_folder_id;
410 EXPECT_EQ(google_apis::HTTP_CREATED,
411 fake_drive_helper_->AddOrphanedFolder(
412 APIUtil::GetSyncRootDirectoryName(),
413 &sync_root_folder_id));
415 std::string origin_root_folder_id;
416 EXPECT_EQ(google_apis::HTTP_CREATED,
417 fake_drive_helper_->AddFolder(
418 sync_root_folder_id, kOrigin.host(), &origin_root_folder_id));
420 RegisterOrigin(kOrigin);
423 EXPECT_EQ(google_apis::HTTP_SUCCESS,
424 fake_drive_helper_->AddFile(
425 origin_root_folder_id, "file", "abcde", &file_id));
427 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
431 void DriveFileSyncServiceSyncTest::TestLocalFileUpdate() {
432 const GURL kOrigin("chrome-extension://example");
433 const base::FilePath kPath(FPL("file"));
435 RegisterOrigin(kOrigin);
436 AddOrUpdateLocalFile(kOrigin, kPath, "abcde");
438 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
439 VerifyConsistencyForOrigin(kOrigin);
441 UpdateLocalFile(kOrigin, kPath, "1234567890");
443 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
447 void DriveFileSyncServiceSyncTest::TestRemoteFileUpdate() {
448 const GURL kOrigin("chrome-extension://example");
449 const base::FilePath kPath(FPL("file"));
450 const std::string kTitle(DriveFileSyncService::PathToTitle(kPath));
452 std::string sync_root_folder_id;
453 EXPECT_EQ(google_apis::HTTP_CREATED,
454 fake_drive_helper_->AddOrphanedFolder(
455 APIUtil::GetSyncRootDirectoryName(),
456 &sync_root_folder_id));
458 std::string origin_root_folder_id;
459 EXPECT_EQ(google_apis::HTTP_CREATED,
460 fake_drive_helper_->AddFolder(
461 sync_root_folder_id, kOrigin.host(), &origin_root_folder_id));
463 std::string remote_file_id;
464 EXPECT_EQ(google_apis::HTTP_SUCCESS,
465 fake_drive_helper_->AddFile(
466 origin_root_folder_id, kTitle, "abcde", &remote_file_id));
468 RegisterOrigin(kOrigin);
469 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
470 VerifyConsistencyForOrigin(kOrigin);
472 EXPECT_EQ(google_apis::HTTP_SUCCESS,
473 fake_drive_helper_->UpdateFile(remote_file_id, "1234567890"));
475 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
479 void DriveFileSyncServiceSyncTest::TestLocalFileDeletion() {
480 const GURL kOrigin("chrome-extension://example");
481 const base::FilePath kPath(FPL("file"));
483 RegisterOrigin(kOrigin);
484 AddOrUpdateLocalFile(kOrigin, kPath, "abcde");
486 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
487 VerifyConsistencyForOrigin(kOrigin);
489 RemoveLocal(kOrigin, kPath);
491 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
495 void DriveFileSyncServiceSyncTest::TestRemoteFileDeletion() {
496 const GURL kOrigin("chrome-extension://example");
497 const base::FilePath kPath(FPL("file"));
498 const std::string kTitle(DriveFileSyncService::PathToTitle(kPath));
500 std::string sync_root_folder_id;
501 EXPECT_EQ(google_apis::HTTP_CREATED,
502 fake_drive_helper_->AddOrphanedFolder(
503 APIUtil::GetSyncRootDirectoryName(),
504 &sync_root_folder_id));
506 std::string origin_root_folder_id;
507 EXPECT_EQ(google_apis::HTTP_CREATED,
508 fake_drive_helper_->AddFolder(
509 sync_root_folder_id, kOrigin.host(), &origin_root_folder_id));
511 std::string remote_file_id;
512 EXPECT_EQ(google_apis::HTTP_SUCCESS,
513 fake_drive_helper_->AddFile(
514 origin_root_folder_id, kTitle, "abcde", &remote_file_id));
516 RegisterOrigin(kOrigin);
517 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
518 VerifyConsistencyForOrigin(kOrigin);
520 EXPECT_EQ(google_apis::HTTP_SUCCESS,
521 fake_drive_helper_->TrashResource(remote_file_id));
523 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
527 TEST_F(DriveFileSyncServiceSyncTest, InitializationTest) {
528 ASSERT_FALSE(IsDriveAPIDisabled());
529 TestInitialization();
532 TEST_F(DriveFileSyncServiceSyncTest, InitializationTest_WAPI) {
533 ScopedDisableDriveAPI disable_drive_api;
534 TestInitialization();
537 TEST_F(DriveFileSyncServiceSyncTest, LocalToRemoteBasicTest) {
538 ASSERT_FALSE(IsDriveAPIDisabled());
539 TestLocalToRemoteBasic();
542 TEST_F(DriveFileSyncServiceSyncTest, LocalToRemoteBasicTest_WAPI) {
543 ScopedDisableDriveAPI disable_drive_api;
544 TestLocalToRemoteBasic();
547 TEST_F(DriveFileSyncServiceSyncTest, RemoteToLocalBasicTest) {
548 ASSERT_FALSE(IsDriveAPIDisabled());
549 TestRemoteToLocalBasic();
552 TEST_F(DriveFileSyncServiceSyncTest, RemoteToLocalBasicTest_WAPI) {
553 ScopedDisableDriveAPI disable_drive_api;
554 TestRemoteToLocalBasic();
557 TEST_F(DriveFileSyncServiceSyncTest, LocalFileUpdateTest) {
558 ASSERT_FALSE(IsDriveAPIDisabled());
559 TestLocalFileUpdate();
562 TEST_F(DriveFileSyncServiceSyncTest, LocalFileUpdateTest_WAPI) {
563 ScopedDisableDriveAPI disable_drive_api;
564 TestLocalFileUpdate();
567 TEST_F(DriveFileSyncServiceSyncTest, RemoteFileUpdateTest) {
568 ASSERT_FALSE(IsDriveAPIDisabled());
569 TestRemoteFileUpdate();
572 TEST_F(DriveFileSyncServiceSyncTest, RemoteFileUpdateTest_WAPI) {
573 ScopedDisableDriveAPI disable_drive_api;
574 TestRemoteFileUpdate();
577 TEST_F(DriveFileSyncServiceSyncTest, LocalFileDeletionTest) {
578 ASSERT_FALSE(IsDriveAPIDisabled());
579 TestLocalFileDeletion();
582 TEST_F(DriveFileSyncServiceSyncTest, LocalFileDeletionTest_WAPI) {
583 ScopedDisableDriveAPI disable_drive_api;
584 TestLocalFileDeletion();
587 TEST_F(DriveFileSyncServiceSyncTest, RemoteFileDeletionTest) {
588 ASSERT_FALSE(IsDriveAPIDisabled());
589 TestRemoteFileDeletion();
592 TEST_F(DriveFileSyncServiceSyncTest, RemoteFileDeletionTest_WAPI) {
593 ScopedDisableDriveAPI disable_drive_api;
594 TestRemoteFileDeletion();
597 } // namespace sync_file_system