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.
4
5 #include "chrome/browser/sync_file_system/drive_backend/list_changes_task.h"
6
7 #include <stddef.h>
8 #include <string>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/format_macros.h"
14 #include "base/macros.h"
15 #include "base/run_loop.h"
16 #include "base/threading/thread_task_runner_handle.h"
17 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
18 #include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
19 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
20 #include "chrome/browser/sync_file_system/drive_backend/register_app_task.h"
21 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
22 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
23 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
24 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
25 #include "content/public/test/browser_task_environment.h"
26 #include "google_apis/drive/drive_api_parser.h"
27 #include "mojo/public/cpp/bindings/pending_remote.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "third_party/leveldatabase/leveldb_chrome.h"
30
31 namespace sync_file_system {
32 namespace drive_backend {
33
34 namespace {
35
36 const char kAppID[] = "app_id";
37 const char kUnregisteredAppID[] = "app_id unregistered";
38
39 } // namespace
40
41 class ListChangesTaskTest : public testing::Test {
42 public:
ListChangesTaskTest()43 ListChangesTaskTest()
44 : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {}
~ListChangesTaskTest()45 ~ListChangesTaskTest() override {}
46
SetUp()47 void SetUp() override {
48 ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
49 in_memory_env_ = leveldb_chrome::NewMemEnv("ListChangesTaskTest");
50
51 std::unique_ptr<drive::FakeDriveService> fake_drive_service(
52 new drive::FakeDriveService);
53
54 std::unique_ptr<drive::DriveUploaderInterface> drive_uploader(
55 new drive::DriveUploader(fake_drive_service.get(),
56 base::ThreadTaskRunnerHandle::Get(),
57 mojo::NullRemote()));
58
59 fake_drive_service_helper_.reset(
60 new FakeDriveServiceHelper(fake_drive_service.get(),
61 drive_uploader.get(),
62 kSyncRootFolderTitle));
63
64 sync_task_manager_.reset(new SyncTaskManager(
65 base::WeakPtr<SyncTaskManager::Client>(),
66 10 /* maximum_background_task */, base::ThreadTaskRunnerHandle::Get()));
67 sync_task_manager_->Initialize(SYNC_STATUS_OK);
68
69 context_.reset(new SyncEngineContext(
70 std::move(fake_drive_service), std::move(drive_uploader),
71 nullptr /* task_logger */, base::ThreadTaskRunnerHandle::Get(),
72 base::ThreadTaskRunnerHandle::Get()));
73
74 SetUpRemoteFolders();
75
76 InitializeMetadataDatabase();
77 RegisterApp(kAppID);
78 }
79
TearDown()80 void TearDown() override {
81 sync_task_manager_.reset();
82 context_.reset();
83 base::RunLoop().RunUntilIdle();
84 }
85
86 protected:
RunTask(std::unique_ptr<SyncTask> sync_task)87 SyncStatusCode RunTask(std::unique_ptr<SyncTask> sync_task) {
88 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
89 sync_task_manager_->ScheduleSyncTask(FROM_HERE, std::move(sync_task),
90 SyncTaskManager::PRIORITY_MED,
91 CreateResultReceiver(&status));
92 base::RunLoop().RunUntilIdle();
93 return status;
94 }
95
CountDirtyTracker()96 size_t CountDirtyTracker() {
97 return context_->GetMetadataDatabase()->CountDirtyTracker();
98 }
99
fake_drive_service_helper()100 FakeDriveServiceHelper* fake_drive_service_helper() {
101 return fake_drive_service_helper_.get();
102 }
103
SetUpChangesInFolder(const std::string & folder_id)104 void SetUpChangesInFolder(const std::string& folder_id) {
105 std::string new_file_id;
106 ASSERT_EQ(google_apis::HTTP_SUCCESS,
107 fake_drive_service_helper()->AddFile(
108 folder_id, "new file", "file contents", &new_file_id));
109 std::string same_name_file_id;
110 ASSERT_EQ(google_apis::HTTP_SUCCESS,
111 fake_drive_service_helper()->AddFile(
112 folder_id, "new file", "file contents",
113 &same_name_file_id));
114
115 std::string new_folder_id;
116 ASSERT_EQ(google_apis::HTTP_CREATED,
117 fake_drive_service_helper()->AddFolder(
118 folder_id, "new folder", &new_folder_id));
119
120 std::string modified_file_id;
121 ASSERT_EQ(google_apis::HTTP_SUCCESS,
122 fake_drive_service_helper()->AddFile(
123 folder_id, "modified file", "file content",
124 &modified_file_id));
125 ASSERT_EQ(google_apis::HTTP_SUCCESS,
126 fake_drive_service_helper()->UpdateFile(
127 modified_file_id, "modified file content"));
128
129
130 std::string deleted_file_id;
131 ASSERT_EQ(google_apis::HTTP_SUCCESS,
132 fake_drive_service_helper()->AddFile(
133 folder_id, "trashed file", "file content",
134 &deleted_file_id));
135 ASSERT_EQ(google_apis::HTTP_NO_CONTENT,
136 fake_drive_service_helper()->DeleteResource(deleted_file_id));
137 }
138
root_resource_id()139 std::string root_resource_id() {
140 return context_->GetDriveService()->GetRootResourceId();
141 }
142
app_root_folder_id()143 std::string app_root_folder_id() {
144 return app_root_folder_id_;
145 }
146
unregistered_app_root_folder_id()147 std::string unregistered_app_root_folder_id() {
148 return unregistered_app_root_folder_id_;
149 }
150
GetSyncEngineContext()151 SyncEngineContext* GetSyncEngineContext() {
152 return context_.get();
153 }
154
155 private:
SetUpRemoteFolders()156 void SetUpRemoteFolders() {
157 ASSERT_EQ(google_apis::HTTP_CREATED,
158 fake_drive_service_helper_->AddOrphanedFolder(
159 kSyncRootFolderTitle, &sync_root_folder_id_));
160 ASSERT_EQ(google_apis::HTTP_CREATED,
161 fake_drive_service_helper_->AddFolder(
162 sync_root_folder_id_, kAppID, &app_root_folder_id_));
163 ASSERT_EQ(google_apis::HTTP_CREATED,
164 fake_drive_service_helper_->AddFolder(
165 sync_root_folder_id_, kUnregisteredAppID,
166 &unregistered_app_root_folder_id_));
167 }
168
InitializeMetadataDatabase()169 void InitializeMetadataDatabase() {
170 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
171 SyncEngineInitializer* initializer = new SyncEngineInitializer(
172 context_.get(), database_dir_.GetPath(), in_memory_env_.get());
173
174 sync_task_manager_->ScheduleSyncTask(
175 FROM_HERE, std::unique_ptr<SyncTask>(initializer),
176 SyncTaskManager::PRIORITY_MED,
177 base::Bind(&ListChangesTaskTest::DidInitializeMetadataDatabase,
178 base::Unretained(this), initializer, &status));
179
180 base::RunLoop().RunUntilIdle();
181
182 EXPECT_EQ(SYNC_STATUS_OK, status);
183 }
184
DidInitializeMetadataDatabase(SyncEngineInitializer * initializer,SyncStatusCode * status_out,SyncStatusCode status)185 void DidInitializeMetadataDatabase(SyncEngineInitializer* initializer,
186 SyncStatusCode* status_out,
187 SyncStatusCode status) {
188 context_->SetMetadataDatabase(initializer->PassMetadataDatabase());
189 *status_out = status;
190 }
191
RegisterApp(const std::string & app_id)192 void RegisterApp(const std::string& app_id) {
193 EXPECT_EQ(SYNC_STATUS_OK,
194 RunTask(std::unique_ptr<SyncTask>(
195 new RegisterAppTask(context_.get(), app_id))));
196 }
197
198 std::unique_ptr<leveldb::Env> in_memory_env_;
199
200 std::string sync_root_folder_id_;
201 std::string app_root_folder_id_;
202 std::string unregistered_app_root_folder_id_;
203
204 content::BrowserTaskEnvironment task_environment_;
205 base::ScopedTempDir database_dir_;
206
207 std::unique_ptr<SyncEngineContext> context_;
208 std::unique_ptr<FakeDriveServiceHelper> fake_drive_service_helper_;
209
210 std::unique_ptr<SyncTaskManager> sync_task_manager_;
211
212 DISALLOW_COPY_AND_ASSIGN(ListChangesTaskTest);
213 };
214
TEST_F(ListChangesTaskTest,NoChange)215 TEST_F(ListChangesTaskTest, NoChange) {
216 size_t num_dirty_trackers = CountDirtyTracker();
217
218 EXPECT_EQ(SYNC_STATUS_NO_CHANGE_TO_SYNC,
219 RunTask(std::unique_ptr<SyncTask>(
220 new ListChangesTask(GetSyncEngineContext()))));
221
222 EXPECT_EQ(num_dirty_trackers, CountDirtyTracker());
223 }
224
TEST_F(ListChangesTaskTest,UnrelatedChange)225 TEST_F(ListChangesTaskTest, UnrelatedChange) {
226 size_t num_dirty_trackers = CountDirtyTracker();
227
228 SetUpChangesInFolder(root_resource_id());
229 SetUpChangesInFolder(unregistered_app_root_folder_id());
230
231 EXPECT_EQ(SYNC_STATUS_OK, RunTask(std::unique_ptr<SyncTask>(
232 new ListChangesTask(GetSyncEngineContext()))));
233
234 EXPECT_EQ(num_dirty_trackers, CountDirtyTracker());
235 }
236
TEST_F(ListChangesTaskTest,UnderTrackedFolder)237 TEST_F(ListChangesTaskTest, UnderTrackedFolder) {
238 size_t num_dirty_trackers = CountDirtyTracker();
239
240 SetUpChangesInFolder(app_root_folder_id());
241
242 EXPECT_EQ(SYNC_STATUS_OK, RunTask(std::unique_ptr<SyncTask>(
243 new ListChangesTask(GetSyncEngineContext()))));
244
245 EXPECT_EQ(num_dirty_trackers + 4, CountDirtyTracker());
246 }
247
TEST_F(ListChangesTaskTest,TeamDriveChangeInChangeList)248 TEST_F(ListChangesTaskTest, TeamDriveChangeInChangeList) {
249 size_t num_dirty_trackers = CountDirtyTracker();
250
251 SetUpChangesInFolder(app_root_folder_id());
252
253 // Adding a team drive will return a TeamDriveResource entry when the
254 // change list is retrieved.
255 fake_drive_service_helper()->AddTeamDrive("team_drive_id", "team_drive_name");
256
257 EXPECT_EQ(SYNC_STATUS_OK, RunTask(std::unique_ptr<SyncTask>(
258 new ListChangesTask(GetSyncEngineContext()))));
259
260 EXPECT_EQ(num_dirty_trackers + 4, CountDirtyTracker());
261 }
262
263 } // namespace drive_backend
264 } // namespace sync_file_system
265