OLD | NEW |
| (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 "chrome/browser/chromeos/gdata/gdata_db.h" | |
6 | |
7 #include "base/message_loop.h" | |
8 #include "base/string_number_conversions.h" | |
9 #include "chrome/browser/chromeos/gdata/gdata.pb.h" | |
10 #include "chrome/browser/chromeos/gdata/gdata_db_factory.h" | |
11 #include "chrome/browser/chromeos/gdata/gdata_files.h" | |
12 #include "chrome/browser/chromeos/gdata/gdata_test_util.h" | |
13 #include "chrome/test/base/testing_profile.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 | |
16 namespace gdata { | |
17 namespace { | |
18 | |
19 class GDataDBTest : public testing::Test { | |
20 public: | |
21 GDataDBTest() { | |
22 } | |
23 | |
24 virtual ~GDataDBTest() { | |
25 } | |
26 | |
27 protected: | |
28 // testing::Test implementation. | |
29 virtual void SetUp() OVERRIDE; | |
30 | |
31 // Tests GDataDB::GetPath and GDataDB::ResourceId, ensuring that an entry | |
32 // matching |source| does not exist. | |
33 void TestGetNotFound(const GDataEntry& source); | |
34 | |
35 // Tests GDataDB::GetPath and GDataDB::ResourceId, ensuring that an entry | |
36 // matching |source| exists. | |
37 void TestGetFound(const GDataEntry& source); | |
38 | |
39 // Tests GDataDB::GetPath and GDataDB::ResourceId, ensuring that an entry | |
40 // matching |source| is corrupt. | |
41 void TestGetCorrupt(const GDataEntry& source); | |
42 | |
43 // Initialize the database with the following entries: | |
44 // drive/dir1 | |
45 // drive/dir2 | |
46 // drive/dir1/dir3 | |
47 // drive/dir1/file4 | |
48 // drive/dir1/file5 | |
49 // drive/dir2/file6 | |
50 // drive/dir2/file7 | |
51 // drive/dir2/file8 | |
52 // drive/dir1/dir3/file9 | |
53 // drive/dir1/dir3/file10 | |
54 void InitDB(); | |
55 | |
56 // Helper functions to add a directory/file, incrementing index. | |
57 GDataDirectory* AddDirectory(GDataDirectory* parent, | |
58 GDataDirectoryService* root, int sequence_id); | |
59 GDataFile* AddFile(GDataDirectory* parent, | |
60 GDataDirectoryService* directory_service, int sequence_id); | |
61 | |
62 // Tests GDataDB::NewIterator and GDataDBIter::GetNext. | |
63 // Creates an iterator with start at |parent|, and iterates comparing with | |
64 // expected |filenames|. | |
65 void TestIter(const std::string& parent, | |
66 const char* file_paths[], | |
67 size_t file_paths_size); | |
68 | |
69 scoped_ptr<TestingProfile> profile_; | |
70 scoped_ptr<GDataDB> gdata_db_; | |
71 MessageLoopForUI message_loop; | |
72 }; | |
73 | |
74 void GDataDBTest::SetUp() { | |
75 profile_.reset(new TestingProfile()); | |
76 gdata_db_ = db_factory::CreateGDataDB( | |
77 profile_->GetPath().Append("testdb")); | |
78 } | |
79 | |
80 void GDataDBTest::TestGetNotFound(const GDataEntry& source) { | |
81 scoped_ptr<GDataEntry> entry; | |
82 GDataDB::Status status = gdata_db_->GetByPath(source.GetFilePath(), &entry); | |
83 EXPECT_EQ(GDataDB::DB_KEY_NOT_FOUND, status); | |
84 EXPECT_FALSE(entry.get()); | |
85 | |
86 status = gdata_db_->GetByResourceId(source.resource_id(), &entry); | |
87 EXPECT_EQ(GDataDB::DB_KEY_NOT_FOUND, status); | |
88 EXPECT_FALSE(entry.get()); | |
89 } | |
90 | |
91 void GDataDBTest::TestGetFound(const GDataEntry& source) { | |
92 scoped_ptr<GDataEntry> entry; | |
93 GDataDB::Status status = gdata_db_->GetByPath(source.GetFilePath(), &entry); | |
94 EXPECT_EQ(GDataDB::DB_OK, status); | |
95 ASSERT_TRUE(entry.get()); | |
96 EXPECT_EQ(source.title(), entry->title()); | |
97 EXPECT_EQ(source.resource_id(), entry->resource_id()); | |
98 EXPECT_EQ(source.content_url(), entry->content_url()); | |
99 entry.reset(); | |
100 | |
101 status = gdata_db_->GetByResourceId(source.resource_id(), &entry); | |
102 EXPECT_EQ(GDataDB::DB_OK, status); | |
103 ASSERT_TRUE(entry.get()); | |
104 EXPECT_EQ(source.title(), entry->title()); | |
105 EXPECT_EQ(source.resource_id(), entry->resource_id()); | |
106 EXPECT_EQ(source.content_url(), entry->content_url()); | |
107 } | |
108 | |
109 void GDataDBTest::TestGetCorrupt(const GDataEntry& source) { | |
110 scoped_ptr<GDataEntry> entry; | |
111 GDataDB::Status status = gdata_db_->GetByPath(source.GetFilePath(), &entry); | |
112 EXPECT_EQ(GDataDB::DB_CORRUPTION, status); | |
113 EXPECT_FALSE(entry.get()); | |
114 | |
115 status = gdata_db_->GetByResourceId(source.resource_id(), &entry); | |
116 EXPECT_EQ(GDataDB::DB_CORRUPTION, status); | |
117 EXPECT_FALSE(entry.get()); | |
118 } | |
119 | |
120 void GDataDBTest::InitDB() { | |
121 int sequence_id = 1; | |
122 GDataDirectoryService directory_service; | |
123 GDataDirectory* dir1 = AddDirectory(directory_service.root(), | |
124 &directory_service, sequence_id++); | |
125 GDataDirectory* dir2 = AddDirectory(directory_service.root(), | |
126 &directory_service, sequence_id++); | |
127 GDataDirectory* dir3 = AddDirectory(dir1, &directory_service, sequence_id++); | |
128 | |
129 AddFile(dir1, &directory_service, sequence_id++); | |
130 AddFile(dir1, &directory_service, sequence_id++); | |
131 | |
132 AddFile(dir2, &directory_service, sequence_id++); | |
133 AddFile(dir2, &directory_service, sequence_id++); | |
134 AddFile(dir2, &directory_service, sequence_id++); | |
135 | |
136 AddFile(dir3, &directory_service, sequence_id++); | |
137 AddFile(dir3, &directory_service, sequence_id++); | |
138 } | |
139 | |
140 GDataDirectory* GDataDBTest::AddDirectory( | |
141 GDataDirectory* parent, | |
142 GDataDirectoryService* directory_service, | |
143 int sequence_id) { | |
144 GDataDirectory* dir = new GDataDirectory(parent, directory_service); | |
145 const std::string dir_name = "dir" + base::IntToString(sequence_id); | |
146 const std::string resource_id = std::string("dir_resource_id:") + | |
147 dir_name; | |
148 dir->set_title(dir_name); | |
149 dir->SetBaseNameFromTitle(); | |
150 dir->set_resource_id(resource_id); | |
151 GDataFileError error = GDATA_FILE_ERROR_FAILED; | |
152 directory_service->AddEntryToDirectory( | |
153 parent->GetFilePath(), | |
154 dir, | |
155 base::Bind(&test_util::CopyErrorCodeFromFileOperationCallback, &error)); | |
156 test_util::RunBlockingPoolTask(); | |
157 EXPECT_EQ(GDATA_FILE_OK, error); | |
158 | |
159 GDataDB::Status status = gdata_db_->Put(*dir); | |
160 EXPECT_EQ(GDataDB::DB_OK, status); | |
161 DVLOG(1) << "AddDirectory " << dir->GetFilePath().value() | |
162 << ", " << resource_id; | |
163 return dir; | |
164 } | |
165 | |
166 GDataFile* GDataDBTest::AddFile(GDataDirectory* parent, | |
167 GDataDirectoryService* directory_service, | |
168 int sequence_id) { | |
169 GDataFile* file = new GDataFile(parent, directory_service); | |
170 const std::string title = "file" + base::IntToString(sequence_id); | |
171 const std::string resource_id = std::string("file_resource_id:") + | |
172 title; | |
173 file->set_title(title); | |
174 file->SetBaseNameFromTitle(); | |
175 file->set_resource_id(resource_id); | |
176 GDataFileError error = GDATA_FILE_ERROR_FAILED; | |
177 directory_service->AddEntryToDirectory( | |
178 parent->GetFilePath(), | |
179 file, | |
180 base::Bind(&test_util::CopyErrorCodeFromFileOperationCallback, &error)); | |
181 test_util::RunBlockingPoolTask(); | |
182 EXPECT_EQ(GDATA_FILE_OK, error); | |
183 | |
184 GDataDB::Status status = gdata_db_->Put(*file); | |
185 EXPECT_EQ(GDataDB::DB_OK, status); | |
186 DVLOG(1) << "AddFile " << file->GetFilePath().value() | |
187 << ", " << resource_id; | |
188 return file; | |
189 } | |
190 | |
191 void GDataDBTest::TestIter(const std::string& parent, | |
192 const char* file_paths[], | |
193 size_t file_paths_size) { | |
194 scoped_ptr<GDataDBIter> iter = gdata_db_->CreateIterator( | |
195 FilePath::FromUTF8Unsafe(parent)); | |
196 for (size_t i = 0; ; ++i) { | |
197 scoped_ptr<GDataEntry> entry; | |
198 std::string path; | |
199 if (!iter->GetNext(&path, &entry)) { | |
200 EXPECT_EQ(i, file_paths_size); | |
201 break; | |
202 } | |
203 ASSERT_LT(i, file_paths_size); | |
204 // TODO(achuith): Also test entry->GetFilePath(). | |
205 EXPECT_EQ(FilePath(file_paths[i]).BaseName().value(), entry->base_name()); | |
206 EXPECT_EQ(file_paths[i], path); | |
207 DVLOG(1) << "Iter " << path; | |
208 } | |
209 } | |
210 | |
211 } // namespace | |
212 | |
213 TEST_F(GDataDBTest, PutTest) { | |
214 GDataDirectoryService directory_service; | |
215 GDataDirectory dir(directory_service.root(), &directory_service); | |
216 dir.set_title("dir"); | |
217 dir.set_base_name("dir"); | |
218 dir.set_resource_id("dir_resource_id"); | |
219 dir.set_content_url(GURL("http://content/dir")); | |
220 dir.set_upload_url(GURL("http://upload/dir")); | |
221 | |
222 TestGetNotFound(dir); | |
223 | |
224 GDataDB::Status status = gdata_db_->Put(dir); | |
225 ASSERT_EQ(GDataDB::DB_OK, status); | |
226 | |
227 TestGetFound(dir); | |
228 | |
229 scoped_ptr<GDataEntry> entry; | |
230 status = gdata_db_->GetByPath(dir.GetFilePath(), &entry); | |
231 ASSERT_EQ(GDataDB::DB_OK, status); | |
232 EXPECT_EQ(dir.upload_url(), entry->AsGDataDirectory()->upload_url()); | |
233 EXPECT_TRUE(entry->AsGDataDirectory()->file_info().is_directory); | |
234 | |
235 status = gdata_db_->DeleteByPath(dir.GetFilePath()); | |
236 ASSERT_EQ(GDataDB::DB_OK, status); | |
237 | |
238 TestGetNotFound(dir); | |
239 | |
240 GDataFile file(&dir, &directory_service); | |
241 file.set_title("file"); | |
242 file.set_base_name("file"); | |
243 file.set_resource_id("file_resource_id"); | |
244 file.set_content_url(GURL("http://content/dir/file")); | |
245 file.set_file_md5("file_md5"); | |
246 | |
247 TestGetNotFound(file); | |
248 | |
249 status = gdata_db_->Put(file); | |
250 ASSERT_EQ(GDataDB::DB_OK, status); | |
251 | |
252 TestGetFound(file); | |
253 | |
254 status = gdata_db_->GetByPath(file.GetFilePath(), &entry); | |
255 ASSERT_EQ(GDataDB::DB_OK, status); | |
256 EXPECT_EQ(file.file_md5(), entry->AsGDataFile()->file_md5()); | |
257 EXPECT_FALSE(entry->AsGDataFile()->file_info().is_directory); | |
258 | |
259 status = gdata_db_->DeleteByPath(file.GetFilePath()); | |
260 ASSERT_EQ(GDataDB::DB_OK, status); | |
261 | |
262 TestGetNotFound(file); | |
263 } | |
264 | |
265 TEST_F(GDataDBTest, IterTest) { | |
266 InitDB(); | |
267 | |
268 const char* dir1_children[] = { | |
269 "drive/dir1", | |
270 "drive/dir1/dir3", | |
271 "drive/dir1/dir3/file10", | |
272 "drive/dir1/dir3/file9", | |
273 "drive/dir1/file4", | |
274 "drive/dir1/file5", | |
275 }; | |
276 TestIter("drive/dir1", dir1_children, arraysize(dir1_children)); | |
277 | |
278 const char* dir2_children[] = { | |
279 "drive/dir2", | |
280 "drive/dir2/file6", | |
281 "drive/dir2/file7", | |
282 "drive/dir2/file8", | |
283 }; | |
284 TestIter("drive/dir2", dir2_children, arraysize(dir2_children)); | |
285 | |
286 const char* dir3_children[] = { | |
287 "drive/dir1/dir3", | |
288 "drive/dir1/dir3/file10", | |
289 "drive/dir1/dir3/file9", | |
290 }; | |
291 TestIter("drive/dir1/dir3", dir3_children, arraysize(dir3_children)); | |
292 | |
293 const char* file10[] = { | |
294 "drive/dir1/dir3/file10", | |
295 }; | |
296 TestIter(file10[0], file10, arraysize(file10)); | |
297 | |
298 const char* all_entries[] = { | |
299 "drive/dir1", | |
300 "drive/dir1/dir3", | |
301 "drive/dir1/dir3/file10", | |
302 "drive/dir1/dir3/file9", | |
303 "drive/dir1/file4", | |
304 "drive/dir1/file5", | |
305 "drive/dir2", | |
306 "drive/dir2/file6", | |
307 "drive/dir2/file7", | |
308 "drive/dir2/file8", | |
309 }; | |
310 TestIter("", all_entries, arraysize(all_entries)); | |
311 | |
312 TestIter("dir4", NULL, 0); | |
313 } | |
314 | |
315 TEST_F(GDataDBTest, IncompatibleProtoTest) { | |
316 GDataDirectoryService directory_service; | |
317 GDataFile file(directory_service.root(), &directory_service); | |
318 file.set_title("file"); | |
319 file.set_base_name("file"); | |
320 file.set_resource_id("file_resource_id"); | |
321 file.set_content_url(GURL("http://content/dir/file")); | |
322 file.set_file_md5("file_md5"); | |
323 | |
324 // Add a file and check if it's found. | |
325 GDataDB::Status status = gdata_db_->Put(file); | |
326 ASSERT_EQ(GDataDB::DB_OK, status); | |
327 TestGetFound(file); | |
328 // Check if the iterator works too. | |
329 const char* all_entries[] = { | |
330 "drive/file", | |
331 }; | |
332 TestIter("", all_entries, arraysize(all_entries)); | |
333 | |
334 // Tweak the file proto to simulate an incompatible proto in the DB. | |
335 GDataEntryProto entry_proto; | |
336 file.ToProto(&entry_proto); | |
337 // This will make FromProto() fail. | |
338 entry_proto.clear_upload_url(); | |
339 std::string serialized_proto; | |
340 entry_proto.SerializeToString(&serialized_proto); | |
341 gdata_db_->PutRawForTesting("file_resource_id", serialized_proto); | |
342 | |
343 // Check if the corruption is detected. | |
344 TestGetCorrupt(file); | |
345 // We should no longer be able to find the file by iteration. | |
346 TestIter("", NULL, 0); | |
347 } | |
348 | |
349 } // namespace gdata | |
OLD | NEW |